diff --git a/core/api/current.txt b/core/api/current.txt index 847e1c3ecd671..38f0481cfbfa0 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -10071,6 +10071,7 @@ package android.content { field public static final String BATTERY_SERVICE = "batterymanager"; field public static final int BIND_ABOVE_CLIENT = 8; // 0x8 field public static final int BIND_ADJUST_WITH_ACTIVITY = 128; // 0x80 + field public static final int BIND_ALLOW_ACTIVITY_STARTS = 512; // 0x200 field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10 field public static final int BIND_AUTO_CREATE = 1; // 0x1 field public static final int BIND_DEBUG_UNBIND = 2; // 0x2 diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index c8d48c1892470..a58cac3c6326e 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -278,6 +278,7 @@ public abstract class Context { BIND_IMPORTANT, BIND_ADJUST_WITH_ACTIVITY, BIND_NOT_PERCEPTIBLE, + BIND_ALLOW_ACTIVITY_STARTS, BIND_INCLUDE_CAPABILITIES, BIND_SHARED_ISOLATED_PROCESS }) @@ -381,6 +382,15 @@ public abstract class Context { */ public static final int BIND_NOT_PERCEPTIBLE = 0x00000100; + /** + * Flag for {@link #bindService}: If binding from an app that is visible, the bound service is + * allowed to start an activity from background. This was the default behavior before SDK + * version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}. Since then, the default + * behavior changed to disallow the bound service to start a background activity even if the app + * bound to it is in foreground, unless this flag is specified when binding. + */ + public static final int BIND_ALLOW_ACTIVITY_STARTS = 0X000000200; + /** * Flag for {@link #bindService}: If binding from an app that has specific capabilities * due to its foreground state such as an activity or foreground service, then this flag will diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index 18d84d50aa7d1..ab7b0ab8d1fc7 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -543,6 +543,7 @@ message ConnectionRecordProto { DEAD = 15; NOT_PERCEPTIBLE = 16; INCLUDE_CAPABILITIES = 17; + ALLOW_ACTIVITY_STARTS = 18; } repeated Flag flags = 3; optional string service_name = 4; diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java index 17fff919ba209..f9c0c492626f8 100644 --- a/services/core/java/com/android/server/am/ConnectionRecord.java +++ b/services/core/java/com/android/server/am/ConnectionRecord.java @@ -77,6 +77,7 @@ final class ConnectionRecord { Context.BIND_NOT_VISIBLE, Context.BIND_NOT_PERCEPTIBLE, Context.BIND_INCLUDE_CAPABILITIES, + Context.BIND_ALLOW_ACTIVITY_STARTS, }; private static final int[] BIND_PROTO_ENUMS = new int[] { ConnectionRecordProto.AUTO_CREATE, @@ -96,6 +97,7 @@ final class ConnectionRecord { ConnectionRecordProto.NOT_VISIBLE, ConnectionRecordProto.NOT_PERCEPTIBLE, ConnectionRecordProto.INCLUDE_CAPABILITIES, + ConnectionRecordProto.ALLOW_ACTIVITY_STARTS, }; void dump(PrintWriter pw, String prefix) { @@ -237,6 +239,9 @@ final class ConnectionRecord { if ((flags & Context.BIND_NOT_PERCEPTIBLE) != 0) { sb.append("!PRCP "); } + if ((flags & Context.BIND_ALLOW_ACTIVITY_STARTS) != 0) { + sb.append("BALF "); + } if ((flags & Context.BIND_INCLUDE_CAPABILITIES) != 0) { sb.append("CAPS "); } diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java index df442e83dc9ef..bd7f96ae8b843 100644 --- a/services/core/java/com/android/server/am/ProcessServiceRecord.java +++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java @@ -28,6 +28,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; +import com.android.server.wm.WindowProcessController; import java.io.PrintWriter; import java.util.ArrayList; @@ -506,19 +507,21 @@ final class ProcessServiceRecord { return mConnections.size(); } - void addBoundClientUid(int clientUid) { + void addBoundClientUid(int clientUid, String clientPackageName, int bindFlags) { mBoundClientUids.add(clientUid); - mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids); + mApp.getWindowProcessController() + .addBoundClientUid(clientUid, clientPackageName, bindFlags); } void updateBoundClientUids() { + clearBoundClientUids(); if (mServices.isEmpty()) { - clearBoundClientUids(); return; } // grab a set of clientUids of all mConnections of all services final ArraySet boundClientUids = new ArraySet<>(); final int serviceCount = mServices.size(); + WindowProcessController controller = mApp.getWindowProcessController(); for (int j = 0; j < serviceCount; j++) { final ArrayMap> conns = mServices.valueAt(j).getConnections(); @@ -526,12 +529,13 @@ final class ProcessServiceRecord { for (int conni = 0; conni < size; conni++) { ArrayList c = conns.valueAt(conni); for (int i = 0; i < c.size(); i++) { - boundClientUids.add(c.get(i).clientUid); + ConnectionRecord cr = c.get(i); + boundClientUids.add(cr.clientUid); + controller.addBoundClientUid(cr.clientUid, cr.clientPackageName, cr.flags); } } } mBoundClientUids = boundClientUids; - mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids); } void addBoundClientUidsOfNewService(ServiceRecord sr) { @@ -542,15 +546,18 @@ final class ProcessServiceRecord { for (int conni = conns.size() - 1; conni >= 0; conni--) { ArrayList c = conns.valueAt(conni); for (int i = 0; i < c.size(); i++) { - mBoundClientUids.add(c.get(i).clientUid); + ConnectionRecord cr = c.get(i); + mBoundClientUids.add(cr.clientUid); + mApp.getWindowProcessController() + .addBoundClientUid(cr.clientUid, cr.clientPackageName, cr.flags); + } } - mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids); } void clearBoundClientUids() { mBoundClientUids.clear(); - mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids); + mApp.getWindowProcessController().clearBoundClientUids(); } @GuardedBy("mService") diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index f667e33fc17b5..2a7f181dd8329 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -894,7 +894,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN // if we have a process attached, add bound client uid of this connection to it if (app != null) { - app.mServices.addBoundClientUid(c.clientUid); + app.mServices.addBoundClientUid(c.clientUid, c.clientPackageName, c.flags); app.mProfile.addHostingComponentType(HOSTING_COMPONENT_TYPE_BOUND_SERVICE); } } diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java index ecc8aadf09928..bdb06a97a037d 100644 --- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java +++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java @@ -33,11 +33,17 @@ import static java.util.Objects.requireNonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.BackgroundStartPrivileges; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; +import android.compat.annotation.Overridable; +import android.content.Context; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.os.SystemClock; +import android.os.UserHandle; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.IntArray; import android.util.Slog; @@ -58,6 +64,12 @@ class BackgroundLaunchProcessController { private static final String TAG = TAG_WITH_CLASS_NAME ? "BackgroundLaunchProcessController" : TAG_ATM; + /** If enabled BAL are prevented by default in applications targeting U and later. */ + @ChangeId + @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @Overridable + private static final long DEFAULT_RESCIND_BAL_FG_PRIVILEGES_BOUND_SERVICE = 261072174; + /** It is {@link ActivityTaskManagerService#hasActiveVisibleWindow(int)}. */ private final IntPredicate mUidHasActiveVisibleWindowPredicate; @@ -71,9 +83,11 @@ class BackgroundLaunchProcessController { @GuardedBy("this") private @Nullable ArrayMap mBackgroundStartPrivileges; - /** Set of UIDs of clients currently bound to this process. */ + /** Set of UIDs of clients currently bound to this process and opt in to allow this process to + * launch background activity. + */ @GuardedBy("this") - private @Nullable IntArray mBoundClientUids; + private @Nullable IntArray mBalOptInBoundClientUids; BackgroundLaunchProcessController(@NonNull IntPredicate uidHasActiveVisibleWindowPredicate, @Nullable BackgroundActivityStartCallback callback) { @@ -204,9 +218,9 @@ class BackgroundLaunchProcessController { private boolean isBoundByForegroundUid() { synchronized (this) { - if (mBoundClientUids != null) { - for (int i = mBoundClientUids.size() - 1; i >= 0; i--) { - if (mUidHasActiveVisibleWindowPredicate.test(mBoundClientUids.get(i))) { + if (mBalOptInBoundClientUids != null) { + for (int i = mBalOptInBoundClientUids.size() - 1; i >= 0; i--) { + if (mUidHasActiveVisibleWindowPredicate.test(mBalOptInBoundClientUids.get(i))) { return true; } } @@ -215,19 +229,27 @@ class BackgroundLaunchProcessController { return false; } - void setBoundClientUids(ArraySet boundClientUids) { + void clearBalOptInBoundClientUids() { synchronized (this) { - if (boundClientUids == null || boundClientUids.isEmpty()) { - mBoundClientUids = null; - return; - } - if (mBoundClientUids == null) { - mBoundClientUids = new IntArray(); + if (mBalOptInBoundClientUids == null) { + mBalOptInBoundClientUids = new IntArray(); } else { - mBoundClientUids.clear(); + mBalOptInBoundClientUids.clear(); } - for (int i = boundClientUids.size() - 1; i >= 0; i--) { - mBoundClientUids.add(boundClientUids.valueAt(i)); + } + } + + void addBoundClientUid(int clientUid, String clientPackageName, int bindFlags) { + if (!CompatChanges.isChangeEnabled( + DEFAULT_RESCIND_BAL_FG_PRIVILEGES_BOUND_SERVICE, + clientPackageName, + UserHandle.getUserHandleForUid(clientUid)) + || (bindFlags & Context.BIND_ALLOW_ACTIVITY_STARTS) != 0) { + if (mBalOptInBoundClientUids == null) { + mBalOptInBoundClientUids = new IntArray(); + } + if (mBalOptInBoundClientUids.indexOf(clientUid) == -1) { + mBalOptInBoundClientUids.add(clientUid); } } } @@ -298,10 +320,10 @@ class BackgroundLaunchProcessController { pw.println(mBackgroundStartPrivileges.valueAt(i)); } } - if (mBoundClientUids != null && mBoundClientUids.size() > 0) { + if (mBalOptInBoundClientUids != null && mBalOptInBoundClientUids.size() > 0) { pw.print(prefix); pw.print("BoundClientUids:"); - pw.println(Arrays.toString(mBoundClientUids.toArray())); + pw.println(Arrays.toString(mBalOptInBoundClientUids.toArray())); } } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 8f6ac15646cb8..2980c76a682c8 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -70,7 +70,6 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; -import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -594,8 +593,18 @@ public class WindowProcessController extends ConfigurationContainer boundClientUids) { - mBgLaunchController.setBoundClientUids(boundClientUids); + /** + * Clear all bound client Uids. + */ + public void clearBoundClientUids() { + mBgLaunchController.clearBalOptInBoundClientUids(); + } + + /** + * Add bound client Uid. + */ + public void addBoundClientUid(int clientUid, String clientPackageName, int bindFlags) { + mBgLaunchController.addBoundClientUid(clientUid, clientPackageName, bindFlags); } /**