Implement naming of isolated service bindings.
This allows clients to run multiple instances of the same
manifest service declaration. It only works for isolated
services, to avoid too much abuse temptation. This is part
of the "Chrome site isolation" work, to allow chrome to have
many more render processes running and help it manage them.
Bug: 111434506
Test: atest CtsAppTestCases:ServiceTest
Change-Id: I22e65758678a07075ed32ed6463082ddf846d3a4
diff --git a/api/current.txt b/api/current.txt
index 28863b8..56275c5 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -9475,6 +9475,7 @@
public abstract class Context {
ctor public Context();
+ method public abstract boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
method public abstract boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public abstract int checkCallingOrSelfPermission(java.lang.String);
method public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -9686,6 +9687,7 @@
public class ContextWrapper extends android.content.Context {
ctor public ContextWrapper(android.content.Context);
method protected void attachBaseContext(android.content.Context);
+ method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public int checkCallingOrSelfPermission(java.lang.String);
method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index dc707e8..9837deb 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -140,6 +140,13 @@
throw new ReceiverCallNotAllowedException(
"BroadcastReceiver components are not allowed to bind to services");
}
+
+ @Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+ String instanceName) {
+ throw new ReceiverCallNotAllowedException(
+ "BroadcastReceiver components are not allowed to bind to services");
+ }
}
/**
@@ -1630,14 +1637,25 @@
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
- return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
+ return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), getUser());
+ }
+
+ @Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn,
+ int flags, String instanceName) {
+ warnIfCallingFromSystemProcess();
+ if (instanceName == null) {
+ throw new NullPointerException("null instanceName");
+ }
+ return bindServiceCommon(service, conn, flags, instanceName, mMainThread.getHandler(),
+ getUser());
}
/** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
- return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), user);
+ return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), user);
}
/** @hide */
@@ -1647,7 +1665,7 @@
if (handler == null) {
throw new IllegalArgumentException("handler must not be null.");
}
- return bindServiceCommon(service, conn, flags, handler, user);
+ return bindServiceCommon(service, conn, flags, null, handler, user);
}
/** @hide */
@@ -1669,7 +1687,8 @@
return mMainThread.getHandler();
}
- private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
+ private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
+ String instanceName, Handler
handler, UserHandle user) {
// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
@@ -1690,10 +1709,10 @@
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess(this);
- int res = ActivityManager.getService().bindService(
+ int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
- sd, flags, getOpPackageName(), user.getIdentifier());
+ sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index e2312a5..f27c667 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -133,9 +133,13 @@
in String resolvedType, boolean requireForeground, in String callingPackage, int userId);
int stopService(in IApplicationThread caller, in Intent service,
in String resolvedType, int userId);
+ // Currently keeping old bindService because it is on the greylist
int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
in String resolvedType, in IServiceConnection connection, int flags,
in String callingPackage, int userId);
+ int bindIsolatedService(in IApplicationThread caller, in IBinder token, in Intent service,
+ in String resolvedType, in IServiceConnection connection, int flags,
+ in String instanceName, in String callingPackage, int userId);
boolean unbindService(in IServiceConnection connection);
void publishService(in IBinder token, in Intent intent, in IBinder service);
void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9f8ae0b..03eba7e 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2906,8 +2906,9 @@
* @param flags Operation options for the binding. May be 0,
* {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
* {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
- * {@link #BIND_ALLOW_OOM_MANAGEMENT}, or
- * {@link #BIND_WAIVE_PRIORITY}.
+ * {@link #BIND_ALLOW_OOM_MANAGEMENT}, {@link #BIND_WAIVE_PRIORITY}.
+ * {@link #BIND_IMPORTANT}, or
+ * {@link #BIND_ADJUST_WITH_ACTIVITY}.
* @return {@code true} if the system is in the process of bringing up a
* service that your client has permission to bind to; {@code false}
* if the system couldn't find the service or if your client doesn't
@@ -2923,11 +2924,38 @@
* @see #BIND_AUTO_CREATE
* @see #BIND_DEBUG_UNBIND
* @see #BIND_NOT_FOREGROUND
+ * @see #BIND_ABOVE_CLIENT
+ * @see #BIND_ALLOW_OOM_MANAGEMENT
+ * @see #BIND_WAIVE_PRIORITY
+ * @see #BIND_IMPORTANT
+ * @see #BIND_ADJUST_WITH_ACTIVITY
*/
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
/**
+ * Variation of {@link #bindService} that, in the specific case of isolated
+ * services, allows the caller to generate multiple instances of a service
+ * from a single component declaration.
+ *
+ * @param service Identifies the service to connect to. The Intent must
+ * specify an explicit component name.
+ * @param conn Receives information as the service is started and stopped.
+ * This must be a valid ServiceConnection object; it must not be null.
+ * @param flags Operation options for the binding as per {@link #bindService}.
+ * @param instanceName Unique identifier for the service instance. Each unique
+ * name here will result in a different service instance being created.
+ * @return Returns success of binding as per {@link #bindService}.
+ *
+ * @throws SecurityException If the caller does not have permission to access the service
+ *
+ * @see #bindService
+ */
+ public abstract boolean bindIsolatedService(@RequiresPermission Intent service,
+ @NonNull ServiceConnection conn, @BindServiceFlags int flags,
+ @NonNull String instanceName);
+
+ /**
* Same as {@link #bindService(Intent, ServiceConnection, int)}, but with an explicit userHandle
* argument for use by system server and other multi-user aware code.
* @hide
@@ -2941,7 +2969,7 @@
}
/**
- * Same as {@link #bindService(Intent, ServiceConnection, int, UserHandle)}, but with an
+ * Same as {@link #bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)}, but with an
* explicit non-null Handler to run the ServiceConnection callbacks on.
*
* @hide
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index bfad2b4..88696b0e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -705,6 +705,12 @@
return mBase.bindService(service, conn, flags);
}
+ @Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn,
+ int flags, String instanceName) {
+ return mBase.bindIsolatedService(service, conn, flags, instanceName);
+ }
+
/** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a33ac70..b5217ad 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -192,10 +192,10 @@
public void stopForegroundServicesForUidPackage(final int uid, final String packageName) {
synchronized (mAm) {
final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid));
- final int N = smap.mServicesByName.size();
+ final int N = smap.mServicesByInstanceName.size();
final ArrayList<ServiceRecord> toStop = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
- final ServiceRecord r = smap.mServicesByName.valueAt(i);
+ final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i);
if (uid == r.serviceInfo.applicationInfo.uid
|| packageName.equals(r.serviceInfo.packageName)) {
if (r.isForeground) {
@@ -246,7 +246,7 @@
*/
final class ServiceMap extends Handler {
final int mUserId;
- final ArrayMap<ComponentName, ServiceRecord> mServicesByName = new ArrayMap<>();
+ final ArrayMap<ComponentName, ServiceRecord> mServicesByInstanceName = new ArrayMap<>();
final ArrayMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent = new ArrayMap<>();
final ArrayList<ServiceRecord> mDelayedStartList = new ArrayList<>();
@@ -368,7 +368,7 @@
// TODO: Deal with global services
if (DEBUG_MU)
Slog.v(TAG_MU, "getServiceByNameLocked(" + name + "), callingUser = " + callingUser);
- return getServiceMapLocked(callingUser).mServicesByName.get(name);
+ return getServiceMapLocked(callingUser).mServicesByInstanceName.get(name);
}
boolean hasBackgroundServicesLocked(int callingUser) {
@@ -386,7 +386,7 @@
}
ArrayMap<ComponentName, ServiceRecord> getServicesLocked(int callingUser) {
- return getServiceMapLocked(callingUser).mServicesByName;
+ return getServiceMapLocked(callingUser).mServicesByInstanceName;
}
private boolean appRestrictedAnyInBackground(final int uid, final String packageName) {
@@ -416,7 +416,7 @@
}
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType, callingPackage,
+ retrieveServiceLocked(service, null, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
if (res == null) {
return null;
@@ -444,7 +444,7 @@
boolean forcedStandby = false;
if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
if (DEBUG_FOREGROUND_SERVICE) {
- Slog.d(TAG, "Forcing bg-only service start only for " + r.shortName
+ Slog.d(TAG, "Forcing bg-only service start only for " + r.shortInstanceName
+ " : bgLaunch=" + bgLaunch + " callerFg=" + callerFg);
}
forcedStandby = true;
@@ -464,7 +464,7 @@
// Not allowed, fall back to normal start service, failing siliently
// if background check restricts that.
Slog.w(TAG, "startForegroundService not allowed due to app op: service "
- + service + " to " + r.name.flattenToShortString()
+ + service + " to " + r.shortInstanceName
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage);
fgRequired = false;
@@ -484,7 +484,7 @@
r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
Slog.w(TAG, "Background start not allowed: service "
- + service + " to " + r.name.flattenToShortString()
+ + service + " to " + r.shortInstanceName
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage + " startFg?=" + fgRequired);
if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) {
@@ -741,7 +741,7 @@
}
// If this service is active, make sure it is stopped.
- ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
+ ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null,
Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false);
if (r != null) {
if (r.record != null) {
@@ -765,8 +765,8 @@
ServiceMap services = mServiceMap.get(UserHandle.getUserId(uid));
ArrayList<ServiceRecord> stopping = null;
if (services != null) {
- for (int i=services.mServicesByName.size()-1; i>=0; i--) {
- ServiceRecord service = services.mServicesByName.valueAt(i);
+ for (int i = services.mServicesByInstanceName.size() - 1; i >= 0; i--) {
+ ServiceRecord service = services.mServicesByInstanceName.valueAt(i);
if (service.appInfo.uid == uid && service.startRequested) {
if (mAm.getAppStartModeLocked(service.appInfo.uid, service.packageName,
service.appInfo.targetSdkVersion, -1, false, false, false)
@@ -774,7 +774,7 @@
if (stopping == null) {
stopping = new ArrayList<>();
}
- String compName = service.name.flattenToShortString();
+ String compName = service.shortInstanceName;
EventLogTags.writeAmStopIdleService(service.appInfo.uid, compName);
StringBuilder sb = new StringBuilder(64);
sb.append("Stopping service due to app idle: ");
@@ -801,7 +801,7 @@
}
IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
- ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, callingPackage,
+ ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(),
UserHandle.getCallingUserId(), false, false, false, false);
@@ -1228,7 +1228,7 @@
case AppOpsManager.MODE_IGNORED:
// Whoops, silently ignore this.
Slog.w(TAG, "Service.startForeground() not allowed due to app op: service "
- + r.shortName);
+ + r.shortInstanceName);
ignoreForeground = true;
break;
default:
@@ -1239,7 +1239,7 @@
appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
Slog.w(TAG,
"Service.startForeground() not allowed due to bg restriction: service "
- + r.shortName);
+ + r.shortInstanceName);
// Back off of any foreground expectations around this service, since we've
// just turned down its fg request.
updateServiceForegroundLocked(r.app, false);
@@ -1293,7 +1293,7 @@
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
true);
StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
- r.appInfo.uid, r.shortName,
+ r.appInfo.uid, r.shortInstanceName,
StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
}
@@ -1343,7 +1343,7 @@
AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
- r.appInfo.uid, r.shortName,
+ r.appInfo.uid, r.shortInstanceName,
StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
if (r.app != null) {
@@ -1373,8 +1373,8 @@
// due the other service.
ServiceMap sm = getServiceMapLocked(r.userId);
if (sm != null) {
- for (int i = sm.mServicesByName.size()-1; i >= 0; i--) {
- ServiceRecord other = sm.mServicesByName.valueAt(i);
+ for (int i = sm.mServicesByInstanceName.size() - 1; i >= 0; i--) {
+ ServiceRecord other = sm.mServicesByInstanceName.valueAt(i);
if (other != r && other.foregroundId == r.foregroundId
&& other.packageName.equals(r.packageName)) {
// Found one! Abort the cancel.
@@ -1466,7 +1466,8 @@
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
- String callingPackage, final int userId) throws TransactionTooLargeException {
+ String instanceName, String callingPackage, final int userId)
+ throws TransactionTooLargeException {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
@@ -1530,8 +1531,9 @@
final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
- Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
+ retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
+ Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
+ callerFg, isBindExternal, allowInstant);
if (res == null) {
return 0;
}
@@ -1637,7 +1639,7 @@
mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
callerApp.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
- s.name, s.processName);
+ s.instanceName, s.processName);
// Once the apps have become associated, if one of them is caller is ephemeral
// the target app should now be able to see the calling app
mAm.grantEphemeralAccessLocked(callerApp.userId, service,
@@ -1709,7 +1711,7 @@
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
- Slog.w(TAG, "Failure sending service " + s.shortName
+ Slog.w(TAG, "Failure sending service " + s.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
@@ -1763,9 +1765,9 @@
try {
c.conn.connected(r.name, service, false);
} catch (Exception e) {
- Slog.w(TAG, "Failure sending service " + r.name +
- " to connection " + c.conn.asBinder() +
- " (in " + c.binding.client.processName + ")", e);
+ Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+ + " to connection " + c.conn.asBinder()
+ + " (in " + c.binding.client.processName + ")", e);
}
}
}
@@ -1898,7 +1900,8 @@
}
private ServiceLookupResult retrieveServiceLocked(Intent service,
- String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
+ String instanceName, String resolvedType, String callingPackage,
+ int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
boolean allowInstant) {
ServiceRecord r = null;
@@ -1909,12 +1912,23 @@
ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE, "service", null);
ServiceMap smap = getServiceMapLocked(userId);
- final ComponentName comp = service.getComponent();
+ final ComponentName comp;
+ if (instanceName == null) {
+ comp = service.getComponent();
+ } else {
+ final ComponentName realComp = service.getComponent();
+ if (realComp == null) {
+ throw new IllegalArgumentException("Can't use custom instance name '" + instanceName
+ + "' without expicit component in Intent");
+ }
+ comp = new ComponentName(realComp.getPackageName(),
+ realComp.getClassName() + ":" + instanceName);
+ }
if (comp != null) {
- r = smap.mServicesByName.get(comp);
+ r = smap.mServicesByInstanceName.get(comp);
if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by component: " + r);
}
- if (r == null && !isBindExternal) {
+ if (r == null && !isBindExternal && instanceName == null) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
r = smap.mServicesByIntent.get(filter);
if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r);
@@ -1936,24 +1950,29 @@
// TODO: come back and remove this assumption to triage all services
ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
resolvedType, flags, userId, callingUid);
- ServiceInfo sInfo =
- rInfo != null ? rInfo.serviceInfo : null;
+ ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
": not found");
return null;
}
- ComponentName name = new ComponentName(
+ if (instanceName != null
+ && (sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
+ throw new IllegalArgumentException("Can't use instance name '" + instanceName
+ + "' with non-isolated service '" + sInfo.name + "'");
+ }
+ ComponentName className = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
+ ComponentName name = comp != null ? comp : className;
if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) {
if (isBindExternal) {
if (!sInfo.exported) {
- throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
- " is not exported");
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+ + className + " is not exported");
}
if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
- throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
- " is not an isolatedProcess");
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+ + className + " is not an isolatedProcess");
}
// Run the service under the calling package's application.
ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
@@ -1967,6 +1986,9 @@
sInfo.applicationInfo.packageName = aInfo.packageName;
sInfo.applicationInfo.uid = aInfo.uid;
name = new ComponentName(aInfo.packageName, name.getClassName());
+ className = new ComponentName(aInfo.packageName,
+ instanceName == null ? className.getClassName()
+ : (className.getClassName() + ":" + instanceName));
service.setComponent(name);
} else {
throw new SecurityException("BIND_EXTERNAL_SERVICE required for " +
@@ -1986,7 +2008,7 @@
sInfo = new ServiceInfo(sInfo);
sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
}
- r = smap.mServicesByName.get(name);
+ r = smap.mServicesByInstanceName.get(name);
if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE,
"Retrieved via pm by intent: " + r);
if (r == null && createIfNeeded) {
@@ -1997,19 +2019,20 @@
final BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
ss = stats.getServiceStatsLocked(
- sInfo.applicationInfo.uid, sInfo.packageName,
- sInfo.name);
+ sInfo.applicationInfo.uid, name.getPackageName(),
+ name.getClassName());
}
- r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
+ r = new ServiceRecord(mAm, ss, className, name, filter, sInfo, callingFromFg,
+ res);
res.setService(r);
- smap.mServicesByName.put(name, r);
+ smap.mServicesByInstanceName.put(name, r);
smap.mServicesByIntent.put(filter, r);
// Make sure this component isn't in the pending list.
for (int i=mPendingServices.size()-1; i>=0; i--) {
final ServiceRecord pr = mPendingServices.get(i);
if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
- && pr.name.equals(name)) {
+ && pr.instanceName.equals(name)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Remove pending: " + pr);
mPendingServices.remove(i);
}
@@ -2024,14 +2047,14 @@
if (mAm.checkComponentPermission(r.permission,
callingPid, callingUid, r.appInfo.uid, r.exported) != PERMISSION_GRANTED) {
if (!r.exported) {
- Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ Slog.w(TAG, "Permission Denial: Accessing service " + r.shortInstanceName
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " that is not exported from uid " + r.appInfo.uid);
return new ServiceLookupResult(null, "not exported from uid "
+ r.appInfo.uid);
}
- Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ Slog.w(TAG, "Permission Denial: Accessing service " + r.shortInstanceName
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " requires " + r.permission);
@@ -2040,7 +2063,7 @@
final int opCode = AppOpsManager.permissionToOpCode(r.permission);
if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation(
opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
- Slog.w(TAG, "Appop Denial: Accessing service " + r.name
+ Slog.w(TAG, "Appop Denial: Accessing service " + r.shortInstanceName
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " requires appop " + AppOpsManager.opToName(opCode));
@@ -2061,7 +2084,7 @@
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
+ why + " of " + r + " in app " + r.app);
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "
- + why + " of " + r.shortName);
+ + why + " of " + r.shortInstanceName);
// For b/34123235: Services within the system server won't start until SystemServer
// does Looper.loop(), so we shouldn't try to start/bind to them too early in the boot
@@ -2146,14 +2169,14 @@
boolean canceled = false;
if (mAm.mAtmInternal.isShuttingDown()) {
- Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortName
+ Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortInstanceName
+ " - system is shutting down");
return false;
}
ServiceMap smap = getServiceMapLocked(r.userId);
- if (smap.mServicesByName.get(r.name) != r) {
- ServiceRecord cur = smap.mServicesByName.get(r.name);
+ if (smap.mServicesByInstanceName.get(r.instanceName) != r) {
+ ServiceRecord cur = smap.mServicesByInstanceName.get(r.instanceName);
Slog.wtf(TAG, "Attempting to schedule restart of " + r
+ " when found in map: " + cur);
return false;
@@ -2184,7 +2207,7 @@
if (resetTime < dur) resetTime = dur;
} else {
Slog.w(TAG, "Canceling start item " + si.intent + " in service "
- + r.name);
+ + r.shortInstanceName);
canceled = true;
}
}
@@ -2256,9 +2279,9 @@
mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Slog.w(TAG, "Scheduling restart of crashed service "
- + r.shortName + " in " + r.restartDelay + "ms");
+ + r.shortInstanceName + " in " + r.restartDelay + "ms");
EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
- r.userId, r.shortName, r.restartDelay);
+ r.userId, r.shortInstanceName, r.restartDelay);
return canceled;
}
@@ -2393,7 +2416,7 @@
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
- Slog.w(TAG, "Exception when starting service " + r.shortName, e);
+ Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
// If a dead object exception was thrown -- fall through to
@@ -2417,7 +2440,7 @@
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
- hostingType, r.name, false, isolated, false)) == null) {
+ hostingType, r.instanceName, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
@@ -2488,8 +2511,9 @@
try {
if (LOG_SERVICE_START_STOP) {
String nameTerm;
- int lastPeriod = r.shortName.lastIndexOf('.');
- nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
+ int lastPeriod = r.shortInstanceName.lastIndexOf('.');
+ nameTerm = lastPeriod >= 0 ? r.shortInstanceName.substring(lastPeriod)
+ : r.shortInstanceName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
}
@@ -2705,9 +2729,9 @@
try {
cr.conn.connected(r.name, null, true);
} catch (Exception e) {
- Slog.w(TAG, "Failure disconnecting service " + r.name +
- " to connection " + c.get(i).conn.asBinder() +
- " (in " + c.get(i).binding.client.processName + ")", e);
+ Slog.w(TAG, "Failure disconnecting service " + r.shortInstanceName
+ + " to connection " + c.get(i).conn.asBinder()
+ + " (in " + c.get(i).binding.client.processName + ")", e);
}
}
}
@@ -2728,7 +2752,7 @@
ibr.intent.getIntent());
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service "
- + r.shortName, e);
+ + r.shortInstanceName, e);
serviceProcessGoneLocked(r);
}
}
@@ -2773,14 +2797,14 @@
}
final ServiceMap smap = getServiceMapLocked(r.userId);
- ServiceRecord found = smap.mServicesByName.remove(r.name);
+ ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName);
// Note when this method is called by bringUpServiceLocked(), the service is not found
- // in mServicesByName and found will be null.
+ // in mServicesByInstanceName and found will be null.
if (found != null && found != r) {
// This is not actually the service we think is running... this should not happen,
// but if it does, fail hard.
- smap.mServicesByName.put(r.name, found);
+ smap.mServicesByInstanceName.put(r.instanceName, found);
throw new IllegalStateException("Bringing down " + r + " but actually running "
+ found);
}
@@ -2807,8 +2831,8 @@
mAm.mAppOpsService.finishOperation(
AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
- StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
- StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+ StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid,
+ r.shortInstanceName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
}
@@ -2838,7 +2862,7 @@
r.app.thread.scheduleStopService(r);
} catch (Exception e) {
Slog.w(TAG, "Exception when destroying service "
- + r.shortName, e);
+ + r.shortInstanceName, e);
serviceProcessGoneLocked(r);
}
} else {
@@ -2915,7 +2939,7 @@
}
mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid,
- s.appInfo.longVersionCode, s.name, s.processName);
+ s.appInfo.longVersionCode, s.instanceName, s.processName);
if (b.connections.size() == 0) {
b.intent.apps.remove(b.client);
@@ -2942,7 +2966,7 @@
b.intent.doRebind = false;
s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
} catch (Exception e) {
- Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
+ Slog.w(TAG, "Exception when unbinding service " + s.shortInstanceName, e);
serviceProcessGoneLocked(s);
}
}
@@ -3061,17 +3085,17 @@
+ ": nesting=" + r.executeNesting
+ ", inDestroying=" + inDestroying + ", app=" + r.app);
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
- "<<< DONE EXECUTING " + r.shortName);
+ "<<< DONE EXECUTING " + r.shortInstanceName);
r.executeNesting--;
if (r.executeNesting <= 0) {
if (r.app != null) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
- "Nesting at 0 of " + r.shortName);
+ "Nesting at 0 of " + r.shortInstanceName);
r.app.execServicesFg = false;
r.app.executingServices.remove(r);
if (r.app.executingServices.size() == 0) {
if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
- "No more executingServices of " + r.shortName);
+ "No more executingServices of " + r.shortInstanceName);
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
} else if (r.executeFg) {
// Need to re-evaluate whether the app still needs to be in the foreground.
@@ -3141,7 +3165,7 @@
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
- + sr.shortName, e);
+ + sr.shortInstanceName, e);
throw e;
}
}
@@ -3227,7 +3251,8 @@
if (userId == UserHandle.USER_ALL) {
for (int i = mServiceMap.size() - 1; i >= 0; i--) {
didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
- evenPersistent, doit, killProcess, mServiceMap.valueAt(i).mServicesByName);
+ evenPersistent, doit, killProcess,
+ mServiceMap.valueAt(i).mServicesByInstanceName);
if (!doit && didSomething) {
return true;
}
@@ -3238,7 +3263,7 @@
} else {
ServiceMap smap = mServiceMap.get(userId);
if (smap != null) {
- ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
+ ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByInstanceName;
didSomething = collectPackageServicesLocked(packageName, filterByClasses,
evenPersistent, doit, killProcess, items);
}
@@ -3288,7 +3313,7 @@
ServiceRecord sr = services.get(i);
if (sr.startRequested) {
if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
- Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
+ Slog.i(TAG, "Stopping service " + sr.shortInstanceName + ": remove task");
stopServiceLocked(sr);
} else {
sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
@@ -3326,7 +3351,7 @@
} catch (Exception e) {
// todo: this should be asynchronous!
Slog.w(TAG, "Exception thrown disconnected servce "
- + r.shortName
+ + r.shortInstanceName
+ " from app " + app.processName, e);
}
}
@@ -3400,7 +3425,7 @@
if (false && proc != null && !proc.isPersistent() && proc.thread != null
&& proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID
&& proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
- proc.kill("bound to service " + sr.name.flattenToShortString()
+ proc.kill("bound to service " + sr.shortInstanceName
+ " in dying proc " + (app != null ? app.processName : "??"), true);
}
}
@@ -3421,7 +3446,7 @@
// Sanity check: if the service listed for the app is not one
// we actually are maintaining, just let it drop.
- final ServiceRecord curRec = smap.mServicesByName.get(sr.name);
+ final ServiceRecord curRec = smap.mServicesByInstanceName.get(sr.instanceName);
if (curRec != sr) {
if (curRec != null) {
Slog.wtf(TAG, "Service " + sr + " in process " + app
@@ -3438,7 +3463,7 @@
Slog.w(TAG, "Service crashed " + sr.crashCount
+ " times, stopping: " + sr);
EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
- sr.userId, sr.crashCount, sr.shortName, app.pid);
+ sr.userId, sr.crashCount, sr.shortInstanceName, app.pid);
bringDownServiceLocked(sr);
} else if (!allowRestart
|| !mAm.mUserController.isUserRunning(sr.userId, 0)) {
@@ -3644,7 +3669,7 @@
mLastAnrDump = sw.toString();
mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);
- anrMessage = "executing service " + timeout.shortName;
+ anrMessage = "executing service " + timeout.shortInstanceName;
} else {
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
@@ -3690,7 +3715,8 @@
final int userId = UserHandle.getUserId(applicationInfo.uid);
ServiceMap serviceMap = mServiceMap.get(userId);
if (serviceMap != null) {
- ArrayMap<ComponentName, ServiceRecord> servicesByName = serviceMap.mServicesByName;
+ ArrayMap<ComponentName, ServiceRecord> servicesByName
+ = serviceMap.mServicesByInstanceName;
for (int j = servicesByName.size() - 1; j >= 0; j--) {
ServiceRecord serviceRecord = servicesByName.valueAt(j);
if (applicationInfo.packageName.equals(serviceRecord.appInfo.packageName)) {
@@ -3761,9 +3787,9 @@
final int[] users = mAm.mUserController.getUsers();
for (int user : users) {
ServiceMap smap = getServiceMapLocked(user);
- if (smap.mServicesByName.size() > 0) {
- for (int si=0; si<smap.mServicesByName.size(); si++) {
- ServiceRecord r = smap.mServicesByName.valueAt(si);
+ if (smap.mServicesByInstanceName.size() > 0) {
+ for (int si=0; si<smap.mServicesByInstanceName.size(); si++) {
+ ServiceRecord r = smap.mServicesByInstanceName.valueAt(si);
if (!matcher.match(r, r.name)) {
continue;
}
@@ -4164,7 +4190,7 @@
}
long token = proto.start(ActiveServicesProto.SERVICES_BY_USERS);
proto.write(ActiveServicesProto.ServicesByUser.USER_ID, user);
- ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName;
+ ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByInstanceName;
for (int i=0; i<alls.size(); i++) {
alls.valueAt(i).writeToProto(proto,
ActiveServicesProto.ServicesByUser.SERVICE_RECORDS);
@@ -4197,7 +4223,7 @@
if (smap == null) {
continue;
}
- ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName;
+ ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByInstanceName;
for (int i=0; i<alls.size(); i++) {
ServiceRecord r1 = alls.valueAt(i);
@@ -4235,7 +4261,7 @@
String innerPrefix = prefix + " ";
synchronized (mAm) {
pw.print(prefix); pw.print("SERVICE ");
- pw.print(r.shortName); pw.print(" ");
+ pw.print(r.shortInstanceName); pw.print(" ");
pw.print(Integer.toHexString(System.identityHashCode(r)));
pw.print(" pid=");
if (r.app != null) pw.println(r.app.pid);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0bae1f3..9a6c438 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13183,8 +13183,15 @@
}
public int bindService(IApplicationThread caller, IBinder token, Intent service,
- String resolvedType, IServiceConnection connection, int flags, String callingPackage,
- int userId) throws TransactionTooLargeException {
+ String resolvedType, IServiceConnection connection, int flags,
+ String callingPackage, int userId) throws TransactionTooLargeException {
+ return bindIsolatedService(caller, token, service, resolvedType, connection, flags,
+ null, callingPackage, userId);
+ }
+
+ public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
+ String resolvedType, IServiceConnection connection, int flags, String instanceName,
+ String callingPackage, int userId) throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
// Refuse possible leaked file descriptors
@@ -13198,7 +13205,7 @@
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
- resolvedType, connection, flags, callingPackage, userId);
+ resolvedType, connection, flags, instanceName, callingPackage, userId);
}
}
@@ -15831,7 +15838,7 @@
mayBeTop = true;
mayBeTopType = "service";
mayBeTopSource = cr.binding.client;
- mayBeTopTarget = s.name;
+ mayBeTopTarget = s.instanceName;
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
} else {
// Special handling for above-top states (persistent
@@ -15885,7 +15892,7 @@
.REASON_SERVICE_IN_USE;
app.adjSource = cr.binding.client;
app.adjSourceProcState = clientProcState;
- app.adjTarget = s.name;
+ app.adjTarget = s.instanceName;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
+ ": " + app + ", due to " + cr.binding.client
@@ -15915,7 +15922,7 @@
.REASON_SERVICE_IN_USE;
app.adjSource = a;
app.adjSourceProcState = procState;
- app.adjTarget = s.name;
+ app.adjTarget = s.instanceName;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise to service w/activity: " + app);
diff --git a/services/core/java/com/android/server/am/AppBindRecord.java b/services/core/java/com/android/server/am/AppBindRecord.java
index 4eaebd0..9870420 100644
--- a/services/core/java/com/android/server/am/AppBindRecord.java
+++ b/services/core/java/com/android/server/am/AppBindRecord.java
@@ -59,12 +59,12 @@
public String toString() {
return "AppBindRecord{"
+ Integer.toHexString(System.identityHashCode(this))
- + " " + service.shortName + ":" + client.processName + "}";
+ + " " + service.shortInstanceName + ":" + client.processName + "}";
}
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
- proto.write(AppBindRecordProto.SERVICE_NAME, service.shortName);
+ proto.write(AppBindRecordProto.SERVICE_NAME, service.shortInstanceName);
proto.write(AppBindRecordProto.CLIENT_PROC_NAME, client.processName);
final int N = connections.size();
for (int i=0; i<N; i++) {
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index 37d07bb..bfa3f66 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -115,16 +115,16 @@
&& (binding.service.appInfo.uid != clientUid
|| !binding.service.processName.equals(clientProcessName))) {
ProcessStats.ProcessStateHolder holder = binding.service.app.pkgList.get(
- binding.service.name.getPackageName());
+ binding.service.instanceName.getPackageName());
if (holder == null) {
Slog.wtf(TAG_AM, "No package in referenced service "
- + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+ + binding.service.shortInstanceName + ": proc=" + binding.service.app);
} else if (holder.pkg == null) {
Slog.wtf(TAG_AM, "Inactive holder in referenced service "
- + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+ + binding.service.shortInstanceName + ": proc=" + binding.service.app);
} else {
association = holder.pkg.getAssociationStateLocked(holder.state,
- binding.service.name.getClassName()).startSource(clientUid,
+ binding.service.instanceName.getClassName()).startSource(clientUid,
clientProcessName);
}
@@ -202,7 +202,7 @@
if (serviceDead) {
sb.append("DEAD ");
}
- sb.append(binding.service.shortName);
+ sb.append(binding.service.shortInstanceName);
sb.append(":@");
sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
sb.append('}');
@@ -223,7 +223,7 @@
proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEAD);
}
if (binding.service != null) {
- proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortName);
+ proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortInstanceName);
}
proto.end(token);
}
diff --git a/services/core/java/com/android/server/am/IntentBindRecord.java b/services/core/java/com/android/server/am/IntentBindRecord.java
index 839b6e1..90aef3e 100644
--- a/services/core/java/com/android/server/am/IntentBindRecord.java
+++ b/services/core/java/com/android/server/am/IntentBindRecord.java
@@ -99,7 +99,7 @@
if ((collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
sb.append("CR ");
}
- sb.append(service.shortName);
+ sb.append(service.shortInstanceName);
sb.append(':');
if (intent != null) {
intent.getIntent().toShortString(sb, false, false, false, false);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index d8f94c9..09f8c3e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -70,7 +70,8 @@
final ActivityManagerService ams;
final BatteryStatsImpl.Uid.Pkg.Serv stats;
final ComponentName name; // service component.
- final String shortName; // name.flattenToShortString().
+ final ComponentName instanceName; // service component's per-instance name.
+ final String shortInstanceName; // instanceName.flattenToShortString().
final Intent.FilterComparison intent;
// original intent used to find service.
final ServiceInfo serviceInfo;
@@ -190,7 +191,7 @@
StringBuilder sb = new StringBuilder(128);
sb.append("ServiceRecord{")
.append(Integer.toHexString(System.identityHashCode(sr)))
- .append(' ').append(sr.shortName)
+ .append(' ').append(sr.shortInstanceName)
.append(" StartItem ")
.append(Integer.toHexString(System.identityHashCode(this)))
.append(" id=").append(id).append('}');
@@ -235,7 +236,7 @@
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
- proto.write(ServiceRecordProto.SHORT_NAME, this.shortName);
+ proto.write(ServiceRecordProto.SHORT_NAME, this.shortInstanceName);
proto.write(ServiceRecordProto.IS_RUNNING, app != null);
if (app != null) {
proto.write(ServiceRecordProto.PID, app.pid);
@@ -448,12 +449,14 @@
ServiceRecord(ActivityManagerService ams,
BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
+ ComponentName instanceName,
Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg,
Runnable restarter) {
this.ams = ams;
this.stats = servStats;
this.name = name;
- shortName = name.flattenToShortString();
+ this.instanceName = instanceName;
+ shortInstanceName = instanceName.flattenToShortString();
this.intent = intent;
serviceInfo = sInfo;
appInfo = sInfo.applicationInfo;
@@ -618,7 +621,7 @@
// those dirty apps we will create a notification clearly
// blaming the app.
Slog.v(TAG, "Attempted to start a foreground service ("
- + name
+ + shortInstanceName
+ ") with a broken notification (no icon: "
+ localForegroundNoti
+ ")");
@@ -701,7 +704,7 @@
Slog.w(TAG, "Error showing notification for service", e);
// If it gave us a garbage notification, it doesn't
// get to be foreground.
- ams.setServiceForeground(name, ServiceRecord.this,
+ ams.setServiceForeground(instanceName, ServiceRecord.this,
0, null, 0);
ams.crashApplication(appUid, appPid, localPackageName, -1,
"Bad notification for startForeground: " + e);
@@ -773,7 +776,7 @@
sb.append("ServiceRecord{")
.append(Integer.toHexString(System.identityHashCode(this)))
.append(" u").append(userId)
- .append(' ').append(shortName).append('}');
+ .append(' ').append(shortInstanceName).append('}');
return stringName = sb.toString();
}
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index fc9b4c6..f91d74a 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -31,6 +31,7 @@
public class MockContext extends android.content.Context {
ctor public MockContext();
+ method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public int checkCallingOrSelfPermission(java.lang.String);
method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index fa5b896..66be6d9 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -576,6 +576,13 @@
throw new UnsupportedOperationException();
}
+ @Override
+ public boolean bindIsolatedService(Intent service,
+ ServiceConnection conn, int flags,
+ String instanceName) {
+ throw new UnsupportedOperationException();
+ }
+
/** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index 6e4c41e..73db451 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -75,6 +75,12 @@
}
@Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+ String instanceName) {
+ return false;
+ }
+
+ @Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return null;
}