Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c7bac3f authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Create UidState for SdkSandbox uids related to app." into main

parents 83ffd6d3 8c8cd487
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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);
+62 −11
Original line number Diff line number Diff line
@@ -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