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 |