From 989265e3f6ec0cf4cdfc5b58e60db684827bf4b5 Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Tue, 26 Jul 2016 18:32:26 -0700 Subject: Add WiFi toggle prompts - wifi If permission review is enabled toggling WiFi on or off results in a user prompt to collect a consent. This applies only to legacy apps, i.e. ones that don't support runtime permissions as they target SDK 22. bug:28715749 Change-Id: Ie60ae91bd8e9c67a3e14a2820055234f669df1df --- .../com/android/server/wifi/WifiServiceImpl.java | 77 ++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 740ef6e54..d4ad0a7e0 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -36,6 +36,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; @@ -70,6 +71,7 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; +import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; @@ -160,6 +162,8 @@ public class WifiServiceImpl extends IWifiManager.Stub { */ private AsyncChannel mWifiStateMachineChannel; + private final boolean mPermissionReviewRequired; + /** * Handles client connections */ @@ -348,6 +352,10 @@ public class WifiServiceImpl extends IWifiManager.Stub { mSettingsStore, mWifiLockManager, wifiThread.getLooper(), mFacade); // Set the WifiController for WifiLastResortWatchdog mWifiInjector.getWifiLastResortWatchdog().setWifiController(mWifiController); + + mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED + || context.getResources().getBoolean( + com.android.internal.R.bool.config_permissionReviewRequired); } @@ -408,7 +416,13 @@ public class WifiServiceImpl extends IWifiManager.Stub { // If we are already disabled (could be due to airplane mode), avoid changing persist // state here - if (wifiEnabled) setWifiEnabled(wifiEnabled); + if (wifiEnabled) { + try { + setWifiEnabled(mContext.getPackageName(), wifiEnabled); + } catch (RemoteException e) { + /* ignore - local call */ + } + } } public void handleUserSwitch(int userId) { @@ -547,7 +561,8 @@ public class WifiServiceImpl extends IWifiManager.Stub { * @return {@code true} if the enable/disable operation was * started or is already in the queue. */ - public synchronized boolean setWifiEnabled(boolean enable) { + public synchronized boolean setWifiEnabled(String packageName, boolean enable) + throws RemoteException { enforceChangePermission(); Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); @@ -556,7 +571,6 @@ public class WifiServiceImpl extends IWifiManager.Stub { * Caller might not have WRITE_SECURE_SETTINGS, * only CHANGE_WIFI_STATE is enforced */ - long ident = Binder.clearCallingIdentity(); try { if (! mSettingsStore.handleWifiToggled(enable)) { @@ -567,6 +581,26 @@ public class WifiServiceImpl extends IWifiManager.Stub { Binder.restoreCallingIdentity(ident); } + + if (mPermissionReviewRequired) { + final int wiFiEnabledState = getWifiEnabledState(); + if (enable) { + if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING + || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) { + if (startConsentUiIfNeeded(packageName, Binder.getCallingUid(), + WifiManager.ACTION_REQUEST_ENABLE)) { + return true; + } + } + } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING + || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) { + if (startConsentUiIfNeeded(packageName, Binder.getCallingUid(), + WifiManager.ACTION_REQUEST_DISABLE)) { + return true; + } + } + } + mWifiController.sendMessage(CMD_WIFI_TOGGLED); return true; } @@ -1384,6 +1418,37 @@ public class WifiServiceImpl extends IWifiManager.Stub { } }; + private boolean startConsentUiIfNeeded(String packageName, + int callingUid, String intentAction) throws RemoteException { + if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { + return false; + } + try { + // Validate the package only if we are going to use it + ApplicationInfo applicationInfo = mContext.getPackageManager() + .getApplicationInfoAsUser(packageName, + PackageManager.MATCH_DEBUG_TRIAGED_MISSING, + UserHandle.getUserId(callingUid)); + if (applicationInfo.uid != callingUid) { + throw new SecurityException("Package " + callingUid + + " not in uid " + callingUid); + } + + // Legacy apps in permission review mode trigger a user prompt + if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + Intent intent = new Intent(intentAction); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); + mContext.startActivity(intent); + return true; + } + } catch (PackageManager.NameNotFoundException e) { + throw new RemoteException(e.getMessage()); + } + return false; + } + /** * Observes settings changes to scan always mode. */ @@ -1735,7 +1800,11 @@ public class WifiServiceImpl extends IWifiManager.Stub { if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) { // Enable wifi - setWifiEnabled(true); + try { + setWifiEnabled(mContext.getOpPackageName(), true); + } catch (RemoteException e) { + /* ignore - local call */ + } // Delete all Wifi SSIDs List networks = getConfiguredNetworks(); if (networks != null) { -- cgit v1.2.3