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

Commit fe2fc3a9 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Package manager is not ready when reading app-ops state

Test: atest AppOpsUpgradeTest#testUpgradeFromNoVersion
Bug: 148180766
Change-Id: I924cae529d358d7e8f467fa27282bf23f6910281
parent 94faa4a7
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -2617,7 +2617,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mProcessCpuThread.start();
        mBatteryStatsService.publish();
        mAppOpsService.publish(mContext);
        mAppOpsService.publish();
        Slog.d("AppOps", "AppOpsService published");
        LocalServices.addService(ActivityManagerInternal.class, mInternal);
        mActivityTaskManager.onActivityManagerInternalAdded();
@@ -19507,7 +19507,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        public AppOpsService getAppOpsService(File file, Handler handler) {
            return new AppOpsService(file, handler);
            return new AppOpsService(file, handler, getContext());
        }
        public Handler getUiHandler(ActivityManagerService service) {
+11 −4
Original line number Diff line number Diff line
@@ -225,7 +225,7 @@ public class AppOpsService extends IAppOpsService.Stub {
    //TODO: remove this when development is done.
    private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;

    Context mContext;
    final Context mContext;
    final AtomicFile mFile;
    final Handler mHandler;

@@ -1353,7 +1353,9 @@ public class AppOpsService extends IAppOpsService.Stub {
        featureOp.onClientDeath(clientId);
    }

    public AppOpsService(File storagePath, Handler handler) {
    public AppOpsService(File storagePath, Handler handler, Context context) {
        mContext = context;

        LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
        mFile = new AtomicFile(storagePath, "appops");
        mHandler = handler;
@@ -1367,8 +1369,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    public void publish(Context context) {
        mContext = context;
    public void publish() {
        ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
        LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
    }
@@ -2143,6 +2144,12 @@ public class AppOpsService extends IAppOpsService.Stub {

    private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) {
        PackageManager packageManager = mContext.getPackageManager();
        if (packageManager == null) {
            // This can only happen during early boot. At this time the permission state and appop
            // state are in sync
            return;
        }

        String[] packageNames = packageManager.getPackagesForUid(uid);
        if (ArrayUtils.isEmpty(packageNames)) {
            return;
+1 −2
Original line number Diff line number Diff line
@@ -101,9 +101,8 @@ public class AppOpsServiceTest {
    private StaticMockitoSession mMockingSession;

    private void setupAppOpsService() {
        mAppOpsService = new AppOpsService(mAppOpsFile, mHandler);
        mAppOpsService = new AppOpsService(mAppOpsFile, mHandler, spy(sContext));
        mAppOpsService.mHistoricalRegistry.systemReady(sContext.getContentResolver());
        mAppOpsService.mContext = spy(sContext);

        // Always approve all permission checks
        doNothing().when(mAppOpsService.mContext).enforcePermission(anyString(), anyInt(),
+25 −3
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -19,9 +19,17 @@ package com.android.server.appop;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.os.Handler;
import android.os.HandlerThread;
@@ -133,10 +141,24 @@ public class AppOpsUpgradeTest {
        AppOpsDataParser parser = new AppOpsDataParser(mAppOpsFile);
        assertTrue(parser.parse());
        assertEquals(AppOpsDataParser.NO_VERSION, parser.mVersion);
        AppOpsService testService = new AppOpsService(mAppOpsFile, mHandler); // trigger upgrade

        // Use mock context and package manager to fake permision package manager calls.
        Context testContext = spy(mContext);

        // Pretent everybody has all permissions
        doNothing().when(testContext).enforcePermission(anyString(), anyInt(), anyInt(),
                nullable(String.class));

        PackageManager testPM = mock(PackageManager.class);
        when(testContext.getPackageManager()).thenReturn(testPM);

        // Stub out package calls to disable AppOpsService#updatePermissionRevokedCompat
        when(testPM.getPackagesForUid(anyInt())).thenReturn(null);

        AppOpsService testService = spy(
                new AppOpsService(mAppOpsFile, mHandler, testContext)); // trigger upgrade
        assertSameModes(testService.mUidStates, AppOpsManager.OP_RUN_IN_BACKGROUND,
                AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
        testService.mContext = mContext;
        mHandler.removeCallbacks(testService.mWriteRunner);
        testService.writeState();
        assertTrue(parser.parse());