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

Commit dfebe6bd authored by Alan Stokes's avatar Alan Stokes
Browse files

Clean up BLOCK_ACTIVITY_STARTS_AFTER_HOME_FLAG.

This flag was only introduced to allow teamfood testing of the change
to use background activity launch blocking instead of delaying app
launches after app switching protection is engaged. The flag has been
on everywhere for 2 weeks (ag/176961146) without problems and is no
longer needed.

This CL went in three stages:

- Change getBalAppSwitchesProtectionEnabled() in
  ActivityTaskManagerService to always return true.

- Inline the function (and selected others) into call sites and then
  eliminate the resulting dead code - done as a serious of automatic
  refactorings to minimise the risk of human error.

- Delete unit tests for code that no longer exists.

Apart from deleting the use of the flag I believe this CL is a pure
refactoring with no new behavior changes.

The end result is we eliminate quite a lot of code - especially
PendingActivityLaunch and all uses of it.

Test: atest BackgroundActivityLauncherTest
Test: atest ActivityStarterTests (both of them)
Test: manual
Bug: 176961146
Bug: 159433730
Change-Id: I01625843f67b00e5901833cff99aec16c1287a0c
Merged-In: I01625843f67b00e5901833cff99aec16c1287a0c
Exempt-From-Owner-Approval: proto change approved on main branch
(cherry picked from commit 5897ecc6)
parent 7e56827d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ message RootWindowContainerProto {
    // Whether or not the home activity is the recents activity. This is needed for the CTS tests to
    // know what activity types to check for when invoking splitscreen multi-window.
    optional bool is_home_recents_component = 6;
    repeated IdentifierProto pending_activities = 7;
    repeated IdentifierProto pending_activities = 7 [deprecated=true];
}

message BarControllerProto {
+0 −75
Original line number Diff line number Diff line
@@ -37,15 +37,11 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.RemoteAnimationAdapter;

import com.android.internal.annotations.VisibleForTesting;
@@ -55,10 +51,8 @@ import com.android.server.am.PendingIntentRecord;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityStarter.DefaultFactory;
import com.android.server.wm.ActivityStarter.Factory;
import com.android.server.wm.ActivityTaskSupervisor.PendingActivityLaunch;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
@@ -87,35 +81,12 @@ public class ActivityStartController {
    /** The result of the last home activity we attempted to start. */
    private int mLastHomeActivityStartResult;

    /** A list of activities that are waiting to launch. */
    private final ArrayList<ActivityTaskSupervisor.PendingActivityLaunch>
            mPendingActivityLaunches = new ArrayList<>();

    private final Factory mFactory;

    private final Handler mHandler;

    private final PendingRemoteAnimationRegistry mPendingRemoteAnimationRegistry;

    boolean mCheckedForSetup = false;

    private final class StartHandler extends Handler {
        public StartHandler(Looper looper) {
            super(looper, null, true);
        }

        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case DO_PENDING_ACTIVITY_LAUNCHES_MSG:
                    synchronized (mService.mGlobalLock) {
                        doPendingActivityLaunches(true);
                    }
                    break;
            }
        }
    }

    /**
     * TODO(b/64750076): Capture information necessary for dump and
     * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object
@@ -134,7 +105,6 @@ public class ActivityStartController {
            Factory factory) {
        mService = service;
        mSupervisor = supervisor;
        mHandler = new StartHandler(mService.mH.getLooper());
        mFactory = factory;
        mFactory.setController(this);
        mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service.mGlobalLock,
@@ -514,45 +484,6 @@ public class ActivityStartController {
        return START_SUCCESS;
    }

    void schedulePendingActivityLaunches(long delayMs) {
        mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
        Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
        mHandler.sendMessageDelayed(msg, delayMs);
    }

    void doPendingActivityLaunches(boolean doResume) {
        while (!mPendingActivityLaunches.isEmpty()) {
            final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
            final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
            final ActivityStarter starter = obtainStarter(null /* intent */,
                    "pendingActivityLaunch");
            try {
                starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags,
                        resume, pal.r.getOptions(), null, pal.intentGrants);
            } catch (Exception e) {
                Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
                pal.sendErrorResult(e.getMessage());
            }
        }
    }

    void addPendingActivityLaunch(PendingActivityLaunch launch) {
        mPendingActivityLaunches.add(launch);
    }

    boolean clearPendingActivityLaunches(String packageName) {
        final int pendingLaunches = mPendingActivityLaunches.size();

        for (int palNdx = pendingLaunches - 1; palNdx >= 0; --palNdx) {
            final PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
            final ActivityRecord r = pal.r;
            if (r != null && r.packageName.equals(packageName)) {
                mPendingActivityLaunches.remove(palNdx);
            }
        }
        return mPendingActivityLaunches.size() < pendingLaunches;
    }

    void registerRemoteAnimationForNextActivityStart(String packageName,
            RemoteAnimationAdapter adapter) {
        mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter);
@@ -609,10 +540,4 @@ public class ActivityStartController {
            pw.println("(nothing)");
        }
    }

    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        for (PendingActivityLaunch activity: mPendingActivityLaunches) {
            activity.r.writeIdentifierToProto(proto, fieldId);
        }
    }
}
+11 −38
Original line number Diff line number Diff line
@@ -122,7 +122,6 @@ import com.android.server.power.ShutdownCheckPoints;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
import com.android.server.wm.ActivityTaskSupervisor.PendingActivityLaunch;
import com.android.server.wm.LaunchParamsController.LaunchParams;

import java.io.PrintWriter;
@@ -1171,24 +1170,6 @@ class ActivityStarter {
            r.appTimeTracker = sourceRecord.appTimeTracker;
        }

        final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();

        // If we are starting an activity that is not from the same uid as the currently resumed
        // one, check whether app switches are allowed.
        if (voiceSession == null && rootTask != null && (rootTask.getResumedActivity() == null
                || rootTask.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                    realCallingPid, realCallingUid, "Activity start")) {
                if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) {
                    mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                            sourceRecord, startFlags, rootTask, callerApp, intentGrants));
                }
                ActivityOptions.abort(checkedOptions);
                return ActivityManager.START_SWITCHES_CANCELED;
            }
        }

        if (mService.getBalAppSwitchesProtectionEnabled()) {
        // Only allow app switching to be resumed if activity is not a restricted background
        // activity and target app is not home process, otherwise any background activity
        // started in background task can stop home button protection mode.
@@ -1201,11 +1182,6 @@ class ActivityStarter {
        if (!restrictedBgActivity && !isHomeProcess) {
            mService.resumeAppSwitches();
        }
        } else {
            mService.onStartActivitySetDidAppSwitch();
        }

        mController.doPendingActivityLaunches(false);

        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
@@ -1286,8 +1262,6 @@ class ActivityStarter {
            return false;
        }

        // App switching will be allowed if BAL app switching flag is not enabled, or if
        // its app switching rule allows it.
        // This is used to block background activity launch even if the app is still
        // visible to user after user clicking home button.
        final boolean appSwitchAllowed = mService.getBalAppSwitchesAllowed();
@@ -1438,7 +1412,6 @@ class ActivityStarter {
        Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
                + "; callingUid: " + callingUid
                + "; appSwitchAllowed: " + appSwitchAllowed
                + "; balAppSwitchEnabled: " + mService.getBalAppSwitchesProtectionEnabled()
                + "; isCallingUidForeground: " + isCallingUidForeground
                + "; callingUidHasAnyVisibleWindow: " + callingUidHasAnyVisibleWindow
                + "; callingUidProcState: " + DebugUtils.valueToString(ActivityManager.class,
+9 −122
Original line number Diff line number Diff line
@@ -202,7 +202,6 @@ import android.os.UserManager;
import android.os.WorkSource;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.dreams.DreamActivity;
import android.service.voice.IVoiceInteractionSession;
@@ -324,12 +323,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    /** This activity is being relaunched due to a free-resize operation. */
    public static final int RELAUNCH_REASON_FREE_RESIZE = 2;

    /**
     * Apps are blocked from starting activities in the foreground after the user presses home.
     */
    public static final String BLOCK_ACTIVITY_STARTS_AFTER_HOME_FLAG =
            "am_block_activity_starts_after_home";

    Context mContext;

    /**
@@ -386,7 +379,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    volatile WindowProcessController mHeavyWeightProcess;
    boolean mHasHeavyWeightFeature;
    boolean mHasLeanbackFeature;
    boolean mBlockActivityAfterHomeEnabled;
    /** The process of the top most activity. */
    volatile WindowProcessController mTopApp;
    /**
@@ -490,20 +482,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    /** Temporary to avoid allocations. */
    final StringBuilder mStringBuilder = new StringBuilder(256);

    // Amount of time after a call to stopAppSwitches() during which we will
    // prevent further untrusted switches from happening.
    private static final long APP_SWITCH_DELAY_TIME = 5 * 1000;

    /**
     * The time at which we will allow normal application switches again,
     * after a call to {@link #stopAppSwitches()}.
     * Whether normal application switches are allowed; a call to {@link #stopAppSwitches()
     * disables this.
     */
    private long mAppSwitchesAllowedTime;
    /**
     * This is set to true after the first switch after mAppSwitchesAllowedTime
     * is set; any switches after that will clear the time.
     */
    private boolean mDidAppSwitch;
    private boolean mAppSwitchesAllowed = true;

    /**
     * Last stop app switches time, apps finished before this time cannot start background activity
@@ -749,9 +732,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            mRecentTasks.onSystemReadyLocked();
            mTaskSupervisor.onSystemReady();
            mActivityClientController.onSystemReady();
            mBlockActivityAfterHomeEnabled = DeviceConfig.getBoolean(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    BLOCK_ACTIVITY_STARTS_AFTER_HOME_FLAG, true);
        }
    }

@@ -1146,7 +1126,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            if (topFocusedRootTask != null && topFocusedRootTask.getResumedActivity() != null
                    && topFocusedRootTask.getResumedActivity().info.applicationInfo.uid
                    == Binder.getCallingUid()) {
                mAppSwitchesAllowedTime = 0;
                mAppSwitchesAllowed = true;
            }
        }
        return pir.sendInner(0, fillInIntent, resolvedType, allowlistToken, null, null,
@@ -2002,10 +1982,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        assertPackageMatchesCallingUid(callingPackage);
        if (!checkAppSwitchAllowedLocked(callingPid, callingUid, -1, -1, "Task to front")) {
            SafeActivityOptions.abort(options);
            return;
        }

        final long origId = Binder.clearCallingIdentity();
        WindowProcessController callerApp = null;
        if (appThread != null) {
@@ -2085,77 +2062,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        throw new SecurityException(msg);
    }

    /**
     * Return true if app switch protection will be handled by background activity launch logic.
     */
    boolean getBalAppSwitchesProtectionEnabled() {
         return mBlockActivityAfterHomeEnabled;
    }

    /**
     * Return true if app switching is allowed.
     */
    boolean getBalAppSwitchesAllowed() {
        if (getBalAppSwitchesProtectionEnabled()) {
            // Apps no longer able to start BAL again until app switching is resumed.
            return mAppSwitchesAllowedTime == 0;
        } else {
            // Legacy behavior, BAL logic won't block app switching.
            return true;
        }
    }

    boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid,
            int callingPid, int callingUid, String name) {

        // Background activity launch logic replaces app switching protection, so allow
        // apps to start activity here now.
        if (getBalAppSwitchesProtectionEnabled()) {
            return true;
        }

        if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
            return true;
        }

        if (getRecentTasks().isCallerRecents(sourceUid)) {
            return true;
        }

        int perm = checkComponentPermission(STOP_APP_SWITCHES, sourcePid, sourceUid, -1, true);
        if (perm == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        if (checkAllowAppSwitchUid(sourceUid)) {
            return true;
        }

        // If the actual IPC caller is different from the logical source, then
        // also see if they are allowed to control app switches.
        if (callingUid != -1 && callingUid != sourceUid) {
            perm = checkComponentPermission(STOP_APP_SWITCHES, callingPid, callingUid, -1, true);
            if (perm == PackageManager.PERMISSION_GRANTED) {
                return true;
            }
            if (checkAllowAppSwitchUid(callingUid)) {
                return true;
            }
        }

        Slog.w(TAG, name + " request from " + sourceUid + " stopped");
        return false;
    }

    private boolean checkAllowAppSwitchUid(int uid) {
        ArrayMap<String, Integer> types = mAllowAppSwitchUids.get(UserHandle.getUserId(uid));
        if (types != null) {
            for (int i = types.size() - 1; i >= 0; i--) {
                if (types.valueAt(i).intValue() == uid) {
                    return true;
                }
            }
        }
        return false;
        return mAppSwitchesAllowed;
    }

    @Override
@@ -3663,13 +3574,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    public void stopAppSwitches() {
        enforceCallerIsRecentsOrHasPermission(STOP_APP_SWITCHES, "stopAppSwitches");
        synchronized (mGlobalLock) {
            mAppSwitchesAllowedTime = SystemClock.uptimeMillis() + APP_SWITCH_DELAY_TIME;
            mAppSwitchesAllowed = false;
            mLastStopAppSwitchesTime = SystemClock.uptimeMillis();
            mDidAppSwitch = false;
            // If BAL app switching enabled, app switches are blocked not delayed.
            if (!getBalAppSwitchesProtectionEnabled()) {
                getActivityStartController().schedulePendingActivityLaunches(APP_SWITCH_DELAY_TIME);
            }
        }
    }

@@ -3677,10 +3583,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    public void resumeAppSwitches() {
        enforceCallerIsRecentsOrHasPermission(STOP_APP_SWITCHES, "resumeAppSwitches");
        synchronized (mGlobalLock) {
            // Note that we don't execute any pending app switches... we will
            // let those wait until either the timeout, or the next start
            // activity request.
            mAppSwitchesAllowedTime = 0;
            mAppSwitchesAllowed = true;
        }
    }

@@ -3688,19 +3591,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        return mLastStopAppSwitchesTime;
    }

    void onStartActivitySetDidAppSwitch() {
        if (mDidAppSwitch) {
            // This is the second allowed switch since we stopped switches, so now just generally
            // allow switches. Use case:
            // - user presses home (switches disabled, switch to home, mDidAppSwitch now true);
            // - user taps a home icon (coming from home so allowed, we hit here and now allow
            // anyone to switch again).
            mAppSwitchesAllowedTime = 0;
        } else {
            mDidAppSwitch = true;
        }
    }

    /** @return whether the system should disable UI modes incompatible with VR mode. */
    boolean shouldDisableNonVrUiLocked() {
        return mVrController.shouldDisableNonVrUiLocked();
@@ -5822,15 +5712,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                int userId) {
            synchronized (mGlobalLock) {

                boolean didSomething =
                        getActivityStartController().clearPendingActivityLaunches(packageName);
                didSomething |= mRootWindowContainer.finishDisabledPackageActivities(packageName,
                return mRootWindowContainer.finishDisabledPackageActivities(packageName,
                        null /* filterByClasses */, doit, evenPersistent, userId,
                        // Only remove the activities without process because the activities with
                        // attached process will be removed when handling process died with
                        // WindowProcessController#isRemoved == true.
                        true /* onlyRemoveNoProcess */);
                return didSomething;
            }
        }

+0 −36
Original line number Diff line number Diff line
@@ -142,7 +142,6 @@ import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.UserState;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;

import java.io.FileDescriptor;
@@ -376,41 +375,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {

    private boolean mInitialized;

    /**
     * Description of a request to start a new activity, which has been held
     * due to app switches being disabled.
     */
    static class PendingActivityLaunch {
        final ActivityRecord r;
        final ActivityRecord sourceRecord;
        final int startFlags;
        final Task rootTask;
        final WindowProcessController callerApp;
        final NeededUriGrants intentGrants;

        PendingActivityLaunch(ActivityRecord r, ActivityRecord sourceRecord,
                int startFlags, Task rootTask, WindowProcessController callerApp,
                NeededUriGrants intentGrants) {
            this.r = r;
            this.sourceRecord = sourceRecord;
            this.startFlags = startFlags;
            this.rootTask = rootTask;
            this.callerApp = callerApp;
            this.intentGrants = intentGrants;
        }

        void sendErrorResult(String message) {
            try {
                if (callerApp != null && callerApp.hasThread()) {
                    callerApp.getThread().scheduleCrash(message);
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception scheduling crash of failed "
                        + "activity launcher sourceRecord=" + sourceRecord, e);
            }
        }
    }

    public ActivityTaskSupervisor(ActivityTaskManagerService service, Looper looper) {
        mService = service;
        mLooper = looper;
Loading