summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2018-11-12 15:01:40 -0800
committerDianne Hackborn <hackbod@google.com>2018-11-13 16:03:02 -0800
commit27b4d94a07ac00367ad12b667c983a89153537d8 (patch)
tree6e7786697585c7cbefe705c79ddc83f7eeb85109
parent59805434784886d79c6bdb8253b0aae5351be8d3 (diff)
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
-rwxr-xr-xapi/current.txt2
-rw-r--r--core/java/android/app/ContextImpl.java31
-rw-r--r--core/java/android/app/IActivityManager.aidl4
-rw-r--r--core/java/android/content/Context.java34
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java206
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java19
-rw-r--r--services/core/java/com/android/server/am/AppBindRecord.java4
-rw-r--r--services/core/java/com/android/server/am/ConnectionRecord.java12
-rw-r--r--services/core/java/com/android/server/am/IntentBindRecord.java2
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java17
-rw-r--r--test-mock/api/current.txt1
-rw-r--r--test-mock/src/android/test/mock/MockContext.java7
-rw-r--r--test-runner/src/android/test/IsolatedContext.java6
14 files changed, 230 insertions, 121 deletions
diff --git a/api/current.txt b/api/current.txt
index 28863b87d1de..56275c5ce9fc 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -9475,6 +9475,7 @@ package android.content {
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 @@ package android.content {
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 dc707e892d9a..9837deb6143c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -140,6 +140,13 @@ class ReceiverRestrictedContext extends ContextWrapper {
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 @@ class ContextImpl extends Context {
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 @@ class ContextImpl extends Context {
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 @@ class ContextImpl extends Context {
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 @@ class ContextImpl extends Context {
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 e2312a539ae4..f27c6677ed22 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -133,9 +133,13 @@ interface IActivityManager {
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 9f8ae0bb6ab3..03eba7efea91 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2906,8 +2906,9 @@ public abstract class Context {
* @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 @@ public abstract class Context {
* @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 @@ public abstract class Context {
}
/**
- * 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 bfad2b42bc94..88696b0e1e4d 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -705,6 +705,12 @@ public class ContextWrapper extends Context {
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 a33ac700ba95..b5217ad7af19 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 final class ActiveServices {
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 @@ public final class ActiveServices {
*/
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 @@ public final class ActiveServices {
// 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 @@ public final class ActiveServices {
}
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 @@ public final class ActiveServices {
}
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
// 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
}
// 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
}
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
// 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
}
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
// 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
} 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 @@ public final class ActiveServices {
// 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
}
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
}
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
+ ": 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 @@ public final class ActiveServices {
}
} 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
} 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
} 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
// 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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
}
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 @@ public final class ActiveServices {
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 @@ public final class ActiveServices {
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 0bae1f30cbdb..9a6c438545fd 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 class ActivityManagerService extends IActivityManager.Stub
}
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 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
- resolvedType, connection, flags, callingPackage, userId);
+ resolvedType, connection, flags, instanceName, callingPackage, userId);
}
}
@@ -15831,7 +15838,7 @@ public class ActivityManagerService extends IActivityManager.Stub
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 @@ public class ActivityManagerService extends IActivityManager.Stub
.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 @@ public class ActivityManagerService extends IActivityManager.Stub
.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 4eaebd04a8ad..9870420cae13 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 @@ final class AppBindRecord {
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 37d07bbda760..bfa3f66ce726 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 @@ final class ConnectionRecord {
&& (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 @@ final class ConnectionRecord {
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 @@ final class ConnectionRecord {
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 839b6e1bd634..90aef3efea46 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 @@ final class IntentBindRecord {
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 d8f94c933ac8..09f8c3eee3b6 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 class ServiceRecord extends Binder implements ComponentName.WithComponentN
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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
// 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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
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 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
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 fc9b4c6831e8..f91d74a30693 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -31,6 +31,7 @@ package android.test.mock {
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 fa5b896ea126..66be6d9d9840 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -576,6 +576,13 @@ public class MockContext extends Context {
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 6e4c41eef81c..73db4517e130 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -75,6 +75,12 @@ public class IsolatedContext extends ContextWrapper {
}
@Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+ String instanceName) {
+ return false;
+ }
+
+ @Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return null;
}