Service源码分析。

service 8.0+ (app处于后台)延迟调用startService会报异常。31的源码。

8.0 新特性

IntentService,startService,BindService

startService

startService--> ContextImpl::startService--> startServiceCommon()
--> service.prepareToLeaveProcess() 离开当前进程。
AMS是system_server进程。 通过IActivityManager通信 app。// 跨进程通信1。app调用AMS.

ComponentName cn = ActivityManager.getService.startService(). // 调用AMS启动服务。跨进程调用
ActivityManagerService.java
ComponentName res = mServices.startServiceLocked()
ActiveService.java 真正启动对应的service。
startServiceLocked()--startServiceLocked()
mAm.getRecordForAppLOSP() // 通过AMS 找对应的app进程。
ActivityManagerService.java
appRestrictedInBackgroundLOSP() // app在后台。8.0以后抛异常。
if(packageTargetSdk >= Build.VERSION_CODES_O) {
return ActivityManager.APP_START_MODE_DELAYED_RIGID;
}
return new ComponentName("?", "app is in background uid " + uinRec)

startService 在哪里调用。
startServiceLocked-- startServiceInnerLocked-- startServiceInnerLocked
bringUpServiceLocked-- sendServiceArgsLocked
realStartServiceLocked
thread.scheduleCreateService()--> ActivityThread(IApplicationThread)::scheduleCreateService() // 跨进程通信2:ams调用app。调用service的onCreate
--sendMessage(H.CREATE_SERVICE, s);
--handleCreateService()
--LoadedApk packageInfo = getPackageInfoNoCheck();
--Application app = packageInfo.makeApplication(); // 通过LoadedApk,拿到Application
--service = packageInfo.getAppFactory().instantiateService(); // 真正生产service
-- return (Service)cl.loadClass(className).newInstance(); // 类加载器,生成Service,Service一定要有无参的构造方法。
--service.attach(); //
--service.onCreate(); // 执行生命周期onCreate。
--mServices.put(data.token, service); 缓存service

ActiveServices.java
--sendServiceArgcLocked()
-- r.app.getThread().scheduleServiceArgs(); // 跨进程通信3。
ActivityThread.java
-- scheduleServiceArgs-- sendMessage(H.SERVICE_ARGS, s) // handler 发消息,处理多线程问题。
-- handleServiceArgs()-- Service s = mServices.get(data.token) // 拿到service
res = s.onStartCommand()

总结:

app进程(service进程 ), ams进程。三次跨进程通信。

  1. app通过startService 去调用AMS.app通过startService()。
  2. AMS通过一些操作后,调用IApplicationThread,调用scheduleCreate,调用onCreate
  3. 又调用onStartCommand。

stopService()

ContextWrapper--stopService()-- mBase.stopService(name)
ContextImpl -- stopService-- stopServiceCommon(service, mUser)
-- service.prepareToLeaveProcess() 准备离开当前进程,进入AMS
-- int res = ActivityManager.getService().stopService()
ActivityManagerService::
stopService()-- mServices.stopServiceLocked()
ActiveService::
stopServiceLocked-- mAm.getRecordForAppLOSP(caller) // 找对应的进程。
--stopServiceLocked()
--bringDownServiceIfNeededLocked() // 真正停止service
--bringDownServiceLocked()
// r.app.getThread.scheduleUnbindService() // unbind 解绑service
--r.app.getThread().scheduleStopService(r) // 又一次跨进程通信。

ActivityThread::ApplicationThread 内部类 ,进入app进程(service)
scheduleStopService--> sendMessage(H.STOP_SERVICE, token)
-- handleStopService()
--mServiceData.remove(token)
--mServices.remove(token)
--s.onDestroy(); // 执行生命周期。


bindService 流程分析,onCreate流程同上。service是新的进程。

app进程; AMS进程;Service进程(新的进程)。

bindService -- mBase.bindService(service, conn, flag); // 1. 传递conn 方便service进程与app进程通信。
ContextImpl:: bindServiceCommon // 将IServiceConnection 传递给AMS里面。
为什么传IServiceConnection, 因为不知道service是不是在新的进程,只能把它当一个新进程。
---int res = ActivityManager.getService().bindIsolatedService()

ActivityManagerService::
bindIsolatedService-- mServices.bindServiceLocked()
ActiveService::
bindServiceLocked-- mAm.getRecordForAppLOSP()
activity = mAm.mAtmInternal.getServiceConnectionsHolder(token) // 保证一定是Activity binderService。
bringUpServiceLocked()
requestServiceBindingsLocked()--> requestServiceBindingsLocked
r.app.getThread().scheduleBindService() // 2.通过AMS,进入Service进程。

ActivityThread::
scheduleBindService-- sendMessage(H.BIND_SERVICE, s)
-- handleBindService()
Service s = mServices.get(data.token);
IBinder binder = s.onBinder(data.intent) // 执行onBind生命周期。
ActivityManager.getService().publishService() // 3.跨进程通信:service进程,通信给ams。
AMS:
publishService()-- mServices.publishServiceLocked()
ActiveService:: // 4.跨进程通信,AMS,通信给App进程。
c.conn.connected();---> ServiceConnection:onServiceConnected // 执行什么周期函数。

UnbindService

mBase.unbindService(conn)--ContextImpl.unbindService
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(getOuterContext(), conn);
ActivityManager.getService().unbindService(sd);

ActivityManagerService::
unbindService()-- mServices.unbindServiceLocked()
ActiveService::
unbindServiceLocked()--removeConnectionLocked
-- b.connections.remove(c) 移除
c.activity.removeConnections(c)
s.app.getThread().scheduleUnbindService(s, b.intent.intent.getIntent());
进入ActivityThread
scheduleUnbindService-- sendMessage(H.UNBIND_SERVICE, s);
-- handleUnbindService()
-- boolean doRebind = s.onUnbind(); // 调用onUnbind方法
--ActivityManager.getService().unbindFinished()
--ActivityManager.getService().serviceDoneExecuting()

service 启用新进程的几种情况

  • 配置android:process=":remote"
  • aidl
  • 隐式启动Service,使用包名启动service。
    所属的service就是新进程。

几个通信的关键类:
AMS中的类:ActivityManagerService
App中的类:ApplicationThread
Service: IServiceConnection
AMS 与zygote通信,使用的 socket通信。

Manifest中配置参数。

android:enable="true" 能否被系统实例化
android:exported="true" 能否可别别的应用隐式启动。
android:isolatedProcess="true"
android:label="service" 别名
android:process=" :remote" service使用新的进程,前面补齐报名
android:process=":remote" 不补齐报名

IntentService

onHandleIntent 执行在子线程中。
IntentService 的handleMessage在子线程中。

onCreate-- HandlerThread

进程保活:

  1. 开启一个1像素activity
  2. 后台播放一个没声音的音频
  3. 守护进程
  4. 定时启动,
  5. 加白名单。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容