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

Commit 728fc342 authored by Evan Severson's avatar Evan Severson
Browse files

Split appops.xml into two files

Currently AppOpsService persists appop state into a single "appops.xml"
file. Instead, split this file into two:

1. "appops.xml": stores appop state
2. "appops_accesses.xml": stores recent appop accesses

This allows us to split the responsibility of maintaining different
types of state across different services:

- app-op state: maintained by AppOpsServiceInterface (where the
  implementation can vary)
- app-op accesses: maintained by AppOpsService

For transition purposes, the app-op history will be read from the
original "appops.xml" file before the new file exists.

(Also, bring back the unrelated AppOpsCheckingServiceTracingDecorator
which was accidentally nuked in a recent change.)

Test: atest AppOpsUpgradeTest CtsAppOpsTestCases
Bug: 266163878
Change-Id: I1ffc6375abaf8c62f91e7aefe0b76923f437ee0e
parent e07c6141
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -2314,7 +2314,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        mUiContext = null;
        mAppErrors = null;
        mPackageWatchdog = null;
        mAppOpsService = mInjector.getAppOpsService(null /* file */, null /* handler */);
        mAppOpsService = mInjector.getAppOpsService(null /* recentAccessesFile */,
            null /* storageFile */, null /* handler */);
        mBatteryStatsService = mInjector.getBatteryStatsService();
        mHandler = new MainHandler(handlerThread.getLooper());
        mHandlerThread = handlerThread;
@@ -2443,7 +2444,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
        mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler);
        mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops_accesses.xml"),
                new File(systemDir, "appops.xml"), mHandler);
        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
@@ -19001,8 +19003,9 @@ public class ActivityManagerService extends IActivityManager.Stub
            return mContext;
        }
        public AppOpsService getAppOpsService(File file, Handler handler) {
            return new AppOpsService(file, handler, getContext());
        public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile,
                Handler handler) {
            return new AppOpsService(recentAccessesFile, storageFile, handler, getContext());
        }
        public Handler getUiHandler(ActivityManagerService service) {
+575 −10

File changed.

Preview size limit exceeded, changes collapsed.

+28 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import android.util.ArraySet;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;

import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;

/**
@@ -31,6 +33,32 @@ import java.io.PrintWriter;
 * In the future this interface will also include op restrictions.
 */
public interface AppOpsCheckingServiceInterface {

    /**
     * Tells the checking service to write its state to persistence (unconditionally).
     * This is only made visible for testing.
     */
    @VisibleForTesting
    void writeState();

    /**
     * Tells the checking service to read its state from persistence. This is generally called
     * shortly after instantiation. If extra system services need to be guaranteed to be published
     * that work should be done in {@link #systemReady()}
     */
    void readState();

    /**
     * Tells the checking service that a shutdown is occurring. This gives it a chance to write its
     * state to persistence (if there are any pending changes).
     */
    void shutdown();

    /**
     * Do additional initialization work that is dependent on external system services.
     */
    void systemReady();

    /**
     * Returns a copy of non-default app-ops with op as keys and their modes as values for a uid.
     * Returns an empty SparseIntArray if nothing is set.
+24 −0
Original line number Diff line number Diff line
@@ -39,6 +39,30 @@ public class AppOpsCheckingServiceLoggingDecorator implements AppOpsCheckingServ
        mService = service;
    }

    @Override
    public void writeState() {
        Log.i(LOG_TAG, "writeState()");
        mService.writeState();
    }

    @Override
    public void readState() {
        Log.i(LOG_TAG, "readState()");
        mService.readState();
    }

    @Override
    public void shutdown() {
        Log.i(LOG_TAG, "shutdown()");
        mService.shutdown();
    }

    @Override
    public void systemReady() {
        Log.i(LOG_TAG, "systemReady()");
        mService.systemReady();
    }

    @Override
    public SparseIntArray getNonDefaultUidModes(int uid) {
        Log.i(LOG_TAG, "getNonDefaultUidModes(uid = " + uid + ")");
+334 −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 android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.os.Trace;
import android.util.ArraySet;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;

import java.io.PrintWriter;

/**
 * Surrounds all AppOpsCheckingServiceInterface method calls with Trace.traceBegin and
 * Trace.traceEnd. These traces are used for performance testing.
 */
public class AppOpsCheckingServiceTracingDecorator implements AppOpsCheckingServiceInterface {
    private static final long TRACE_TAG = Trace.TRACE_TAG_SYSTEM_SERVER;
    private final AppOpsCheckingServiceInterface mService;

    AppOpsCheckingServiceTracingDecorator(
            @NonNull AppOpsCheckingServiceInterface appOpsCheckingServiceInterface) {
        mService = appOpsCheckingServiceInterface;
    }

    @Override
    public void writeState() {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#writeState");
        try {
            mService.writeState();
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void readState() {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#readState");
        try {
            mService.readState();
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void shutdown() {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#shutdown");
        try {
            mService.shutdown();
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void systemReady() {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#systemReady");
        try {
            mService.systemReady();
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public SparseIntArray getNonDefaultUidModes(int uid) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getNonDefaultUidModes");
        try {
            return mService.getNonDefaultUidModes(uid);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public SparseIntArray getNonDefaultPackageModes(String packageName, int userId) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getNonDefaultPackageModes");
        try {
            return mService.getNonDefaultPackageModes(packageName, userId);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public int getUidMode(int uid, int op) {
        Trace.traceBegin(TRACE_TAG, "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getUidMode");
        try {
            return mService.getUidMode(uid, op);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public boolean setUidMode(int uid, int op, @AppOpsManager.Mode int mode) {
        Trace.traceBegin(TRACE_TAG, "TaggedTracingAppOpsCheckingServiceInterfaceImpl#setUidMode");
        try {
            return mService.setUidMode(uid, op, mode);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public int getPackageMode(@NonNull String packageName, int op, @UserIdInt int userId) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getPackageMode");
        try {
            return mService.getPackageMode(packageName, op, userId);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void setPackageMode(@NonNull String packageName, int op, @AppOpsManager.Mode int mode,
            @UserIdInt int userId) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#setPackageMode");
        try {
            mService.setPackageMode(packageName, op, mode, userId);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public boolean removePackage(@NonNull String packageName, @UserIdInt int userId) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#removePackage");
        try {
            return mService.removePackage(packageName, userId);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void removeUid(int uid) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#removeUid");
        try {
            mService.removeUid(uid);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public boolean areUidModesDefault(int uid) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#areUidModesDefault");
        try {
            return mService.areUidModesDefault(uid);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public boolean arePackageModesDefault(String packageName, @UserIdInt int userId) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#arePackageModesDefault");
        try {
            return mService.arePackageModesDefault(packageName, userId);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void clearAllModes() {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#clearAllModes");
        try {
            mService.clearAllModes();
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
            int op) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#startWatchingOpModeChanged");
        try {
            mService.startWatchingOpModeChanged(changedListener, op);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
            @NonNull String packageName) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#startWatchingPackageModeChanged");
        try {
            mService.startWatchingPackageModeChanged(changedListener, packageName);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#removeListener");
        try {
            mService.removeListener(changedListener);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getOpModeChangedListeners");
        try {
            return mService.getOpModeChangedListeners(op);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
            @NonNull String packageName) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#getPackageModeChangedListeners");
        try {
            return mService.getPackageModeChangedListeners(packageName);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void notifyWatchersOfChange(int op, int uid) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyWatchersOfChange");
        try {
            mService.notifyWatchersOfChange(op, uid);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
            @Nullable String packageName) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyOpChanged");
        try {
            mService.notifyOpChanged(changedListener, op, uid, packageName);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
            @Nullable OnOpModeChangedListener callbackToIgnore) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#notifyOpChangedForAllPkgsInUid");
        try {
            mService.notifyOpChangedForAllPkgsInUid(op, uid, onlyForeground, callbackToIgnore);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#evalForegroundUidOps");
        try {
            return mService.evalForegroundUidOps(uid, foregroundOps);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public SparseBooleanArray evalForegroundPackageOps(String packageName,
            SparseBooleanArray foregroundOps, @UserIdInt int userId) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#evalForegroundPackageOps");
        try {
            return mService.evalForegroundPackageOps(packageName, foregroundOps, userId);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }

    @Override
    public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
            PrintWriter printWriter) {
        Trace.traceBegin(TRACE_TAG,
                "TaggedTracingAppOpsCheckingServiceInterfaceImpl#dumpListeners");
        try {
            return mService.dumpListeners(dumpOp, dumpUid, dumpPackage, printWriter);
        } finally {
            Trace.traceEnd(TRACE_TAG);
        }
    }
}
Loading