Merge "Allow package verifier to hide specific fgs notifications." into rvc-qpr-dev am: 1706f9c22f
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12378562 Change-Id: I49a977a18f40504b7bea8e0280d975cccb18c897
This commit is contained in:
@@ -186,6 +186,16 @@ class ContextImpl extends Context {
|
||||
private static final String XATTR_INODE_CACHE = "user.inode_cache";
|
||||
private static final String XATTR_INODE_CODE_CACHE = "user.inode_code_cache";
|
||||
|
||||
/**
|
||||
* Special intent extra that critical system apps can use to hide the notification for a
|
||||
* foreground service. This extra should be placed in the intent passed into {@link
|
||||
* #startForegroundService(Intent)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
private static final String EXTRA_HIDDEN_FOREGROUND_SERVICE =
|
||||
"android.intent.extra.HIDDEN_FOREGROUND_SERVICE";
|
||||
|
||||
/**
|
||||
* Map from package name, to preference name, to cached preferences.
|
||||
*/
|
||||
@@ -1697,9 +1707,12 @@ class ContextImpl extends Context {
|
||||
try {
|
||||
validateServiceIntent(service);
|
||||
service.prepareToLeaveProcess(this);
|
||||
final boolean hideForegroundNotification = requireForeground
|
||||
&& service.getBooleanExtra(EXTRA_HIDDEN_FOREGROUND_SERVICE, false);
|
||||
ComponentName cn = ActivityManager.getService().startService(
|
||||
mMainThread.getApplicationThread(), service,
|
||||
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
|
||||
hideForegroundNotification,
|
||||
getOpPackageName(), getAttributionTag(), user.getIdentifier());
|
||||
if (cn != null) {
|
||||
if (cn.getPackageName().equals("!")) {
|
||||
|
||||
@@ -155,7 +155,8 @@ interface IActivityManager {
|
||||
boolean refContentProvider(in IBinder connection, int stableDelta, int unstableDelta);
|
||||
PendingIntent getRunningServiceControlPanel(in ComponentName service);
|
||||
ComponentName startService(in IApplicationThread caller, in Intent service,
|
||||
in String resolvedType, boolean requireForeground, in String callingPackage,
|
||||
in String resolvedType, boolean requireForeground,
|
||||
boolean hideForegroundNotification, in String callingPackage,
|
||||
in String callingFeatureId, int userId);
|
||||
@UnsupportedAppUsage
|
||||
int stopService(in IApplicationThread caller, in Intent service,
|
||||
|
||||
@@ -453,16 +453,16 @@ public final class ActiveServices {
|
||||
}
|
||||
|
||||
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
|
||||
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
|
||||
@Nullable String callingFeatureId, final int userId)
|
||||
int callingPid, int callingUid, boolean fgRequired, boolean hideFgNotification,
|
||||
String callingPackage, @Nullable String callingFeatureId, final int userId)
|
||||
throws TransactionTooLargeException {
|
||||
return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
|
||||
callingPackage, callingFeatureId, userId, false);
|
||||
hideFgNotification, callingPackage, callingFeatureId, userId, false);
|
||||
}
|
||||
|
||||
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
|
||||
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
|
||||
@Nullable String callingFeatureId, final int userId,
|
||||
int callingPid, int callingUid, boolean fgRequired, boolean hideFgNotification,
|
||||
String callingPackage, @Nullable String callingFeatureId, final int userId,
|
||||
boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
|
||||
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
|
||||
+ " type=" + resolvedType + " args=" + service.getExtras());
|
||||
@@ -609,6 +609,7 @@ public final class ActiveServices {
|
||||
r.startRequested = true;
|
||||
r.delayedStop = false;
|
||||
r.fgRequired = fgRequired;
|
||||
r.hideFgNotification = hideFgNotification;
|
||||
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
|
||||
service, neededGrants, callingUid));
|
||||
|
||||
|
||||
@@ -1438,6 +1438,10 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
final Injector mInjector;
|
||||
|
||||
/** The package verifier app. */
|
||||
private String mPackageVerifier;
|
||||
private int mPackageVerifierUid = UserHandle.USER_NULL;
|
||||
|
||||
static final class ProcessChangeItem {
|
||||
static final int CHANGE_ACTIVITIES = 1<<0;
|
||||
static final int CHANGE_FOREGROUND_SERVICES = 1<<1;
|
||||
@@ -2362,6 +2366,18 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
if (phase == PHASE_SYSTEM_SERVICES_READY) {
|
||||
mService.mBatteryStatsService.systemServicesReady();
|
||||
mService.mServices.systemServicesReady();
|
||||
mService.mPackageVerifier = ArrayUtils.firstOrNull(
|
||||
LocalServices.getService(PackageManagerInternal.class).getKnownPackageNames(
|
||||
PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM));
|
||||
if (mService.mPackageVerifier != null) {
|
||||
try {
|
||||
mService.mPackageVerifierUid =
|
||||
getContext().getPackageManager().getPackageUid(
|
||||
mService.mPackageVerifier, UserHandle.USER_SYSTEM);
|
||||
} catch (NameNotFoundException e) {
|
||||
Slog.wtf(TAG, "Package manager couldn't get package verifier uid", e);
|
||||
}
|
||||
}
|
||||
} else if (phase == PHASE_ACTIVITY_MANAGER_READY) {
|
||||
mService.startBroadcastObservers();
|
||||
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
|
||||
@@ -15007,8 +15023,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public ComponentName startService(IApplicationThread caller, Intent service,
|
||||
String resolvedType, boolean requireForeground, String callingPackage,
|
||||
String callingFeatureId, int userId)
|
||||
String resolvedType, boolean requireForeground, boolean hideForegroundNotification,
|
||||
String callingPackage, String callingFeatureId, int userId)
|
||||
throws TransactionTooLargeException {
|
||||
enforceNotIsolatedCaller("startService");
|
||||
// Refuse possible leaked file descriptors
|
||||
@@ -15020,17 +15036,27 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
throw new IllegalArgumentException("callingPackage cannot be null");
|
||||
}
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
if (requireForeground && hideForegroundNotification) {
|
||||
if (!UserHandle.isSameApp(callingUid, mPackageVerifierUid)
|
||||
|| !callingPackage.equals(mPackageVerifier)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Only the package verifier can hide its foreground service notification");
|
||||
}
|
||||
Slog.i(TAG, "Foreground service notification hiding requested by " + callingPackage);
|
||||
}
|
||||
|
||||
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
|
||||
"*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
|
||||
synchronized(this) {
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
ComponentName res;
|
||||
try {
|
||||
res = mServices.startServiceLocked(caller, service,
|
||||
resolvedType, callingPid, callingUid,
|
||||
requireForeground, callingPackage, callingFeatureId, userId);
|
||||
requireForeground, hideForegroundNotification,
|
||||
callingPackage, callingFeatureId, userId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
}
|
||||
@@ -19470,7 +19496,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
ComponentName res;
|
||||
try {
|
||||
res = mServices.startServiceLocked(null, service,
|
||||
resolvedType, -1, uid, fgRequired, callingPackage,
|
||||
resolvedType, -1, uid, fgRequired, false, callingPackage,
|
||||
callingFeatureId, userId, allowBackgroundActivityStarts);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
|
||||
@@ -654,7 +654,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
pw.println("Starting service: " + intent);
|
||||
pw.flush();
|
||||
ComponentName cn = mInterface.startService(null, intent, intent.getType(),
|
||||
asForeground, SHELL_PACKAGE_NAME, null, mUserId);
|
||||
asForeground, false, SHELL_PACKAGE_NAME, null, mUserId);
|
||||
if (cn == null) {
|
||||
err.println("Error: Not found; no service started.");
|
||||
return -1;
|
||||
|
||||
@@ -104,6 +104,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
|
||||
boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
|
||||
boolean delayed; // are we waiting to start this service in the background?
|
||||
boolean fgRequired; // is the service required to go foreground after starting?
|
||||
boolean hideFgNotification; // Hide the fg service notification
|
||||
boolean fgWaiting; // is a timeout for going foreground already scheduled?
|
||||
boolean isForeground; // is service currently in foreground mode?
|
||||
int foregroundId; // Notification ID of last foreground req.
|
||||
@@ -823,6 +824,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
|
||||
}
|
||||
|
||||
public void postNotification() {
|
||||
if (hideFgNotification) {
|
||||
return;
|
||||
}
|
||||
final int appUid = appInfo.uid;
|
||||
final int appPid = app.pid;
|
||||
if (foregroundId != 0 && foregroundNoti != null) {
|
||||
@@ -915,7 +919,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
|
||||
}
|
||||
if (localForegroundNoti.getSmallIcon() == null) {
|
||||
// Notifications whose icon is 0 are defined to not show
|
||||
// a notification, silently ignoring it. We don't want to
|
||||
// a notification. We don't want to
|
||||
// just ignore it, we want to prevent the service from
|
||||
// being foreground.
|
||||
throw new RuntimeException("invalid service notification: "
|
||||
|
||||
Reference in New Issue
Block a user