CarService启动Cluster的过程分析
基于Android 8.1系统源码
本文涉及到的源码路径:
packages/services/Car/car_product/build/car.mk
packages/services/Car/service/res/values/config.xml
packages/services/Car/service/src/com/android/car/CarService.java
packages/services/Car/service/src/com/android/car/ICarImpl.java
packages/services/Car/service/src/com/android/car/cluster/InstrumentClusterService.java
packages/services/Car/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/SampleClusterServiceImpl.java
packages/services/Car/tests/DirectRenderingClusterSample/src/android/car/cluster/sample/MainClusterActivity.java
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/car/CarServiceHelperService.java
SystemServer启动CarService
SystemServer
里会启动CarServiceHelperService
,如下:
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
traceBeginAndSlog("StartCarServiceHelperService");
mSystemServiceManager.startService(CarServiceHelperService.class);
traceEnd();
}
而CarServiceHelperService.onStart()
会bind到CarService
,如下:
Intent intent = new Intent();
intent.setPackage("com.android.car");
intent.setAction(CAR_SERVICE_INTERFACE); // "android.car.ICar"
if (!context.bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
Slog.wtf(TAG, "cannot start car service");
}
注意:这里用的是bindService方式,mCarServiceConnection是ServiceConnection类对象,它能监听目标Service的状态,当目标Service所在进程异常退出时,会导致其onServiceDisconnected()
方法被调用。
CarService启动ClusterActivity
CarService.onCreate()
里会创建ICarImpl
的实例,并调用ICarImpl.init()
方法;
而ICarImpl.init()
里会启动一大堆Service,其中就包括InstrumentClusterService
,如下:
// Be careful with order. Service depending on other service should be inited later.
List<CarServiceBase> allServices = new ArrayList<>(Arrays.asList(
mSystemActivityMonitoringService,
mCarPowerManagementService,
//add ExtCarPowerManagementService
mExtCarPowerManagementService,
mCarSensorService,
mCarPackageManagerService,
mCarInputService,
mGarageModeService,
mCarInfoService,
mAppFocusService,
mCarAudioService,
mCarCabinService,
mCarHvacService,
mCarRadioService,
mCarNightService,
mInstrumentClusterService,
mCarProjectionService,
mSystemStateControllerService,
mCarVendorExtensionService,
mCarBluetoothService,
mCarDiagnosticService,
mPerUserCarServiceHelper
));
mAllServices = allServices.toArray(new CarServiceBase[0]);
}
public void init() {
traceBegin("VehicleHal.init");
mHal.init();
traceEnd();
traceBegin("CarService.initAllServices");
for (CarServiceBase service : mAllServices) {
service.init();
}
traceEnd();
}
继续看InstrumentClusterService.init()
方法,里面会调用bindInstrumentClusterRendererService()
来bind到SampleClusterServiceImpl
这个Service,如下:
private boolean bindInstrumentClusterRendererService() {
String rendererService = mContext.getString(R.string.instrumentClusterRendererService);
if (TextUtils.isEmpty(rendererService)) {
Log.i(TAG, "Instrument cluster renderer was not configured");
return false;
}
Log.d(TAG, "bindInstrumentClusterRendererService, component: " + rendererService);
Intent intent = new Intent();
intent.setComponent(ComponentName.unflattenFromString(rendererService));
Bundle extras = new Bundle();
extras.putBinder(
InstrumentClusterRenderingService.EXTRA_KEY_CALLBACK_SERVICE,
mClusterCallback);
intent.putExtras(extras);
return mContext.bindService(intent, mRendererServiceConnection, Context.BIND_AUTO_CREATE);
}
继续,SampleClusterServiceImpl.onCreate()
方法里面在另一Display上启动了MainClusterActivity
,如下:
Display clusterDisplay = getInstrumentClusterDisplay(this);
if (clusterDisplay == null) {
Log.e(TAG, "Unable to find instrument cluster display");
return;
}
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(clusterDisplay.getDisplayId());
Intent intent = new Intent(this, MainClusterActivity.class);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
startActivity(intent, options.toBundle());
我们再回头看下InstrumentClusterService.init().bindInstrumentClusterRendererService()
这个方法,关注它在调用bindService()
时的第二个参数mRendererServiceConnection
;
mRendererServiceConnection
是ServiceConnection
类的实例,其源码如下:
private final ServiceConnection mRendererServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
IInstrumentCluster service = IInstrumentCluster.Stub.asInterface(binder);
// ...
}
@Override
public void onServiceDisconnected(ComponentName name) {
// Try to rebind with instrument cluster.
mRendererBound = bindInstrumentClusterRendererService();
}
};
在mRendererServiceConnection.onServiceDisconnected()
里面,会重新调用bindInstrumentClusterRendererService()
来rebind;也就是当SampleClusterServiceImpl
挂掉时会重新启动它。
注:
-
R.string.instrumentClusterRendererService
就是指的android.car.cluster.sample/.SampleClusterServiceImpl
;在
packages/services/Car/service/res/values/config.xml
有:
<string name="instrumentClusterRendererService">android.car.cluster.sample/.SampleClusterServiceImpl</string>
SampleClusterServiceImpl
继承自InstrumentClusterRenderingService
,所以它是一个Service;InstrumentClusterService.bindInstrumentClusterRendererService()
方法会bind这个SampleClusterServiceImpl
;
扩展
需要注意,CarService
本质上是一个特殊的APP,在其AndroidManifest.xml里有:
<service android:name=".CarService"
android:singleUser="true">
<intent-filter>
<action android:name="android.car.ICar" />
</intent-filter>
</service>
即其核心是com.android.car/.CarService
这个service;
它编译后生成CarService.apk;在真机上,它是在/system/priv-app/CarService/CarService.apk
这里。
而DirectRenderingClusterSample
实质上也是一个APP,其主Activity是android.car.cluster.sample/.MainClusterActivity
;还有个关键的Service即android.car.cluster.sample/.SampleClusterServiceImpl
。
需要注意的是,在packages/services/Car/car_product/build/car.mk
里面决定了是否编译DirectRenderingClusterSample
!