ActivityManagerService的stopServiceToken用于停止一个Service,代码如下:
//frameworks/base/service/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback, ActivityManagerGlobalLock {
final ActiveServices mServices;
public boolean stopServiceToken(ComponentName className, IBinder token,
int startId) {
synchronized(this) {
return mServices.stopServiceTokenLocked(className, token, startId);
}
}
}
ActiveServices stopServiceTokenLocked
调用ActiveServices的stopServiceTokenLocked方法:
//frameworks/base/service/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
final ActivityManagerService mAm;
boolean stopServiceTokenLocked(ComponentName className, IBinder token,
int startId) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopServiceToken: " + className
+ " " + token + " startId=" + startId);
ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
if (r != null) {
if (startId >= 0) {
// Asked to only stop if done with all work. Note that
// to avoid leaks, we will take this as dropping all
// start items up to and including this one.
ServiceRecord.StartItem si = r.findDeliveredStart(startId, false, false);
if (si != null) {
while (r.deliveredStarts.size() > 0) {
ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
cur.removeUriPermissionsLocked();
if (cur == si) {
break;
}
}
}
if (r.getLastStartId() != startId) {
return false;
}
if (r.deliveredStarts.size() > 0) {
Slog.w(TAG, "stopServiceToken startId " + startId
+ " is last, but have " + r.deliveredStarts.size()
+ " remaining args");
}
}
final int uid = r.appInfo.uid;
final String packageName = r.name.getPackageName();
final String serviceName = r.name.getClassName();
FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, uid, packageName,
serviceName, FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__STOP);
mAm.mBatteryStatsService.noteServiceStopRunning(uid, packageName, serviceName);
r.startRequested = false;
if (r.tracker != null) {
synchronized (mAm.mProcessStats.mLock) {
r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
}
r.callStart = false;
final long origId = Binder.clearCallingIdentity();
bringDownServiceIfNeededLocked(r, false, false, false);
Binder.restoreCallingIdentity(origId);
return true;
}
return false;
}
}
调用bringDownServiceIfNeededLocked方法:
//frameworks/base/service/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
boolean hasConn, boolean enqueueOomAdj) {
//Slog.i(TAG, "Bring down service:");
//r.dump(" ");
if (isServiceNeededLocked(r, knowConn, hasConn)) {
return;
}
// Are we in the process of launching?
if (mPendingServices.contains(r)) {
return;
}
bringDownServiceLocked(r, enqueueOomAdj);
}
}
调用bringDownServiceLocked方法:
//frameworks/base/service/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
private void bringDownServiceLocked(ServiceRecord r, boolean enqueueOomAdj) {
//Slog.i(TAG, "Bring down service:");
//r.dump(" ");
// Report to all of the connections that the service is no longer
// available.
ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> c = connections.valueAt(conni);
for (int i=0; i<c.size(); i++) {
ConnectionRecord cr = c.get(i);
// There is still a connection to the service that is
// being brought down. Mark it as dead.
cr.serviceDead = true;
cr.stopAssociation();
final ComponentName clientSideComponentName =
cr.aliasComponent != null ? cr.aliasComponent : r.name;
try {
cr.conn.connected(r.name, null, true);
} catch (Exception e) {
Slog.w(TAG, "Failure disconnecting service " + r.shortInstanceName
+ " to connection " + c.get(i).conn.asBinder()
+ " (in " + c.get(i).binding.client.processName + ")", e);
}
}
}
boolean oomAdjusted = false;
// Tell the service that it has been unbound.
if (r.app != null && r.app.getThread() != null) {
for (int i = r.bindings.size() - 1; i >= 0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr
+ ": hasBound=" + ibr.hasBound);
if (ibr.hasBound) {
try {
oomAdjusted |= bumpServiceExecutingLocked(r, false, "bring down unbind",
OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
ibr.hasBound = false;
ibr.requested = false;
r.app.getThread().scheduleUnbindService(r,
ibr.intent.getIntent());
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service "
+ r.shortInstanceName, e);
serviceProcessGoneLocked(r, enqueueOomAdj);
break;
}
}
}
}
// Check to see if the service had been started as foreground, but being
// brought down before actually showing a notification. That is not allowed.
if (r.fgRequired) {
Slog.w(TAG_SERVICE, "Bringing down service while still waiting for start foreground: "
+ r);
r.fgRequired = false;
r.fgWaiting = false;
synchronized (mAm.mProcessStats.mLock) {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
}
mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
mAm.mHandler.removeMessages(
ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
if (r.app != null) {
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
SomeArgs args = SomeArgs.obtain();
args.arg1 = r.app;
args.arg2 = r.toString();
args.arg3 = r.getComponentName();
msg.obj = args;
mAm.mHandler.sendMessage(msg);
}
}
if (DEBUG_SERVICE) {
RuntimeException here = new RuntimeException();
here.fillInStackTrace();
Slog.v(TAG_SERVICE, "Bringing down " + r + " " + r.intent, here);
}
r.destroyTime = SystemClock.uptimeMillis();
if (LOG_SERVICE_START_STOP) {
EventLogTags.writeAmDestroyService(
r.userId, System.identityHashCode(r), (r.app != null) ? r.app.getPid() : -1);
}
final ServiceMap smap = getServiceMapLocked(r.userId);
ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName);
// Note when this method is called by bringUpServiceLocked(), the service is not found
// 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.mServicesByInstanceName.put(r.instanceName, found);
throw new IllegalStateException("Bringing down " + r + " but actually running "
+ found);
}
smap.mServicesByIntent.remove(r.intent);
r.totalRestartCount = 0;
unscheduleServiceRestartLocked(r, 0, true);
// Also make sure it is not on the pending list.
for (int i=mPendingServices.size()-1; i>=0; i--) {
if (mPendingServices.get(i) == r) {
mPendingServices.remove(i);
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r);
}
}
if (mPendingBringups.remove(r) != null) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending bringup: " + r);
}
cancelForegroundNotificationLocked(r);
final boolean exitingFg = r.isForeground;
if (exitingFg) {
decActiveForegroundAppLocked(smap, r);
synchronized (mAm.mProcessStats.mLock) {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
}
mAm.mAppOpsService.finishOperation(
AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
unregisterAppOpCallbackLocked(r);
r.mFgsExitTime = SystemClock.uptimeMillis();
logFGSStateChangeLocked(r,
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
r.mFgsExitTime > r.mFgsEnterTime
? (int) (r.mFgsExitTime - r.mFgsEnterTime) : 0,
FGS_STOP_REASON_STOP_SERVICE);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
}
r.isForeground = false;
r.mFgsNotificationWasDeferred = false;
dropFgsNotificationStateLocked(r);
r.foregroundId = 0;
r.foregroundNoti = null;
resetFgsRestrictionLocked(r);
// Signal FGS observers *after* changing the isForeground state, and
// only if this was an actual state change.
if (exitingFg) {
signalForegroundServiceObserversLocked(r);
}
// Clear start entries.
r.clearDeliveredStartsLocked();
r.pendingStarts.clear();
smap.mDelayedStartList.remove(r);
if (r.app != null) {
mAm.mBatteryStatsService.noteServiceStopLaunch(r.appInfo.uid, r.name.getPackageName(),
r.name.getClassName());
stopServiceAndUpdateAllowlistManagerLocked(r);
if (r.app.getThread() != null) {
// Bump the process to the top of LRU list
mAm.updateLruProcessLocked(r.app, false, null);
updateServiceForegroundLocked(r.app.mServices, false);
try {
oomAdjusted |= bumpServiceExecutingLocked(r, false, "destroy",
oomAdjusted ? null : OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
mDestroyingServices.add(r);
r.destroying = true;
r.app.getThread().scheduleStopService(r);
} catch (Exception e) {
Slog.w(TAG, "Exception when destroying service "
+ r.shortInstanceName, e);
serviceProcessGoneLocked(r, enqueueOomAdj);
}
} else {
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Removed service that has no process: " + r);
}
} else {
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Removed service that is not running: " + r);
}
if (!oomAdjusted) {
mAm.enqueueOomAdjTargetLocked(r.app);
if (!enqueueOomAdj) {
mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
}
}
if (r.bindings.size() > 0) {
r.bindings.clear();
}
if (r.restarter instanceof ServiceRestarter) {
((ServiceRestarter)r.restarter).setService(null);
}
synchronized (mAm.mProcessStats.mLock) {
final int memFactor = mAm.mProcessStats.getMemFactorLocked();
if (r.tracker != null) {
final long now = SystemClock.uptimeMillis();
r.tracker.setStarted(false, memFactor, now);
r.tracker.setBound(false, memFactor, now);
if (r.executeNesting == 0) {
r.tracker.clearCurrentOwner(r, false);
r.tracker = null;
}
}
}
smap.ensureNotStartingBackgroundLocked(r);
updateNumForegroundServicesLocked();
}
}
ApplicationThread scheduleStopService
r.app.getThread()返回IApplicationThread接口,调用IApplicationThread的scheduleStopService方法,IApplicationThread是一个接口由ActivityThread的内部类ApplicationThread实现:
//frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler
implements ActivityThreadInternal {
private class ApplicationThread extends IApplicationThread.Stub {
public final void scheduleStopService(IBinder token) {
sendMessage(H.STOP_SERVICE, token);
}
}
}
发送STOP_SERVICE消息,消息在H的handleMessage中处理:
//frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler implements ActivityThreadInternal {
class H extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case STOP_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
handleStopService((IBinder)msg.obj);
schedulePurgeIdler();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
}
}
ActivityThread handleStopService
调用ActivityThread的handleStopService方法: