Merge "Block service bound by foreground app to launch background activity by default"

This commit is contained in:
Nan Wu
2023-01-17 19:52:25 +00:00
committed by Android (Google) Code Review
8 changed files with 85 additions and 30 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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 ");
}

View File

@@ -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<Integer> boundClientUids = new ArraySet<>();
final int serviceCount = mServices.size();
WindowProcessController controller = mApp.getWindowProcessController();
for (int j = 0; j < serviceCount; j++) {
final ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns =
mServices.valueAt(j).getConnections();
@@ -526,12 +529,13 @@ final class ProcessServiceRecord {
for (int conni = 0; conni < size; conni++) {
ArrayList<ConnectionRecord> 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<ConnectionRecord> 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")

View File

@@ -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);
}
}

View File

@@ -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<Binder, BackgroundStartPrivileges> 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<Integer> 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()));
}
}
}

View File

@@ -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<Configuratio
return mBgLaunchController.canCloseSystemDialogsByToken(mUid);
}
public void setBoundClientUids(ArraySet<Integer> 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);
}
/**