diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 0f3aa6531e354..562f8f4498337 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -21,38 +21,40 @@ import static android.Manifest.permission.REQUEST_COMPANION_START_FOREGROUND_SER import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND; import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; +import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI; import static android.app.ActivityManager.PROCESS_STATE_RECEIVER; import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST; +import static android.os.PowerExemptionManager.REASON_ACTIVITY_STARTER; import static android.os.PowerExemptionManager.REASON_ACTIVITY_VISIBILITY_GRACE_PERIOD; +import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE; +import static android.os.PowerExemptionManager.REASON_BACKGROUND_ACTIVITY_PERMISSION; +import static android.os.PowerExemptionManager.REASON_BACKGROUND_FGS_PERMISSION; +import static android.os.PowerExemptionManager.REASON_COMPANION_DEVICE_MANAGER; +import static android.os.PowerExemptionManager.REASON_DENIED; +import static android.os.PowerExemptionManager.REASON_DEVICE_DEMO_MODE; +import static android.os.PowerExemptionManager.REASON_DEVICE_OWNER; +import static android.os.PowerExemptionManager.REASON_FGS_BINDING; +import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION; +import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION; import static android.os.PowerExemptionManager.REASON_OPT_OUT_REQUESTED; import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_PLATFORM_VPN; import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_VPN; +import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT; +import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI; +import static android.os.PowerExemptionManager.REASON_PROC_STATE_TOP; +import static android.os.PowerExemptionManager.REASON_PROFILE_OWNER; +import static android.os.PowerExemptionManager.REASON_SERVICE_LAUNCH; +import static android.os.PowerExemptionManager.REASON_START_ACTIVITY_FLAG; +import static android.os.PowerExemptionManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION; +import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED; +import static android.os.PowerExemptionManager.REASON_SYSTEM_UID; import static android.os.PowerExemptionManager.REASON_TEMP_ALLOWED_WHILE_IN_USE; -import static android.os.PowerWhitelistManager.REASON_ACTIVITY_STARTER; -import static android.os.PowerWhitelistManager.REASON_ALLOWLISTED_PACKAGE; -import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_COMPANION_DEVICE_MANAGER; -import static android.os.PowerWhitelistManager.REASON_DENIED; -import static android.os.PowerWhitelistManager.REASON_DEVICE_DEMO_MODE; -import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER; -import static android.os.PowerWhitelistManager.REASON_FGS_BINDING; -import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_PROC_STATE_PERSISTENT; -import static android.os.PowerWhitelistManager.REASON_PROC_STATE_PERSISTENT_UI; -import static android.os.PowerWhitelistManager.REASON_PROC_STATE_TOP; -import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER; -import static android.os.PowerWhitelistManager.REASON_START_ACTIVITY_FLAG; -import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED; -import static android.os.PowerWhitelistManager.REASON_SYSTEM_UID; -import static android.os.PowerWhitelistManager.REASON_UID_VISIBLE; -import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; -import static android.os.PowerWhitelistManager.getReasonCodeFromProcState; -import static android.os.PowerWhitelistManager.reasonCodeToString; +import static android.os.PowerExemptionManager.REASON_UID_VISIBLE; +import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; +import static android.os.PowerExemptionManager.getReasonCodeFromProcState; +import static android.os.PowerExemptionManager.reasonCodeToString; import static android.os.Process.INVALID_UID; import static android.os.Process.NFC_UID; import static android.os.Process.ROOT_UID; @@ -118,8 +120,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.PowerWhitelistManager; -import android.os.PowerWhitelistManager.ReasonCode; +import android.os.PowerExemptionManager.ReasonCode; import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; @@ -135,6 +136,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; +import android.util.Pair; import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; @@ -3614,8 +3616,9 @@ public final class ActiveServices { + " for fg-service launch"); } mAm.tempAllowlistUidLocked(r.appInfo.uid, - SERVICE_START_FOREGROUND_TIMEOUT, PowerWhitelistManager.REASON_SERVICE_LAUNCH, - "fg-service-launch", TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, + SERVICE_START_FOREGROUND_TIMEOUT, REASON_SERVICE_LAUNCH, + "fg-service-launch", + TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, r.mRecentCallingUid); } @@ -5740,6 +5743,66 @@ public final class ActiveServices { int ret = shouldAllowFgsStartForegroundLocked(allowWhileInUse, callingPid, callingUid, callingPackage, r); + String bindFromPackage = null; + if (ret == REASON_DENIED) { + // If the callingUid is not allowed to start FGS, check if the callingUid has any + // service that is bound by a clientUid, the clientUid can propagate its BG-FGS-start + // capability down to the callingUid. + final ArraySet checkedClientUids = new ArraySet<>(); + final Pair isAllowed = mAm.mProcessList.searchEachLruProcessesLOSP( + false, pr -> { + if (pr.uid == callingUid) { + final ProcessServiceRecord psr = pr.mServices; + final int serviceCount = psr.mServices.size(); + for (int svc = 0; svc < serviceCount; svc++) { + final ArrayMap> conns = + psr.mServices.valueAt(svc).getConnections(); + final int size = conns.size(); + for (int conni = 0; conni < size; conni++) { + final ArrayList crs = conns.valueAt(conni); + for (int con = 0; con < crs.size(); con++) { + final ConnectionRecord cr = crs.get(con); + final ProcessRecord clientPr = cr.binding.client; + // Persistent process does not propagate BG-FGS-start capability + // down to service over binding. + if (clientPr.mState.getCurProcState() + <= PROCESS_STATE_PERSISTENT_UI) { + continue; + } + final int clientPid = clientPr.mPid; + final int clientUid = clientPr.uid; + // An UID can bind to itself, do not check on itself again. + // Also skip already checked clientUid. + if (clientUid == callingUid + || checkedClientUids.contains(clientUid)) { + continue; + } + final String clientPackageName = cr.clientPackageName; + final @ReasonCode int allowWhileInUse2 = + shouldAllowFgsWhileInUsePermissionLocked(clientPackageName, + clientPid, clientUid, null /* serviceRecord */, + false /* allowBackgroundActivityStarts */); + final @ReasonCode int allowStartFgs = + shouldAllowFgsStartForegroundLocked(allowWhileInUse2, + clientPid, clientUid, clientPackageName, null /* targetService */); + if (allowStartFgs != REASON_DENIED) { + return new Pair<>(allowStartFgs, clientPackageName); + } else { + checkedClientUids.add(clientUid); + } + + } + } + } + } + return null; + }); + if (isAllowed != null) { + ret = REASON_FGS_BINDING; + bindFromPackage = isAllowed.second; + } + } + final int uidState = mAm.getUidStateLocked(callingUid); int callerTargetSdkVersion = INVALID_UID; try { @@ -5765,6 +5828,7 @@ public final class ActiveServices { + "; targetSdkVersion:" + r.appInfo.targetSdkVersion + "; callerTargetSdkVersion:" + callerTargetSdkVersion + "; startForegroundCount:" + r.mStartForegroundCount + + "; bindFromPackage:" + bindFromPackage + "]"; if (!debugInfo.equals(r.mInfoAllowStartForeground)) { r.mLoggedInfoAllowStartForeground = false; @@ -5790,9 +5854,7 @@ public final class ActiveServices { final Integer allowedType = mAm.mProcessList.searchEachLruProcessesLOSP(false, app -> { if (app.uid == callingUid) { final ProcessStateRecord state = app.mState; - if (state.getAllowedStartFgs() != REASON_DENIED) { - return state.getAllowedStartFgs(); - } else if (state.isAllowedStartFgsState()) { + if (state.isAllowedStartFgsState()) { return getReasonCodeFromProcState(state.getAllowStartFgsState()); } else if (state.areBackgroundFgsStartsAllowedByToken()) { return REASON_FGS_BINDING; @@ -5891,6 +5953,7 @@ public final class ActiveServices { } if (ret == REASON_DENIED) { if (mAm.mConstants.mFgsAllowOptOut + && targetService != null && targetService.appInfo.hasRequestForegroundServiceExemption()) { ret = REASON_OPT_OUT_REQUESTED; } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 2e2a29751f79d..661e0b886c254 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -42,7 +42,6 @@ import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; -import static android.os.PowerWhitelistManager.REASON_DENIED; import static android.os.Process.SCHED_OTHER; import static android.os.Process.THREAD_GROUP_BACKGROUND; import static android.os.Process.THREAD_GROUP_DEFAULT; @@ -1574,8 +1573,7 @@ public class OomAdjuster { state.setAdjTarget(null); state.setEmpty(false); state.setCached(false); - state.setAllowStartFgsState(PROCESS_STATE_NONEXISTENT); - state.resetAllowStartFgs(); + state.resetAllowStartFgsState(); app.mOptRecord.setShouldNotFreeze(false); final int appUid = app.info.uid; @@ -1630,7 +1628,6 @@ public class OomAdjuster { state.setCurAdj(state.getMaxAdj()); state.setCompletedAdjSeq(state.getAdjSeq()); state.bumpAllowStartFgsState(state.getCurProcState()); - state.setAllowStartFgs(); // if curAdj is less than prevAppAdj, then this process was promoted return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState; } @@ -2028,12 +2025,6 @@ public class OomAdjuster { final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP; - // pass client's mAllowStartFgs to the app if client is not persistent process. - if (cstate.getAllowedStartFgs() != REASON_DENIED - && cstate.getMaxAdj() >= ProcessList.FOREGROUND_APP_ADJ) { - state.setAllowStartFgs(cstate.getAllowedStartFgs()); - } - if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) { if (shouldSkipDueToCycle(state, cstate, procState, adj, cycleReEval)) { continue; @@ -2524,7 +2515,6 @@ public class OomAdjuster { state.updateLastInvisibleTime(hasVisibleActivities); state.setHasForegroundActivities(foregroundActivities); state.setCompletedAdjSeq(mAdjSeq); - state.setAllowStartFgs(); // if curAdj or curProcState improved, then this process was promoted return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java index 5c3bf605f71a0..8f77b87f5308f 100644 --- a/services/core/java/com/android/server/am/ProcessServiceRecord.java +++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java @@ -89,7 +89,7 @@ final class ProcessServiceRecord { /** * All ServiceRecord running in this process. */ - private final ArraySet mServices = new ArraySet<>(); + final ArraySet mServices = new ArraySet<>(); /** * Services that are currently executing code (need to remain foreground). diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java index 801e3824d7b02..d83e13cb2e412 100644 --- a/services/core/java/com/android/server/am/ProcessStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessStateRecord.java @@ -16,28 +16,9 @@ package com.android.server.am; -import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; -import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND; -import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_DENIED; -import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER; -import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER; -import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION; -import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED; -import static android.os.PowerWhitelistManager.REASON_SYSTEM_UID; -import static android.os.PowerWhitelistManager.ReasonCode; -import static android.os.PowerWhitelistManager.getReasonCodeFromProcState; -import static android.os.PowerWhitelistManager.reasonCodeToString; -import static android.os.Process.NFC_UID; -import static android.os.Process.ROOT_UID; -import static android.os.Process.SHELL_UID; -import static android.os.Process.SYSTEM_UID; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ; import static com.android.server.am.ProcessRecord.TAG; @@ -47,7 +28,6 @@ import android.app.ActivityManager; import android.content.ComponentName; import android.os.Binder; import android.os.SystemClock; -import android.os.UserHandle; import android.util.ArraySet; import android.util.Slog; import android.util.TimeUtils; @@ -56,7 +36,6 @@ import com.android.internal.annotations.CompositeRWLock; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FrameworkStatsLog; - import java.io.PrintWriter; /** @@ -326,20 +305,6 @@ final class ProcessStateRecord { @GuardedBy("mService") private final ArraySet mBackgroundFgsStartTokens = new ArraySet<>(); - /** - * Does the process has permission to start FGS from background. - */ - @GuardedBy("mService") - private @ReasonCode int mAllowStartFgsByPermission = REASON_DENIED; - - /** - * Can this process start FGS from background? - * If this process has the ability to start FGS from background, this ability can be passed to - * another process through service binding. - */ - @GuardedBy("mService") - private @ReasonCode int mAllowStartFgs = REASON_DENIED; - /** * Whether or not this process has been in forced-app-standby state. */ @@ -435,7 +400,6 @@ final class ProcessStateRecord { mApp = app; mService = app.mService; mProcLock = mService.mProcLock; - setAllowStartFgsByPermission(); } void init(long now) { @@ -1152,9 +1116,8 @@ final class ProcessStateRecord { } @GuardedBy("mService") - void resetAllowStartFgs() { + void resetAllowStartFgsState() { mAllowStartFgsState = PROCESS_STATE_NONEXISTENT; - mAllowStartFgs = mAllowStartFgsByPermission; } @GuardedBy("mService") @@ -1164,11 +1127,6 @@ final class ProcessStateRecord { } } - @GuardedBy("mService") - void setAllowStartFgsState(int allowStartFgsState) { - mAllowStartFgsState = allowStartFgsState; - } - @GuardedBy("mService") int getAllowStartFgsState() { return mAllowStartFgsState; @@ -1179,98 +1137,6 @@ final class ProcessStateRecord { return mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE; } - @GuardedBy("mService") - void setAllowStartFgsByPermission() { - int ret = REASON_DENIED; - boolean isSystem = false; - final int uid = UserHandle.getAppId(mApp.info.uid); - switch (uid) { - case ROOT_UID: - case SYSTEM_UID: - case NFC_UID: - case SHELL_UID: - isSystem = true; - break; - default: - isSystem = false; - break; - } - - if (isSystem) { - ret = REASON_SYSTEM_UID; - } - - if (ret == REASON_DENIED) { - if (ActivityManager.checkComponentPermission(START_ACTIVITIES_FROM_BACKGROUND, - mApp.info.uid, -1, true) == PERMISSION_GRANTED) { - ret = REASON_BACKGROUND_ACTIVITY_PERMISSION; - } else if (ActivityManager.checkComponentPermission( - START_FOREGROUND_SERVICES_FROM_BACKGROUND, - mApp.info.uid, -1, true) == PERMISSION_GRANTED) { - ret = REASON_BACKGROUND_FGS_PERMISSION; - } else if (ActivityManager.checkComponentPermission(SYSTEM_ALERT_WINDOW, - mApp.info.uid, -1, true) == PERMISSION_GRANTED) { - ret = REASON_SYSTEM_ALERT_WINDOW_PERMISSION; - } - } - mAllowStartFgs = mAllowStartFgsByPermission = ret; - } - - // TODO(b/188063200) Clean up this method. Why do we need to duplicate only some of the checks? - @GuardedBy("mService") - void setAllowStartFgs() { - if (mAllowStartFgs != REASON_DENIED) { - return; - } - if (mAllowStartFgs == REASON_DENIED) { - if (isAllowedStartFgsState()) { - mAllowStartFgs = getReasonCodeFromProcState(mAllowStartFgsState); - } - } - - if (mAllowStartFgs == REASON_DENIED) { - // Is the calling UID a device owner app? - if (mService.mInternal != null) { - if (mService.mInternal.isDeviceOwner(mApp.info.uid)) { - mAllowStartFgs = REASON_DEVICE_OWNER; - } - } - } - - if (mAllowStartFgs == REASON_DENIED) { - // Is the calling UID a profile owner app? - if (mService.mInternal != null) { - if (mService.mInternal.isProfileOwner(mApp.info.uid)) { - mAllowStartFgs = REASON_PROFILE_OWNER; - } - } - } - - if (mAllowStartFgs == REASON_DENIED) { - // uid is on DeviceIdleController's user/system allowlist - // or AMS's FgsStartTempAllowList. - ActivityManagerService.FgsTempAllowListItem item = - mService.isAllowlistedForFgsStartLOSP(mApp.info.uid); - if (item != null) { - if (item == ActivityManagerService.FAKE_TEMP_ALLOW_LIST_ITEM) { - mAllowStartFgs = REASON_SYSTEM_ALLOW_LISTED; - } else { - mAllowStartFgs = item.mReasonCode; - } - } - } - } - - @GuardedBy("mService") - void setAllowStartFgs(@ReasonCode int allowStartFgs) { - mAllowStartFgs = allowStartFgs; - } - - @GuardedBy("mService") - @ReasonCode int getAllowedStartFgs() { - return mAllowStartFgs; - } - @GuardedBy("mService") void setForcedAppStandby(boolean standby) { mForcedAppStandby = standby; @@ -1334,10 +1200,6 @@ final class ProcessStateRecord { pw.println(); pw.print(prefix); pw.print("allowStartFgsState="); pw.println(mAllowStartFgsState); - if (mAllowStartFgs != REASON_DENIED) { - pw.print(prefix); pw.print("allowStartFgs="); - pw.println(reasonCodeToString(mAllowStartFgs)); - } if (mHasShownUi || mApp.mProfile.hasPendingUiClean()) { pw.print(prefix); pw.print("hasShownUi="); pw.print(mHasShownUi); pw.print(" pendingUiClean="); pw.println(mApp.mProfile.hasPendingUiClean());