From a6e534fc17203d535ec786b25aad9ff65afdbbea Mon Sep 17 00:00:00 2001 From: Rebecca Silberstein Date: Thu, 8 Jun 2017 00:12:44 -0700 Subject: WifiServiceImpl: check app status for startLOHS When apps register a request for LOHS, they should be the foreground app at the time of the request. If the requesting app is not the foreground app, the ERROR_INCOMPATIBLE_MODE error will be returned. Bug: 62356000 Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh Test: softap integration tests locally Test: in progress LOHS integration tests locally Test: cts-tradefed run cts-dev --module CtsNetTestCases -t android.net.wifi.cts.WifiManagerTest Change-Id: Ic51bbc28478f90983555943a45f4fd70f4b2b385 --- .../com/android/server/wifi/FrameworkFacade.java | 11 ++++++ .../com/android/server/wifi/WifiServiceImpl.java | 10 ++++++ .../android/server/wifi/WifiServiceImplTest.java | 40 ++++++++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/service/java/com/android/server/wifi/FrameworkFacade.java b/service/java/com/android/server/wifi/FrameworkFacade.java index 2c3e5f7e0..ba114df8a 100644 --- a/service/java/com/android/server/wifi/FrameworkFacade.java +++ b/service/java/com/android/server/wifi/FrameworkFacade.java @@ -16,6 +16,7 @@ package com.android.server.wifi; +import android.app.ActivityManager; import android.app.AppGlobals; import android.app.PendingIntent; import android.content.Context; @@ -161,4 +162,14 @@ public class FrameworkFacade { public boolean inStorageManagerCryptKeeperBounce() { return StorageManager.inCryptKeeperBounce(); } + + /** + * Check if the provided uid is the app in the foreground. + * @param uid the uid to check + * @return true if the app is in the foreground, false otherwise + * @throws RemoteException + */ + public boolean isAppForeground(int uid) throws RemoteException { + return ActivityManager.getService().isAppForeground(uid); + } } diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index d32a579ac..1e63433f4 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -1159,6 +1159,16 @@ public class WifiServiceImpl extends IWifiManager.Stub { return LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; } + // the app should be in the foreground + try { + if (!mFrameworkFacade.isAppForeground(uid)) { + return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; + } + } catch (RemoteException e) { + mLog.trace("RemoteException during isAppForeground when calling startLOHS"); + return LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; + } + mLog.trace("startLocalOnlyHotspot uid=% pid=%").c(uid).c(pid).flush(); synchronized (mLocalOnlyHotspotRequests) { diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java index 562143335..e45bee549 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -74,6 +74,7 @@ import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.Process; +import android.os.RemoteException; import android.os.UserManager; import android.os.WorkSource; import android.os.test.TestLooper; @@ -760,6 +761,9 @@ public class WifiServiceImplTest { // allow test to proceed without a permission check failure when(mSettingsStore.getLocationModeSetting(mContext)) .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + try { + when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true); + } catch (RemoteException e) { } when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) .thenReturn(false); int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, @@ -811,13 +815,44 @@ public class WifiServiceImplTest { mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, TEST_PACKAGE_NAME); } + /** + * Only start LocalOnlyHotspot if the caller is the foreground app at the time of the request. + */ + @Test + public void testStartLocalOnlyHotspotFailsIfRequestorNotForegroundApp() throws Exception { + when(mSettingsStore.getLocationModeSetting(mContext)) + .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + + when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(false); + int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, + TEST_PACKAGE_NAME); + assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result); + } + + /** + * Do not register the LocalOnlyHotspot request if the caller app cannot be verified as the + * foreground app at the time of the request (ie, throws an exception in the check). + */ + @Test + public void testStartLocalOnlyHotspotFailsIfForegroundAppCheckThrowsRemoteException() + throws Exception { + when(mSettingsStore.getLocationModeSetting(mContext)) + .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + + when(mFrameworkFacade.isAppForeground(anyInt())).thenThrow(new RemoteException()); + int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, + TEST_PACKAGE_NAME); + assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result); + } + /** * Only start LocalOnlyHotspot if we are not tethering. */ @Test - public void testHotspotDoesNotStartWhenAlreadyTethering() { + public void testHotspotDoesNotStartWhenAlreadyTethering() throws Exception { when(mSettingsStore.getLocationModeSetting(mContext)) .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true); mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED); mLooper.dispatchAll(); int returnCode = mWifiServiceImpl.startLocalOnlyHotspot( @@ -829,9 +864,10 @@ public class WifiServiceImplTest { * Only start LocalOnlyHotspot if admin setting does not disallow tethering. */ @Test - public void testHotspotDoesNotStartWhenTetheringDisallowed() { + public void testHotspotDoesNotStartWhenTetheringDisallowed() throws Exception { when(mSettingsStore.getLocationModeSetting(mContext)) .thenReturn(LOCATION_MODE_HIGH_ACCURACY); + when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true); when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) .thenReturn(true); int returnCode = mWifiServiceImpl.startLocalOnlyHotspot( -- cgit v1.2.3