1. 啟動方式的區別
系統服務啟動:系統服務大部分跑在system server里,一般都是在system server里面啟動的,在system server啟動時順便把服務都啟動了如AMS,WMS,PMS都在system server里面。
private void run(){
...
startBootstrapService();
startCoreService();
startOtherServices();
...
}
應用服務啟動:無論是start service,還是bind service,都是從應用端發起的請求會調到AMS里面。
ComponentName startServiceCommon(...){
....
//拿到AMS的binder對象,startSetvice是IPC調用,它里面會創建ServiceRecord,
//ServiceRecord只是service的記錄,AMS只是負責service的管理和調度,service的啟動和加載還是要在應用端做的
ActivityManagerNative.getDefault().startService(...); }
應用端啟動和加載Service的方式如下:
private void handleCreateService(CreateServiceData data) {
//通過loadClass加載service的類,newInstance給service創建對象
Service service = (Service)cl.loadClass(data.info.name).newInstance(); //給service創建上下文 ContextImpl context = ContextImpl.createAppContext(this, ..); //create application Application app = packageInfo.makeApplication(false, ...); //attach service service.attach(context, this, ...); //執行聲明周期回調 service.onCreate(); }
2. 注冊方式的區別
系統服務的注冊
//跑在system server進程,java層實現
pubic void setSystemProcess(){
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); ... } //跑在單獨進程,native層實現 int main(int, char**){ sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName(), flinger, false)); }
無論是在sysemserver進程,還是單獨進程,都要在service manager注冊服務。
應用端的binder實體對象注冊到service manager,肯定提示權限錯誤,因為只有系統服務可以注冊到service mananger。
應用服務的注冊
應用端向AMS發起binderService調用,
AMS看service注冊過沒有,注冊過直接把binder的service對象返回給應用。
若沒有,AMS去請求binder對象,Service響應請求,把自己的binder對象注冊到AMS,AMS再把binder對象回調給應用端。
3. 使用方式的區別
系統服務的使用
//通過context的getSystemService(),傳入名字,查到服務的管理對象
PowerManager pm = context.getSystemService(Context.POWER_SERVICE);
//調用對象的接口函數使用系統服務
PowerManagfer.WakeLock = pm.newWakelock(Flags. TAG);
SystemServiceRegistry.java
獲取系統服務
registerService(Context.POWER_SERVICE, PowerManager.class, //先找到Service對應的serviceFetcher,再通過Fecher拿到服務的管理對象 new CachedServiceFetcher<PowerManager>(){ @Override public PowerManager createService(ContextImpl ctx){ //先通過service manager的getService函數獲取系統服務的binder對象 IBinder b = ServiceManager.getService(Context.POWER_SERVICE); //用對象封裝了一層服務的管理對象再傳給AP層,方便應用層調用 IPowerManager service = IPowerManager.Stub.asInterface(b); return new PowerManager(ctx.getOuterContext(),..); } });
應用服務的使用
bindService(serviceIntent, new ServiceConection(){
@Override
//AMS通過onServiceConnected回調,把服務的IBinder對象返回給AP端,
public void onServiceConnected(ComponentName name, IBinder service){ //把binder對象service封裝一層業務接口對象,就可以持有對象向AP服務發起調用了 IMyInterface myInterface = IMyInterface.Stub.asInterface(service); } })