diff options
| -rw-r--r-- | services/core/java/com/android/server/appop/AppOpsService.java | 9 | ||||
| -rw-r--r-- | services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java | 73 |
2 files changed, 71 insertions, 11 deletions
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 344673793700..7780b3906b9f 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -1180,6 +1180,8 @@ public class AppOpsService extends IAppOpsService.Stub { uidState.pkgOps.put(packageName, new Ops(packageName, uidState)); } + + createSandboxUidStateIfNotExistsForAppLocked(uid); } } } @@ -1261,6 +1263,8 @@ public class AppOpsService extends IAppOpsService.Stub { ops.put(code, new Op(uidState, packageName, code, uid)); } } + + createSandboxUidStateIfNotExistsForAppLocked(uid); } /** @@ -4011,6 +4015,11 @@ public class AppOpsService extends IAppOpsService.Stub { return uidState; } + private void createSandboxUidStateIfNotExistsForAppLocked(int uid) { + final int sandboxUid = Process.toSdkSandboxUid(uid); + getUidStateLocked(sandboxUid, true); + } + private void updateAppWidgetVisibility(SparseArray<String> uidPackageNames, boolean visible) { synchronized (this) { getUidStateTracker().updateAppWidgetVisibility(uidPackageNames, visible); diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java index 646f4862d75d..79b39b82ee56 100644 --- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java @@ -20,7 +20,9 @@ import static android.app.AppOpsManager.MODE_ERRORED; import static android.app.AppOpsManager.OP_COARSE_LOCATION; import static android.app.AppOpsManager.OP_FLAGS_ALL; import static android.app.AppOpsManager.OP_FLAG_SELF; +import static android.app.AppOpsManager.OP_READ_DEVICE_IDENTIFIERS; import static android.app.AppOpsManager.OP_READ_SMS; +import static android.app.AppOpsManager.OP_TAKE_AUDIO_FOCUS; import static android.app.AppOpsManager.OP_WIFI_SCAN; import static android.app.AppOpsManager.OP_WRITE_SMS; import static android.os.UserHandle.getAppId; @@ -49,8 +51,10 @@ import static org.mockito.ArgumentMatchers.nullable; import android.app.AppOpsManager; import android.app.AppOpsManager.OpEntry; import android.app.AppOpsManager.PackageOps; +import android.app.SyncNotedAppOp; import android.content.ContentResolver; import android.content.Context; +import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.os.Handler; import android.os.HandlerThread; @@ -58,6 +62,7 @@ import android.os.Process; import android.permission.PermissionManager; import android.provider.Settings; import android.util.ArrayMap; +import android.util.Log; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -79,7 +84,6 @@ import org.junit.runner.RunWith; import org.mockito.quality.Strictness; import java.io.File; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -99,12 +103,15 @@ public class AppOpsServiceTest { private static final Context sContext = InstrumentationRegistry.getTargetContext(); private static final String sMyPackageName = sContext.getOpPackageName(); + private static final String sSdkSandboxPackageName = sContext.getPackageManager() + .getSdkSandboxPackageName(); private File mStorageFile; private File mRecentAccessesFile; private Handler mHandler; private AppOpsService mAppOpsService; private int mMyUid; + private int mSdkSandboxPackageUid; private long mTestStartMillis; private StaticMockitoSession mMockingSession; @@ -132,6 +139,7 @@ public class AppOpsServiceTest { handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); mMyUid = Process.myUid(); + mSdkSandboxPackageUid = resolveSdkSandboxPackageUid(); initializeStaticMocks(); @@ -152,6 +160,39 @@ public class AppOpsServiceTest { mMockingSession.finishMocking(); } + private static int resolveSdkSandboxPackageUid() { + try { + return sContext.getPackageManager().getPackageUid( + sSdkSandboxPackageName, + PackageManager.PackageInfoFlags.of(0) + ); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Can't resolve sandbox package uid", e); + return Process.INVALID_UID; + } + } + + private static void mockGetPackage( + PackageManagerInternal managerMock, + String packageName + ) { + AndroidPackage packageMock = mock(AndroidPackage.class); + when(managerMock.getPackage(packageName)).thenReturn(packageMock); + } + + private static void mockGetPackageStateInternal( + PackageManagerInternal managerMock, + String packageName, + int uid + ) { + PackageStateInternal packageStateInternalMock = mock(PackageStateInternal.class); + when(packageStateInternalMock.isPrivileged()).thenReturn(false); + when(packageStateInternalMock.getAppId()).thenReturn(uid); + when(packageStateInternalMock.getAndroidPackage()).thenReturn(mock(AndroidPackage.class)); + when(managerMock.getPackageStateInternal(packageName)) + .thenReturn(packageStateInternalMock); + } + private void initializeStaticMocks() { mMockingSession = mockitoSession() .strictness(Strictness.LENIENT) @@ -163,16 +204,11 @@ public class AppOpsServiceTest { // Mock LocalServices.getService(PackageManagerInternal.class).getPackageStateInternal // and getPackage dependency needed by AppOpsService PackageManagerInternal mockPackageManagerInternal = mock(PackageManagerInternal.class); - AndroidPackage mockMyPkg = mock(AndroidPackage.class); - when(mockMyPkg.getAttributions()).thenReturn(Collections.emptyList()); - PackageStateInternal mockMyPSInternal = mock(PackageStateInternal.class); - when(mockMyPSInternal.isPrivileged()).thenReturn(false); - when(mockMyPSInternal.getAppId()).thenReturn(mMyUid); - when(mockMyPSInternal.getAndroidPackage()).thenReturn(mockMyPkg); - - when(mockPackageManagerInternal.getPackageStateInternal(sMyPackageName)) - .thenReturn(mockMyPSInternal); - when(mockPackageManagerInternal.getPackage(sMyPackageName)).thenReturn(mockMyPkg); + mockGetPackage(mockPackageManagerInternal, sMyPackageName); + mockGetPackageStateInternal(mockPackageManagerInternal, sMyPackageName, mMyUid); + mockGetPackage(mockPackageManagerInternal, sSdkSandboxPackageName); + mockGetPackageStateInternal(mockPackageManagerInternal, sSdkSandboxPackageName, + mSdkSandboxPackageUid); when(mockPackageManagerInternal.getPackageUid(eq(sMyPackageName), anyLong(), eq(getUserId(mMyUid)))).thenReturn(mMyUid); doReturn(mockPackageManagerInternal).when( @@ -233,6 +269,21 @@ public class AppOpsServiceTest { assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED); } + @Test + public void testNoteOperationFromSdkSandbox() { + int sandboxUid = Process.toSdkSandboxUid(mMyUid); + + // Note an op that's allowed. + SyncNotedAppOp allowedResult = mAppOpsService.noteOperation(OP_TAKE_AUDIO_FOCUS, sandboxUid, + sSdkSandboxPackageName, null, false, null, false); + assertThat(allowedResult.getOpMode()).isEqualTo(MODE_ALLOWED); + + // Note another op that's not allowed. + SyncNotedAppOp erroredResult = mAppOpsService.noteOperation(OP_READ_DEVICE_IDENTIFIERS, + sandboxUid, sSdkSandboxPackageName, null, false, null, false); + assertThat(erroredResult.getOpMode()).isEqualTo(MODE_ERRORED); + } + /** * Tests the scenario where an operation's permission is controlled by another operation. * For example the results of a WIFI_SCAN can be used to infer the location of a user, so the |