• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi;
18 
19 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
20 import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
21 
22 import android.annotation.NonNull;
23 import android.app.ActivityManager;
24 import android.app.AlertDialog;
25 import android.app.Notification;
26 import android.app.PendingIntent;
27 import android.app.admin.DevicePolicyManager;
28 import android.content.ContentResolver;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.pm.PackageManager;
32 import android.content.pm.ResolveInfo;
33 import android.content.res.Configuration;
34 import android.database.ContentObserver;
35 import android.net.TrafficStats;
36 import android.net.Uri;
37 import android.net.ip.IpClientCallbacks;
38 import android.net.ip.IpClientUtil;
39 import android.os.PersistableBundle;
40 import android.os.Process;
41 import android.os.UserHandle;
42 import android.os.WorkSource;
43 import android.provider.Settings;
44 import android.security.KeyChain;
45 import android.telephony.CarrierConfigManager;
46 import android.util.Log;
47 import android.widget.Toast;
48 
49 import com.android.server.wifi.util.WifiAsyncChannel;
50 
51 import java.util.List;
52 import java.util.NoSuchElementException;
53 
54 /**
55  * This class allows overriding objects with mocks to write unit tests
56  */
57 public class FrameworkFacade {
58     public static final String TAG = "FrameworkFacade";
59 
60     private ContentResolver mContentResolver = null;
61     private CarrierConfigManager mCarrierConfigManager = null;
62     private ActivityManager mActivityManager = null;
63 
getContentResolver(Context context)64     private ContentResolver getContentResolver(Context context) {
65         if (mContentResolver == null) {
66             mContentResolver = context.getContentResolver();
67         }
68         return mContentResolver;
69     }
70 
getCarrierConfigManager(Context context)71     private CarrierConfigManager getCarrierConfigManager(Context context) {
72         if (mCarrierConfigManager == null) {
73             mCarrierConfigManager =
74                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
75         }
76         return mCarrierConfigManager;
77     }
78 
getActivityManager(Context context)79     private ActivityManager getActivityManager(Context context) {
80         if (mActivityManager == null) {
81             mActivityManager =
82                 (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
83         }
84         return mActivityManager;
85     }
86 
87     /**
88      * Mockable setter for Settings.Global
89      */
setIntegerSetting(ContentResolver contentResolver, String name, int value)90     public boolean setIntegerSetting(ContentResolver contentResolver, String name, int value) {
91         return Settings.Global.putInt(contentResolver, name, value);
92     }
93 
94     /**
95      * Mockable getter for Settings.Global
96      */
getIntegerSetting(ContentResolver contentResolver, String name, int def)97     public int getIntegerSetting(ContentResolver contentResolver, String name, int def) {
98         return Settings.Global.getInt(contentResolver, name, def);
99     }
100 
setIntegerSetting(Context context, String name, int def)101     public boolean setIntegerSetting(Context context, String name, int def) {
102         return Settings.Global.putInt(getContentResolver(context), name, def);
103     }
104 
getIntegerSetting(Context context, String name, int def)105     public int getIntegerSetting(Context context, String name, int def) {
106         return Settings.Global.getInt(getContentResolver(context), name, def);
107     }
108 
getLongSetting(Context context, String name, long def)109     public long getLongSetting(Context context, String name, long def) {
110         return Settings.Global.getLong(getContentResolver(context), name, def);
111     }
112 
setStringSetting(Context context, String name, String def)113     public boolean setStringSetting(Context context, String name, String def) {
114         return Settings.Global.putString(getContentResolver(context), name, def);
115     }
116 
getStringSetting(Context context, String name)117     public String getStringSetting(Context context, String name) {
118         return Settings.Global.getString(getContentResolver(context), name);
119     }
120 
121     /**
122      * Mockable facade to Settings.Secure.getInt(.).
123      */
getSecureIntegerSetting(Context context, String name, int def)124     public int getSecureIntegerSetting(Context context, String name, int def) {
125         return Settings.Secure.getInt(getContentResolver(context), name, def);
126     }
127 
128     /**
129      * Mockable facade to Settings.Secure.getString(.).
130      */
getSecureStringSetting(Context context, String name)131     public String getSecureStringSetting(Context context, String name) {
132         return Settings.Secure.getString(getContentResolver(context), name);
133     }
134 
135     /**
136      * Returns whether the device is in NIAP mode or not.
137      */
isNiapModeOn(Context context)138     public boolean isNiapModeOn(Context context) {
139         DevicePolicyManager devicePolicyManager =
140                 context.getSystemService(DevicePolicyManager.class);
141         if (devicePolicyManager == null
142                 && context.getPackageManager().hasSystemFeature(FEATURE_DEVICE_ADMIN)) {
143             Log.e(TAG, "Error retrieving DPM service");
144         }
145         if (devicePolicyManager == null) return false;
146         return devicePolicyManager.isCommonCriteriaModeEnabled(null);
147     }
148 
149     /**
150      * Helper method for classes to register a ContentObserver
151      * {@see ContentResolver#registerContentObserver(Uri,boolean,ContentObserver)}.
152      *
153      * @param context
154      * @param uri
155      * @param notifyForDescendants
156      * @param contentObserver
157      */
registerContentObserver(Context context, Uri uri, boolean notifyForDescendants, ContentObserver contentObserver)158     public void registerContentObserver(Context context, Uri uri,
159             boolean notifyForDescendants, ContentObserver contentObserver) {
160         getContentResolver(context).registerContentObserver(uri, notifyForDescendants,
161                 contentObserver);
162     }
163 
164     /**
165      * Helper method for classes to unregister a ContentObserver
166      * {@see ContentResolver#unregisterContentObserver(ContentObserver)}.
167      *
168      * @param context
169      * @param contentObserver
170      */
unregisterContentObserver(Context context, ContentObserver contentObserver)171     public void unregisterContentObserver(Context context, ContentObserver contentObserver) {
172         getContentResolver(context).unregisterContentObserver(contentObserver);
173     }
174 
getBroadcast(Context context, int requestCode, Intent intent, int flags)175     public PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags) {
176         return PendingIntent.getBroadcast(context, requestCode, intent, flags);
177     }
178 
179     /**
180      * Wrapper for {@link PendingIntent#getActivity}.
181      */
getActivity(Context context, int requestCode, Intent intent, int flags)182     public PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags) {
183         return PendingIntent.getActivity(context, requestCode, intent, flags);
184     }
185 
getConfigWiFiDisableInECBM(Context context)186     public boolean getConfigWiFiDisableInECBM(Context context) {
187         CarrierConfigManager configManager = getCarrierConfigManager(context);
188         if (configManager == null) {
189             return false;
190         }
191         PersistableBundle bundle = configManager.getConfig();
192         if (bundle == null) {
193             return false;
194         }
195         return bundle.getBoolean(CarrierConfigManager.KEY_CONFIG_WIFI_DISABLE_IN_ECBM);
196     }
197 
getTxPackets(String iface)198     public long getTxPackets(String iface) {
199         return TrafficStats.getTxPackets(iface);
200     }
201 
getRxPackets(String iface)202     public long getRxPackets(String iface) {
203         return TrafficStats.getRxPackets(iface);
204     }
205 
206     /**
207      * Request a new IpClient to be created asynchronously.
208      * @param context Context to use for creation.
209      * @param iface Interface the client should act on.
210      * @param callback IpClient event callbacks.
211      */
makeIpClient(Context context, String iface, IpClientCallbacks callback)212     public void makeIpClient(Context context, String iface, IpClientCallbacks callback) {
213         IpClientUtil.makeIpClient(context, iface, callback);
214     }
215 
216     /**
217      * Create a new instance of WifiAsyncChannel
218      * @param tag String corresponding to the service creating the channel
219      * @return WifiAsyncChannel object created
220      */
makeWifiAsyncChannel(String tag)221     public WifiAsyncChannel makeWifiAsyncChannel(String tag) {
222         return new WifiAsyncChannel(tag);
223     }
224 
225     /**
226      * Check if the provided uid is the app in the foreground.
227      * @param uid the uid to check
228      * @return true if the app is in the foreground, false otherwise
229      */
isAppForeground(Context context, int uid)230     public boolean isAppForeground(Context context, int uid) {
231         ActivityManager activityManager = getActivityManager(context);
232         if (activityManager == null) return false;
233         return activityManager.getUidImportance(uid) <= IMPORTANCE_VISIBLE;
234     }
235 
236     /**
237      * Create a new instance of {@link Notification.Builder}.
238      * @param context reference to a Context
239      * @param channelId ID of the notification channel
240      * @return an instance of Notification.Builder
241      */
makeNotificationBuilder(Context context, String channelId)242     public Notification.Builder makeNotificationBuilder(Context context, String channelId) {
243         return new Notification.Builder(context, channelId);
244     }
245 
246     /**
247      * Starts supplicant
248      */
startSupplicant()249     public boolean startSupplicant() {
250         try {
251             SupplicantManager.start();
252             return true;
253         } catch (NoSuchElementException e) {
254             return false;
255         }
256     }
257 
258     /**
259      * Stops supplicant
260      */
stopSupplicant()261     public void stopSupplicant() {
262         SupplicantManager.stop();
263     }
264 
265     /**
266      * Create a new instance of {@link AlertDialog.Builder}.
267      * @param context reference to a Context
268      * @return an instance of AlertDialog.Builder
269      */
makeAlertDialogBuilder(Context context)270     public AlertDialog.Builder makeAlertDialogBuilder(Context context) {
271         boolean isDarkTheme = (context.getResources().getConfiguration().uiMode
272                 & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
273         return new AlertDialog.Builder(context, isDarkTheme
274                 ? android.R.style.Theme_DeviceDefault_Dialog_Alert : 0);
275     }
276 
277     /**
278      * Show a toast message
279      * @param context reference to a Context
280      * @param text the message to display
281      */
showToast(Context context, String text)282     public void showToast(Context context, String text) {
283         Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
284         toast.show();
285     }
286 
287     /**
288      * Wrapper for {@link TrafficStats#getMobileTxBytes}.
289      */
getMobileTxBytes()290     public long getMobileTxBytes() {
291         return TrafficStats.getMobileTxBytes();
292     }
293 
294     /**
295      * Wrapper for {@link TrafficStats#getMobileRxBytes}.
296      */
getMobileRxBytes()297     public long getMobileRxBytes() {
298         return TrafficStats.getMobileRxBytes();
299     }
300 
301     /**
302      * Wrapper for {@link TrafficStats#getTotalTxBytes}.
303      */
getTotalTxBytes()304     public long getTotalTxBytes() {
305         return TrafficStats.getTotalTxBytes();
306     }
307 
308     /**
309      * Wrapper for {@link TrafficStats#getTotalRxBytes}.
310      */
getTotalRxBytes()311     public long getTotalRxBytes() {
312         return TrafficStats.getTotalRxBytes();
313     }
314 
315     private String mSettingsPackageName;
316 
317     /**
318      * @return Get settings package name.
319      */
getSettingsPackageName(@onNull Context context)320     public String getSettingsPackageName(@NonNull Context context) {
321         if (mSettingsPackageName != null) return mSettingsPackageName;
322 
323         Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
324         List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivitiesAsUser(
325                 intent, PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEFAULT_ONLY,
326                 UserHandle.of(ActivityManager.getCurrentUser()));
327         if (resolveInfos == null || resolveInfos.isEmpty()) {
328             Log.e(TAG, "Failed to resolve wifi settings activity");
329             return null;
330         }
331         // Pick the first one if there are more than 1 since the list is ordered from best to worst.
332         mSettingsPackageName = resolveInfos.get(0).activityInfo.packageName;
333         return mSettingsPackageName;
334     }
335 
336     /**
337      * @return Get a worksource to blame settings apps.
338      */
getSettingsWorkSource(Context context)339     public WorkSource getSettingsWorkSource(Context context) {
340         String settingsPackageName = getSettingsPackageName(context);
341         if (settingsPackageName == null) return new WorkSource(Process.SYSTEM_UID);
342         return new WorkSource(Process.SYSTEM_UID, settingsPackageName);
343     }
344 
345     /**
346      * Returns whether a KeyChain key is granted to the WiFi stack.
347      */
hasWifiKeyGrantAsUser(Context context, UserHandle user, String alias)348     public boolean hasWifiKeyGrantAsUser(Context context, UserHandle user, String alias) {
349         return KeyChain.hasWifiKeyGrantAsUser(context, user, alias);
350     }
351 
352     /**
353      * Returns grant string for a given KeyChain alias or null if key not granted.
354      */
getWifiKeyGrantAsUser(Context context, UserHandle user, String alias)355     public String getWifiKeyGrantAsUser(Context context, UserHandle user, String alias) {
356         return KeyChain.getWifiKeyGrantAsUser(context, user, alias);
357     }
358 }
359