Android Framework—Service
介绍
Service是一种可以在后台执行长时间运行操作而不提供界面的应用组件。服务可以由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可以通过绑定到服务与之进行交互,甚至是执行进程之间的通信。
正文
1.Service的介绍
<service android:name=".MyService"android:isolatedProcess="true"android:directBootAware="true"android:process=":subService"/>
import android.app.Service
import android.content.Intent
import android.os.IBinderclass PreloadService : Service() {override fun onBind(p0: Intent?): IBinder? {return null}
}
service的标签属性比较简单,具体可以参考官网。我在这里就举几个属性的例子:
isolatedProcess:服务与系统其余部分隔离的特殊进程下运行。
process:指定服务运行的进程名称。以:开头,系统会根据需要时创建新进程,并且服务会在该进程运行。
directBootAware:服务是否支持直接启动,也就是可以在用户解锁设备之前运行。
Service的生命周期

它的生命周期会和我们使用Service的不同 也有所不同。左边是startService 右边是bindService。我们汇编可以根据源码 再来看看执行的时机。
Service的运行模式
1.前台Service:执行一些用户能注意到的操作,前台服务必须显示通知。
2.后台Service:后台服务不会影响用户,在26以后,系统会对后台服务施加限制。
更多Android Framework 学习资料 请点击免费领取
2.Service的启动
1.startService
在源码中我们可以直接在Activity中调用startService,那就跟一下 看看它是如何开启Service的。 文件目录:/android/frameworks/base/core/java/android/content/ContextWrapper.java
public ComponentName startServiceAsUser(Intent service, UserHandle user) {return mBase.startServiceAsUser(service, user);
}
//mBase就是ContextImpl 参考Activity创建流程
Context mBase;public ComponentName startService(Intent service) {warnIfCallingFromSystemProcess();return startServiceCommon(service, false, mUser);
}//开启Service
private ComponentName startServiceCommon(Intent service, boolean requireForeground,UserHandle user) {try {//校验intentvalidateServiceIntent(service);//设置intent的属性,准备离开现有进程service.prepareToLeaveProcess(this);//调用AMS的startService 传入了 当前进程,service(目标servcie),true ComponentName cn = ActivityManager.getService().startService(mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground,getOpPackageName(), user.getIdentifier());return cn;} catch (RemoteException e) {throw e.rethrowFromSystemServer();}
}
看看AMS是如何开启Service
public ComponentName startService(IApplicationThread caller, Intent service,String resolvedType, boolean requireForeground, String callingPackage, int userId)throws TransactionTooLargeException {//判断是否是隔离进程调用enforceNotIsolatedCaller("startService");synchronized(this) {//获取pidfinal int callingPid = Binder.getCallingPid();//获取uidfinal int callingUid = Binder.getCallingUid();//获取origidfinal long origId = Binder.clearCallingIdentity();ComponentName res;try {//调用mService的startServiceLocked 这里的mService就是之前讲AMS启动流程时创建的ActiveServices 用来管理Service的res = mServices.startServiceLocked(caller, service,resolvedType, callingPid, callingUid,requireForeground, callingPackage, userId);} finally {Binder.restoreCallingIdentity(origId);}return res;}
}
文件目录:/android/frameworks/base/services/core/java/com/android/server/am/ActiveServices.javaComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)throws TransactionTooLargeException {return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,callingPackage, userId, false);
}ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,int callingPid, int callingUid, boolean fgRequired, String callingPackage,final int userId, boolean allowBackgroundActivityStarts)throws TransactionTooLargeException {final boolean callerFg;if (caller != null) {//不为null 获取到当前进程的ProcessRecordfinal ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;} else {callerFg = true;}//得到ServiceRecord对象:先从mServiceMap中查找 如果有就返回 没有的话就创建(通过pkms.resolveService 查找service创建ServiceRecord包装成ServiceLookupResult返回)ServiceLookupResult res =retrieveServiceLocked(service, null, resolvedType, callingPackage,callingPid, callingUid, userId, true, callerFg, false, false);//拿到ServiceRecord ServiceRecord继承自BinderServiceRecord r = res.record;final boolean bgLaunch = !mAm.isUidActiveLocked(r.appInfo.uid);boolean forcedStandby = false;if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {forcedStandby = true;}boolean forceSilentAbort = false;if (fgRequired) {//这里是false不走 前台走这里}if (forcedStandby || (!r.startRequested && !fgRequired)) {//判断是否运行启动服务:常驻内存、蓝牙、电源白名单允许直接启动服务 否则执行默认策略:如果大于AndroidO不允许启动后台服务final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);if (allowed != ActivityManager.APP_START_MODE_NORMAL) {//不允许启动服务的逻辑if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) {return null;}if (forcedStandby) {if (fgRequired) {//falsereturn null;}}UidRecord uidRec = mAm.mProcessList.getUidRecordLocked(r.appInfo.uid);return new ComponentName("?", "app is in background uid " + uidRec);}}if (r.appInfo.targetSdkVersion < Build.VERSION_CODES.O && fgRequired) {//不走这里fgRequired = false;}//记录时间戳r.lastActivity = SystemClock.uptimeMillis();//设置已经开启了r.startRequested = true;r.delayedStop = false;r.fgRequired = fgRequired;//添加了一个ServiceRecord.StartItem taskRemoved = false 如果是BindService 不会添加 因为他直接调用的是realStartServicer.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),service, neededGrants, callingUid));if (fgRequired) {//这里不走}final ServiceMap smap = getServiceMapLocked(r.userId);boolean addToStarting = false;if (allowBackgroundActivityStarts) {r.whitelistBgActivityStartsOnServiceStart();}//调用startServiceInnerLockedComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);return cmp;
}ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {ServiceState stracker = r.getTracker();if (stracker != null) {stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);}r.callStart = false;synchronized (r.stats.getBatteryStats()) {r.stats.startRunningLocked();}//调用bringUpServiceLocked 开启进程String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);if (error != null) {return new ComponentName("!!", error);}if (r.startRequested && addToStarting) {boolean first = smap.mStartingBackground.size() == 0;smap.mStartingBackground.add(r);r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT;if (DEBUG_DELAYED_SERVICE) {RuntimeException here = new RuntimeException("here");here.fillInStackTrace();} else if (DEBUG_DELAYED_STARTS) {}if (first) {smap.rescheduleDelayedStartsLocked();}} else if (callerFg || r.fgRequired) {smap.ensureNotStartingBackgroundLocked(r);}return r.name;
}private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,boolean whileRestarting, boolean permissionsReviewRequired)throws TransactionTooLargeException {if (r.app != null && r.app.thread != null) {//已经运行sendServiceArgsLocked(r, execInFg, false);return null;}if (!whileRestarting && mRestartingServices.contains(r)) {return null;}if (mRestartingServices.remove(r)) {clearRestartingIfNeededLocked(r);}if (r.delayed) {getServiceMapLocked(r.userId).mDelayedStartList.remove(r);r.delayed = false;}//是否需要进程隔离下 运行final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;//获取进程名final String procName = r.processName;//创建HostingRecordHostingRecord hostingRecord = new HostingRecord("service", r.instanceName);ProcessRecord app;if (!isolated) {//非隔离进程//获取到service的ProcessRecordapp = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);if (app != null && app.thread != null) {//进程已经存在 启动了try {app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);realStartServiceLocked(r, app, execInFg);return null;} catch (TransactionTooLargeException e) {throw e;} catch (RemoteException e) {}}} else {//隔离进程//第一次开启isolatedProc是nullapp = r.isolatedProc;if (WebViewZygote.isMultiprocessEnabled()&& r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {hostingRecord = HostingRecord.byWebviewZygote(r.instanceName);}if ((r.serviceInfo.flags & ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0) {hostingRecord = HostingRecord.byAppZygote(r.instanceName, r.definingPackageName,r.definingUid);}}//服务还没启动调用startProcessLocked 创建进程if (app == null && !permissionsReviewRequired) {if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,hostingRecord, false, isolated, false)) == null) {String msg = "Unable to launch app "+ r.appInfo.packageName + "/"+ r.appInfo.uid + " for service "+ r.intent.getIntent() + ": process is bad"; bringDownServiceLocked(r);return msg;}if (isolated) {r.isolatedProc = app;}}if (r.fgRequired) {//不走这里 是falsemAm.tempWhitelistUidLocked(r.appInfo.uid,SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");}if (!mPendingServices.contains(r)) {//假如mPendingServices中mPendingServices.add(r);}if (r.delayedStop) {r.delayedStop = false;if (r.startRequested) {stopServiceLocked(r);}}return null;
}
在AMS这里会先检查Service是否可以执行(常驻内存、蓝牙、电源白名单允许直接启动服务),接着调用bringUpServiceLocked 判断是否需要隔离进程如果非隔离 就看是否已经启动进程 执行realStartServiceLocked,否则是隔离进程 直接开启新进程。我们没有设置隔离进程 所以我们会直接开启新进程,开启进程的过程在之前已经接触很多次了,我们直接跳过,开启成功之后会将ServiceRecord添加到mPendingServices中去。所以我们看看进程创建成功之后会如何开启Service。
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {//到这里来thread.bindApplication(processName, appInfo, providers,instr2.mClass,profilerInfo, instr2.mArguments,instr2.mWatcher,instr2.mUiAutomationConnection, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.compat, getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions);boolean badApp = false;boolean didSomething = false;//在这里开启activityif (normalMode) {try {didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());} catch (Exception e) {badApp = true;}}if (!badApp) {try {//开启ServicedidSomething |= mServices.attachApplicationLocked(app, processName);} catch (Exception e) {badApp = true;}}return true;
}
//还是在ActiveService中boolean attachApplicationLocked(ProcessRecord proc, String processName)throws RemoteException {boolean didSomething = false;//此时Services的size是大于0的if (mPendingServices.size() > 0) {ServiceRecord sr = null;try {for (int i=0; i<mPendingServices.size(); i++) {sr = mPendingServices.get(i);if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid|| !processName.equals(sr.processName))) {continue;}mPendingServices.remove(i);i--;proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode,mAm.mProcessStats);//调用realStartServiceLocked开启servicerealStartServiceLocked(sr, proc, sr.createdFromFg);didSomething = true;if (!isServiceNeededLocked(sr, false, false)) {bringDownServiceLocked(sr);}}} catch (RemoteException e) {throw e;}}return didSomething;
}//开启service
private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {//服务和当前进程绑定r.setProcess(app);r.restartTime = r.lastActivity = SystemClock.uptimeMillis();//添加到ProcessRecord中final boolean newService = app.services.add(r);//埋炸弹scheduleServiceTimeoutLockedbumpServiceExecutingLocked(r, execInFg, "create");//更新进程LRUmAm.updateLruProcessLocked(app, false, null);updateServiceForegroundLocked(r.app, /* oomAdj= */ false);//更新OOMAdjmAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE);boolean created = false;try {synchronized (r.stats.getBatteryStats()) {r.stats.startLaunchedLocked();}mAm.notifyPackageUse(r.serviceInfo.packageName,PackageManager.NOTIFY_PACKAGE_USE_SERVICE);app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);//调用到应用进程 也就是服务进程 ActivityThreadapp.thread.scheduleCreateService(r, r.serviceInfo,mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),app.getReportedProcState());r.postNotification();created = true;} catch (DeadObjectException e) {} finally {}if (r.whitelistManager) {app.whitelistManager = true;}//处理Bind我们不处理 没有Bind 此时直说startServicerequestServiceBindingsLocked(r, execInFg);updateServiceClientActivitiesLocked(app, null, true);if (newService && created) {app.addBoundClientUidsOfNewService(r);}if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),null, null, 0));}//发送Service的argssendServiceArgsLocked(r, execInFg, true);if (r.delayed) {getServiceMapLocked(r.userId).mDelayedStartList.remove(r);r.delayed = false;}
}回到ActivityThread看看它的scheduleCreateServicepublic final void scheduleCreateService(IBinder token,ServiceInfo info, CompatibilityInfo compatInfo, int processState) {updateProcessState(processState, false);CreateServiceData s = new CreateServiceData();s.token = token;s.info = info;s.compatInfo = compatInfo;//给mH发送了H.CREATE_SERVICEsendMessage(H.CREATE_SERVICE, s);
}case CREATE_SERVICE:handleCreateService((CreateServiceData)msg.obj);break;
//创建Service
private void handleCreateService(CreateServiceData data) {unscheduleGcIdler();LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);Service service = null;try {//反射创建Servicejava.lang.ClassLoader cl = packageInfo.getClassLoader();service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent);} catch (Exception e) {}try {//创建ContextContextImpl context = ContextImpl.createAppContext(this, packageInfo);context.setOuterContext(service);//调用makeApplicationApplication app = packageInfo.makeApplication(false, mInstrumentation);//调用service的attach 绑定ActivityThread token Application 以及AMSservice.attach(context, this, data.info.name, data.token, app,ActivityManager.getService());//调用service的onCreateservice.onCreate();//存入到mService中去mServices.put(data.token, service);try {//告诉AMS创建完成ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}} catch (Exception e) {}
}public final void attach(Context context,ActivityThread thread, String className, IBinder token,Application application, Object activityManager) {attachBaseContext(context);mThread = thread; // NOTE: unused - remove?mClassName = className;mToken = token;mApplication = application;mActivityManager = (IActivityManager)activityManager;mStartCompatibility = getApplicationInfo().targetSdkVersion< Build.VERSION_CODES.ECLAIR;
}到AMS 处理服务创建public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {synchronized(this) {if (!(token instanceof ServiceRecord)) {throw new IllegalArgumentException("Invalid service token");}mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);}
}//AMS开启Service成功
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {boolean inDestroying = mDestroyingServices.contains(r);if (r != null) {//在这里把炸弹拆除serviceDoneExecutingLocked(r, inDestroying, inDestroying);}
}
发送的args
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,boolean oomAdjusted) throws TransactionTooLargeException {final int N = r.pendingStarts.size();if (N == 0) {//不是0return;}ArrayList<ServiceStartArgs> args = new ArrayList<>();while (r.pendingStarts.size() > 0) {ServiceRecord.StartItem si = r.pendingStarts.remove(0);if (si.intent == null && N > 1) {continue;}si.deliveredTime = SystemClock.uptimeMillis();r.deliveredStarts.add(si);si.deliveryCount++;//埋炸弹bumpServiceExecutingLocked(r, execInFg, "start");if (!oomAdjusted) {oomAdjusted = true;mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);}if (r.fgRequired && !r.fgWaiting) {//前台Serviceif (!r.isForeground) {scheduleServiceForegroundTransitionTimeoutLocked(r);} else {r.fgRequired = false;}}int flags = 0;if (si.deliveryCount > 1) {flags |= Service.START_FLAG_RETRY;}if (si.doneExecutingCount > 0) {flags |= Service.START_FLAG_REDELIVERY;}args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));}//执行ActivityThread的scheduleServiceArgsr.app.thread.scheduleServiceArgs(r, slice);
}public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {List<ServiceStartArgs> list = args.getList();for (int i = 0; i < list.size(); i++) {ServiceStartArgs ssa = list.get(i);ServiceArgsData s = new ServiceArgsData();s.token = token;s.taskRemoved = ssa.taskRemoved;s.startId = ssa.startId;s.flags = ssa.flags;s.args = ssa.args;//给mH发送SERVICE_ARGSsendMessage(H.SERVICE_ARGS, s);}
}case SERVICE_ARGS:handleServiceArgs((ServiceArgsData)msg.obj);break;//处理Args
private void handleServiceArgs(ServiceArgsData data) {Service s = mServices.get(data.token);if (s != null) {try {if (data.args != null) {data.args.setExtrasClassLoader(s.getClassLoader());data.args.prepareToEnterProcess();}int res;if (!data.taskRemoved) {//这里是false 所以会执行onStartCommandres = s.onStartCommand(data.args, data.flags, data.startId);} else {}QueuedWork.waitToFinish();try {//通知AMS 拆除炸弹ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);} catch (RemoteException e) {}} catch (Exception e) {}}
}
进程创建之后,会调用AMS的attachApplication 接着处理service(ActiveService),之前创建之后会添加到mPendingServices中,现在继续处理调用realStartServiceLocked来开启Service,在开启的过程中会埋入一个炸弹(给Handler发送一个SERVICE_TIMEOUT_MSG) 如果超时未处理会弹出ANR,然后调用app.thread.scheduleCreateService通知客户端创建反射Service、Context 调用onCreate 把Service存入到mService中,调用AMS的serviceDoneExecuting进行炸弹的拆除。 然后再埋炸弹 调用app.thread.scheduleServiceArgs 调用service.onStartCommand再通知AMS 拆除炸弹。 这样Service就运行起来了。我们再看看Service的onStop。
还是回到ContextImpl
public boolean stopService(Intent service) {return stopServiceCommon(service, mUser);
}private boolean stopServiceCommon(Intent service, UserHandle user) {validateServiceIntent(service);service.prepareToLeaveProcess(this);//调用AMS的stopServiceint res = ActivityManager.getService().stopService(mMainThread.getApplicationThread(), service,service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());return res != 0;
}public int stopService(IApplicationThread caller, Intent service,String resolvedType, int userId) {enforceNotIsolatedCaller("stopService");synchronized(this) {//调用ActiveService的stopServiceLockedreturn mServices.stopServiceLocked(caller, service, resolvedType, userId);}
}int stopServiceLocked(IApplicationThread caller, Intent service,String resolvedType, int userId) {//获取到调用这的ProcessRecordfinal ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);//获取ServiceRecord ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null,Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false);if (r != null) {if (r.record != null) {final long origId = Binder.clearCallingIdentity();try {//调用stopServiceLockedstopServiceLocked(r.record);} finally {Binder.restoreCallingIdentity(origId);}return 1;}return -1;}return 0;
}private void stopServiceLocked(ServiceRecord service) {if (service.delayed) {service.delayedStop = true;return;}synchronized (service.stats.getBatteryStats()) {service.stats.stopRunningLocked();}service.startRequested = false;if (service.tracker != null) {service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),SystemClock.uptimeMillis());}service.callStart = false;bringDownServiceIfNeededLocked(service, false, false);
}private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,boolean hasConn) {if (isServiceNeededLocked(r, knowConn, hasConn)) {return;}if (mPendingServices.contains(r)) {return;}bringDownServiceLocked(r);
}private final void bringDownServiceLocked(ServiceRecord r) {if (r.app != null && r.app.thread != null) {boolean needOomAdj = false;//执行unBindfor (int i = r.bindings.size() - 1; i >= 0; i--) {IntentBindRecord ibr = r.bindings.valueAt(i);if (ibr.hasBound) {try {bumpServiceExecutingLocked(r, false, "bring down unbind");needOomAdj = true;ibr.hasBound = false;ibr.requested = false;r.app.thread.scheduleUnbindService(r,ibr.intent.getIntent());} catch (Exception e) {serviceProcessGoneLocked(r);}}}if (needOomAdj) {mAm.updateOomAdjLocked(r.app, true,OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);}}r.fgRequired = false;r.fgWaiting = false;ServiceState stracker = r.getTracker();if (stracker != null) {stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),r.lastActivity);}mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);if (r.app != null) {Message msg = mAm.mHandler.obtainMessage(ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);msg.obj = r.app;msg.getData().putCharSequence(ActivityManagerService.SERVICE_RECORD_KEY, r.toString());mAm.mHandler.sendMessage(msg);}}
//记录销毁时间r.destroyTime = SystemClock.uptimeMillis();final ServiceMap smap = getServiceMapLocked(r.userId);//从map中移除ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName);//移除smap.mServicesByIntent.remove(r.intent);r.totalRestartCount = 0;r.isForeground = false;r.foregroundId = 0;r.foregroundNoti = null;r.clearDeliveredStartsLocked();r.pendingStarts.clear();smap.mDelayedStartList.remove(r);if (r.app != null) {synchronized (r.stats.getBatteryStats()) {r.stats.stopLaunchedLocked();}r.app.services.remove(r);r.app.updateBoundClientUids();if (r.whitelistManager) {updateWhitelistManagerLocked(r.app);}if (r.app.thread != null) {updateServiceForegroundLocked(r.app, false);try {//埋炸弹bumpServiceExecutingLocked(r, false, "destroy");mDestroyingServices.add(r);r.destroying = true;mAm.updateOomAdjLocked(r.app, true,OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);//到客户端执行scheduleStopServicer.app.thread.scheduleStopService(r);} catch (Exception e) {serviceProcessGoneLocked(r);}} else {}} if (r.bindings.size() > 0) {//清空bindingsr.bindings.clear();}if (r.restarter instanceof ServiceRestarter) {((ServiceRestarter)r.restarter).setService(null);}int memFactor = mAm.mProcessStats.getMemFactorLocked();long now = SystemClock.uptimeMillis();if (r.tracker != null) {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);
}public final void scheduleStopService(IBinder token) {sendMessage(H.STOP_SERVICE, token);
}case STOP_SERVICE:handleStopService((IBinder)msg.obj);schedulePurgeIdler();//清空待清理的资源break;private void handleStopService(IBinder token) {
//从mService中移除掉 只是从map中移除掉了引用,所以我们需要注意Service内部的thread 以及变量不要引起内存泄漏或者线程没有停止Service s = mServices.remove(token);if (s != null) {try {//调用s的onDestorys.onDestroy();s.detachAndCleanUp();Context context = s.getBaseContext();if (context instanceof ContextImpl) {final String who = s.getClassName();((ContextImpl) context).scheduleFinalCleanup(who, "Service");}QueuedWork.waitToFinish();try {//调用AMS的serviceDoneExecuting 拆除炸弹ActivityManager.getService().serviceDoneExecuting(token, SERVICE_DONE_EXECUTING_STOP, 0, 0);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}} catch (Exception e) {}} else {}
}
stop的流程和start的流程差不多,需要注意的是stop只是从map中移除了,我们需要自己释放资源。
相关文章:
Android Framework—Service
介绍 Service是一种可以在后台执行长时间运行操作而不提供界面的应用组件。服务可以由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可以通过绑定到服务与之进行交互,甚至是执行进程之间的通信…...
leetcode (重排数组使得)连续子数组的权值和最小
题目描述:请重新排列某个仅包含2和3的数组,使得数组的所有连续子数组权值之和最小数组的权值定义为,数组中所有元素之积的因子个数,例如:rank([2,3])4 x p 1 c 1 p 2 c 2 p 3 c 3 ⋅ ⋅ ⋅ p k c k r a n k ( c 1 1 ) ( c …...
JSP计算机等级考试查询系统(源代码+论文+答辩PPT)
第一章 引言 计算机等级考试查询系统是有其开发的必要性的,它的应用将大大节省了学校的人力资源,从而从人工劳动中解脱出来。我们这次开发的软件系统一共包括了三个部分:等级考试的报名系统、查询系统和管理系统。其中管理系统是另外两部分…...
python 基础系列篇:七、以函数方式编写一个数字华容道
python 基础系列篇:七、以函数方式编写一个数字华容道 数字华容道游戏分析开始编写完整代码代码解说定义方法的规律 小结 数字华容道 嗯,就是一个简单的益智游戏,把数字按照特定规律排列,并比矩阵少一个格,用来进行移…...
2023年前端面试题
1.position都有哪些属性 2.1px等于多少rem,rem根据根元素的大小,根元素是谁 3.Es6操作数组的方法 4.防抖和节流以及应用场景 5.Vue和ajax最大的区别是什么(Vue和ajax怎么操作dom的,vue虚拟dom) 6.js数据类型有哪些&…...
快速入门量化交易
本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注"慕课网"! 原作者:袁霄|慕课网讲师 近来“量化交易”这个词听得越来越频繁,多数人对量化交易的第一印象是“高大上的技术”…...
Mongodb oplog
在MongoDB复制集中,oplog信息存储在oplog.rs集合中。 oplog.rs集合是一个固定大小的集合(capped collection),它位于local数据库中。 当我们在源MongoDB实例上启用了复制(replication)功能,MongoDB会自动在local数据库中创建oplog.rs集合。此后,所有在该实例上的写操作都会生…...
python基础篇: python字符串方法都有哪些?你知道多少?
❝ Python提供了丰富的字符串处理方法,可以方便地对字符串进行操作、处理和转换。在本文中,我们将介绍Python中常用的字符串方法。 ❞ python中字符串内置方法很多,可以通过dir()方式查看具体有哪些方法,下表是python字符串的全部…...
chmod 命令 (chmod 0660)
chmod的作用: 用于设置文件所有者和文件关联组的命令,就是控制用户的权限命令 注意事项: chown 需要超级用户 root 的权限才能执行此命令。 自己常用chmod 命令是 chmod 777 * 给所有文件权限 chmod 777 文件名 给单独文件权限 这个777 是怎么来的, 或者chmod 0660 这…...
Qt应用开发常用功能
Qt判断当前操作系统? #ifdef Q_OS_MAC //mac ... #endif#ifdef Q_OS_LINUX //linux ... #endif#ifdef Q_OS_WIN32 //win ... #endif#ifdef __arm__ //arm ... #endifQt实现应用程序关闭和重启? //关机按钮-点击槽函数 void SystemD::on_shutdownButton…...
麻了,部门新来的00后给我卷崩溃了...
今天上班开早会就是新人见面仪式,听说来了个很厉害的大佬,年纪还不大,是上家公司离职过来的,薪资已经达到中高等水平,很多人都好奇不已,能拿到这个薪资应该人不简单,果然,自我介绍的…...
代码随想录算法训练营第56天|583. 两个字符串的删除操作,72. 编辑距离
代码随想录算法训练营第56天|583. 两个字符串的删除操作,72. 编辑距离 583. 两个字符串的删除操作72. 编辑距离 583. 两个字符串的删除操作 题目链接:583. 两个字符串的删除操作,难度:中等 【实现代码】 class Solution { publi…...
【嵌入式笔/面试】嵌入式软件基础题和真题总结——操作系统
在学习的时候找到几个十分好的工程和个人博客,先码一下,内容都摘自其中,有些重难点做了补充! 才鲸 / 嵌入式软件笔试题汇总 嵌入式与Linux那些事 阿秀的学习笔记 小林coding 百问网linux 嵌入式软件面试合集 2022年春招实习十四面…...
2023浙江省赛“信息安全管理与评估“--Web渗透测试(高职组)
2022全国职业技能大赛“信息安全管理与评估”(高职组)任务书 2022全国职业技能大赛“信息安全管理与评估”任务书第一阶段竞赛项目试题第二阶段竞赛项目试题第三阶段竞赛项目试题任务2:Web渗透测试2022全国职业技能大赛“信息安全管理与评估”任务书 第一阶段竞赛项目试题 …...
垃圾收集器面试总结(二)
G1 收集器 G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。 被视为 JDK1.7 中 HotSpot 虚拟机的一个重要进化特征。它具备以下特点: 并行与并发&am…...
语音交友app开发中的用户积分系统
引言 在当今数字时代,语音交友app已成为一种流行的社交工具。它们给用户提供了一个平台,在这里他们可以结交新朋友,分享他们的生活和信仰,并建立深厚的人际关系。然而,市场上存在大量的语音交友app,这使得…...
Nature:惊人的突破!科学家们成功破译人类嗅觉感应机制的奥秘!
加州大学旧金山分校(UCSF)的科学家们创造了第一张关于气味分子如何激活人类气味受体的分子水平的3D图片,这是破译嗅觉的关键一步,该成果打破了长期以来研究人员对嗅觉理解的僵局。 该研究成果于2023年3月15日发表在《Nature》&…...
WPF教程(九)--数据绑定(2)--绑定模式
一、绑定模式 绑定模式以及模式的使用效果。 示例如下是根据ListBox中的选中项,去改变TextBlock的背景色。将 TextBlock 的背景色绑定到在 ListBox 中选择的颜色。在下面的代码中针对TextBlock的 Background 属性使用绑定语法绑定从 ListBox 中选择的值。代码如下。…...
湿法冶金以及铼提取工艺,湿法冶金工艺特点及工艺流程
湿法冶金是利用浸出剂在一定温度压力下与矿石接触,把矿石中有用的金属溶解后再从溶液中回收有价金属的一种工艺,因为其过程大都是在水溶液中进行,所以又被称为“水法冶金”。 01 湿法冶金工艺特点及工艺流程 湿法冶金作为解决我国金属矿产资…...
kafka集群搭建
1.本次搭建涉及3台centos7主机,防火墙与selinux服务均关闭 2.主机参数如下表所示 nameIPportserviceA10.1.60.1122128、2888、3888、9092kafka、zookeeperB10.1.60.1142128、2888、3888、9092kafka、zookeeperC10.1.60.1152128、2888、3888、9092kafka、zookeeper…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
