1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
20 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
21 import static android.app.ActivityOptions.BackgroundActivityStartMode;
22 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
23 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_COMPAT;
24 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
25 import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
26 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
27 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
28 import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
29 import static android.os.Process.INVALID_PID;
30 import static android.os.Process.INVALID_UID;
31 import static android.os.Process.ROOT_UID;
32 import static android.os.Process.SYSTEM_UID;
33 import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER;
34 import static android.security.Flags.asmOptSystemIntoEnforcement;
35 
36 import static com.android.server.wm.ActivityStarter.ASM_RESTRICTIONS;
37 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
38 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
39 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
40 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
41 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
42 import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel;
43 import static com.android.server.wm.PendingRemoteAnimationRegistry.TIMEOUT_MS;
44 import static com.android.window.flags.Flags.balDontBringExistingBackgroundTaskStackToFg;
45 import static com.android.window.flags.Flags.balImprovedMetrics;
46 import static com.android.window.flags.Flags.balImproveRealCallerVisibilityCheck;
47 import static com.android.window.flags.Flags.balRequireOptInByPendingIntentCreator;
48 import static com.android.window.flags.Flags.balRequireOptInSameUid;
49 import static com.android.window.flags.Flags.balRespectAppSwitchStateWhenCheckBoundByForegroundUid;
50 import static com.android.window.flags.Flags.balShowToastsBlocked;
51 
52 import static java.lang.annotation.RetentionPolicy.SOURCE;
53 import static java.util.Objects.requireNonNull;
54 
55 import android.annotation.IntDef;
56 import android.annotation.NonNull;
57 import android.annotation.Nullable;
58 import android.app.ActivityManager;
59 import android.app.ActivityOptions;
60 import android.app.AppOpsManager;
61 import android.app.BackgroundStartPrivileges;
62 import android.app.compat.CompatChanges;
63 import android.compat.annotation.ChangeId;
64 import android.compat.annotation.EnabledAfter;
65 import android.content.ComponentName;
66 import android.content.Intent;
67 import android.content.pm.ApplicationInfo;
68 import android.content.pm.PackageManager;
69 import android.os.Process;
70 import android.os.SystemClock;
71 import android.os.UserHandle;
72 import android.provider.DeviceConfig;
73 import android.util.ArraySet;
74 import android.util.DebugUtils;
75 import android.util.Slog;
76 import android.widget.Toast;
77 
78 import com.android.internal.R;
79 import com.android.internal.annotations.GuardedBy;
80 import com.android.internal.annotations.VisibleForTesting;
81 import com.android.internal.util.FrameworkStatsLog;
82 import com.android.internal.util.Preconditions;
83 import com.android.server.UiThread;
84 import com.android.server.am.PendingIntentRecord;
85 
86 import java.lang.annotation.Retention;
87 import java.util.ArrayList;
88 import java.util.HashMap;
89 import java.util.StringJoiner;
90 import java.util.function.Consumer;
91 import java.util.function.Function;
92 import java.util.function.Predicate;
93 
94 /**
95  * Helper class to check permissions for starting Activities.
96  *
97  * <p>This class collects all the logic to prevent malicious attempts to start activities.
98  */
99 public class BackgroundActivityStartController {
100 
101     private static final String TAG =
102             TAG_WITH_CLASS_NAME ? "BackgroundActivityStartController" : TAG_ATM;
103 
104     private static final long ASM_GRACEPERIOD_TIMEOUT_MS = TIMEOUT_MS;
105     private static final int ASM_GRACEPERIOD_MAX_REPEATS = 5;
106     private static final int NO_PROCESS_UID = -1;
107 
108     static final String AUTO_OPT_IN_NOT_PENDING_INTENT = "notPendingIntent";
109     static final String AUTO_OPT_IN_CALL_FOR_RESULT = "callForResult";
110     static final String AUTO_OPT_IN_SAME_UID = "sameUid";
111     static final String AUTO_OPT_IN_COMPAT = "compatibility";
112 
113     /** If enabled the creator will not allow BAL on its behalf by default. */
114     @ChangeId
115     @EnabledAfter(targetSdkVersion = UPSIDE_DOWN_CAKE)
116     private static final long DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_CREATOR =
117             296478951;
118     public static final ActivityOptions ACTIVITY_OPTIONS_SYSTEM_DEFINED =
119             ActivityOptions.makeBasic()
120                     .setPendingIntentBackgroundActivityStartMode(
121                             MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED)
122                     .setPendingIntentCreatorBackgroundActivityStartMode(
123                             MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED);
124 
125     private final ActivityTaskManagerService mService;
126 
127     private final ActivityTaskSupervisor mSupervisor;
128 
129     // TODO(b/263368846) Rename when ASM logic is moved in
130     @Retention(SOURCE)
131     @IntDef({BAL_BLOCK,
132             BAL_ALLOW_DEFAULT,
133             BAL_ALLOW_ALLOWLISTED_UID,
134             BAL_ALLOW_ALLOWLISTED_COMPONENT,
135             BAL_ALLOW_VISIBLE_WINDOW,
136             BAL_ALLOW_PENDING_INTENT,
137             BAL_ALLOW_PERMISSION,
138             BAL_ALLOW_SAW_PERMISSION,
139             BAL_ALLOW_GRACE_PERIOD,
140             BAL_ALLOW_FOREGROUND,
141             BAL_ALLOW_SDK_SANDBOX
142     })
143     public @interface BalCode {}
144 
145     static final int BAL_BLOCK = 0;
146 
147     static final int BAL_ALLOW_DEFAULT =
148             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_DEFAULT;
149 
150     // Following codes are in order of precedence
151 
152     /** Important UIDs which should be always allowed to launch activities */
153     static final int BAL_ALLOW_ALLOWLISTED_UID =
154             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_ALLOWLISTED_UID;
155 
156     /** Apps that fulfill a certain role that can can always launch new tasks */
157     static final int BAL_ALLOW_ALLOWLISTED_COMPONENT =
158             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_ALLOWLISTED_COMPONENT;
159 
160     /**
161      * Apps which currently have a visible window or are bound by a service with a visible
162      * window
163      */
164     static final int BAL_ALLOW_VISIBLE_WINDOW =
165             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_VISIBLE_WINDOW;
166 
167     /** Allowed due to the PendingIntent sender */
168     static final int BAL_ALLOW_PENDING_INTENT =
169             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_PENDING_INTENT;
170 
171     /**
172      * App has START_ACTIVITIES_FROM_BACKGROUND permission or BAL instrumentation privileges
173      * granted to it
174      */
175     static final int BAL_ALLOW_PERMISSION =
176             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_BAL_PERMISSION;
177 
178     /** Process has SYSTEM_ALERT_WINDOW permission granted to it */
179     static final int BAL_ALLOW_SAW_PERMISSION =
180             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_SAW_PERMISSION;
181 
182     /** App is in grace period after an activity was started or finished */
183     static final int BAL_ALLOW_GRACE_PERIOD =
184             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_GRACE_PERIOD;
185 
186     /** App is in a foreground task or bound to a foreground service (but not itself visible) */
187     static final int BAL_ALLOW_FOREGROUND =
188             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_FOREGROUND;
189 
190     /** Process belongs to a SDK sandbox */
191     static final int BAL_ALLOW_SDK_SANDBOX =
192             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_SDK_SANDBOX;
193 
194     /** Process belongs to a SDK sandbox */
195     static final int BAL_ALLOW_NON_APP_VISIBLE_WINDOW =
196             FrameworkStatsLog.BAL_ALLOWED__ALLOWED_REASON__BAL_ALLOW_NON_APP_VISIBLE_WINDOW;
197 
balCodeToString(@alCode int balCode)198     static String balCodeToString(@BalCode int balCode) {
199         return switch (balCode) {
200             case BAL_ALLOW_ALLOWLISTED_COMPONENT -> "BAL_ALLOW_ALLOWLISTED_COMPONENT";
201             case BAL_ALLOW_ALLOWLISTED_UID -> "BAL_ALLOW_ALLOWLISTED_UID";
202             case BAL_ALLOW_DEFAULT -> "BAL_ALLOW_DEFAULT";
203             case BAL_ALLOW_FOREGROUND -> "BAL_ALLOW_FOREGROUND";
204             case BAL_ALLOW_GRACE_PERIOD -> "BAL_ALLOW_GRACE_PERIOD";
205             case BAL_ALLOW_NON_APP_VISIBLE_WINDOW -> "BAL_ALLOW_NON_APP_VISIBLE_WINDOW";
206             case BAL_ALLOW_PENDING_INTENT -> "BAL_ALLOW_PENDING_INTENT";
207             case BAL_ALLOW_PERMISSION -> "BAL_ALLOW_PERMISSION";
208             case BAL_ALLOW_SAW_PERMISSION -> "BAL_ALLOW_SAW_PERMISSION";
209             case BAL_ALLOW_SDK_SANDBOX -> "BAL_ALLOW_SDK_SANDBOX";
210             case BAL_ALLOW_VISIBLE_WINDOW -> "BAL_ALLOW_VISIBLE_WINDOW";
211             case BAL_BLOCK -> "BAL_BLOCK";
212             default -> throw new IllegalArgumentException("Unexpected value: " + balCode);
213         };
214     }
215 
216     @GuardedBy("mService.mGlobalLock")
217     private final HashMap<Integer, FinishedActivityEntry> mTaskIdToFinishedActivity =
218             new HashMap<>();
219     @GuardedBy("mService.mGlobalLock")
220     private FinishedActivityEntry mTopFinishedActivity = null;
221 
BackgroundActivityStartController( final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor)222     BackgroundActivityStartController(
223             final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor) {
224         mService = service;
225         mSupervisor = supervisor;
226     }
227 
isHomeApp(int uid, @Nullable String packageName)228     private boolean isHomeApp(int uid, @Nullable String packageName) {
229         if (mService.mHomeProcess != null) {
230             // Fast check
231             return uid == mService.mHomeProcess.mUid;
232         }
233         if (packageName == null) {
234             return false;
235         }
236         ComponentName activity =
237                 mService.getPackageManagerInternalLocked()
238                         .getDefaultHomeActivity(UserHandle.getUserId(uid));
239         return activity != null && packageName.equals(activity.getPackageName());
240     }
241 
242     @VisibleForTesting class BalState {
243 
244         private final String mCallingPackage;
245         private final int mCallingUid;
246         private final int mCallingPid;
247         private final @ActivityTaskManagerService.AppSwitchState int mAppSwitchState;
248         private final boolean mCallingUidHasAnyVisibleWindow;
249         private final @ActivityManager.ProcessState int mCallingUidProcState;
250         private final boolean mIsCallingUidPersistentSystemProcess;
251         final BackgroundStartPrivileges mBalAllowedByPiSender;
252         final BackgroundStartPrivileges mBalAllowedByPiCreatorWithHardening;
253         final BackgroundStartPrivileges mBalAllowedByPiCreator;
254         private final String mRealCallingPackage;
255         private final int mRealCallingUid;
256         private final int mRealCallingPid;
257         private final boolean mRealCallingUidHasAnyVisibleWindow;
258         private final @ActivityManager.ProcessState int mRealCallingUidProcState;
259         private final boolean mIsRealCallingUidPersistentSystemProcess;
260         private final PendingIntentRecord mOriginatingPendingIntent;
261         private final BackgroundStartPrivileges mForcedBalByPiSender;
262         private final Intent mIntent;
263         private final WindowProcessController mCallerApp;
264         private final WindowProcessController mRealCallerApp;
265         private final boolean mIsCallForResult;
266         private final ActivityOptions mCheckedOptions;
267         final String mAutoOptInReason;
268         private final boolean mAutoOptInCaller;
269         private BalVerdict mResultForCaller;
270         private BalVerdict mResultForRealCaller;
271 
BalState(int callingUid, int callingPid, final String callingPackage, int realCallingUid, int realCallingPid, WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent, BackgroundStartPrivileges forcedBalByPiSender, ActivityRecord resultRecord, Intent intent, ActivityOptions checkedOptions)272         @VisibleForTesting BalState(int callingUid, int callingPid, final String callingPackage,
273                  int realCallingUid, int realCallingPid,
274                  WindowProcessController callerApp,
275                  PendingIntentRecord originatingPendingIntent,
276                  BackgroundStartPrivileges forcedBalByPiSender,
277                  ActivityRecord resultRecord,
278                  Intent intent,
279                  ActivityOptions checkedOptions) {
280             this.mCallingPackage = callingPackage;
281             mCallingUid = callingUid;
282             mCallingPid = callingPid;
283             mRealCallingUid = realCallingUid;
284             mRealCallingPid = realCallingPid;
285             mCallerApp = callerApp;
286             mForcedBalByPiSender = forcedBalByPiSender;
287             mOriginatingPendingIntent = originatingPendingIntent;
288             mIntent = intent;
289             mRealCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid);
290             mIsCallForResult = resultRecord != null;
291             mCheckedOptions = checkedOptions;
292             @BackgroundActivityStartMode int callerBackgroundActivityStartMode =
293                     checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode();
294             @BackgroundActivityStartMode int realCallerBackgroundActivityStartMode =
295                     checkedOptions.getPendingIntentBackgroundActivityStartMode();
296 
297             if (!balImproveRealCallerVisibilityCheck()) {
298                 // without this fix the auto-opt ins below would violate CTS tests
299                 mAutoOptInReason = null;
300                 mAutoOptInCaller = false;
301             } else if (originatingPendingIntent == null) {
302                 mAutoOptInReason = AUTO_OPT_IN_NOT_PENDING_INTENT;
303                 mAutoOptInCaller = true;
304             } else if (mIsCallForResult) {
305                 mAutoOptInReason = AUTO_OPT_IN_CALL_FOR_RESULT;
306                 mAutoOptInCaller = false;
307             } else if (callingUid == realCallingUid && !balRequireOptInSameUid()) {
308                 mAutoOptInReason = AUTO_OPT_IN_SAME_UID;
309                 mAutoOptInCaller = false;
310             } else if (realCallerBackgroundActivityStartMode
311                     == MODE_BACKGROUND_ACTIVITY_START_COMPAT) {
312                 mAutoOptInReason = AUTO_OPT_IN_COMPAT;
313                 mAutoOptInCaller = false;
314             } else {
315                 mAutoOptInReason = null;
316                 mAutoOptInCaller = false;
317             }
318 
319             if (mAutoOptInCaller) {
320                 // grant BAL privileges unless explicitly opted out
321                 mBalAllowedByPiCreatorWithHardening = mBalAllowedByPiCreator =
322                         callerBackgroundActivityStartMode == MODE_BACKGROUND_ACTIVITY_START_DENIED
323                                 ? BackgroundStartPrivileges.NONE
324                                 : BackgroundStartPrivileges.ALLOW_BAL;
325             } else {
326                 // for PendingIntents we restrict BAL based on target_sdk
327                 mBalAllowedByPiCreatorWithHardening = getBackgroundStartPrivilegesAllowedByCreator(
328                         callingUid, callingPackage, checkedOptions);
329                 final BackgroundStartPrivileges mBalAllowedByPiCreatorWithoutHardening =
330                         callerBackgroundActivityStartMode
331                                 == MODE_BACKGROUND_ACTIVITY_START_DENIED
332                                 ? BackgroundStartPrivileges.NONE
333                                 : BackgroundStartPrivileges.ALLOW_BAL;
334                 mBalAllowedByPiCreator = balRequireOptInByPendingIntentCreator()
335                         ? mBalAllowedByPiCreatorWithHardening
336                         : mBalAllowedByPiCreatorWithoutHardening;
337             }
338 
339             if (mAutoOptInReason != null) {
340                 // grant BAL privileges unless explicitly opted out
341                 mBalAllowedByPiSender = realCallerBackgroundActivityStartMode
342                         == MODE_BACKGROUND_ACTIVITY_START_DENIED
343                         ? BackgroundStartPrivileges.NONE
344                         : BackgroundStartPrivileges.ALLOW_BAL;
345             } else {
346                 // for PendingIntents we restrict BAL based on target_sdk
347                 mBalAllowedByPiSender =
348                         PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller(
349                                 checkedOptions, realCallingUid, mRealCallingPackage);
350             }
351 
352             mAppSwitchState = mService.getBalAppSwitchesState();
353             mCallingUidProcState = mService.mActiveUids.getUidState(callingUid);
354             mIsCallingUidPersistentSystemProcess =
355                     mCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
356             mCallingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid);
357             if (realCallingUid == NO_PROCESS_UID) {
358                 // no process provided
359                 mRealCallingUidProcState = PROCESS_STATE_NONEXISTENT;
360                 mRealCallingUidHasAnyVisibleWindow = false;
361                 mRealCallerApp = null;
362                 mIsRealCallingUidPersistentSystemProcess = false;
363             } else if (callingUid == realCallingUid) {
364                 mRealCallingUidProcState = mCallingUidProcState;
365                 mRealCallingUidHasAnyVisibleWindow = mCallingUidHasAnyVisibleWindow;
366                 // In the PendingIntent case callerApp is not passed in, so resolve it ourselves.
367                 mRealCallerApp = callerApp == null
368                         ? mService.getProcessController(realCallingPid, realCallingUid)
369                         : callerApp;
370                 mIsRealCallingUidPersistentSystemProcess = mIsCallingUidPersistentSystemProcess;
371             } else {
372                 mRealCallingUidProcState = mService.mActiveUids.getUidState(realCallingUid);
373                 mRealCallingUidHasAnyVisibleWindow =
374                         mService.hasActiveVisibleWindow(realCallingUid);
375                 mRealCallerApp = mService.getProcessController(realCallingPid, realCallingUid);
376                 mIsRealCallingUidPersistentSystemProcess =
377                         mRealCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
378             }
379         }
380 
getBackgroundStartPrivilegesAllowedByCreator( int callingUid, String callingPackage, ActivityOptions checkedOptions)381         private BackgroundStartPrivileges getBackgroundStartPrivilegesAllowedByCreator(
382                 int callingUid, String callingPackage, ActivityOptions checkedOptions) {
383             switch (checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()) {
384                 case MODE_BACKGROUND_ACTIVITY_START_ALLOWED:
385                     return BackgroundStartPrivileges.ALLOW_BAL;
386                 case MODE_BACKGROUND_ACTIVITY_START_DENIED:
387                     return BackgroundStartPrivileges.NONE;
388                 case MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED:
389                     // no explicit choice by the app - let us decide what to do
390                     if (callingUid == ROOT_UID || callingUid == SYSTEM_UID) {
391                         // root and system must always opt in explicitly
392                         return BackgroundStartPrivileges.NONE;
393                     }
394                     if (callingPackage != null) {
395                         // determine based on the calling/creating package
396                         boolean changeEnabled = CompatChanges.isChangeEnabled(
397                                 DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_CREATOR,
398                                 callingPackage,
399                                 UserHandle.getUserHandleForUid(callingUid));
400                         return changeEnabled ? BackgroundStartPrivileges.NONE
401                                 : BackgroundStartPrivileges.ALLOW_BAL;
402                     }
403                     // determine based on the calling/creating uid if we cannot determine the
404                     // actual package name (e.g. shared uid)
405                     boolean changeEnabled = CompatChanges.isChangeEnabled(
406                             DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_CREATOR,
407                             callingUid);
408                     return changeEnabled ? BackgroundStartPrivileges.NONE
409                             : BackgroundStartPrivileges.ALLOW_BAL;
410                 default:
411                     throw new IllegalStateException("unsupported BackgroundActivityStartMode: "
412                             + checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode());
413             }
414         }
415 
getDebugPackageName(String packageName, int uid)416         private String getDebugPackageName(String packageName, int uid) {
417             if (packageName != null) {
418                 return packageName; // use actual package
419             }
420             if (uid == 0) {
421                 return "root[debugOnly]";
422             }
423             String name = mService.getPackageManagerInternalLocked().getNameForUid(uid);
424             if (name == null) {
425                 name = "uid=" + uid;
426             }
427             return name + "[debugOnly]";
428         }
429 
hasRealCaller()430         private boolean hasRealCaller() {
431             return mRealCallingUid != NO_PROCESS_UID;
432         }
433 
isPendingIntent()434         boolean isPendingIntent() {
435             return mOriginatingPendingIntent != null && hasRealCaller();
436         }
437 
callerIsRealCaller()438         private boolean callerIsRealCaller() {
439             return mCallingUid == mRealCallingUid;
440         }
441 
setResultForCaller(BalVerdict resultForCaller)442         public void setResultForCaller(BalVerdict resultForCaller) {
443             Preconditions.checkState(mResultForCaller == null,
444                     "mResultForCaller can only be set once");
445             this.mResultForCaller = resultForCaller;
446         }
447 
setResultForRealCaller(BalVerdict resultForRealCaller)448         public void setResultForRealCaller(BalVerdict resultForRealCaller) {
449             Preconditions.checkState(mResultForRealCaller == null,
450                     "mResultForRealCaller can only be set once");
451             this.mResultForRealCaller = resultForRealCaller;
452         }
453 
isPendingIntentBalAllowedByPermission()454         public boolean isPendingIntentBalAllowedByPermission() {
455             return PendingIntentRecord.isPendingIntentBalAllowedByPermission(mCheckedOptions);
456         }
457 
callerExplicitOptInOrAutoOptIn()458         public boolean callerExplicitOptInOrAutoOptIn() {
459             if (mAutoOptInCaller) {
460                 return !callerExplicitOptOut();
461             }
462             return mCheckedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
463                     == MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
464         }
465 
realCallerExplicitOptInOrAutoOptIn()466         public boolean realCallerExplicitOptInOrAutoOptIn() {
467             if (mAutoOptInReason != null) {
468                 return !realCallerExplicitOptOut();
469             }
470             return mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
471                     == MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
472         }
473 
callerExplicitOptOut()474         public boolean callerExplicitOptOut() {
475             return mCheckedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
476                     == MODE_BACKGROUND_ACTIVITY_START_DENIED;
477         }
478 
realCallerExplicitOptOut()479         public boolean realCallerExplicitOptOut() {
480             return mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
481                     == MODE_BACKGROUND_ACTIVITY_START_DENIED;
482         }
483 
callerExplicitOptInOrOut()484         public boolean callerExplicitOptInOrOut() {
485             return mCheckedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
486                     != MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
487         }
488 
realCallerExplicitOptInOrOut()489         public boolean realCallerExplicitOptInOrOut() {
490             return mCheckedOptions.getPendingIntentBackgroundActivityStartMode()
491                     != MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
492         }
493 
494         @Override
toString()495         public String toString() {
496             StringBuilder sb = new StringBuilder(2048);
497             sb.append("[callingPackage: ")
498                     .append(getDebugPackageName(mCallingPackage, mCallingUid));
499             sb.append("; callingPackageTargetSdk: ").append(getTargetSdk(mCallingPackage));
500             sb.append("; callingUid: ").append(mCallingUid);
501             sb.append("; callingPid: ").append(mCallingPid);
502             sb.append("; appSwitchState: ").append(mAppSwitchState);
503             sb.append("; callingUidHasAnyVisibleWindow: ").append(mCallingUidHasAnyVisibleWindow);
504             sb.append("; callingUidProcState: ").append(DebugUtils.valueToString(
505                     ActivityManager.class, "PROCESS_STATE_", mCallingUidProcState));
506             sb.append("; isCallingUidPersistentSystemProcess: ")
507                     .append(mIsCallingUidPersistentSystemProcess);
508             sb.append("; forcedBalByPiSender: ").append(mForcedBalByPiSender);
509             sb.append("; intent: ").append(mIntent);
510             sb.append("; callerApp: ").append(mCallerApp);
511             if (mCallerApp != null) {
512                 sb.append("; inVisibleTask: ").append(mCallerApp.hasActivityInVisibleTask());
513             }
514             sb.append("; balAllowedByPiCreator: ").append(mBalAllowedByPiCreator);
515             sb.append("; balAllowedByPiCreatorWithHardening: ")
516                     .append(mBalAllowedByPiCreatorWithHardening);
517             sb.append("; resultIfPiCreatorAllowsBal: ").append(mResultForCaller);
518             sb.append("; hasRealCaller: ").append(hasRealCaller());
519             sb.append("; isCallForResult: ").append(mIsCallForResult);
520             sb.append("; isPendingIntent: ").append(isPendingIntent());
521             sb.append("; autoOptInReason: ").append(mAutoOptInReason);
522             if (hasRealCaller()) {
523                 sb.append("; realCallingPackage: ")
524                         .append(getDebugPackageName(mRealCallingPackage, mRealCallingUid));
525                 sb.append("; realCallingPackageTargetSdk: ")
526                         .append(getTargetSdk(mRealCallingPackage));
527                 sb.append("; realCallingUid: ").append(mRealCallingUid);
528                 sb.append("; realCallingPid: ").append(mRealCallingPid);
529                 sb.append("; realCallingUidHasAnyVisibleWindow: ")
530                         .append(mRealCallingUidHasAnyVisibleWindow);
531                 sb.append("; realCallingUidProcState: ").append(DebugUtils.valueToString(
532                         ActivityManager.class, "PROCESS_STATE_", mRealCallingUidProcState));
533                 sb.append("; isRealCallingUidPersistentSystemProcess: ")
534                         .append(mIsRealCallingUidPersistentSystemProcess);
535                 sb.append("; originatingPendingIntent: ").append(mOriginatingPendingIntent);
536                 sb.append("; realCallerApp: ").append(mRealCallerApp);
537                 if (mRealCallerApp != null) {
538                     sb.append("; realInVisibleTask: ")
539                             .append(mRealCallerApp.hasActivityInVisibleTask());
540                 }
541                 sb.append("; balAllowedByPiSender: ").append(mBalAllowedByPiSender);
542                 sb.append("; resultIfPiSenderAllowsBal: ").append(mResultForRealCaller);
543             }
544             // features
545             sb.append("; balImproveRealCallerVisibilityCheck: ")
546                     .append(balImproveRealCallerVisibilityCheck());
547             sb.append("; balRequireOptInByPendingIntentCreator: ")
548                     .append(balRequireOptInByPendingIntentCreator());
549             sb.append("; balRequireOptInSameUid: ").append(balRequireOptInSameUid());
550             sb.append("; balRespectAppSwitchStateWhenCheckBoundByForegroundUid: ")
551                     .append(balRespectAppSwitchStateWhenCheckBoundByForegroundUid());
552             sb.append("; balDontBringExistingBackgroundTaskStackToFg: ")
553                     .append(balDontBringExistingBackgroundTaskStackToFg());
554             sb.append("]");
555             return sb.toString();
556         }
557     }
558 
559     static class BalVerdict {
560 
561         static final BalVerdict BLOCK = new BalVerdict(BAL_BLOCK, false, "Blocked");
562         static final BalVerdict ALLOW_BY_DEFAULT =
563                 new BalVerdict(BAL_ALLOW_DEFAULT, false, "Default");
564         // Careful using this - it will bypass all ASM checks.
565         static final BalVerdict ALLOW_PRIVILEGED =
566                 new BalVerdict(BAL_ALLOW_ALLOWLISTED_UID, false, "PRIVILEGED");
567         private final @BalCode int mCode;
568         private final boolean mBackground;
569         private final String mMessage;
570         private String mProcessInfo;
571         // indicates BAL would be blocked because only creator of the PI has the privilege to allow
572         // BAL, the sender does not have the privilege to allow BAL.
573         private boolean mOnlyCreatorAllows;
574         /** indicates that this verdict is based on the real calling UID and not the calling UID */
575         private boolean mBasedOnRealCaller;
576 
BalVerdict(@alCode int balCode, boolean background, String message)577         BalVerdict(@BalCode int balCode, boolean background, String message) {
578             this.mBackground = background;
579             this.mCode = balCode;
580             this.mMessage = message;
581         }
582 
withProcessInfo(String msg, WindowProcessController process)583         public BalVerdict withProcessInfo(String msg, WindowProcessController process) {
584             mProcessInfo = msg + " (uid=" + process.mUid + ",pid=" + process.getPid() + ")";
585             return this;
586         }
587 
blocks()588         boolean blocks() {
589             return mCode == BAL_BLOCK;
590         }
591 
allows()592         boolean allows() {
593             return !blocks();
594         }
595 
setOnlyCreatorAllows(boolean onlyCreatorAllows)596         void setOnlyCreatorAllows(boolean onlyCreatorAllows) {
597             mOnlyCreatorAllows = onlyCreatorAllows;
598         }
599 
onlyCreatorAllows()600         boolean onlyCreatorAllows() {
601             return mOnlyCreatorAllows;
602         }
603 
604         @VisibleForTesting
setBasedOnRealCaller()605         BalVerdict setBasedOnRealCaller() {
606             mBasedOnRealCaller = true;
607             return this;
608         }
609 
toString()610         public String toString() {
611             StringBuilder builder = new StringBuilder();
612             builder.append(balCodeToString(mCode));
613             if (DEBUG_ACTIVITY_STARTS) {
614                 builder.append(" (");
615                 if (mBackground) {
616                     builder.append("Background ");
617                 }
618                 builder.append("Activity start ");
619                 if (mCode == BAL_BLOCK) {
620                     builder.append("denied");
621                 } else {
622                     builder.append("allowed: ").append(mMessage);
623                 }
624                 if (mProcessInfo != null) {
625                     builder.append(" ");
626                     builder.append(mProcessInfo);
627                 }
628                 builder.append(")");
629             }
630             return builder.toString();
631         }
632 
getRawCode()633         public @BalCode int getRawCode() {
634             return mCode;
635         }
636 
getCode()637         public @BalCode int getCode() {
638             if (mBasedOnRealCaller && mCode != BAL_BLOCK) {
639                 // for compatibility always return BAL_ALLOW_PENDING_INTENT if based on real caller
640                 return BAL_ALLOW_PENDING_INTENT;
641             }
642             return mCode;
643         }
644     }
645 
646     /**
647      * Check if a (background) activity start is allowed.
648      *
649      * @param callingUid The UID that wants to start the activity.
650      * @param callingPid The PID that wants to start the activity.
651      * @param callingPackage The package name that wants to start the activity.
652      * @param realCallingUid The UID that actually calls this method (only if this handles a
653      *      PendingIntent, otherwise -1)
654      * @param realCallingPid The PID that actually calls this method (only if this handles a
655      *      *      PendingIntent, otherwise -1)
656      * @param callerApp The process that calls this method (only if not a PendingIntent)
657      * @param originatingPendingIntent PendingIntentRecord that originated this activity start or
658      *        null if not originated by PendingIntent
659      * @param forcedBalByPiSender If set to allow, the
660      *        PendingIntent's sender will try to force allow background activity starts.
661      *        This is only possible if the sender of the PendingIntent is a system process.
662      * @param resultRecord If not null, this indicates that the caller expects a result.
663      * @param intent Intent that should be started.
664      * @param checkedOptions ActivityOptions to allow specific opt-ins/opt outs.
665      *
666      * @return A verdict denoting which BAL rule allows an activity to be started,
667      *        or if the launch should be blocked.
668      */
checkBackgroundActivityStart( int callingUid, int callingPid, final String callingPackage, int realCallingUid, int realCallingPid, WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent, BackgroundStartPrivileges forcedBalByPiSender, ActivityRecord resultRecord, Intent intent, ActivityOptions checkedOptions)669     BalVerdict checkBackgroundActivityStart(
670             int callingUid,
671             int callingPid,
672             final String callingPackage,
673             int realCallingUid,
674             int realCallingPid,
675             WindowProcessController callerApp,
676             PendingIntentRecord originatingPendingIntent,
677             BackgroundStartPrivileges forcedBalByPiSender,
678             ActivityRecord resultRecord,
679             Intent intent,
680             ActivityOptions checkedOptions) {
681 
682         if (checkedOptions == null) {
683             // replace null with a constant to simplify evaluation
684             checkedOptions = ACTIVITY_OPTIONS_SYSTEM_DEFINED;
685         }
686 
687         BalState state = new BalState(callingUid, callingPid, callingPackage,
688                 realCallingUid, realCallingPid, callerApp, originatingPendingIntent,
689                 forcedBalByPiSender, resultRecord, intent, checkedOptions);
690 
691         // In the case of an SDK sandbox calling uid, check if the corresponding app uid has a
692         // visible window.
693         if (Process.isSdkSandboxUid(state.mRealCallingUid)) {
694             int realCallingSdkSandboxUidToAppUid =
695                     Process.getAppUidForSdkSandboxUid(state.mRealCallingUid);
696             // realCallingSdkSandboxUidToAppUid should probably just be used instead (or in addition
697             // to realCallingUid when calculating resultForRealCaller below.
698             if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
699                 state.setResultForRealCaller(new BalVerdict(BAL_ALLOW_SDK_SANDBOX,
700                         /*background*/ false,
701                         "uid in SDK sandbox has visible (non-toast) window"));
702                 return allowBasedOnRealCaller(state);
703             }
704         }
705 
706         BalVerdict resultForCaller = checkBackgroundActivityStartAllowedByCaller(state);
707         state.setResultForCaller(resultForCaller);
708 
709         if (!state.hasRealCaller()) {
710             if (resultForCaller.allows()) {
711                 return allowBasedOnCaller(state);
712             }
713             return abortLaunch(state);
714         }
715 
716         // The realCaller result is only calculated for PendingIntents (indicated by a valid
717         // realCallingUid). If caller and realCaller are same UID and we are already allowed based
718         // on the caller (i.e. creator of the PendingIntent) there is no need to calculate this
719         // again, but if the result is block it is possible that there are additional exceptions
720         // that allow based on the realCaller (i.e. sender of the PendingIntent), e.g. if the
721         // realCallerApp process is allowed to start (in the creator path the callerApp for
722         // PendingIntents is null).
723         BalVerdict resultForRealCaller = state.callerIsRealCaller() && resultForCaller.allows()
724                 ? resultForCaller
725                 : checkBackgroundActivityStartAllowedBySender(state)
726                         .setBasedOnRealCaller();
727         state.setResultForRealCaller(resultForRealCaller);
728 
729         if (state.isPendingIntent()) {
730             resultForCaller.setOnlyCreatorAllows(
731                     resultForCaller.allows() && resultForRealCaller.blocks());
732         }
733 
734         // Handle cases with explicit opt-in
735         if (resultForCaller.allows() && state.callerExplicitOptInOrAutoOptIn()) {
736             return allowBasedOnCaller(state);
737         }
738         if (resultForRealCaller.allows() && state.realCallerExplicitOptInOrAutoOptIn()) {
739             return allowBasedOnRealCaller(state);
740         }
741         // Handle PendingIntent cases with default behavior next
742         boolean callerCanAllow = resultForCaller.allows() && !state.callerExplicitOptOut();
743         boolean realCallerCanAllow = resultForRealCaller.allows()
744                 && !state.realCallerExplicitOptOut();
745         if (callerCanAllow) {
746             // Allowed before V by creator
747             if (state.mBalAllowedByPiCreator.allowsBackgroundActivityStarts()) {
748                 Slog.wtf(TAG, "With Android 15 BAL hardening this activity start may be blocked"
749                         + " if the PI creator upgrades target_sdk to 35+! "
750                         + " (missing opt in by PI creator)!" + state);
751                 return allowBasedOnCaller(state);
752             }
753         }
754         if (realCallerCanAllow) {
755             // Allowed before U by sender
756             if (state.mBalAllowedByPiSender.allowsBackgroundActivityStarts()) {
757                 Slog.wtf(TAG, "With Android 14 BAL hardening this activity start will be blocked"
758                         + " if the PI sender upgrades target_sdk to 34+! "
759                         + " (missing opt in by PI sender)!" + state);
760                 return allowBasedOnRealCaller(state);
761             }
762         }
763         // caller or real caller could start the activity, but would need to explicitly opt in
764         if (callerCanAllow || realCallerCanAllow) {
765             Slog.w(TAG, "Without BAL hardening this activity start would be allowed");
766         }
767         // neither the caller not the realCaller can allow or have explicitly opted out
768         return abortLaunch(state);
769     }
770 
allowBasedOnCaller(BalState state)771     private BalVerdict allowBasedOnCaller(BalState state) {
772         if (DEBUG_ACTIVITY_STARTS) {
773             Slog.d(TAG, "Background activity launch allowed based on caller. " + state);
774         }
775         return statsLog(state.mResultForCaller, state);
776     }
777 
allowBasedOnRealCaller(BalState state)778     private BalVerdict allowBasedOnRealCaller(BalState state) {
779         if (DEBUG_ACTIVITY_STARTS) {
780             Slog.d(TAG, "Background activity launch allowed based on real caller. " + state);
781         }
782         return statsLog(state.mResultForRealCaller, state);
783     }
784 
abortLaunch(BalState state)785     private BalVerdict abortLaunch(BalState state) {
786         Slog.wtf(TAG, "Background activity launch blocked! " + state);
787         if (balShowToastsBlocked()
788                 && (state.mResultForCaller.allows() || state.mResultForRealCaller.allows())) {
789             // only show a toast if either caller or real caller could launch if they opted in
790             showToast("BAL blocked. goo.gle/android-bal");
791         }
792         return statsLog(BalVerdict.BLOCK, state);
793     }
794 
795     /**
796      * @return A code denoting which BAL rule allows an activity to be started,
797      * or {@link #BAL_BLOCK} if the launch should be blocked
798      */
checkBackgroundActivityStartAllowedByCaller(BalState state)799     BalVerdict checkBackgroundActivityStartAllowedByCaller(BalState state) {
800         // This is used to block background activity launch even if the app is still
801         // visible to user after user clicking home button.
802 
803         // Normal apps with visible app window will be allowed to start activity if app switching
804         // is allowed, or apps like live wallpaper with non app visible window will be allowed.
805         final boolean appSwitchAllowedOrFg = state.mAppSwitchState == APP_SWITCH_ALLOW
806                 || state.mAppSwitchState == APP_SWITCH_FG_ONLY;
807         if (appSwitchAllowedOrFg && state.mCallingUidHasAnyVisibleWindow) {
808             return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
809                     /*background*/ false, "callingUid has visible window");
810         }
811         if (mService.mActiveUids.hasNonAppVisibleWindow(state.mCallingUid)) {
812             return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW,
813                     /*background*/ false, "callingUid has non-app visible window");
814         }
815 
816         // don't abort for the most important UIDs
817         final int callingAppId = UserHandle.getAppId(state.mCallingUid);
818         if (state.mCallingUid == Process.ROOT_UID
819                 || callingAppId == Process.SYSTEM_UID
820                 || callingAppId == Process.NFC_UID) {
821             return new BalVerdict(
822                     BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false,
823                      "Important callingUid");
824         }
825 
826         // Always allow home application to start activities.
827         if (isHomeApp(state.mCallingUid, state.mCallingPackage)) {
828             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
829                     /*background*/ false,
830                     "Home app");
831         }
832 
833         // IME should always be allowed to start activity, like IME settings.
834         final WindowState imeWindow =
835                 mService.mRootWindowContainer.getCurrentInputMethodWindow();
836         if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
837             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
838                     /*background*/ false,
839                     "Active ime");
840         }
841 
842         // don't abort if the callingUid is a persistent system process
843         if (state.mIsCallingUidPersistentSystemProcess) {
844             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
845                     /*background*/ false, "callingUid is persistent system process");
846         }
847 
848         // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
849         if (hasBalPermission(state.mCallingUid, state.mCallingPid)) {
850             return new BalVerdict(BAL_ALLOW_PERMISSION,
851                     /*background*/ true,
852                     "START_ACTIVITIES_FROM_BACKGROUND permission granted");
853         }
854         // don't abort if the caller has the same uid as the recents component
855         if (mSupervisor.mRecentTasks.isCallerRecents(state.mCallingUid)) {
856             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
857                     /*background*/ true, "Recents Component");
858         }
859         // don't abort if the callingUid is the device owner
860         if (mService.isDeviceOwner(state.mCallingUid)) {
861             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
862                     /*background*/ true, "Device Owner");
863         }
864         // don't abort if the callingUid is a affiliated profile owner
865         if (mService.isAffiliatedProfileOwner(state.mCallingUid)) {
866             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
867                     /*background*/ true, "Affiliated Profile Owner");
868         }
869         // don't abort if the callingUid has companion device
870         final int callingUserId = UserHandle.getUserId(state.mCallingUid);
871         if (mService.isAssociatedCompanionApp(callingUserId, state.mCallingUid)) {
872             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
873                     /*background*/ true, "Companion App");
874         }
875         // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
876         if (mService.hasSystemAlertWindowPermission(state.mCallingUid, state.mCallingPid,
877                 state.mCallingPackage)) {
878             Slog.w(
879                     TAG,
880                     "Background activity start for "
881                             + state.mCallingPackage
882                             + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
883             return new BalVerdict(BAL_ALLOW_SAW_PERMISSION,
884                     /*background*/ true, "SYSTEM_ALERT_WINDOW permission is granted");
885         }
886         // don't abort if the callingUid and callingPackage have the
887         // OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop
888         if (isSystemExemptFlagEnabled() && mService.getAppOpsManager().checkOpNoThrow(
889                 AppOpsManager.OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
890                 state.mCallingUid, state.mCallingPackage) == AppOpsManager.MODE_ALLOWED) {
891             return new BalVerdict(BAL_ALLOW_PERMISSION, /*background*/ true,
892                     "OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
893         }
894 
895         // If we don't have callerApp at this point, no caller was provided to startActivity().
896         // That's the case for PendingIntent-based starts, since the creator's process might not be
897         // up and alive.
898         // Don't abort if the callerApp or other processes of that uid are allowed in any way.
899         BalVerdict callerAppAllowsBal = checkProcessAllowsBal(state.mCallerApp, state);
900         if (callerAppAllowsBal.allows()) {
901             return callerAppAllowsBal;
902         }
903 
904         // If we are here, it means all exemptions based on the creator failed
905         return BalVerdict.BLOCK;
906     }
907 
908     /**
909      * @return A code denoting which BAL rule allows an activity to be started,
910      * or {@link #BAL_BLOCK} if the launch should be blocked
911      */
checkBackgroundActivityStartAllowedBySender(BalState state)912     BalVerdict checkBackgroundActivityStartAllowedBySender(BalState state) {
913 
914         // Normal apps with visible app window will be allowed to start activity if app switching
915         // is allowed, or apps like live wallpaper with non app visible window will be allowed.
916         // The home app can start apps even if app switches are usually disallowed.
917         final boolean appSwitchAllowedOrFg = state.mAppSwitchState == APP_SWITCH_ALLOW
918                 || state.mAppSwitchState == APP_SWITCH_FG_ONLY
919                 || isHomeApp(state.mRealCallingUid, state.mRealCallingPackage);
920         if (balImproveRealCallerVisibilityCheck()) {
921             if (appSwitchAllowedOrFg && state.mRealCallingUidHasAnyVisibleWindow) {
922                 return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
923                         /*background*/ false, "realCallingUid has visible window");
924             }
925             if (mService.mActiveUids.hasNonAppVisibleWindow(state.mRealCallingUid)) {
926                 return new BalVerdict(BAL_ALLOW_NON_APP_VISIBLE_WINDOW,
927                         /*background*/ false, "realCallingUid has non-app visible window");
928             }
929         } else {
930             // don't abort if the realCallingUid has a visible window
931             // TODO(b/171459802): We should check appSwitchAllowed also
932             if (state.mRealCallingUidHasAnyVisibleWindow) {
933                 return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
934                         /*background*/ false,
935                         "realCallingUid has visible (non-toast) window.");
936             }
937         }
938 
939         if (state.isPendingIntentBalAllowedByPermission()
940                 && hasBalPermission(state.mRealCallingUid, state.mRealCallingPid)) {
941             return new BalVerdict(BAL_ALLOW_PERMISSION,
942                     /*background*/ false,
943                     "realCallingUid has BAL permission.");
944         }
945 
946         // if the realCallingUid is a persistent system process, abort if the IntentSender
947         // wasn't allowed to start an activity
948         if (state.mForcedBalByPiSender.allowsBackgroundActivityStarts()
949                 && state.mIsRealCallingUidPersistentSystemProcess) {
950             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_UID,
951                     /*background*/ false,
952                     "realCallingUid is persistent system process AND intent "
953                             + "sender forced to allow.");
954         }
955         // don't abort if the realCallingUid is an associated companion app
956         if (mService.isAssociatedCompanionApp(
957                 UserHandle.getUserId(state.mRealCallingUid), state.mRealCallingUid)) {
958             return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
959                     /*background*/ false,
960                     "realCallingUid is a companion app.");
961         }
962 
963         // don't abort if the callerApp or other processes of that uid are allowed in any way
964         BalVerdict realCallerAppAllowsBal =
965                 checkProcessAllowsBal(state.mRealCallerApp, state);
966         if (realCallerAppAllowsBal.allows()) {
967             return realCallerAppAllowsBal;
968         }
969 
970         // If we are here, it means all exemptions based on PI sender failed
971         return BalVerdict.BLOCK;
972     }
973 
hasBalPermission(int uid, int pid)974     @VisibleForTesting boolean hasBalPermission(int uid, int pid) {
975         return ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND,
976                 pid, uid) == PERMISSION_GRANTED;
977     }
978 
979     /**
980      * Check if the app allows BAL.
981      * <p>
982      * See {@link BackgroundLaunchProcessController#areBackgroundActivityStartsAllowed(int, int,
983      * String, int, boolean, boolean, boolean, long, long, long)} for details on the
984      * exceptions.
985      */
checkProcessAllowsBal(WindowProcessController app, BalState state)986     @VisibleForTesting BalVerdict checkProcessAllowsBal(WindowProcessController app,
987             BalState state) {
988         if (app == null) {
989             return BalVerdict.BLOCK;
990         }
991         // first check the original calling process
992         final BalVerdict balAllowedForCaller = app
993                 .areBackgroundActivityStartsAllowed(state.mAppSwitchState);
994         if (balAllowedForCaller.allows()) {
995             return balAllowedForCaller.withProcessInfo("callerApp process", app);
996         } else {
997             // only if that one wasn't allowed, check the other ones
998             final ArraySet<WindowProcessController> uidProcesses =
999                     mService.mProcessMap.getProcesses(app.mUid);
1000             if (uidProcesses != null) {
1001                 for (int i = uidProcesses.size() - 1; i >= 0; i--) {
1002                     final WindowProcessController proc = uidProcesses.valueAt(i);
1003                     if (proc != app) {
1004                         BalVerdict balAllowedForUid = proc.areBackgroundActivityStartsAllowed(
1005                                 state.mAppSwitchState);
1006                         if (balAllowedForUid.allows()) {
1007                             return balAllowedForUid.withProcessInfo("process", proc);
1008                         }
1009                     }
1010                 }
1011             }
1012         }
1013         return BalVerdict.BLOCK;
1014     }
1015 
1016     /**
1017      * Check activity starts which violate one of the following rules of the
1018      * activity security model (ASM):
1019      * See go/activity-security for rationale behind the rules.
1020      * 1. Within a task, only an activity matching a top UID of the task can start activities
1021      * 2. Only activities within a foreground task, which match a top UID of the task, can
1022      * create a new task or bring an existing one into the foreground
1023      */
checkActivityAllowedToStart(@ullable ActivityRecord sourceRecord, @NonNull ActivityRecord targetRecord, boolean newTask, boolean avoidMoveTaskToFront, @Nullable Task targetTask, int launchFlags, int balCode, int callingUid, int realCallingUid, TaskDisplayArea preferredTaskDisplayArea)1024     boolean checkActivityAllowedToStart(@Nullable ActivityRecord sourceRecord,
1025             @NonNull ActivityRecord targetRecord, boolean newTask, boolean avoidMoveTaskToFront,
1026             @Nullable Task targetTask, int launchFlags, int balCode, int callingUid,
1027             int realCallingUid, TaskDisplayArea preferredTaskDisplayArea) {
1028         // BAL Exception allowed in all cases
1029         if (balCode == BAL_ALLOW_ALLOWLISTED_UID) {
1030             return true;
1031         }
1032 
1033         // Intents with FLAG_ACTIVITY_NEW_TASK will always be considered as creating a new task
1034         // even if the intent is delivered to an existing task.
1035         boolean taskToFront = newTask
1036                 || (launchFlags & FLAG_ACTIVITY_NEW_TASK) == FLAG_ACTIVITY_NEW_TASK;
1037 
1038         // BAL exception only allowed for new tasks
1039         if (taskToFront) {
1040             if (balCode == BAL_ALLOW_ALLOWLISTED_COMPONENT
1041                     || balCode == BAL_ALLOW_PERMISSION
1042                     || balCode == BAL_ALLOW_PENDING_INTENT
1043                     || balCode == BAL_ALLOW_SAW_PERMISSION
1044                     || balCode == BAL_ALLOW_VISIBLE_WINDOW
1045                     || balCode == BAL_ALLOW_NON_APP_VISIBLE_WINDOW) {
1046                 return true;
1047             }
1048         }
1049 
1050         BlockActivityStart bas = new BlockActivityStart();
1051         if (sourceRecord != null) {
1052             Task sourceTask = sourceRecord.getTask();
1053 
1054             Task taskToCheck = taskToFront ? sourceTask : targetTask;
1055             bas = checkTopActivityForAsm(taskToCheck, sourceRecord.getUid(),
1056                     sourceRecord, bas);
1057 
1058             // Allow launching into a new task (or a task matching the launched activity's
1059             // affinity) only if the current task is foreground or mutating its own task.
1060             // The latter can happen eg. if caller uses NEW_TASK flag and the activity being
1061             // launched matches affinity of source task.
1062             if (taskToFront && bas.mTopActivityMatchesSource) {
1063                 bas.mTopActivityMatchesSource = (sourceTask != null
1064                         && (sourceTask.isVisible() || sourceTask == targetTask));
1065             }
1066         } else if (targetTask != null && (!taskToFront || avoidMoveTaskToFront)) {
1067             // We don't have a sourceRecord, and we're launching into an existing task.
1068             // Allow if callingUid is top of stack.
1069             bas = checkTopActivityForAsm(targetTask, callingUid,
1070                     /*sourceRecord*/null, bas);
1071         } else {
1072             // We're launching from a non-visible activity. Has any visible app opted in?
1073             TaskDisplayArea displayArea = targetTask != null && targetTask.getDisplayArea() != null
1074                     ? targetTask.getDisplayArea()
1075                     : preferredTaskDisplayArea;
1076             if (displayArea != null) {
1077                 ArrayList<Task> visibleTasks = displayArea.getVisibleTasks();
1078                 for (int i = 0; i < visibleTasks.size(); i++) {
1079                     Task task = visibleTasks.get(i);
1080                     if (visibleTasks.size() == 1 && task.isActivityTypeHomeOrRecents()) {
1081                         bas.optedIn(task.getTopMostActivity());
1082                     } else {
1083                         bas = checkTopActivityForAsm(task, callingUid, /*sourceRecord*/null, bas);
1084                     }
1085                 }
1086             }
1087         }
1088 
1089         if (bas.mTopActivityMatchesSource) {
1090             return true;
1091         }
1092 
1093         // ASM rules have failed. Log why
1094         return logAsmFailureAndCheckFeatureEnabled(sourceRecord, callingUid, realCallingUid,
1095                 newTask, avoidMoveTaskToFront, targetTask, targetRecord, balCode, launchFlags,
1096                 bas, taskToFront);
1097     }
1098 
logAsmFailureAndCheckFeatureEnabled(ActivityRecord sourceRecord, int callingUid, int realCallingUid, boolean newTask, boolean avoidMoveTaskToFront, Task targetTask, ActivityRecord targetRecord, @BalCode int balCode, int launchFlags, BlockActivityStart bas, boolean taskToFront)1099     private boolean logAsmFailureAndCheckFeatureEnabled(ActivityRecord sourceRecord, int callingUid,
1100             int realCallingUid, boolean newTask, boolean avoidMoveTaskToFront, Task targetTask,
1101             ActivityRecord targetRecord, @BalCode int balCode, int launchFlags,
1102             BlockActivityStart bas, boolean taskToFront) {
1103 
1104         ActivityRecord targetTopActivity = targetTask == null ? null
1105                 : targetTask.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());
1106 
1107         int action = newTask || sourceRecord == null
1108                 ? FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__ACTIVITY_START_NEW_TASK
1109                 : (sourceRecord.getTask().equals(targetTask)
1110                 ? FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__ACTIVITY_START_SAME_TASK
1111                 : FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__ACTIVITY_START_DIFFERENT_TASK);
1112 
1113         boolean enforceBlock = bas.mTopActivityOptedIn
1114                 && ActivitySecurityModelFeatureFlags.shouldRestrictActivitySwitch(callingUid);
1115 
1116         boolean allowedByGracePeriod = allowedByAsmGracePeriod(callingUid, sourceRecord, targetTask,
1117                 balCode, taskToFront, avoidMoveTaskToFront);
1118 
1119         String asmDebugInfo = getDebugInfoForActivitySecurity("Launch", sourceRecord,
1120                 targetRecord, targetTask, targetTopActivity, realCallingUid, balCode,
1121                 enforceBlock, taskToFront, avoidMoveTaskToFront, allowedByGracePeriod,
1122                 bas.mActivityOptedIn);
1123 
1124         FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
1125                 /* caller_uid */
1126                 sourceRecord != null ? sourceRecord.getUid() : callingUid,
1127                 /* caller_activity_class_name */
1128                 sourceRecord != null ? sourceRecord.info.name : null,
1129                 /* target_task_top_activity_uid */
1130                 targetTopActivity != null ? targetTopActivity.getUid() : NO_PROCESS_UID,
1131                 /* target_task_top_activity_class_name */
1132                 targetTopActivity != null ? targetTopActivity.info.name : null,
1133                 /* target_task_is_different */
1134                 newTask || sourceRecord == null || targetTask == null
1135                         || !targetTask.equals(sourceRecord.getTask()),
1136                 /* target_activity_uid */
1137                 targetRecord.getUid(),
1138                 /* target_activity_class_name */
1139                 targetRecord.info.name,
1140                 /* target_intent_action */
1141                 targetRecord.intent.getAction(),
1142                 /* target_intent_flags */
1143                 launchFlags,
1144                 /* action */
1145                 action,
1146                 /* version */
1147                 ActivitySecurityModelFeatureFlags.ASM_VERSION,
1148                 /* multi_window - we have our source not in the target task, but both are visible */
1149                 targetTask != null && sourceRecord != null
1150                         && !targetTask.equals(sourceRecord.getTask()) && targetTask.isVisible(),
1151                 /* bal_code */
1152                 balCode,
1153                 /* debug_info */
1154                 asmDebugInfo
1155         );
1156 
1157         String launchedFromPackageName = targetRecord.launchedFromPackage;
1158         if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
1159             String toastText = ActivitySecurityModelFeatureFlags.DOC_LINK
1160                     + (enforceBlock ? " blocked " : " would block ")
1161                     + getApplicationLabel(mService.mContext.getPackageManager(),
1162                     launchedFromPackageName);
1163             showToast(toastText);
1164 
1165             Slog.i(TAG, asmDebugInfo);
1166         }
1167 
1168         if (enforceBlock) {
1169             Slog.e(TAG, "[ASM] Abort Launching r: " + targetRecord
1170                     + " as source: "
1171                     + (sourceRecord != null ? sourceRecord : launchedFromPackageName)
1172                     + " is in background. New task: " + newTask
1173                     + ". Top activity: " + targetTopActivity
1174                     + ". BAL Code: " + balCodeToString(balCode));
1175 
1176             return false;
1177         }
1178 
1179         return true;
1180     }
1181 
showToast(String toastText)1182     @VisibleForTesting void showToast(String toastText) {
1183         UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
1184                 toastText, Toast.LENGTH_LONG).show());
1185     }
1186 
1187     /**
1188      * If the top activity uid does not match the launching or launched activity, and the launch was
1189      * not requested from the top uid, we want to clear out all non matching activities to prevent
1190      * the top activity being sandwiched.
1191      * Both creator and sender UID are considered for the launching activity.
1192      */
clearTopIfNeeded(@onNull Task targetTask, @Nullable ActivityRecord sourceRecord, @NonNull ActivityRecord targetRecord, int callingUid, int realCallingUid, int launchFlags, @BalCode int balCode)1193     void clearTopIfNeeded(@NonNull Task targetTask, @Nullable ActivityRecord sourceRecord,
1194             @NonNull ActivityRecord targetRecord, int callingUid, int realCallingUid,
1195             int launchFlags, @BalCode int balCode) {
1196         if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != FLAG_ACTIVITY_NEW_TASK
1197                 || balCode == BAL_ALLOW_ALLOWLISTED_UID) {
1198             // Launch is from the same task, (a top or privileged UID), or is directly privileged.
1199             return;
1200         }
1201 
1202         int startingUid = targetRecord.getUid();
1203         Predicate<ActivityRecord> isLaunchingOrLaunched = ar ->
1204                 ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid);
1205 
1206         // Return early if we know for sure we won't need to clear any activities by just checking
1207         // the top activity.
1208         ActivityRecord targetTaskTop = targetTask.getTopMostActivity();
1209         if (targetTaskTop == null || isLaunchingOrLaunched.test(targetTaskTop)) {
1210             return;
1211         }
1212 
1213         // Find the first activity which matches a safe UID and is not finishing. Clear everything
1214         // above it
1215         int[] finishCount = new int[1];
1216         boolean shouldBlockActivityStart = ActivitySecurityModelFeatureFlags
1217                 .shouldRestrictActivitySwitch(callingUid);
1218         BlockActivityStart bas = checkCrossUidActivitySwitchFromBelow(
1219                 targetTaskTop, callingUid, new BlockActivityStart());
1220         if (shouldBlockActivityStart && bas.mTopActivityOptedIn) {
1221             ActivityRecord activity = targetTask.getActivity(isLaunchingOrLaunched);
1222             if (activity == null) {
1223                 // mStartActivity is not in task, so clear everything
1224                 activity = targetRecord;
1225             }
1226 
1227             targetTask.performClearTop(activity, launchFlags, finishCount);
1228             if (finishCount[0] > 0) {
1229                 Slog.w(TAG, "Cleared top n: " + finishCount[0] + " activities from task t: "
1230                         + targetTask + " not matching top uid: " + callingUid);
1231             }
1232         }
1233 
1234         if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)
1235                 && (!shouldBlockActivityStart || finishCount[0] > 0)) {
1236             showToast((shouldBlockActivityStart
1237                     ? "Top activities cleared by "
1238                     : "Top activities would be cleared by ")
1239                     + ActivitySecurityModelFeatureFlags.DOC_LINK);
1240 
1241             Slog.i(TAG, getDebugInfoForActivitySecurity("Clear Top", sourceRecord, targetRecord,
1242                     targetTask, targetTaskTop, realCallingUid, balCode, shouldBlockActivityStart,
1243                     /* taskToFront */ true, /* avoidMoveTaskToFront */ false,
1244                     /* allowedByAsmGracePeriod */ false, bas.mActivityOptedIn));
1245         }
1246     }
1247 
1248     /**
1249      * Returns home if the passed in callingUid is not top of the stack, rather than returning to
1250      * previous task.
1251      */
checkActivityAllowedToClearTask(@onNull Task task, int callingUid, int callingPid, @NonNull String callerActivityClassName)1252     void checkActivityAllowedToClearTask(@NonNull Task task, int callingUid, int callingPid,
1253             @NonNull String callerActivityClassName) {
1254         // We may have already checked that the callingUid has additional clearTask privileges, and
1255         // cleared the calling identify. If so, we infer we do not need further restrictions here.
1256         if (callingUid == SYSTEM_UID || !task.isVisible() || task.inMultiWindowMode()) {
1257             return;
1258         }
1259 
1260         String packageName =  mService.mContext.getPackageManager().getNameForUid(callingUid);
1261         BalState state = new BalState(callingUid, callingPid, packageName, INVALID_UID,
1262                 INVALID_PID, null, null, null, null, null, ActivityOptions.makeBasic());
1263         @BalCode int balCode = checkBackgroundActivityStartAllowedByCaller(state).mCode;
1264         if (balCode == BAL_ALLOW_ALLOWLISTED_UID
1265                 || balCode == BAL_ALLOW_ALLOWLISTED_COMPONENT
1266                 || balCode == BAL_ALLOW_PERMISSION
1267                 || balCode == BAL_ALLOW_SAW_PERMISSION
1268                 || balCode == BAL_ALLOW_VISIBLE_WINDOW
1269                 || balCode == BAL_ALLOW_NON_APP_VISIBLE_WINDOW) {
1270             return;
1271         }
1272 
1273         TaskDisplayArea displayArea = task.getTaskDisplayArea();
1274         if (displayArea == null) {
1275             // If there is no associated display area, we can not return home.
1276             return;
1277         }
1278 
1279         BlockActivityStart bas = checkTopActivityForAsm(task, callingUid, null,
1280                 new BlockActivityStart());
1281         if (bas.mTopActivityMatchesSource) {
1282             return;
1283         }
1284 
1285         ActivityRecord topActivity = task.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());
1286         FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
1287                 /* caller_uid */
1288                 callingUid,
1289                 /* caller_activity_class_name */
1290                 callerActivityClassName,
1291                 /* target_task_top_activity_uid */
1292                 topActivity == null ? NO_PROCESS_UID : topActivity.getUid(),
1293                 /* target_task_top_activity_class_name */
1294                 topActivity == null ? null : topActivity.info.name,
1295                 /* target_task_is_different */
1296                 false,
1297                 /* target_activity_uid */
1298                 NO_PROCESS_UID,
1299                 /* target_activity_class_name */
1300                 null,
1301                 /* target_intent_action */
1302                 null,
1303                 /* target_intent_flags */
1304                 0,
1305                 /* action */
1306                 FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__FINISH_TASK,
1307                 /* version */
1308                 ActivitySecurityModelFeatureFlags.ASM_VERSION,
1309                 /* multi_window */
1310                 false,
1311                 /* bal_code */
1312                 -1,
1313                 /* debug_info */
1314                 null
1315         );
1316 
1317         boolean restrictActivitySwitch = ActivitySecurityModelFeatureFlags
1318                 .shouldRestrictActivitySwitch(callingUid) && bas.mTopActivityOptedIn;
1319 
1320         PackageManager pm = mService.mContext.getPackageManager();
1321         String callingPackage = pm.getNameForUid(callingUid);
1322         final CharSequence callingLabel;
1323         if (callingPackage == null) {
1324             callingPackage = String.valueOf(callingUid);
1325             callingLabel = callingPackage;
1326         } else {
1327             callingLabel = getApplicationLabel(pm, callingPackage);
1328         }
1329 
1330         if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
1331             showToast((ActivitySecurityModelFeatureFlags.DOC_LINK
1332                     + (restrictActivitySwitch ? " returned home due to "
1333                     : " would return home due to ")
1334                     + callingLabel));
1335         }
1336 
1337         // If the activity switch should be restricted, return home rather than the
1338         // previously top task, to prevent users from being confused which app they're
1339         // viewing
1340         if (restrictActivitySwitch) {
1341             Slog.w(TAG, "[ASM] Return to home as source: " + callingPackage
1342                     + " is not on top of task t: " + task);
1343             displayArea.moveHomeActivityToTop("taskRemoved");
1344         } else {
1345             Slog.i(TAG, "[ASM] Would return to home as source: " + callingPackage
1346                     + " is not on top of task t: " + task);
1347         }
1348     }
1349 
1350     /**
1351      * For the purpose of ASM, ‘Top UID” for a task is defined as an activity UID
1352      * 1. Which is top of the stack in z-order
1353      * a. Excluding any activities with the flag ‘isAlwaysOnTop’ and
1354      * b. Excluding any activities which are `finishing`
1355      * 2. Or top of an adjacent task fragment to (1)
1356      * <p>
1357      * The 'sourceRecord' can be considered top even if it is 'finishing'
1358      * <p>
1359      */
checkTopActivityForAsm(@onNull Task task, int uid, @Nullable ActivityRecord sourceRecord, BlockActivityStart bas)1360     private BlockActivityStart checkTopActivityForAsm(@NonNull Task task,
1361             int uid, @Nullable ActivityRecord sourceRecord, BlockActivityStart bas) {
1362         // If the source is visible, consider it 'top'.
1363         if (sourceRecord != null && sourceRecord.isVisibleRequested()) {
1364             return bas.matchesSource();
1365         }
1366 
1367         // Always allow actual top activity
1368         ActivityRecord topActivity = task.getTopMostActivity();
1369         if (topActivity == null) {
1370             Slog.wtf(TAG, "Activities for task: " + task + " not found.");
1371             return bas.optedIn(topActivity);
1372         }
1373 
1374         bas = checkCrossUidActivitySwitchFromBelow(topActivity, uid, bas);
1375         if (bas.mTopActivityMatchesSource) {
1376             return bas;
1377         }
1378 
1379         // If UID is visible in target task, allow launch
1380         if (task.forAllActivities((Predicate<ActivityRecord>)
1381                 ar -> ar.isUid(uid) && ar.isVisibleRequested())) {
1382             return bas.matchesSource();
1383         }
1384 
1385         // Consider the source activity, whether or not it is finishing. Do not consider any other
1386         // finishing activity.
1387         Predicate<ActivityRecord> topOfStackPredicate = (ar) -> ar.equals(sourceRecord)
1388                 || (!ar.finishing && !ar.isAlwaysOnTop());
1389 
1390         // Check top of stack (or the first task fragment for embedding).
1391         topActivity = task.getActivity(topOfStackPredicate);
1392         if (topActivity == null) {
1393             return bas;
1394         }
1395 
1396         bas = checkCrossUidActivitySwitchFromBelow(topActivity, uid, bas);
1397         if (bas.mTopActivityMatchesSource) {
1398             return bas;
1399         }
1400 
1401         // Even if the top activity is not a match, we may be in an embedded activity scenario with
1402         // an adjacent task fragment. Get the second fragment.
1403         TaskFragment taskFragment = topActivity.getTaskFragment();
1404         if (taskFragment == null) {
1405             return bas;
1406         }
1407 
1408         TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
1409         if (adjacentTaskFragment == null) {
1410             return bas;
1411         }
1412 
1413         // Check the second fragment.
1414         topActivity = adjacentTaskFragment.getActivity(topOfStackPredicate);
1415         if (topActivity == null) {
1416             return bas;
1417         }
1418 
1419         return checkCrossUidActivitySwitchFromBelow(topActivity, uid, bas);
1420     }
1421 
1422     /**
1423      * Determines if a source is allowed to add or remove activities from the task,
1424      * if the current ActivityRecord is above it in the stack
1425      * <p>
1426      * A transition is blocked if all of the following are met:
1427      * <pre>
1428      * 1. The source activity and the current activity record belong to different apps
1429      * (i.e, have different UIDs).
1430      * 2. The current activity target V+
1431      * 3. The current app has set
1432      * {@link R.styleable#AndroidManifestApplication_allowCrossUidActivitySwitchFromBelow}
1433      * to {@code false}
1434      * 4. The current activity has not set
1435      * {@link ActivityRecord#setAllowCrossUidActivitySwitchFromBelow(boolean)} to {@code true}
1436      * </pre>
1437      *
1438      *
1439      * @param sourceUid The source (s) activity performing the state change
1440      */
checkCrossUidActivitySwitchFromBelow(ActivityRecord ar, int sourceUid, BlockActivityStart bas)1441     private BlockActivityStart checkCrossUidActivitySwitchFromBelow(ActivityRecord ar,
1442             int sourceUid, BlockActivityStart bas) {
1443         if (ar.isUid(sourceUid)) {
1444             return bas.matchesSource();
1445         }
1446 
1447         // We don't need to check package level if activity has opted out.
1448         if (ar.mAllowCrossUidActivitySwitchFromBelow) {
1449             bas.mTopActivityOptedIn = false;
1450             return bas.matchesSource();
1451         }
1452 
1453         if (ar.isUid(SYSTEM_UID)) {
1454             if (asmOptSystemIntoEnforcement()) {
1455                 return bas.optedIn(ar);
1456             } else {
1457                 return bas;
1458             }
1459         }
1460 
1461         if (!CompatChanges.isChangeEnabled(ASM_RESTRICTIONS, ar.getUid())) {
1462             return bas;
1463         }
1464 
1465 
1466         String packageName = ar.packageName;
1467         if (packageName == null) {
1468             Slog.wtf(TAG, "Package name: " + ar + " not found.");
1469             return bas.optedIn(ar);
1470         }
1471 
1472         PackageManager pm = mService.mContext.getPackageManager();
1473         ApplicationInfo applicationInfo;
1474 
1475         try {
1476             applicationInfo = pm.getApplicationInfo(packageName, 0);
1477         } catch (PackageManager.NameNotFoundException e) {
1478             Slog.wtf(TAG, "Package name: " + packageName + " not found.");
1479             return bas.optedIn(ar);
1480         }
1481 
1482         return applicationInfo.allowCrossUidActivitySwitchFromBelow ? bas : bas.optedIn(ar);
1483     }
1484 
1485     /**
1486      * Only called when an activity launch may be blocked, which should happen very rarely
1487      */
getDebugInfoForActivitySecurity(@onNull String action, @Nullable ActivityRecord sourceRecord, @NonNull ActivityRecord targetRecord, @Nullable Task targetTask, @Nullable ActivityRecord targetTopActivity, int realCallingUid, @BalCode int balCode, boolean enforceBlock, boolean taskToFront, boolean avoidMoveTaskToFront, boolean allowedByGracePeriod, ActivityRecord activityOptedIn)1488     private String getDebugInfoForActivitySecurity(@NonNull String action,
1489             @Nullable ActivityRecord sourceRecord, @NonNull ActivityRecord targetRecord,
1490             @Nullable Task targetTask, @Nullable ActivityRecord targetTopActivity,
1491             int realCallingUid, @BalCode int balCode,
1492             boolean enforceBlock, boolean taskToFront,
1493             boolean avoidMoveTaskToFront, boolean allowedByGracePeriod,
1494             ActivityRecord activityOptedIn) {
1495         final String prefix = "[ASM] ";
1496         Function<ActivityRecord, String> recordToString = (ar) -> {
1497             if (ar == null) {
1498                 return null;
1499             }
1500 
1501             return (ar == sourceRecord ?        " [source]=> "
1502                     : ar == targetTopActivity ? " [ top  ]=> "
1503                     : ar == targetRecord ?      " [target]=> "
1504                     :                           "         => ")
1505                     + getDebugStringForActivityRecord(ar);
1506         };
1507 
1508         StringJoiner joiner = new StringJoiner("\n");
1509         joiner.add(prefix + "------ Activity Security " + action + " Debug Logging Start ------");
1510         joiner.add(prefix + "Block Enabled: " + enforceBlock);
1511         if (!enforceBlock) {
1512             joiner.add(prefix + "Feature Flag Enabled: " + android.security
1513                     .Flags.asmRestrictionsEnabled());
1514             joiner.add(prefix + "Mendel Override: " + ActivitySecurityModelFeatureFlags
1515                     .asmRestrictionsEnabledForAll());
1516         }
1517         joiner.add(prefix + "ASM Version: " + ActivitySecurityModelFeatureFlags.ASM_VERSION);
1518         joiner.add(prefix + "System Time: " + SystemClock.uptimeMillis());
1519         joiner.add(prefix + "Activity Opted In: " + recordToString.apply(activityOptedIn));
1520 
1521         boolean targetTaskMatchesSourceTask = targetTask != null
1522                 && sourceRecord != null && sourceRecord.getTask() == targetTask;
1523 
1524         if (sourceRecord == null) {
1525             joiner.add(prefix + "Source Package: " + targetRecord.launchedFromPackage);
1526             String realCallingPackage = mService.mContext.getPackageManager().getNameForUid(
1527                     realCallingUid);
1528             joiner.add(prefix + "Real Calling Uid Package: " + realCallingPackage);
1529         } else {
1530             joiner.add(prefix + "Source Record: " + recordToString.apply(sourceRecord));
1531             joiner.add(prefix + "Source Launch Package: " + sourceRecord.launchedFromPackage);
1532             joiner.add(prefix + "Source Launch Intent: " + sourceRecord.intent);
1533             if (targetTaskMatchesSourceTask) {
1534                 joiner.add(prefix + "Source/Target Task: " + sourceRecord.getTask());
1535                 joiner.add(prefix + "Source/Target Task Stack: ");
1536             } else {
1537                 joiner.add(prefix + "Source Task: " + sourceRecord.getTask());
1538                 joiner.add(prefix + "Source Task Stack: ");
1539             }
1540             sourceRecord.getTask().forAllActivities((Consumer<ActivityRecord>)
1541                     ar -> joiner.add(prefix + recordToString.apply(ar)));
1542         }
1543 
1544         joiner.add(prefix + "Target Task Top: " + recordToString.apply(targetTopActivity));
1545         if (!targetTaskMatchesSourceTask) {
1546             joiner.add(prefix + "Target Task: " + targetTask);
1547             if (targetTask != null) {
1548                 joiner.add(prefix + "Target Task Stack: ");
1549                 targetTask.forAllActivities((Consumer<ActivityRecord>)
1550                         ar -> joiner.add(prefix + recordToString.apply(ar)));
1551             }
1552         }
1553 
1554         joiner.add(prefix + "Target Record: " + recordToString.apply(targetRecord));
1555         joiner.add(prefix + "Intent: " + targetRecord.intent);
1556         joiner.add(prefix + "TaskToFront: " + taskToFront);
1557         joiner.add(prefix + "AvoidMoveToFront: " + avoidMoveTaskToFront);
1558         joiner.add(prefix + "BalCode: " + balCodeToString(balCode));
1559         joiner.add(prefix + "Allowed By Grace Period: " + allowedByGracePeriod);
1560         joiner.add(prefix + "LastResumedActivity: "
1561                        + recordToString.apply(mService.mLastResumedActivity));
1562         joiner.add(prefix + "System opted into enforcement: " + asmOptSystemIntoEnforcement());
1563 
1564         if (mTopFinishedActivity != null) {
1565             joiner.add(prefix + "TopFinishedActivity: " + mTopFinishedActivity.mDebugInfo);
1566         }
1567 
1568         if (!mTaskIdToFinishedActivity.isEmpty()) {
1569             joiner.add(prefix + "TaskIdToFinishedActivity: ");
1570             mTaskIdToFinishedActivity.values().forEach(
1571                     (fae) -> joiner.add(prefix + "  " + fae.mDebugInfo));
1572         }
1573 
1574         if (balCode == BAL_ALLOW_VISIBLE_WINDOW || balCode == BAL_ALLOW_NON_APP_VISIBLE_WINDOW
1575                 || balCode == BAL_ALLOW_FOREGROUND) {
1576             Task task = sourceRecord != null ? sourceRecord.getTask() : targetTask;
1577             if (task != null && task.getDisplayArea() != null) {
1578                 joiner.add(prefix + "Tasks: ");
1579                 task.getDisplayArea().forAllTasks((Consumer<Task>)
1580                         t -> joiner.add(prefix + "   T: " + t.toFullString()));
1581             }
1582         }
1583 
1584         joiner.add(prefix + "------ Activity Security " + action + " Debug Logging End ------");
1585         return joiner.toString();
1586     }
1587 
allowedByAsmGracePeriod(int callingUid, @Nullable ActivityRecord sourceRecord, @Nullable Task targetTask, @BalCode int balCode, boolean taskToFront, boolean avoidMoveTaskToFront)1588     private boolean allowedByAsmGracePeriod(int callingUid, @Nullable ActivityRecord sourceRecord,
1589             @Nullable Task targetTask, @BalCode int balCode, boolean taskToFront,
1590             boolean avoidMoveTaskToFront) {
1591         if (balCode == BAL_ALLOW_GRACE_PERIOD) {
1592             // Allow if launching into new task, and caller matches most recently finished activity
1593             if (taskToFront && mTopFinishedActivity != null
1594                     && mTopFinishedActivity.mUid == callingUid) {
1595                 return true;
1596             }
1597 
1598             // Launching into existing task - allow if matches most recently finished activity
1599             // within the task.
1600             // We can reach here multiple ways:
1601             // 1. activity in fg fires intent (taskToFront = false, sourceRecord is available)
1602             // 2. activity in bg fires intent (taskToFront = false, sourceRecord is available)
1603             // 3. activity in bg fires intent with NEW_FLAG (taskToFront = true,
1604             //         avoidMoveTaskToFront = true, sourceRecord is available)
1605             // 4. activity in bg fires PI (taskToFront = true, avoidMoveTaskToFront = true,
1606             //         sourceRecord is not available, targetTask may be available)
1607             if (!taskToFront || avoidMoveTaskToFront) {
1608                 if (targetTask != null) {
1609                     FinishedActivityEntry finishedEntry =
1610                             mTaskIdToFinishedActivity.get(targetTask.mTaskId);
1611                     if (finishedEntry != null && finishedEntry.mUid == callingUid) {
1612                         return true;
1613                     }
1614                 }
1615 
1616                 if (sourceRecord != null) {
1617                     FinishedActivityEntry finishedEntry =
1618                             mTaskIdToFinishedActivity.get(sourceRecord.getTask().mTaskId);
1619                     return finishedEntry != null && finishedEntry.mUid == callingUid;
1620                 }
1621             }
1622         }
1623         return false;
1624     }
1625 
isSystemExemptFlagEnabled()1626     private static boolean isSystemExemptFlagEnabled() {
1627         return DeviceConfig.getBoolean(
1628                 NAMESPACE_WINDOW_MANAGER,
1629                 /* name= */ "system_exempt_from_activity_bg_start_restriction_enabled",
1630                 /* defaultValue= */ true);
1631     }
1632 
statsLog(BalVerdict finalVerdict, BalState state)1633     private BalVerdict statsLog(BalVerdict finalVerdict, BalState state) {
1634         if (finalVerdict.blocks() && mService.isActivityStartsLoggingEnabled()) {
1635             // log aborted activity start to TRON
1636             mSupervisor
1637                     .getActivityMetricsLogger()
1638                     .logAbortedBgActivityStart(
1639                             state.mIntent,
1640                             state.mCallerApp,
1641                             state.mCallingUid,
1642                             state.mCallingPackage,
1643                             state.mCallingUidProcState,
1644                             state.mCallingUidHasAnyVisibleWindow,
1645                             state.mRealCallingUid,
1646                             state.mRealCallingUidProcState,
1647                             state.mRealCallingUidHasAnyVisibleWindow,
1648                             (state.mOriginatingPendingIntent != null));
1649         }
1650 
1651         if (balImprovedMetrics()) {
1652             if (shouldLogStats(finalVerdict, state)) {
1653                 String activityName;
1654                 if (shouldLogIntentActivity(finalVerdict, state)) {
1655                     Intent intent = state.mIntent;
1656                     activityName = intent == null ? "noIntent" // should never happen
1657                             : requireNonNull(intent.getComponent()).flattenToShortString();
1658                 } else {
1659                     activityName = "";
1660                 }
1661                 writeBalAllowedLog(activityName, finalVerdict.getCode(), state);
1662             }
1663         } else {
1664             @BalCode int code = finalVerdict.getCode();
1665             int callingUid = state.mCallingUid;
1666             int realCallingUid = state.mRealCallingUid;
1667             Intent intent = state.mIntent;
1668 
1669             if (code == BAL_ALLOW_PENDING_INTENT
1670                     && (callingUid < Process.FIRST_APPLICATION_UID
1671                     || realCallingUid < Process.FIRST_APPLICATION_UID)) {
1672                 String activityName = intent != null
1673                         ? requireNonNull(intent.getComponent()).flattenToShortString() : "";
1674                 writeBalAllowedLog(activityName, BAL_ALLOW_PENDING_INTENT,
1675                         state);
1676             }
1677             if (code == BAL_ALLOW_PERMISSION || code == BAL_ALLOW_FOREGROUND
1678                     || code == BAL_ALLOW_SAW_PERMISSION) {
1679                 // We don't need to know which activity in this case.
1680                 writeBalAllowedLog("", code, state);
1681             }
1682         }
1683         return finalVerdict;
1684     }
1685 
1686     @VisibleForTesting
shouldLogStats(BalVerdict finalVerdict, BalState state)1687     boolean shouldLogStats(BalVerdict finalVerdict, BalState state) {
1688         if (finalVerdict.getRawCode() == BAL_ALLOW_VISIBLE_WINDOW) {
1689             if (!state.isPendingIntent()) {
1690                 // regular activity start by visible app
1691                 return false;
1692             }
1693             if (finalVerdict.mBasedOnRealCaller) {
1694                 // PendingIntent started by visible app
1695                 return false;
1696             }
1697         }
1698         return true;
1699     }
1700 
1701     @VisibleForTesting
shouldLogIntentActivity(BalVerdict finalVerdict, BalState state)1702     boolean shouldLogIntentActivity(BalVerdict finalVerdict, BalState state) {
1703         return finalVerdict.mBasedOnRealCaller
1704                 ? state.mRealCallingUid < Process.FIRST_APPLICATION_UID
1705                 : state.mCallingUid < Process.FIRST_APPLICATION_UID;
1706     }
1707 
writeBalAllowedLog(String activityName, int code, BalState state)1708     @VisibleForTesting void writeBalAllowedLog(String activityName, int code, BalState state) {
1709         FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
1710                 activityName,
1711                 code,
1712                 state.mCallingUid,
1713                 state.mRealCallingUid,
1714                 state.mResultForCaller == null ? BAL_BLOCK : state.mResultForCaller.getRawCode(),
1715                 state.mBalAllowedByPiCreator.allowsBackgroundActivityStarts(),
1716                 state.callerExplicitOptInOrOut(),
1717                 state.mResultForRealCaller == null ? BAL_BLOCK
1718                         : state.mResultForRealCaller.getRawCode(),
1719                 state.mBalAllowedByPiSender.allowsBackgroundActivityStarts(),
1720                 state.realCallerExplicitOptInOrOut(),
1721                 getTargetSdk(state.mCallingPackage),
1722                 getTargetSdk(state.mRealCallingPackage)
1723         );
1724     }
1725 
1726     /**
1727      * Called whenever an activity finishes. Stores the record, so it can be used by ASM grace
1728      * period checks.
1729      */
onActivityRequestedFinishing(@onNull ActivityRecord finishActivity)1730     void onActivityRequestedFinishing(@NonNull ActivityRecord finishActivity) {
1731         // We only update the entry if the passed in activity
1732         // 1. Has been chained less than a set max AND
1733         // 2. Is visible or top
1734         FinishedActivityEntry entry =
1735                 mTaskIdToFinishedActivity.get(finishActivity.getTask().mTaskId);
1736         if (entry != null && finishActivity.isUid(entry.mUid)
1737                 && entry.mLaunchCount > ASM_GRACEPERIOD_MAX_REPEATS) {
1738             return;
1739         }
1740 
1741         if (!finishActivity.isVisibleRequested()
1742                 && finishActivity != finishActivity.getTask().getTopMostActivity()) {
1743             return;
1744         }
1745 
1746         FinishedActivityEntry newEntry = new FinishedActivityEntry(finishActivity);
1747         mTaskIdToFinishedActivity.put(finishActivity.getTask().mTaskId, newEntry);
1748         if (finishActivity.getTask().mVisibleRequested) {
1749             mTopFinishedActivity = newEntry;
1750         }
1751     }
1752 
1753     /**
1754      * Called whenever an activity starts. Updates the record so the activity is no longer
1755      * considered for ASM grace period checks
1756      */
onNewActivityLaunched(ActivityRecord activityStarted)1757     void onNewActivityLaunched(ActivityRecord activityStarted) {
1758         if (activityStarted.getTask() == null) {
1759             return;
1760         }
1761 
1762         if (activityStarted.getTask().mVisibleRequested) {
1763             mTopFinishedActivity = null;
1764         }
1765 
1766         FinishedActivityEntry entry =
1767                 mTaskIdToFinishedActivity.get(activityStarted.getTask().mTaskId);
1768         if (entry != null && activityStarted.getTask().isTaskId(entry.mTaskId)) {
1769             mTaskIdToFinishedActivity.remove(entry.mTaskId);
1770         }
1771     }
1772 
1773     private static class BlockActivityStart {
1774         private boolean mTopActivityOptedIn;
1775         private boolean mTopActivityMatchesSource;
1776         private ActivityRecord mActivityOptedIn;
1777 
optedIn(ActivityRecord activity)1778         BlockActivityStart optedIn(ActivityRecord activity) {
1779             mTopActivityOptedIn = true;
1780             if (mActivityOptedIn == null) {
1781                 mActivityOptedIn = activity;
1782             }
1783             return this;
1784         }
1785 
matchesSource()1786         BlockActivityStart matchesSource() {
1787             mTopActivityMatchesSource = true;
1788             return this;
1789         }
1790     }
1791 
getDebugStringForActivityRecord(ActivityRecord ar)1792     private static String getDebugStringForActivityRecord(ActivityRecord ar) {
1793         return ar
1794                 + " :: visible=" + ar.isVisible()
1795                 + ", visibleRequested=" + ar.isVisibleRequested()
1796                 + ", finishing=" + ar.finishing
1797                 + ", alwaysOnTop=" + ar.isAlwaysOnTop()
1798                 + ", lastLaunchTime=" + ar.lastLaunchTime
1799                 + ", lastVisibleTime=" + ar.lastVisibleTime
1800                 + ", taskFragment=" + ar.getTaskFragment();
1801     }
1802 
1803     /** @return valid targetSdk or <code>-1</code> */
getTargetSdk(String packageName)1804     private int getTargetSdk(String packageName) {
1805         if (packageName == null) {
1806             return -1;
1807         }
1808         try {
1809             PackageManager pm = mService.mContext.getPackageManager();
1810             return pm.getTargetSdkVersion(packageName);
1811         } catch (Exception e) {
1812             return -1;
1813         }
1814     }
1815 
1816     private class FinishedActivityEntry {
1817         int mUid;
1818         int mTaskId;
1819         int mLaunchCount;
1820         String mDebugInfo;
1821 
FinishedActivityEntry(ActivityRecord ar)1822         FinishedActivityEntry(ActivityRecord ar) {
1823             FinishedActivityEntry entry = mTaskIdToFinishedActivity.get(ar.getTask().mTaskId);
1824             int taskId = ar.getTask().mTaskId;
1825             this.mUid = ar.getUid();
1826             this.mTaskId = taskId;
1827             this.mLaunchCount = entry == null || !ar.isUid(entry.mUid) ? 1 : entry.mLaunchCount + 1;
1828             this.mDebugInfo = getDebugStringForActivityRecord(ar);
1829 
1830             mService.mH.postDelayed(() -> {
1831                 synchronized (mService.mGlobalLock) {
1832                     if (mTaskIdToFinishedActivity.get(taskId) == this) {
1833                         mTaskIdToFinishedActivity.remove(taskId);
1834                     }
1835 
1836                     if (mTopFinishedActivity == this) {
1837                         mTopFinishedActivity = null;
1838                     }
1839                 }
1840             }, ASM_GRACEPERIOD_TIMEOUT_MS);
1841         }
1842     }
1843 }
1844