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.content.pm.PackageManager.PERMISSION_GRANTED;
21 import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER;
22 
23 import static com.android.internal.util.Preconditions.checkState;
24 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
25 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
26 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
27 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
28 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
29 
30 import static java.lang.annotation.RetentionPolicy.SOURCE;
31 
32 import android.annotation.IntDef;
33 import android.annotation.Nullable;
34 import android.app.ActivityManager;
35 import android.app.ActivityOptions;
36 import android.app.AppOpsManager;
37 import android.app.BackgroundStartPrivileges;
38 import android.app.ComponentOptions;
39 import android.content.ComponentName;
40 import android.content.Intent;
41 import android.content.pm.PackageManager;
42 import android.os.Process;
43 import android.os.UserHandle;
44 import android.provider.DeviceConfig;
45 import android.util.ArraySet;
46 import android.util.DebugUtils;
47 import android.util.Slog;
48 
49 
50 import com.android.internal.util.FrameworkStatsLog;
51 import com.android.server.am.PendingIntentRecord;
52 
53 import java.lang.annotation.Retention;
54 
55 /**
56  * Helper class to check permissions for starting Activities.
57  *
58  * <p>This class collects all the logic to prevent malicious attempts to start activities.
59  */
60 public class BackgroundActivityStartController {
61 
62     private static final String TAG =
63             TAG_WITH_CLASS_NAME ? "BackgroundActivityStartController" : TAG_ATM;
64     public static final String VERDICT_ALLOWED = "Activity start allowed";
65     public static final String VERDICT_WOULD_BE_ALLOWED_IF_SENDER_GRANTS_BAL =
66             "Activity start would be allowed if the sender granted BAL privileges";
67 
68     private final ActivityTaskManagerService mService;
69     private final ActivityTaskSupervisor mSupervisor;
70 
71     // TODO(b/263368846) Rename when ASM logic is moved in
72     @Retention(SOURCE)
73     @IntDef({BAL_BLOCK,
74             BAL_ALLOW_DEFAULT,
75             BAL_ALLOW_ALLOWLISTED_UID,
76             BAL_ALLOW_ALLOWLISTED_COMPONENT,
77             BAL_ALLOW_VISIBLE_WINDOW,
78             BAL_ALLOW_PENDING_INTENT,
79             BAL_ALLOW_PERMISSION,
80             BAL_ALLOW_SAW_PERMISSION,
81             BAL_ALLOW_GRACE_PERIOD,
82             BAL_ALLOW_FOREGROUND,
83             BAL_ALLOW_SDK_SANDBOX
84     })
85     public @interface BalCode {}
86 
87     static final int BAL_BLOCK = 0;
88 
89     static final int BAL_ALLOW_DEFAULT = 1;
90 
91     // Following codes are in order of precedence
92 
93     /** Important UIDs which should be always allowed to launch activities */
94     static final int BAL_ALLOW_ALLOWLISTED_UID = 2;
95 
96     /** Apps that fulfill a certain role that can can always launch new tasks */
97     static final int BAL_ALLOW_ALLOWLISTED_COMPONENT = 3;
98 
99     /** Apps which currently have a visible window or are bound by a service with a visible
100      * window */
101     static final int BAL_ALLOW_VISIBLE_WINDOW = 4;
102 
103     /** Allowed due to the PendingIntent sender */
104     static final int BAL_ALLOW_PENDING_INTENT = 5;
105 
106     /** App has START_ACTIVITIES_FROM_BACKGROUND permission or BAL instrumentation privileges
107      * granted to it */
108     static final int BAL_ALLOW_PERMISSION = 6;
109 
110     /** Process has SYSTEM_ALERT_WINDOW permission granted to it */
111     static final int BAL_ALLOW_SAW_PERMISSION = 7;
112 
113     /** App is in grace period after an activity was started or finished */
114     static final int BAL_ALLOW_GRACE_PERIOD = 8;
115 
116     /** App is in a foreground task or bound to a foreground service (but not itself visible) */
117     static final int BAL_ALLOW_FOREGROUND = 9;
118 
119     /** Process belongs to a SDK sandbox */
120     static final int BAL_ALLOW_SDK_SANDBOX = 10;
121 
balCodeToString(@alCode int balCode)122     static String balCodeToString(@BalCode int balCode) {
123         switch (balCode) {
124             case BAL_ALLOW_ALLOWLISTED_COMPONENT:
125                 return "BAL_ALLOW_ALLOWLISTED_COMPONENT";
126             case BAL_ALLOW_ALLOWLISTED_UID:
127                 return "BAL_ALLOW_ALLOWLISTED_UID";
128             case BAL_ALLOW_DEFAULT:
129                 return "BAL_ALLOW_DEFAULT";
130             case BAL_ALLOW_FOREGROUND:
131                 return "BAL_ALLOW_FOREGROUND";
132             case BAL_ALLOW_GRACE_PERIOD:
133                 return "BAL_ALLOW_GRACE_PERIOD";
134             case BAL_ALLOW_PENDING_INTENT:
135                 return "BAL_ALLOW_PENDING_INTENT";
136             case BAL_ALLOW_PERMISSION:
137                 return "BAL_ALLOW_PERMISSION";
138             case BAL_ALLOW_SAW_PERMISSION:
139                 return "BAL_ALLOW_SAW_PERMISSION";
140             case BAL_ALLOW_SDK_SANDBOX:
141                 return "BAL_ALLOW_SDK_SANDBOX";
142             case BAL_ALLOW_VISIBLE_WINDOW:
143                 return "BAL_ALLOW_VISIBLE_WINDOW";
144             case BAL_BLOCK:
145                 return "BAL_BLOCK";
146             default:
147                 throw new IllegalArgumentException("Unexpected value: " + balCode);
148         }
149     }
150 
BackgroundActivityStartController( final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor)151     BackgroundActivityStartController(
152             final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor) {
153         mService = service;
154         mSupervisor = supervisor;
155     }
156 
isHomeApp(int uid, @Nullable String packageName)157     private boolean isHomeApp(int uid, @Nullable String packageName) {
158         if (mService.mHomeProcess != null) {
159             // Fast check
160             return uid == mService.mHomeProcess.mUid;
161         }
162         if (packageName == null) {
163             return false;
164         }
165         ComponentName activity =
166                 mService.getPackageManagerInternalLocked()
167                         .getDefaultHomeActivity(UserHandle.getUserId(uid));
168         return activity != null && packageName.equals(activity.getPackageName());
169     }
170 
shouldAbortBackgroundActivityStart( int callingUid, int callingPid, final String callingPackage, int realCallingUid, int realCallingPid, WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent, BackgroundStartPrivileges backgroundStartPrivileges, Intent intent, ActivityOptions checkedOptions)171     boolean shouldAbortBackgroundActivityStart(
172             int callingUid,
173             int callingPid,
174             final String callingPackage,
175             int realCallingUid,
176             int realCallingPid,
177             WindowProcessController callerApp,
178             PendingIntentRecord originatingPendingIntent,
179             BackgroundStartPrivileges backgroundStartPrivileges,
180             Intent intent,
181             ActivityOptions checkedOptions) {
182         return checkBackgroundActivityStart(callingUid, callingPid, callingPackage,
183                 realCallingUid, realCallingPid,
184                 callerApp, originatingPendingIntent,
185                 backgroundStartPrivileges, intent, checkedOptions) == BAL_BLOCK;
186     }
187 
188     /**
189      * @return A code denoting which BAL rule allows an activity to be started,
190      * or {@link BAL_BLOCK} if the launch should be blocked
191      */
192     @BalCode
checkBackgroundActivityStart( int callingUid, int callingPid, final String callingPackage, int realCallingUid, int realCallingPid, WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent, BackgroundStartPrivileges backgroundStartPrivileges, Intent intent, ActivityOptions checkedOptions)193     int checkBackgroundActivityStart(
194             int callingUid,
195             int callingPid,
196             final String callingPackage,
197             int realCallingUid,
198             int realCallingPid,
199             WindowProcessController callerApp,
200             PendingIntentRecord originatingPendingIntent,
201             BackgroundStartPrivileges backgroundStartPrivileges,
202             Intent intent,
203             ActivityOptions checkedOptions) {
204         // don't abort for the most important UIDs
205         final int callingAppId = UserHandle.getAppId(callingUid);
206         final boolean useCallingUidState =
207                 originatingPendingIntent == null
208                         || checkedOptions == null
209                         || checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
210                                 != ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
211         if (useCallingUidState) {
212             if (callingUid == Process.ROOT_UID
213                     || callingAppId == Process.SYSTEM_UID
214                     || callingAppId == Process.NFC_UID) {
215                 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false,
216                         callingUid, realCallingUid, intent, "Important callingUid");
217             }
218 
219             // Always allow home application to start activities.
220             if (isHomeApp(callingUid, callingPackage)) {
221                 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
222                         /*background*/ false, callingUid, realCallingUid, intent,
223                         "Home app");
224             }
225 
226             // IME should always be allowed to start activity, like IME settings.
227             final WindowState imeWindow =
228                     mService.mRootWindowContainer.getCurrentInputMethodWindow();
229             if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
230                 return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
231                         /*background*/ false, callingUid, realCallingUid, intent,
232                         "Active ime");
233             }
234         }
235 
236         // This is used to block background activity launch even if the app is still
237         // visible to user after user clicking home button.
238         final int appSwitchState = mService.getBalAppSwitchesState();
239 
240         // don't abort if the callingUid has a visible window or is a persistent system process
241         final int callingUidProcState = mService.mActiveUids.getUidState(callingUid);
242         final boolean callingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid);
243         final boolean isCallingUidPersistentSystemProcess =
244                 callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
245 
246         // Normal apps with visible app window will be allowed to start activity if app switching
247         // is allowed, or apps like live wallpaper with non app visible window will be allowed.
248         final boolean appSwitchAllowedOrFg =
249                 appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY;
250         final boolean allowCallingUidStartActivity =
251                 ((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
252                                 && callingUidHasAnyVisibleWindow)
253                         || isCallingUidPersistentSystemProcess;
254         if (useCallingUidState && allowCallingUidStartActivity) {
255             return logStartAllowedAndReturnCode(BAL_ALLOW_VISIBLE_WINDOW,
256                     /*background*/ false, callingUid, realCallingUid, intent,
257                     "callingUidHasAnyVisibleWindow = "
258                             + callingUid
259                             + ", isCallingUidPersistentSystemProcess = "
260                             + isCallingUidPersistentSystemProcess);
261         }
262         // take realCallingUid into consideration
263         final int realCallingUidProcState =
264                 (callingUid == realCallingUid)
265                         ? callingUidProcState
266                         : mService.mActiveUids.getUidState(realCallingUid);
267         final boolean realCallingUidHasAnyVisibleWindow =
268                 (callingUid == realCallingUid)
269                         ? callingUidHasAnyVisibleWindow
270                         : mService.hasActiveVisibleWindow(realCallingUid);
271         final int realCallingAppId = UserHandle.getAppId(realCallingUid);
272         final boolean isRealCallingUidPersistentSystemProcess =
273                 (callingUid == realCallingUid)
274                         ? isCallingUidPersistentSystemProcess
275                         : (realCallingAppId == Process.SYSTEM_UID)
276                                 || realCallingUidProcState
277                                         <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
278 
279         // In the case of an SDK sandbox calling uid, check if the corresponding app uid has a
280         // visible window.
281         if (Process.isSdkSandboxUid(realCallingUid)) {
282             int realCallingSdkSandboxUidToAppUid =
283                     Process.getAppUidForSdkSandboxUid(realCallingUid);
284 
285             if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
286                 return logStartAllowedAndReturnCode(BAL_ALLOW_SDK_SANDBOX,
287                         /*background*/ false, callingUid, realCallingUid, intent,
288                         "uid in SDK sandbox has visible (non-toast) window");
289             }
290         }
291 
292         String realCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid);
293 
294         // Legacy behavior allows to use caller foreground state to bypass BAL restriction.
295         // The options here are the options passed by the sender and not those on the intent.
296         final BackgroundStartPrivileges balAllowedByPiSender =
297                 PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller(
298                         checkedOptions, realCallingUid, realCallingPackage);
299 
300         final boolean logVerdictChangeByPiDefaultChange = checkedOptions == null
301                 || checkedOptions.getPendingIntentBackgroundActivityStartMode()
302                         == ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
303         final boolean considerPiRules = logVerdictChangeByPiDefaultChange
304                 || balAllowedByPiSender.allowsBackgroundActivityStarts();
305         final String verdictLogForPiSender =
306                 balAllowedByPiSender.allowsBackgroundActivityStarts() ? VERDICT_ALLOWED
307                         : VERDICT_WOULD_BE_ALLOWED_IF_SENDER_GRANTS_BAL;
308 
309         @BalCode int resultIfPiSenderAllowsBal = BAL_BLOCK;
310         if (realCallingUid != callingUid && considerPiRules) {
311             resultIfPiSenderAllowsBal = checkPiBackgroundActivityStart(callingUid, realCallingUid,
312                 backgroundStartPrivileges, intent, checkedOptions,
313                 realCallingUidHasAnyVisibleWindow, isRealCallingUidPersistentSystemProcess,
314                 verdictLogForPiSender);
315         }
316         if (resultIfPiSenderAllowsBal != BAL_BLOCK
317                 && balAllowedByPiSender.allowsBackgroundActivityStarts()
318                 && !logVerdictChangeByPiDefaultChange) {
319             // The result is to allow (because the sender allows BAL) and we are not interested in
320             // logging differences, so just return.
321             return resultIfPiSenderAllowsBal;
322         }
323         if (useCallingUidState) {
324             // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
325             if (ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND,
326                     callingPid, callingUid) == PERMISSION_GRANTED) {
327                 return logStartAllowedAndReturnCode(BAL_ALLOW_PERMISSION,
328                     resultIfPiSenderAllowsBal, balAllowedByPiSender,
329                     /*background*/ true, callingUid, realCallingUid, intent,
330                     "START_ACTIVITIES_FROM_BACKGROUND permission granted");
331             }
332             // don't abort if the caller has the same uid as the recents component
333             if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
334                 return logStartAllowedAndReturnCode(
335                     BAL_ALLOW_ALLOWLISTED_COMPONENT,
336                     resultIfPiSenderAllowsBal, balAllowedByPiSender,
337                     /*background*/ true, callingUid, realCallingUid,
338                     intent, "Recents Component");
339             }
340             // don't abort if the callingUid is the device owner
341             if (mService.isDeviceOwner(callingUid)) {
342                 return logStartAllowedAndReturnCode(
343                     BAL_ALLOW_ALLOWLISTED_COMPONENT,
344                     resultIfPiSenderAllowsBal, balAllowedByPiSender,
345                     /*background*/ true, callingUid, realCallingUid,
346                     intent, "Device Owner");
347             }
348             // don't abort if the callingUid is a affiliated profile owner
349             if (mService.isAffiliatedProfileOwner(callingUid)) {
350                 return logStartAllowedAndReturnCode(
351                     BAL_ALLOW_ALLOWLISTED_COMPONENT,
352                     resultIfPiSenderAllowsBal, balAllowedByPiSender,
353                     /*background*/ true, callingUid, realCallingUid,
354                     intent, "Affiliated Profile Owner");
355             }
356             // don't abort if the callingUid has companion device
357             final int callingUserId = UserHandle.getUserId(callingUid);
358             if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
359                 return logStartAllowedAndReturnCode(
360                     BAL_ALLOW_ALLOWLISTED_COMPONENT,
361                     resultIfPiSenderAllowsBal, balAllowedByPiSender,
362                     /*background*/ true, callingUid, realCallingUid,
363                     intent, "Companion App");
364             }
365             // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
366             if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
367                 Slog.w(
368                         TAG,
369                         "Background activity start for "
370                                 + callingPackage
371                                 + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
372                 return logStartAllowedAndReturnCode(
373                     BAL_ALLOW_SAW_PERMISSION,
374                     resultIfPiSenderAllowsBal, balAllowedByPiSender,
375                     /*background*/ true, callingUid, realCallingUid,
376                     intent, "SYSTEM_ALERT_WINDOW permission is granted");
377             }
378             // don't abort if the callingUid and callingPackage have the
379             // OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop
380             if (isSystemExemptFlagEnabled() && mService.getAppOpsManager().checkOpNoThrow(
381                         AppOpsManager.OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
382                         callingUid, callingPackage) == AppOpsManager.MODE_ALLOWED) {
383                 return logStartAllowedAndReturnCode(BAL_ALLOW_PERMISSION,
384                         resultIfPiSenderAllowsBal, balAllowedByPiSender,
385                         /*background*/ true, callingUid, realCallingUid, intent,
386                         "OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
387             }
388         }
389         // If we don't have callerApp at this point, no caller was provided to startActivity().
390         // That's the case for PendingIntent-based starts, since the creator's process might not be
391         // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
392         // caller if caller allows, so that we can make the decision based on its state.
393         int callerAppUid = callingUid;
394         boolean callerAppBasedOnPiSender = callerApp == null && considerPiRules
395                 && resultIfPiSenderAllowsBal == BAL_BLOCK;
396         if (callerAppBasedOnPiSender) {
397             callerApp = mService.getProcessController(realCallingPid, realCallingUid);
398             callerAppUid = realCallingUid;
399         }
400         // don't abort if the callerApp or other processes of that uid are allowed in any way
401         if (callerApp != null && useCallingUidState) {
402             // first check the original calling process
403             final @BalCode int balAllowedForCaller = callerApp
404                     .areBackgroundActivityStartsAllowed(appSwitchState);
405             if (balAllowedForCaller != BAL_BLOCK) {
406                 if (callerAppBasedOnPiSender) {
407                     resultIfPiSenderAllowsBal = logStartAllowedAndReturnCode(balAllowedForCaller,
408                         /*background*/ true, callingUid, realCallingUid, intent,
409                         "callerApp process (pid = " + callerApp.getPid()
410                             + ", uid = " + callerAppUid + ") is allowed", verdictLogForPiSender);
411                 } else {
412                     return logStartAllowedAndReturnCode(balAllowedForCaller,
413                         resultIfPiSenderAllowsBal, balAllowedByPiSender,
414                         /*background*/ true, callingUid, realCallingUid, intent,
415                         "callerApp process (pid = " + callerApp.getPid()
416                             + ", uid = " + callerAppUid + ") is allowed");
417                 }
418             } else {
419                 // only if that one wasn't allowed, check the other ones
420                 final ArraySet<WindowProcessController> uidProcesses =
421                     mService.mProcessMap.getProcesses(callerAppUid);
422                 if (uidProcesses != null) {
423                     for (int i = uidProcesses.size() - 1; i >= 0; i--) {
424                         final WindowProcessController proc = uidProcesses.valueAt(i);
425                         int balAllowedForUid = proc.areBackgroundActivityStartsAllowed(
426                                 appSwitchState);
427                         if (proc != callerApp && balAllowedForUid != BAL_BLOCK) {
428                             if (callerAppBasedOnPiSender) {
429                                 resultIfPiSenderAllowsBal = logStartAllowedAndReturnCode(
430                                     balAllowedForUid,
431                                     /*background*/ true, callingUid, realCallingUid, intent,
432                                     "process" + proc.getPid() + " from uid " + callerAppUid
433                                         + " is allowed", verdictLogForPiSender);
434                                 break;
435                             } else {
436                                 return logStartAllowedAndReturnCode(balAllowedForUid,
437                                     resultIfPiSenderAllowsBal, balAllowedByPiSender,
438                                     /*background*/ true, callingUid, realCallingUid, intent,
439                                     "process" + proc.getPid() + " from uid " + callerAppUid
440                                         + " is allowed");
441                             }
442                         }
443                     }
444                 }
445             }
446             if (callerAppBasedOnPiSender) {
447                 // If caller app was based on PI sender, this result is part of
448                 // resultIfPiSenderAllowsBal
449                 if (resultIfPiSenderAllowsBal != BAL_BLOCK
450                         && balAllowedByPiSender.allowsBackgroundActivityStarts()
451                         && !logVerdictChangeByPiDefaultChange) {
452                     // The result is to allow (because the sender allows BAL) and we are not
453                     // interested in logging differences, so just return.
454                     return resultIfPiSenderAllowsBal;
455                 }
456             } else {
457                 // If caller app was NOT based on PI sender and we found a allow reason we should
458                 // have returned already
459                 checkState(balAllowedForCaller == BAL_BLOCK,
460                         "balAllowedForCaller = " + balAllowedForCaller + " (should have returned)");
461             }
462         }
463         // If we are here, it means all exemptions not based on PI sender failed, so we'll block
464         // unless resultIfPiSenderAllowsBal is an allow and the PI sender allows BAL
465 
466         if (realCallingPackage == null) {
467             realCallingPackage = (callingUid == realCallingUid ? callingPackage :
468                     mService.mContext.getPackageManager().getNameForUid(realCallingUid))
469                     + "[debugOnly]";
470         }
471 
472         String stateDumpLog = " [callingPackage: " + callingPackage
473                 + "; callingUid: " + callingUid
474                 + "; appSwitchState: " + appSwitchState
475                 + "; callingUidHasAnyVisibleWindow: " + callingUidHasAnyVisibleWindow
476                 + "; callingUidProcState: " + DebugUtils.valueToString(
477                         ActivityManager.class, "PROCESS_STATE_", callingUidProcState)
478                 + "; isCallingUidPersistentSystemProcess: " + isCallingUidPersistentSystemProcess
479                 + "; balAllowedByPiSender: " + balAllowedByPiSender
480                 + "; realCallingPackage: " + realCallingPackage
481                 + "; realCallingUid: " + realCallingUid
482                 + "; realCallingUidHasAnyVisibleWindow: " + realCallingUidHasAnyVisibleWindow
483                 + "; realCallingUidProcState: " + DebugUtils.valueToString(
484                         ActivityManager.class, "PROCESS_STATE_", realCallingUidProcState)
485                 + "; isRealCallingUidPersistentSystemProcess: "
486                         + isRealCallingUidPersistentSystemProcess
487                 + "; originatingPendingIntent: " + originatingPendingIntent
488                 + "; backgroundStartPrivileges: " + backgroundStartPrivileges
489                 + "; intent: " + intent
490                 + "; callerApp: " + callerApp
491                 + "; inVisibleTask: " + (callerApp != null && callerApp.hasActivityInVisibleTask())
492                 + "]";
493         if (resultIfPiSenderAllowsBal != BAL_BLOCK) {
494             // We should have returned before if !logVerdictChangeByPiDefaultChange
495             checkState(logVerdictChangeByPiDefaultChange,
496                     "resultIfPiSenderAllowsBal = " + balCodeToString(resultIfPiSenderAllowsBal)
497                         + " at the end but logVerdictChangeByPiDefaultChange = false");
498             if (balAllowedByPiSender.allowsBackgroundActivityStarts()) {
499                 // The verdict changed from block to allow, PI sender default change is off and
500                 // we'd block if it were on
501                 Slog.wtf(TAG, "With BAL hardening this activity start would be blocked!"
502                         + stateDumpLog);
503                 return resultIfPiSenderAllowsBal;
504             } else {
505                 // The verdict changed from allow (resultIfPiSenderAllowsBal) to block, PI sender
506                 // default change is on (otherwise we would have fallen into if above) and we'd
507                 // allow if it were off
508                 Slog.wtf(TAG, "Without BAL hardening this activity start would be allowed!"
509                         + stateDumpLog);
510             }
511         }
512         // anything that has fallen through would currently be aborted
513         Slog.w(TAG, "Background activity launch blocked" + stateDumpLog);
514         // log aborted activity start to TRON
515         if (mService.isActivityStartsLoggingEnabled()) {
516             mSupervisor
517                     .getActivityMetricsLogger()
518                     .logAbortedBgActivityStart(
519                             intent,
520                             callerApp,
521                             callingUid,
522                             callingPackage,
523                             callingUidProcState,
524                             callingUidHasAnyVisibleWindow,
525                             realCallingUid,
526                             realCallingUidProcState,
527                             realCallingUidHasAnyVisibleWindow,
528                             (originatingPendingIntent != null));
529         }
530         return BAL_BLOCK;
531     }
532 
checkPiBackgroundActivityStart(int callingUid, int realCallingUid, BackgroundStartPrivileges backgroundStartPrivileges, Intent intent, ActivityOptions checkedOptions, boolean realCallingUidHasAnyVisibleWindow, boolean isRealCallingUidPersistentSystemProcess, String verdictLog)533     private @BalCode int checkPiBackgroundActivityStart(int callingUid, int realCallingUid,
534             BackgroundStartPrivileges backgroundStartPrivileges, Intent intent,
535             ActivityOptions checkedOptions, boolean realCallingUidHasAnyVisibleWindow,
536             boolean isRealCallingUidPersistentSystemProcess, String verdictLog) {
537         final boolean useCallerPermission =
538                 PendingIntentRecord.isPendingIntentBalAllowedByPermission(checkedOptions);
539         if (useCallerPermission
540                 && ActivityManager.checkComponentPermission(
541                                 android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
542                 realCallingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
543             return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
544                 /*background*/ false, callingUid, realCallingUid, intent,
545                 "realCallingUid has BAL permission. realCallingUid: " + realCallingUid,
546                 verdictLog);
547         }
548 
549         // don't abort if the realCallingUid has a visible window
550         // TODO(b/171459802): We should check appSwitchAllowed also
551         if (realCallingUidHasAnyVisibleWindow) {
552             return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
553                     /*background*/ false, callingUid, realCallingUid, intent,
554                     "realCallingUid has visible (non-toast) window. realCallingUid: "
555                             + realCallingUid, verdictLog);
556         }
557         // if the realCallingUid is a persistent system process, abort if the IntentSender
558         // wasn't allowed to start an activity
559         if (isRealCallingUidPersistentSystemProcess
560                 && backgroundStartPrivileges.allowsBackgroundActivityStarts()) {
561             return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
562                     /*background*/ false, callingUid, realCallingUid, intent,
563                     "realCallingUid is persistent system process AND intent "
564                             + "sender allowed (allowBackgroundActivityStart = true). "
565                             + "realCallingUid: " + realCallingUid, verdictLog);
566         }
567         // don't abort if the realCallingUid is an associated companion app
568         if (mService.isAssociatedCompanionApp(
569                 UserHandle.getUserId(realCallingUid), realCallingUid)) {
570             return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
571                     /*background*/ false, callingUid, realCallingUid, intent,
572                     "realCallingUid is a companion app. "
573                             + "realCallingUid: " + realCallingUid, verdictLog);
574         }
575         return BAL_BLOCK;
576     }
577 
logStartAllowedAndReturnCode(@alCode int code, boolean background, int callingUid, int realCallingUid, Intent intent, int pid, String msg)578     static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
579             int callingUid, int realCallingUid, Intent intent, int pid, String msg) {
580         return logStartAllowedAndReturnCode(code, background, callingUid, realCallingUid, intent,
581                 DEBUG_ACTIVITY_STARTS ?  ("[Process(" + pid + ")]" + msg) : "");
582     }
583 
logStartAllowedAndReturnCode(@alCode int code, boolean background, int callingUid, int realCallingUid, Intent intent, String msg)584     static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
585             int callingUid, int realCallingUid, Intent intent, String msg) {
586         return logStartAllowedAndReturnCode(code, background, callingUid, realCallingUid, intent,
587             msg, VERDICT_ALLOWED);
588     }
589 
590     /**
591      * Logs the start and returns one of the provided codes depending on if the PI sender allows
592      * using its BAL privileges.
593      */
logStartAllowedAndReturnCode(@alCode int result, @BalCode int resultIfPiSenderAllowsBal, BackgroundStartPrivileges balAllowedByPiSender, boolean background, int callingUid, int realCallingUid, Intent intent, String msg)594     static @BalCode int logStartAllowedAndReturnCode(@BalCode int result,
595             @BalCode int resultIfPiSenderAllowsBal, BackgroundStartPrivileges balAllowedByPiSender,
596             boolean background, int callingUid, int realCallingUid, Intent intent, String msg) {
597         if (resultIfPiSenderAllowsBal != BAL_BLOCK
598                 && balAllowedByPiSender.allowsBackgroundActivityStarts()) {
599             // resultIfPiSenderAllowsBal was already logged, so just return
600             return resultIfPiSenderAllowsBal;
601         }
602         return logStartAllowedAndReturnCode(result, background, callingUid, realCallingUid,
603             intent, msg, VERDICT_ALLOWED);
604     }
605 
606 
logStartAllowedAndReturnCode(@alCode int code, boolean background, int callingUid, int realCallingUid, Intent intent, String msg, String verdict)607     static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
608             int callingUid, int realCallingUid, Intent intent, String msg, String verdict) {
609         statsLogBalAllowed(code, callingUid, realCallingUid, intent);
610         if (DEBUG_ACTIVITY_STARTS) {
611             StringBuilder builder = new StringBuilder();
612             if (background) {
613                 builder.append("Background ");
614             }
615             builder.append(verdict + ": " + msg + ". callingUid: " + callingUid + ". ");
616             builder.append("BAL Code: ");
617             builder.append(balCodeToString(code));
618             if (verdict.equals(VERDICT_ALLOWED)) {
619                 Slog.i(TAG, builder.toString());
620             } else {
621                 Slog.d(TAG, builder.toString());
622             }
623         }
624         return code;
625     }
626 
isSystemExemptFlagEnabled()627     private static boolean isSystemExemptFlagEnabled() {
628         return DeviceConfig.getBoolean(
629                 NAMESPACE_WINDOW_MANAGER,
630                 /* name= */ "system_exempt_from_activity_bg_start_restriction_enabled",
631                 /* defaultValue= */ true);
632     }
633 
statsLogBalAllowed( @alCode int code, int callingUid, int realCallingUid, Intent intent)634     private static void statsLogBalAllowed(
635             @BalCode int code, int callingUid, int realCallingUid, Intent intent) {
636         if (code == BAL_ALLOW_PENDING_INTENT
637                 && (callingUid == Process.SYSTEM_UID || realCallingUid == Process.SYSTEM_UID)) {
638             String activityName =
639                     intent != null ? intent.getComponent().flattenToShortString() : "";
640             FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
641                     activityName,
642                     code,
643                     callingUid,
644                     realCallingUid);
645         }
646         if (code == BAL_ALLOW_PERMISSION || code == BAL_ALLOW_FOREGROUND
647                     || code == BAL_ALLOW_SAW_PERMISSION) {
648             // We don't need to know which activity in this case.
649             FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
650                     /*activityName*/ "",
651                     code,
652                     callingUid,
653                     realCallingUid);
654         }
655     }
656 }
657