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

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

Merge "Kill all running apps for a process when that process dies" into main

parents daf3a8e0 997368f4
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -482,7 +482,8 @@ public class AppOpsManager {
            UID_STATE_FOREGROUND_SERVICE,
            UID_STATE_FOREGROUND,
            UID_STATE_BACKGROUND,
            UID_STATE_CACHED
            UID_STATE_CACHED,
            UID_STATE_NONEXISTENT
    })
    public @interface UidState {}

@@ -565,6 +566,12 @@ public class AppOpsManager {
     */
    public static final int MIN_PRIORITY_UID_STATE = UID_STATE_CACHED;

    /**
     * Special uid state: The UID is not running
     * @hide
     */
    public static final int UID_STATE_NONEXISTENT = Integer.MAX_VALUE;

    /**
     * Resolves the first unrestricted state given an app op.
     * @param op The op to resolve.
@@ -596,6 +603,7 @@ public class AppOpsManager {
            UID_STATE_FOREGROUND,
            UID_STATE_BACKGROUND,
            UID_STATE_CACHED
            // UID_STATE_NONEXISTENT isn't a real UID state, so it is excluded
    };

    /** @hide */
@@ -615,6 +623,8 @@ public class AppOpsManager {
                return "bg";
            case UID_STATE_CACHED:
                return "cch";
            case UID_STATE_NONEXISTENT:
                return "gone";
            default:
                return "unknown";
        }
+10 −0
Original line number Diff line number Diff line
@@ -165,6 +165,16 @@ flag {
    bug: "325356776"
}

flag {
    name: "finish_running_ops_for_killed_packages"
    namespace: "permissions"
    description: "Finish all appops for a dead app process"
    bug: "234630570"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "runtime_permission_appops_mapping_enabled"
    is_fixed_read_only: true
+89 −5
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import static android.app.AppOpsManager.SAMPLING_STRATEGY_RARELY_USED;
import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM;
import static android.app.AppOpsManager.SAMPLING_STRATEGY_UNIFORM_OPS;
import static android.app.AppOpsManager.SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE;
import static android.app.AppOpsManager.UID_STATE_NONEXISTENT;
import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
import static android.app.AppOpsManager._NUM_OP;
import static android.app.AppOpsManager.extractFlagsFromKey;
@@ -70,7 +71,6 @@ import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import static android.content.Intent.EXTRA_REPLACING;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP;
import static android.permission.flags.Flags.runtimePermissionAppopsMappingEnabled;

import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;

@@ -130,6 +130,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.storage.StorageManagerInternal;
import android.permission.PermissionManager;
import android.permission.flags.Flags;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -140,6 +141,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.Xml;

@@ -153,7 +155,6 @@ import com.android.internal.app.IAppOpsNotedCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IAppOpsStartedCallback;
import com.android.internal.app.MessageSamplingConfig;
import com.android.internal.camera.flags.Flags;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.os.Clock;
import com.android.internal.pm.pkg.component.ParsedAttribution;
@@ -1421,6 +1422,9 @@ public class AppOpsService extends IAppOpsService.Stub {
    // The callback method from AppOpsUidStateTracker
    private void onUidStateChanged(int uid, int state, boolean foregroundModeMayChange) {
        synchronized (this) {
            if (state == UID_STATE_NONEXISTENT) {
                onUidProcessDeathLocked(uid);
            }
            UidState uidState = getUidStateLocked(uid, false);

            boolean hasForegroundWatchers = false;
@@ -1508,6 +1512,11 @@ public class AppOpsService extends IAppOpsService.Stub {
                }
            }

            if (state == UID_STATE_NONEXISTENT) {
                // For UID_STATE_NONEXISTENT, we don't call onUidStateChanged for AttributedOps
                return;
            }

            if (uidState != null) {
                int numPkgs = uidState.pkgOps.size();
                for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
@@ -1532,6 +1541,81 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
    }

    @GuardedBy("this")
    private void onUidProcessDeathLocked(int uid) {
        if (!mUidStates.contains(uid) || !Flags.finishRunningOpsForKilledPackages()) {
            return;
        }
        final SparseLongArray chainsToFinish = new SparseLongArray();
        doForAllAttributedOpsInUidLocked(uid, (attributedOp) -> {
            attributedOp.doForAllInProgressStartOpEvents((event) -> {
                int chainId = event.getAttributionChainId();
                if (chainId != ATTRIBUTION_CHAIN_ID_NONE) {
                    long currentEarliestStartTime =
                            chainsToFinish.get(chainId, Long.MAX_VALUE);
                    if (event.getStartTime() < currentEarliestStartTime) {
                        // Store the earliest chain link we're finishing, so that we can go back
                        // and finish any links in the chain that started after this one
                        chainsToFinish.put(chainId, event.getStartTime());
                    }
                }
                attributedOp.finished(event.getClientId());
            });
        });
        finishChainsLocked(chainsToFinish);
    }

    @GuardedBy("this")
    private void finishChainsLocked(SparseLongArray chainsToFinish) {
        doForAllAttributedOpsLocked((attributedOp) -> {
            attributedOp.doForAllInProgressStartOpEvents((event) -> {
                int chainId = event.getAttributionChainId();
                // If this event is part of a chain, and this event started after the event in the
                // chain we already finished, then finish this event, too
                long earliestEventStart = chainsToFinish.get(chainId, Long.MAX_VALUE);
                if (chainId != ATTRIBUTION_CHAIN_ID_NONE
                        && event.getStartTime() >= earliestEventStart) {
                    attributedOp.finished(event.getClientId());
                }
            });
        });
    }

    @GuardedBy("this")
    private void doForAllAttributedOpsLocked(Consumer<AttributedOp> action) {
        int numUids = mUidStates.size();
        for (int uidNum = 0; uidNum < numUids; uidNum++) {
            int uid = mUidStates.keyAt(uidNum);
            doForAllAttributedOpsInUidLocked(uid, action);
        }
    }

    @GuardedBy("this")
    private void doForAllAttributedOpsInUidLocked(int uid, Consumer<AttributedOp> action) {
        UidState uidState = mUidStates.get(uid);
        if (uidState == null) {
            return;
        }

        int numPkgs = uidState.pkgOps.size();
        for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
            Ops ops = uidState.pkgOps.valueAt(pkgNum);
            int numOps = ops.size();
            for (int opNum = 0; opNum < numOps; opNum++) {
                Op op = ops.valueAt(opNum);
                int numDevices = op.mDeviceAttributedOps.size();
                for (int deviceNum = 0; deviceNum < numDevices; deviceNum++) {
                    ArrayMap<String, AttributedOp> attrOps =
                            op.mDeviceAttributedOps.valueAt(deviceNum);
                    int numAttributions = attrOps.size();
                    for (int attrNum = 0; attrNum < numAttributions; attrNum++) {
                        action.accept(attrOps.valueAt(attrNum));
                    }
                }
            }
        }
    }

    /**
     * Notify the proc state or capability has changed for a certain UID.
     */
@@ -2702,7 +2786,7 @@ public class AppOpsService extends IAppOpsService.Stub {
     * have information on them.
     */
    private static boolean isOpAllowedForUid(int uid) {
        return runtimePermissionAppopsMappingEnabled()
        return Flags.runtimePermissionAppopsMappingEnabled()
                && (uid == Process.ROOT_UID || uid == Process.SYSTEM_UID);
    }

@@ -4775,8 +4859,8 @@ public class AppOpsService extends IAppOpsService.Stub {
        if ((code == OP_CAMERA) && isAutomotive()) {
            final long identity = Binder.clearCallingIdentity();
            try {
                if ((Flags.cameraPrivacyAllowlist())
                        && (mSensorPrivacyManager.isCameraPrivacyEnabled(packageName))) {
                if (com.android.internal.camera.flags.Flags.cameraPrivacyAllowlist()
                        && mSensorPrivacyManager.isCameraPrivacyEnabled(packageName)) {
                    return true;
                }
            } finally {
+1 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ interface AppOpsUidStateTracker {
            return UID_STATE_BACKGROUND;
        }

        // UID_STATE_NONEXISTENT is deliberately excluded here
        return UID_STATE_CACHED;
    }

+17 −4
Original line number Diff line number Diff line
@@ -34,7 +34,9 @@ import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_TAKE_AUDIO_FOCUS;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_NONEXISTENT;
import static android.app.AppOpsManager.UID_STATE_TOP;
import static android.permission.flags.Flags.finishRunningOpsForKilledPackages;

import static com.android.server.appop.AppOpsUidStateTracker.processStateToUidState;

@@ -343,14 +345,15 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
        int capability = mCapability.get(uid, PROCESS_CAPABILITY_NONE);
        boolean appWidgetVisible = mAppWidgetVisible.get(uid, false);

        if (uidState != pendingUidState
                || capability != pendingCapability
                || appWidgetVisible != pendingAppWidgetVisible) {
        boolean foregroundChange = uidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
                != pendingUidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
                || capability != pendingCapability
                || appWidgetVisible != pendingAppWidgetVisible;

        if (uidState != pendingUidState
                || capability != pendingCapability
                || appWidgetVisible != pendingAppWidgetVisible) {

            if (foregroundChange) {
                // To save on memory usage, log only interesting changes.
                mEventLog.logCommitUidState(uid, pendingUidState, pendingCapability,
@@ -372,6 +375,16 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
            mCapability.delete(uid);
            mAppWidgetVisible.delete(uid);
            mPendingGone.delete(uid);
            if (finishRunningOpsForKilledPackages()) {
                for (int i = 0; i < mUidStateChangedCallbacks.size(); i++) {
                    UidStateChangedCallback cb = mUidStateChangedCallbacks.keyAt(i);
                    Executor executor = mUidStateChangedCallbacks.valueAt(i);

                    executor.execute(PooledLambda.obtainRunnable(
                            UidStateChangedCallback::onUidStateChanged, cb, uid,
                            UID_STATE_NONEXISTENT, foregroundChange));
                }
            }
        } else {
            mUidStates.put(uid, pendingUidState);
            mCapability.put(uid, pendingCapability);
Loading