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

Commit 88b8e470 authored by Achim Thesmann's avatar Achim Thesmann
Browse files

Add ownership for BackgroundActivityStartController.

BackgroundActivityStartController is a new class to contain the logic
to permit activity launches from the background. The logic itself has
just been moved from ActivityStarter without any changes.

Bug: 236234252
Test: atest ActivityStarterTests
Ignore-AOSP-First: Internal merge conflict, AOSP change in aosp/2169485
Change-Id: I6ee0e839a4000c9e27630c2e654d945bf45b21e6
parent 3f40a95d
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -97,6 +97,8 @@ public class ActivityStartController {
    /** Whether an {@link ActivityStarter} is currently executing (starting an Activity). */
    /** Whether an {@link ActivityStarter} is currently executing (starting an Activity). */
    private boolean mInExecution = false;
    private boolean mInExecution = false;


    private final BackgroundActivityStartController mBalController;

    /**
    /**
     * TODO(b/64750076): Capture information necessary for dump and
     * TODO(b/64750076): Capture information necessary for dump and
     * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object
     * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object
@@ -119,6 +121,7 @@ public class ActivityStartController {
        mFactory.setController(this);
        mFactory.setController(this);
        mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service.mGlobalLock,
        mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service.mGlobalLock,
                service.mH);
                service.mH);
        mBalController = new BackgroundActivityStartController(mService, mSupervisor);
    }
    }


    /**
    /**
@@ -632,4 +635,8 @@ public class ActivityStartController {
            pw.println("(nothing)");
            pw.println("(nothing)");
        }
        }
    }
    }

    BackgroundActivityStartController getBackgroundActivityLaunchController() {
        return mBalController;
    }
}
}
+14 −291
Original line number Original line Diff line number Diff line
@@ -16,7 +16,6 @@


package com.android.server.wm;
package com.android.server.wm;


import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_CANCELED;
import static android.app.ActivityManager.START_ABORTED;
import static android.app.ActivityManager.START_ABORTED;
import static android.app.ActivityManager.START_CANCELED;
import static android.app.ActivityManager.START_CANCELED;
@@ -52,7 +51,6 @@ import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE_PER_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
import static android.content.pm.ActivityInfo.launchModeToString;
import static android.content.pm.ActivityInfo.launchModeToString;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.INVALID_UID;
import static android.os.Process.INVALID_UID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_OPEN;
@@ -61,7 +59,6 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
@@ -72,8 +69,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
@@ -98,7 +93,6 @@ import android.app.WaitResult;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration;
import android.compat.annotation.ChangeId;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
import android.content.IIntentSender;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender;
@@ -114,15 +108,12 @@ import android.os.Binder;
import android.os.Build;
import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.Trace;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.IVoiceInteractionSession;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.Pools.SynchronizedPool;
import android.util.Pools.SynchronizedPool;
import android.util.Slog;
import android.util.Slog;
import android.window.RemoteTransition;
import android.window.RemoteTransition;
@@ -259,8 +250,6 @@ class ActivityStarter {


        /**
        /**
         * Generates an {@link ActivityStarter} that is ready to handle a new start request.
         * Generates an {@link ActivityStarter} that is ready to handle a new start request.
         * @param controller The {@link ActivityStartController} which the starter who will own
         *                   this instance.
         * @return an {@link ActivityStarter}
         * @return an {@link ActivityStarter}
         */
         */
        ActivityStarter obtain();
        ActivityStarter obtain();
@@ -1033,10 +1022,20 @@ class ActivityStarter {
            try {
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                        "shouldAbortBackgroundActivityStart");
                        "shouldAbortBackgroundActivityStart");
                restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                BackgroundActivityStartController balController =
                        callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                        mController.getBackgroundActivityLaunchController();
                        request.originatingPendingIntent, request.allowBackgroundActivityStart,
                restrictedBgActivity =
                        intent, checkedOptions);
                        balController.shouldAbortBackgroundActivityStart(
                                callingUid,
                                callingPid,
                                callingPackage,
                                realCallingUid,
                                realCallingPid,
                                callerApp,
                                request.originatingPendingIntent,
                                request.allowBackgroundActivityStart,
                                intent,
                                checkedOptions);
            } finally {
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            }
            }
@@ -1270,282 +1269,6 @@ class ActivityStarter {
        mController.onExecutionStarted();
        mController.onExecutionStarted();
    }
    }


    private boolean isHomeApp(int uid, @Nullable String packageName) {
        if (mService.mHomeProcess != null) {
            // Fast check
            return uid == mService.mHomeProcess.mUid;
        }
        if (packageName == null) {
            return false;
        }
        ComponentName activity =
                mService.getPackageManagerInternalLocked().getDefaultHomeActivity(
                        UserHandle.getUserId(uid));
        return activity != null && packageName.equals(activity.getPackageName());
    }

    boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
            final String callingPackage, int realCallingUid, int realCallingPid,
            WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
            boolean allowBackgroundActivityStart, Intent intent, ActivityOptions checkedOptions) {
        // don't abort for the most important UIDs
        final int callingAppId = UserHandle.getAppId(callingUid);
        final boolean useCallingUidState =
                originatingPendingIntent == null || checkedOptions == null
                        || !checkedOptions.getIgnorePendingIntentCreatorForegroundState();
        if (useCallingUidState) {
            if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
                    || callingAppId == Process.NFC_UID) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG,
                            "Activity start allowed for important callingUid (" + callingUid + ")");
                }
                return false;
            }

            // Always allow home application to start activities.
            if (isHomeApp(callingUid, callingPackage)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG,
                            "Activity start allowed for home app callingUid (" + callingUid + ")");
                }
                return false;
            }

            // IME should always be allowed to start activity, like IME settings.
            final WindowState imeWindow = mRootWindowContainer.getCurrentInputMethodWindow();
            if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed for active ime (" + callingUid + ")");
                }
                return false;
            }
        }

        // This is used to block background activity launch even if the app is still
        // visible to user after user clicking home button.
        final int appSwitchState = mService.getBalAppSwitchesState();

        // don't abort if the callingUid has a visible window or is a persistent system process
        final int callingUidProcState = mService.mActiveUids.getUidState(callingUid);
        final boolean callingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid);
        final boolean isCallingUidForeground = callingUidHasAnyVisibleWindow
                || callingUidProcState == ActivityManager.PROCESS_STATE_TOP
                || callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
        final boolean isCallingUidPersistentSystemProcess =
                callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;

        // Normal apps with visible app window will be allowed to start activity if app switching
        // is allowed, or apps like live wallpaper with non app visible window will be allowed.
        final boolean appSwitchAllowedOrFg =
                appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY;
        final boolean allowCallingUidStartActivity =
                ((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
                && callingUidHasAnyVisibleWindow)
                || isCallingUidPersistentSystemProcess;
        if (useCallingUidState && allowCallingUidStartActivity) {
            if (DEBUG_ACTIVITY_STARTS) {
                Slog.d(TAG, "Activity start allowed: callingUidHasAnyVisibleWindow = " + callingUid
                        + ", isCallingUidPersistentSystemProcess = "
                        + isCallingUidPersistentSystemProcess);
            }
            return false;
        }
        // take realCallingUid into consideration
        final int realCallingUidProcState = (callingUid == realCallingUid)
                ? callingUidProcState
                : mService.mActiveUids.getUidState(realCallingUid);
        final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
                ? callingUidHasAnyVisibleWindow
                : mService.hasActiveVisibleWindow(realCallingUid);
        final boolean isRealCallingUidForeground = (callingUid == realCallingUid)
                ? isCallingUidForeground
                : realCallingUidHasAnyVisibleWindow
                        || realCallingUidProcState == ActivityManager.PROCESS_STATE_TOP;
        final int realCallingAppId = UserHandle.getAppId(realCallingUid);
        final boolean isRealCallingUidPersistentSystemProcess = (callingUid == realCallingUid)
                ? isCallingUidPersistentSystemProcess
                : (realCallingAppId == Process.SYSTEM_UID)
                        || realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;

        // In the case of an SDK sandbox calling uid, check if the corresponding app uid has a
        // visible window.
        if (Process.isSdkSandboxUid(realCallingUid)) {
            int realCallingSdkSandboxUidToAppUid = Process.getAppUidForSdkSandboxUid(
                    UserHandle.getAppId(realCallingUid));

            if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed: uid in SDK sandbox ("
                            + realCallingUid + ") has visible (non-toast) window.");
                }
                return false;
            }
        }

        // Legacy behavior allows to use caller foreground state to bypass BAL restriction.
        final boolean balAllowedByPiSender =
                PendingIntentRecord.isPendingIntentBalAllowedByCaller(checkedOptions);

        if (balAllowedByPiSender && realCallingUid != callingUid) {
            final boolean useCallerPermission =
                    PendingIntentRecord.isPendingIntentBalAllowedByPermission(checkedOptions);
            if (useCallerPermission && ActivityManager.checkComponentPermission(
                    android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
                    realCallingUid, -1, true)
                    == PackageManager.PERMISSION_GRANTED) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
                            + ") has BAL permission.");
                }
                return false;
            }

            // don't abort if the realCallingUid has a visible window
            // TODO(b/171459802): We should check appSwitchAllowed also
            if (realCallingUidHasAnyVisibleWindow) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
                            + ") has visible (non-toast) window");
                }
                return false;
            }
            // if the realCallingUid is a persistent system process, abort if the IntentSender
            // wasn't allowed to start an activity
            if (isRealCallingUidPersistentSystemProcess && allowBackgroundActivityStart) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
                            + ") is persistent system process AND intent sender allowed "
                            + "(allowBackgroundActivityStart = true)");
                }
                return false;
            }
            // don't abort if the realCallingUid is an associated companion app
            if (mService.isAssociatedCompanionApp(UserHandle.getUserId(realCallingUid),
                    realCallingUid)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
                            + ") is companion app");
                }
                return false;
            }
        }
        if (useCallingUidState) {
            // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
            if (mService.checkPermission(
                    START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
                    == PERMISSION_GRANTED) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG,
                            "Background activity start allowed: START_ACTIVITIES_FROM_BACKGROUND "
                                    + "permission granted for uid "
                                    + callingUid);
                }
                return false;
            }
            // don't abort if the caller has the same uid as the recents component
            if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
                            + ") is recents");
                }
                return false;
            }
            // don't abort if the callingUid is the device owner
            if (mService.isDeviceOwner(callingUid)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
                            + ") is device owner");
                }
                return false;
            }
            // don't abort if the callingUid has companion device
            final int callingUserId = UserHandle.getUserId(callingUid);
            if (mService.isAssociatedCompanionApp(callingUserId,
                    callingUid)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
                            + ") is companion app");
                }
                return false;
            }
            // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
            if (mService.hasSystemAlertWindowPermission(callingUid,
                    callingPid, callingPackage)) {
                Slog.w(TAG, "Background activity start for " + callingPackage
                        + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
                return false;
            }
        }
        // If we don't have callerApp at this point, no caller was provided to startActivity().
        // That's the case for PendingIntent-based starts, since the creator's process might not be
        // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
        // caller if caller allows, so that we can make the decision based on its state.
        int callerAppUid = callingUid;
        if (callerApp == null && balAllowedByPiSender) {
            callerApp = mService.getProcessController(realCallingPid, realCallingUid);
            callerAppUid = realCallingUid;
        }
        // don't abort if the callerApp or other processes of that uid are allowed in any way
        if (callerApp != null && useCallingUidState) {
            // first check the original calling process
            if (callerApp.areBackgroundActivityStartsAllowed(appSwitchState)) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Background activity start allowed: callerApp process (pid = "
                            + callerApp.getPid() + ", uid = " + callerAppUid + ") is allowed");
                }
                return false;
            }
            // only if that one wasn't allowed, check the other ones
            final ArraySet<WindowProcessController> uidProcesses =
                    mService.mProcessMap.getProcesses(callerAppUid);
            if (uidProcesses != null) {
                for (int i = uidProcesses.size() - 1; i >= 0; i--) {
                    final WindowProcessController proc = uidProcesses.valueAt(i);
                    if (proc != callerApp
                            && proc.areBackgroundActivityStartsAllowed(appSwitchState)) {
                        if (DEBUG_ACTIVITY_STARTS) {
                            Slog.d(TAG,
                                    "Background activity start allowed: process " + proc.getPid()
                                            + " from uid " + callerAppUid + " is allowed");
                        }
                        return false;
                    }
                }
            }
        }
        // anything that has fallen through would currently be aborted
        Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
                + "; callingUid: " + callingUid
                + "; appSwitchState: " + appSwitchState
                + "; isCallingUidForeground: " + isCallingUidForeground
                + "; callingUidHasAnyVisibleWindow: " + callingUidHasAnyVisibleWindow
                + "; callingUidProcState: " + DebugUtils.valueToString(ActivityManager.class,
                "PROCESS_STATE_", callingUidProcState)
                + "; isCallingUidPersistentSystemProcess: " + isCallingUidPersistentSystemProcess
                + "; realCallingUid: " + realCallingUid
                + "; isRealCallingUidForeground: " + isRealCallingUidForeground
                + "; realCallingUidHasAnyVisibleWindow: " + realCallingUidHasAnyVisibleWindow
                + "; realCallingUidProcState: " + DebugUtils.valueToString(ActivityManager.class,
                "PROCESS_STATE_", realCallingUidProcState)
                + "; isRealCallingUidPersistentSystemProcess: "
                + isRealCallingUidPersistentSystemProcess
                + "; originatingPendingIntent: " + originatingPendingIntent
                + "; allowBackgroundActivityStart: " + allowBackgroundActivityStart
                + "; intent: " + intent
                + "; callerApp: " + callerApp
                + "; inVisibleTask: " + (callerApp != null && callerApp.hasActivityInVisibleTask())
                + "]");
        // log aborted activity start to TRON
        if (mService.isActivityStartsLoggingEnabled()) {
            mSupervisor.getActivityMetricsLogger().logAbortedBgActivityStart(intent, callerApp,
                    callingUid, callingPackage, callingUidProcState, callingUidHasAnyVisibleWindow,
                    realCallingUid, realCallingUidProcState, realCallingUidHasAnyVisibleWindow,
                    (originatingPendingIntent != null));
        }
        return true;
    }

    /**
    /**
     * Creates a launch intent for the given auxiliary resolution data.
     * Creates a launch intent for the given auxiliary resolution data.
     */
     */
+13 −4
Original line number Original line Diff line number Diff line
@@ -2179,10 +2179,19 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        if (appThread != null) {
        if (appThread != null) {
            callerApp = getProcessController(appThread);
            callerApp = getProcessController(appThread);
        }
        }
        final ActivityStarter starter = getActivityStartController().obtainStarter(
        final BackgroundActivityStartController balController =
                null /* intent */, "moveTaskToFront");
                getActivityStartController().getBackgroundActivityLaunchController();
        if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, -1,
        if (balController.shouldAbortBackgroundActivityStart(
                -1, callerApp, null, false, null, null)) {
                callingUid,
                callingPid,
                callingPackage,
                -1,
                -1,
                callerApp,
                null,
                false,
                null,
                null)) {
            if (!isBackgroundActivityStartsEnabled()) {
            if (!isBackgroundActivityStartsEnabled()) {
                return;
                return;
            }
            }
+14 −4
Original line number Original line Diff line number Diff line
@@ -119,10 +119,20 @@ class AppTaskImpl extends IAppTask.Stub {
                if (appThread != null) {
                if (appThread != null) {
                    callerApp = mService.getProcessController(appThread);
                    callerApp = mService.getProcessController(appThread);
                }
                }
                final ActivityStarter starter = mService.getActivityStartController().obtainStarter(
                final BackgroundActivityStartController balController =
                        null /* intent */, "moveToFront");
                        mService.getActivityStartController()
                if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid,
                                .getBackgroundActivityLaunchController();
                        callingPackage, -1, -1, callerApp, null, false, null, null)) {
                if (balController.shouldAbortBackgroundActivityStart(
                        callingUid,
                        callingPid,
                        callingPackage,
                        -1,
                        -1,
                        callerApp,
                        null,
                        false,
                        null,
                        null)) {
                    if (!mService.isBackgroundActivityStartsEnabled()) {
                    if (!mService.isBackgroundActivityStartsEnabled()) {
                        return;
                        return;
                    }
                    }
+421 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading