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

Commit 1a68c618 authored by Evan Severson's avatar Evan Severson Committed by Android (Google) Code Review
Browse files

Merge changes I0cab94ba,I73672b59

* changes:
  Add event log for uid state tracker in dumpsys
  Extract uid state foreground logic from AppOpsService
parents 4960560d 8885371b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -554,7 +554,7 @@ public class AppOpsManager {
     * @hide
     */
    public static int resolveFirstUnrestrictedUidState(int op) {
        return UID_STATE_FOREGROUND;
        return UID_STATE_MAX_LAST_NON_RESTRICTED;
    }

    /**
+152 −275

File changed.

Preview size limit exceeded, changes collapsed.

+120 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.appop;

import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
import static android.app.AppOpsManager.UID_STATE_TOP;

import android.os.Handler;
import android.util.SparseArray;

import java.io.PrintWriter;

interface AppOpsUidStateTracker {

    // Map from process states to the uid states we track.
    static int processStateToUidState(int procState) {
        if (procState == PROCESS_STATE_UNKNOWN) {
            return UID_STATE_CACHED;
        }

        if (procState <= PROCESS_STATE_PERSISTENT_UI) {
            return UID_STATE_PERSISTENT;
        }

        if (procState <= PROCESS_STATE_TOP) {
            return UID_STATE_TOP;
        }

        if (procState <= PROCESS_STATE_BOUND_TOP) {
            return UID_STATE_FOREGROUND;
        }

        if (procState <= PROCESS_STATE_FOREGROUND_SERVICE) {
            return UID_STATE_FOREGROUND_SERVICE;
        }

        if (procState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
            return UID_STATE_FOREGROUND;
        }

        if (procState <= PROCESS_STATE_RECEIVER) {
            return UID_STATE_BACKGROUND;
        }

        return UID_STATE_CACHED;
    }

    /*
     * begin data pushed from appopsservice
     */

    void updateUidProcState(int uid, int procState, int capability);

    void updateAppWidgetVisibility(SparseArray<String> uidPackageNames, boolean visible);

    /*
     * end data pushed from appopsservice
     */

    /**
     * Gets the {@link android.app.AppOpsManager.UidState} that the uid current is in.
     */
    int getUidState(int uid);

    /**
     * Given a uid, code, and mode, resolve any foregroundness to MODE_IGNORED or MODE_ALLOWED
     */
    int evalMode(int uid, int code, int mode);

    /**
     * Listen to changes in {@link android.app.AppOpsManager.UidState}
     */
    void addUidStateChangedCallback(Handler handler,
            UidStateChangedCallback callback);

    /**
     * Remove a {@link UidStateChangedCallback}
     */
    void removeUidStateChangedCallback(UidStateChangedCallback callback);

    interface UidStateChangedCallback {
        /**
         * Invoked when a UID's {@link android.app.AppOpsManager.UidState} changes.
         * @param uid The uid that changed.
         * @param uidState The state that was changed to.
         * @param foregroundModeMayChange True if there may be a op in MODE_FOREGROUND whose
         *                               evaluated result may have changed.
         */
        void onUidStateChanged(int uid, int uidState, boolean foregroundModeMayChange);
    }

    void dumpUidState(PrintWriter pw, int uid, long nowElapsed);

    void dumpEvents(PrintWriter pw);
}
+600 −0

File added.

Preview size limit exceeded, changes collapsed.

+0 −121
Original line number Diff line number Diff line
@@ -15,10 +15,8 @@
 */
package com.android.server.appop;

import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_READ_SMS;
@@ -41,7 +39,6 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;

import android.app.ActivityManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
import android.content.ContentResolver;
@@ -335,124 +332,6 @@ public class AppOpsServiceTest {
        assertThat(getLoggedOps()).isNull();
    }

    private void setupProcStateTests() {
        // For the location proc state tests
        mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_FOREGROUND);
        mAppOpsService.mConstants.FG_SERVICE_STATE_SETTLE_TIME = 0;
        mAppOpsService.mConstants.TOP_STATE_SETTLE_TIME = 0;
        mAppOpsService.mConstants.BG_STATE_SETTLE_TIME = 0;
    }

    @Test
    public void testUidProcStateChange_cachedToTopToCached() throws Exception {
        setupProcStateTests();

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        // Second time to make sure that settle time is overcome
        Thread.sleep(50);
        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);
    }

    @Test
    public void testUidProcStateChange_cachedToFgs() {
        setupProcStateTests();
        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);
    }

    @Test
    public void testUidProcStateChange_cachedToFgsLocation() {
        setupProcStateTests();

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isEqualTo(MODE_ALLOWED);
    }

    @Test
    public void testUidProcStateChange_topToFgs() throws Exception {
        setupProcStateTests();

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        // Second time to make sure that settle time is overcome
        Thread.sleep(50);
        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);
    }

    @Test
    public void testUidProcStateChange_topToFgsLocationToFgs() throws Exception {
        setupProcStateTests();

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        // Second time to make sure that settle time is overcome
        Thread.sleep(50);
        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        // Second time to make sure that settle time is overcome
        Thread.sleep(50);
        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null, false).getOpMode()).isNotEqualTo(MODE_ALLOWED);
    }

    private List<PackageOps> getLoggedOps() {
        return mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName, null /* all ops */);
    }
Loading