0 引言
在Android车载应用之EvsCameraPreview源码分析(一)中介绍了两个Activity,一个是CarEvsCameraActivity,另一个是CarEvsCameraPreviewActivity。CarEvsCameraActivity通过调用CarEvsManager的服务startActivity来打开CarEvsCameraPreviewActivity,从而显示出倒车影像。相关代码如下:
private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> {
if (!ready) {
return;
}
try {
CarEvsManager evsManager = (CarEvsManager) car.getCarManager(
Car.CAR_EVS_SERVICE);
if (evsManager.startActivity(CarEvsManager.SERVICE_TYPE_REARVIEW) != ERROR_NONE) {
Log.e(TAG, "Failed to start a camera preview activity");
}
} finally {
mCar = car;
finish();
}
};
下面将详细分析CarEvsManager及其相关类。
1 Car类
在介绍CarManager之前,先介绍一下Car这个类。Car 是 Android 车载系统(Android Automotive)中的核心类之一,表示一个与车载硬件进行交互的接口。它提供了与汽车硬件、车辆信息、车载服务等的交互功能。通过 Car 类,可以访问车载系统的各种功能,如汽车的传感器数据、信息显示、媒体控制等。
一般都是通过Car.createCar函数来创建一个Car,代码如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Car.createCar(getApplicationContext(), /* handler = */ null, CAR_WAIT_TIMEOUT_MS,
mCarServiceLifecycleListener);
}
createCar的函数代码如下:
public static Car createCar(@NonNull Context context,
@Nullable Handler handler, long waitTimeoutMs,
@NonNull CarServiceLifecycleListener statusChangeListener) {
assertNonNullContext(context);
Objects.requireNonNull(statusChangeListener);
Car car = null;
IBinder service = null;
boolean started = false;
int retryCount = 0;
long maxRetryCount = 0;
if (waitTimeoutMs > 0) {
maxRetryCount = waitTimeoutMs / CAR_SERVICE_BINDER_POLLING_INTERVAL_MS;
// at least wait once if it is positive value.
if (maxRetryCount == 0) {
maxRetryCount = 1;
}
}
boolean isMainThread = Looper.myLooper() == Looper.getMainLooper();
while (true) {
// 获取到car service服务
service = ServiceManagerHelper.getService(CAR_SERVICE_BINDER_SERVICE_NAME);
if (car == null) {
// 创建一个新的Car
car = new Car(context, ICar.Stub.asInterface(service), null, statusChangeListener,
handler);
}
if (service != null) {
if (!started) { // specialization for most common case : car service already ready
car.dispatchCarReadyToMainThread(isMainThread);
// Needs this for CarServiceLifecycleListener. Note that ServiceConnection
// will skip the callback as valid mService is set already.
car.startCarService();
return car;
}
// service available after starting.
break;
}
if (!started) {
car.startCarService();
started = true;
}
retryCount++;
if (waitTimeoutMs < 0 && retryCount >= CAR_SERVICE_BINDER_POLLING_MAX_RETRY
&& retryCount % CAR_SERVICE_BINDER_POLLING_MAX_RETRY == 0) {
// Log warning if car service is not alive even for waiting forever case.
Log.w(TAG_CAR, "car_service not ready, waited for car service (ms):"
+ retryCount * CAR_SERVICE_BINDER_POLLING_INTERVAL_MS,
new RuntimeException());
} else if (waitTimeoutMs >= 0 && retryCount > maxRetryCount) {
if (waitTimeoutMs > 0) {
Log.w(TAG_CAR, "car_service not ready, waited for car service (ms):"
+ waitTimeoutMs,
new RuntimeException());
}
return car;
}
try {
Thread.sleep(CAR_SERVICE_BINDER_POLLING_INTERVAL_MS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.w(TAG_CAR, "interrupted", new RuntimeException());
return car;
}
}
// Can be accessed from mServiceConnectionListener in main thread.
synchronized (car.mLock) {
Log.w(TAG_CAR,
"waited for car_service (ms):"
+ retryCount * CAR_SERVICE_BINDER_POLLING_INTERVAL_MS,
new RuntimeException());
// ServiceConnection has handled everything.
if (car.mService != null) {
return car;
}
// mService check in ServiceConnection prevents calling
// onLifecycleChanged. So onLifecycleChanged should be called explicitly
// but do it outside lock.
car.mService = ICar.Stub.asInterface(service);
car.mConnectionState = STATE_CONNECTED;
}
car.dispatchCarReadyToMainThread(isMainThread);
return car;
}
createCar函数的工作主要就是通过ServiceManagerHelper获取到car service服务,然后创建一个Car类,其内部持有car service代理,也就是可以调用car service服务。
2 CarEvsManager类
CarEvsManager顾名思义就是用来管理Evs相关功能的类,引言中的代码告诉我们通过car.getCarManager(Car.CAR_EVS_SERVICE)方法来获取CarEvsManager。下面是getCarManager函数的代码:
public Object getCarManager(String serviceName) {
CarManagerBase manager;
synchronized (mLock) {
if (mService == null) {
Log.w(TAG_CAR, "getCarManager not working while car service not ready");
return null;
}
// 首先在mServiceMap中寻找,如果没有则创建
manager = mServiceMap.get(serviceName);
if (manager == null) {
try {
// 获取Car.CAR_EVS_SERVICE服务的IBinder
IBinder binder = mService.getCarService(serviceName);
if (binder == null) {
Log.w(TAG_CAR, "getCarManager could not get binder for service:"
+ serviceName);
return null;
}
// 创建对应的manager
manager = createCarManagerLocked(serviceName, binder);
if (manager == null) {
Log.w(TAG_CAR, "getCarManager could not create manager for service:"
+ serviceName);
return null;
}
mServiceMap.put(serviceName, manager);
} catch (RemoteException e) {
handleRemoteExceptionFromCarService(e);
}
}
}
return manager;
}
上面的代码主要就是获取Car.CAR_EVS_SERVICE服务的IBinder,然后通过它来创建对应的CarEvsManager。下面是createCarManagerLocked函数的部分代码:
case CAR_EVS_SERVICE:
manager = new CarEvsManager(this, binder);
break;
CarEvsManager的构造函数如下:
public CarEvsManager(Car car, IBinder service) {
super(car);
// Gets CarEvsService
mService = ICarEvsService.Stub.asInterface(service);
}
可以了解到CarEvsManager就是一个内部持有Car.CAR_EVS_SERVICE服务的类。通过它来调用关于Evs的相关服务和方法。至此,创建CarEvsManager的过程就分析完毕了。
3 startActivity过程分析
Car和CarEvsManager创建完毕后,就是调用startActivity方法来打开CarEvsCameraPreviewActivity了。进入startActivity代码中:
public @CarEvsError int startActivity(@CarEvsServiceType int type) {
try {
return mService.startActivity(type);
} catch (RemoteException err) {
handleRemoteExceptionFromCarService(err);
}
return ERROR_UNAVAILABLE;
}
从上面的代码中可以看到,是通过Binder服务来开启Activity的。因此得找到ICarEvsService服务的实现代码,找到在packages/services/Car/service/src/com/android/car/evs/CarEvsService.java中。
public @CarEvsError int startActivity(int type) {
CarServiceUtils.assertPermission(mContext, Car.PERMISSION_REQUEST_CAR_EVS_ACTIVITY);
return mStateEngine.execute(REQUEST_PRIORITY_NORMAL, SERVICE_STATE_REQUESTED, type);
}
继续调用mStateEngine的execute方法:
public @CarEvsError int execute(int priority, int destination, int service) {
return execute(priority, destination, service, null, null);
}
还是执行execute方法:
public @CarEvsError int execute(int priority, int destination, int service, IBinder token,
ICarEvsStreamCallback callback) {
int serviceType;
int newState;
int result = ERROR_NONE;
synchronized (mLock) {
// TODO(b/188970686): Reduce this lock duration.
if (mState == destination && priority < mLastRequestPriority &&
destination != SERVICE_STATE_REQUESTED) {
// Nothing to do
return ERROR_NONE;
}
int previousState = mState;
Slogf.i(TAG_EVS, "Transition requested: %s -> %s", stateToString(previousState),
stateToString(destination));
switch (destination) {
case SERVICE_STATE_UNAVAILABLE:
result = handleTransitionToUnavailableLocked();
break;
case SERVICE_STATE_INACTIVE:
result = handleTransitionToInactiveLocked(priority, service, callback);
break;
case SERVICE_STATE_REQUESTED:
result = handleTransitionToRequestedLocked(priority, service);
break;
case SERVICE_STATE_ACTIVE:
result = handleTransitionToActiveLocked(priority, service, token, callback);
break;
default:
throw new IllegalStateException(
"CarEvsService is in the unknown state, " + previousState);
}
serviceType = mServiceType;
newState = mState;
}
if (result == ERROR_NONE) {
Slogf.i(TAG_EVS, "Transition completed: %s", stateToString(destination));
// Broadcasts current state
broadcastStateTransition(serviceType, newState);
} else {
Slogf.e(TAG_EVS, "Transition failed: error = %d", result);
}
return result;
}
因为我们前面的destination为SERVICE_STATE_REQUESTED,所以执行对应的case,handleTransitionToRequestedLocked方法的代码如下:
private @CarEvsError int handleTransitionToRequestedLocked(int priority, int service) {
switch (mState) {
case SERVICE_STATE_UNAVAILABLE:
// Attempts to connect to the native EVS service and transits to the
// REQUESTED state if it succeeds.
if (!mHalWrapper.connectToHalServiceIfNecessary()) {
return ERROR_UNAVAILABLE;
}
break;
case SERVICE_STATE_INACTIVE:
// Nothing to do
break;
case SERVICE_STATE_REQUESTED:
if (priority < mLastRequestPriority) {
// A current service request has a lower priority than a previous
// service request.
Slogf.e(TAG_EVS, "CarEvsService is busy with a higher priority client.");
return ERROR_BUSY;
}
// Reset a timer for this new request
mHandler.removeCallbacks(mActivityRequestTimeoutRunnable);
break;
case SERVICE_STATE_ACTIVE:
if (priority < mLastRequestPriority) {
// We decline a request because CarEvsService is busy with a higher priority
// client.
return ERROR_BUSY;
} else if (priority == mLastRequestPriority) {
// We do not need to transit to the REQUESTED state because CarEvsService
// was transited to the ACTIVE state by a request that has the same priority
// with current request.
return ERROR_NONE;
} else {
// Stop stream on all lower priority clients.
processStreamEvent(STREAM_EVENT_STREAM_STOPPED);
}
break;
default:
throw new IllegalStateException("CarEvsService is in the unknown state.");
}
// Arms the timer for the high-priority request
if (priority == REQUEST_PRIORITY_HIGH) {
mHandler.postDelayed(
mActivityRequestTimeoutRunnable, STREAM_START_REQUEST_TIMEOUT_MS);
}
mState = SERVICE_STATE_REQUESTED;
mServiceType = service;
mLastRequestPriority = priority;
if (mEvsCameraActivity != null) {
Intent evsIntent = new Intent(Intent.ACTION_MAIN)
.setComponent(mEvsCameraActivity)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
if (priority == REQUEST_PRIORITY_HIGH) {
mSessionToken = new Binder();
Bundle bundle = new Bundle();
bundle.putBinder(CarEvsManager.EXTRA_SESSION_TOKEN, mSessionToken);
evsIntent.replaceExtras(bundle);
}
mContext.startActivity(evsIntent);
}
return ERROR_NONE;
}
这里只关注重点代码就好:
mState = SERVICE_STATE_REQUESTED;
mServiceType = service;
mLastRequestPriority = priority;
if (mEvsCameraActivity != null) {
Intent evsIntent = new Intent(Intent.ACTION_MAIN)
.setComponent(mEvsCameraActivity)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
if (priority == REQUEST_PRIORITY_HIGH) {
mSessionToken = new Binder();
Bundle bundle = new Bundle();
bundle.putBinder(CarEvsManager.EXTRA_SESSION_TOKEN, mSessionToken);
evsIntent.replaceExtras(bundle);
}
mContext.startActivity(evsIntent);
}
这段代码创建了一个Intent,该Intent设置组件为mEvsCameraActivity。最后通过mContext.startActivity(evsIntent)来打开这个Activity。mEvsCameraActivity对应的Activity其实就是CarEvsCameraPreviewActivity。
mEvsCameraActivity的初始化在CarEvsService的构造函数中:
public CarEvsService(Context context, Context builtinContext, EvsHalService halService,
CarPropertyService propertyService) {
mContext = context;
mPropertyService = propertyService;
mEvsHalService = halService;
mHalWrapper = createHalWrapper(builtinContext, this);
String activityName = mContext.getResources().getString(R.string.config_evsCameraActivity);
if (!activityName.isEmpty()) {
mEvsCameraActivity = ComponentName.unflattenFromString(activityName);
} else {
mEvsCameraActivity = null;
}
if (DBG) Slogf.d(TAG_EVS, "evsCameraActivity=" + mEvsCameraActivity);
mDisplayManager = context.getSystemService(DisplayManager.class);
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
}
上面的代码中通过mContext.getResources().getString(R.string.config_evsCameraActivity)来获取到mEvsCameraActivity的名称。通过搜索config_evsCameraActivity找到activityName为com.google.android.car.evs/com.google.android.car.evs.CarEvsCameraPreviewActivity。
这和我们前面的分析也就对应上了。如果我们想要修改Evs应用,可以直接修改CarEvsCameraPreviewActivity类,或者建立一个自己的Activity,然后让其指向自定义的activity(device/google/cuttlefish/shared/auto/rro_overlay/CarServiceOverlay/res/values/config.xml)。