blob: 38ad56d79243acc3cac80448daf36dd57a1dfdb6 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car;
import static android.car.builtin.content.pm.PackageManagerHelper.PROPERTY_CAR_SERVICE_PACKAGE_NAME;
import static com.android.car.CarServiceImpl.CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS;
import static com.android.car.CarServiceImpl.CAR_SERVICE_INIT_TIMING_TAG;
import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DEPRECATED_CODE;
import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
import static com.android.car.internal.SystemConstants.ICAR_SYSTEM_SERVER_CLIENT;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.car.Car;
import android.car.CarFeatures;
import android.car.ICar;
import android.car.ICarResultReceiver;
import android.car.builtin.CarBuiltin;
import android.car.builtin.os.BinderHelper;
import android.car.builtin.os.BuildHelper;
import android.car.builtin.os.TraceHelper;
import android.car.builtin.os.UserManagerHelper;
import android.car.builtin.util.EventLogHelper;
import android.car.builtin.util.Slogf;
import android.car.feature.Flags;
import android.car.user.CarUserManager;
import android.content.Context;
import android.content.om.OverlayInfo;
import android.content.om.OverlayManager;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification;
import android.hardware.automotive.vehicle.VehicleProperty;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import com.android.car.admin.CarDevicePolicyService;
import com.android.car.am.CarActivityService;
import com.android.car.am.FixedActivityService;
import com.android.car.audio.CarAudioService;
import com.android.car.bluetooth.CarBluetoothService;
import com.android.car.cluster.ClusterHomeService;
import com.android.car.cluster.ClusterNavigationService;
import com.android.car.cluster.InstrumentClusterService;
import com.android.car.evs.CarEvsService;
import com.android.car.garagemode.GarageModeService;
import com.android.car.hal.HalPropValue;
import com.android.car.hal.VehicleHal;
import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
import com.android.car.internal.ICarServiceHelper;
import com.android.car.internal.ICarSystemServerClient;
import com.android.car.internal.util.IndentingPrintWriter;
import com.android.car.occupantconnection.CarOccupantConnectionService;
import com.android.car.occupantconnection.CarRemoteDeviceService;
import com.android.car.oem.CarOemProxyService;
import com.android.car.os.CarPerformanceService;
import com.android.car.pm.CarPackageManagerService;
import com.android.car.power.CarPowerManagementService;
import com.android.car.remoteaccess.CarRemoteAccessService;
import com.android.car.stats.CarStatsService;
import com.android.car.systeminterface.SystemInterface;
import com.android.car.systemui.keyguard.ExperimentalCarKeyguardService;
import com.android.car.telemetry.CarTelemetryService;
import com.android.car.user.CarUserNoticeService;
import com.android.car.user.CarUserService;
import com.android.car.user.ExperimentalCarUserService;
import com.android.car.util.LimitedTimingsTraceLog;
import com.android.car.vms.VmsBrokerService;
import com.android.car.watchdog.CarWatchdogService;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
public class ICarImpl extends ICar.Stub {
public static final String INTERNAL_INPUT_SERVICE = "internal_input";
public static final String INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE =
"system_activity_monitoring";
@VisibleForTesting
static final String TAG = CarLog.tagFor(ICarImpl.class);
private static final int INITIAL_VHAL_GET_RETRY = 2;
private final Context mContext;
private final Context mCarServiceBuiltinPackageContext;
private final VehicleHal mHal;
private final CarServiceHelperWrapper mCarServiceHelperWrapper;
private final CarFeatureController mFeatureController;
private final SystemInterface mSystemInterface;
private final CarOemProxyService mCarOemService;
private final SystemActivityMonitoringService mSystemActivityMonitoringService;
private final CarPowerManagementService mCarPowerManagementService;
private final CarPackageManagerService mCarPackageManagerService;
private final CarInputService mCarInputService;
private final CarDrivingStateService mCarDrivingStateService;
private final CarUxRestrictionsManagerService mCarUXRestrictionsService;
private final OccupantAwarenessService mOccupantAwarenessService;
private final CarAudioService mCarAudioService;
private final CarProjectionService mCarProjectionService;
private final CarPropertyService mCarPropertyService;
private final CarNightService mCarNightService;
private final AppFocusService mAppFocusService;
private final FixedActivityService mFixedActivityService;
private final GarageModeService mGarageModeService;
private final ClusterNavigationService mClusterNavigationService;
private final InstrumentClusterService mInstrumentClusterService;
private final CarLocationService mCarLocationService;
private final CarBluetoothService mCarBluetoothService;
private final CarPerUserServiceHelper mCarPerUserServiceHelper;
private final CarDiagnosticService mCarDiagnosticService;
private final CarStorageMonitoringService mCarStorageMonitoringService;
private final CarMediaService mCarMediaService;
private final CarUserService mCarUserService;
@Nullable
private final ExperimentalCarUserService mExperimentalCarUserService;
@Nullable
private final ExperimentalCarKeyguardService mExperimentalCarKeyguardService;
private final CarOccupantZoneService mCarOccupantZoneService;
private final CarUserNoticeService mCarUserNoticeService;
private final VmsBrokerService mVmsBrokerService;
private final CarBugreportManagerService mCarBugreportManagerService;
private final CarStatsService mCarStatsService;
private final CarExperimentalFeatureServiceController mCarExperimentalFeatureServiceController;
private final CarWatchdogService mCarWatchdogService;
private final CarPerformanceService mCarPerformanceService;
private final CarDevicePolicyService mCarDevicePolicyService;
private final ClusterHomeService mClusterHomeService;
private final CarEvsService mCarEvsService;
private final CarTelemetryService mCarTelemetryService;
private final CarActivityService mCarActivityService;
private final CarOccupantConnectionService mCarOccupantConnectionService;
private final CarRemoteDeviceService mCarRemoteDeviceService;
// Only modified at setCarRemoteAccessService for testing.
@Nullable
private CarRemoteAccessService mCarRemoteAccessService;
// Storing all the car services in the order of their init.
private final CarSystemService[] mAllServicesInInitOrder;
private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG);
private final Object mLock = new Object();
// This flag indicates whether priorityInit() should be called in the constructor or
// will be deferred to CarImpl.init(). With the new boot user code flow, the boot user is set
// in initialUserSetter as early as possible. The earliest it can be done is in the ICarImpl
// constructor. In priorityInit() HAL and UserService are initialized which sets boot user.
private final boolean mDoPriorityInitInConstruction;
/** Test only service. Populate it only when necessary. */
@GuardedBy("mLock")
private CarTestService mCarTestService;
private final String mVehicleInterfaceName;
private final ICarSystemServerClientImpl mICarSystemServerClientImpl;
private final BinderHelper.ShellCommandListener mCmdListener =
(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args) ->
newCarShellCommand().exec(ICarImpl.this, in, out, err, args);
public ICarImpl(Context serviceContext, Context builtinContext, VehicleStub vehicle,
SystemInterface systemInterface, String vehicleInterfaceName) {
this(serviceContext, builtinContext, vehicle, systemInterface, vehicleInterfaceName,
/* carUserService= */ null, /* carWatchdogService= */ null,
/* carPerformanceService= */ null, /* garageModeService= */ null,
/* powerPolicyDaemon= */ null, /* carTelemetryService= */ null,
/* carRemoteAccessService= */ null, /* doPriorityInitInConstruction= */ true);
}
@VisibleForTesting
ICarImpl(Context serviceContext, @Nullable Context builtinContext, VehicleStub vehicle,
SystemInterface systemInterface, String vehicleInterfaceName,
@Nullable CarUserService carUserService,
@Nullable CarWatchdogService carWatchdogService,
@Nullable CarPerformanceService carPerformanceService,
@Nullable GarageModeService garageModeService,
@Nullable ICarPowerPolicySystemNotification powerPolicyDaemon,
@Nullable CarTelemetryService carTelemetryService,
@Nullable CarRemoteAccessService carRemoteAccessService,
boolean doPriorityInitInConstruction) {
LimitedTimingsTraceLog t = new LimitedTimingsTraceLog(
CAR_SERVICE_INIT_TIMING_TAG, TraceHelper.TRACE_TAG_CAR_SERVICE,
CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS);
t.traceBegin("ICarImpl.constructor");
mDoPriorityInitInConstruction = doPriorityInitInConstruction;
mContext = serviceContext;
if (builtinContext == null) {
mCarServiceBuiltinPackageContext = serviceContext;
} else {
mCarServiceBuiltinPackageContext = builtinContext;
}
mCarServiceHelperWrapper = CarServiceHelperWrapper.create();
// Currently there are ~36 services, hence using 40 as the initial capacity.
List<CarSystemService> allServices = new ArrayList<>(40);
mCarOemService = constructWithTrace(t, CarOemProxyService.class,
() -> new CarOemProxyService(serviceContext), allServices);
mSystemInterface = systemInterface;
CarLocalServices.addService(SystemInterface.class, mSystemInterface);
mHal = constructWithTrace(t, VehicleHal.class,
() -> new VehicleHal(serviceContext, vehicle), allServices);
HalPropValue disabledOptionalFeatureValue = mHal.getIfSupportedOrFailForEarlyStage(
VehicleProperty.DISABLED_OPTIONAL_FEATURES, INITIAL_VHAL_GET_RETRY);
String[] disabledFeaturesFromVhal = null;
if (disabledOptionalFeatureValue != null) {
String disabledFeatures = disabledOptionalFeatureValue.getStringValue();
if (disabledFeatures != null && !disabledFeatures.isEmpty()) {
disabledFeaturesFromVhal = disabledFeatures.split(",");
}
}
if (disabledFeaturesFromVhal == null) {
disabledFeaturesFromVhal = new String[0];
}
Resources res = mContext.getResources();
String[] defaultEnabledFeatures = res.getStringArray(
R.array.config_allowed_optional_car_features);
final String[] disabledFromVhal = disabledFeaturesFromVhal;
mFeatureController = constructWithTrace(t, CarFeatureController.class,
() -> new CarFeatureController(serviceContext, defaultEnabledFeatures,
disabledFromVhal, mSystemInterface.getSystemCarDir()), allServices);
mVehicleInterfaceName = vehicleInterfaceName;
mCarPropertyService = constructWithTrace(
t, CarPropertyService.class,
() -> new CarPropertyService(serviceContext, mHal.getPropertyHal()), allServices);
mCarDrivingStateService = constructWithTrace(
t, CarDrivingStateService.class,
() -> new CarDrivingStateService(serviceContext, mCarPropertyService), allServices);
mCarOccupantZoneService = constructWithTrace(t, CarOccupantZoneService.class,
() -> new CarOccupantZoneService(serviceContext), allServices);
mCarUXRestrictionsService = constructWithTrace(t, CarUxRestrictionsManagerService.class,
() -> new CarUxRestrictionsManagerService(serviceContext, mCarDrivingStateService,
mCarPropertyService, mCarOccupantZoneService), allServices);
mCarActivityService = constructWithTrace(t, CarActivityService.class,
() -> new CarActivityService(serviceContext), allServices);
mCarPackageManagerService = constructWithTrace(t, CarPackageManagerService.class,
() -> new CarPackageManagerService(serviceContext, mCarUXRestrictionsService,
mCarActivityService, mCarOccupantZoneService), allServices);
UserManager userManager = serviceContext.getSystemService(UserManager.class);
if (carUserService != null) {
mCarUserService = carUserService;
CarLocalServices.addService(CarUserService.class, carUserService);
allServices.add(mCarUserService);
} else {
int maxRunningUsers = UserManagerHelper.getMaxRunningUsers(serviceContext);
mCarUserService = constructWithTrace(t, CarUserService.class,
() -> new CarUserService(serviceContext, mHal.getUserHal(), userManager,
maxRunningUsers, mCarUXRestrictionsService, mCarPackageManagerService,
mCarOccupantZoneService),
allServices);
}
if (mDoPriorityInitInConstruction) {
Slogf.i(TAG, "VHAL Priority Init Enabled");
Slogf.i(TAG, "Car User Service Priority Init Enabled");
priorityInit();
}
if (mFeatureController.isFeatureEnabled(Car.EXPERIMENTAL_CAR_USER_SERVICE)) {
mExperimentalCarUserService = constructWithTrace(t, ExperimentalCarUserService.class,
() -> new ExperimentalCarUserService(serviceContext, mCarUserService,
userManager), allServices);
} else {
mExperimentalCarUserService = null;
}
if (mFeatureController.isFeatureEnabled(Car.EXPERIMENTAL_CAR_KEYGUARD_SERVICE)) {
mExperimentalCarKeyguardService = constructWithTrace(t,
ExperimentalCarKeyguardService.class,
() -> new ExperimentalCarKeyguardService(serviceContext, mCarUserService,
mCarOccupantZoneService), allServices);
} else {
mExperimentalCarKeyguardService = null;
}
mSystemActivityMonitoringService = constructWithTrace(
t, SystemActivityMonitoringService.class,
() -> new SystemActivityMonitoringService(serviceContext), allServices);
mCarPowerManagementService = constructWithTrace(
t, CarPowerManagementService.class,
() -> new CarPowerManagementService(mContext, mHal.getPowerHal(),
systemInterface, mCarUserService, powerPolicyDaemon), allServices);
if (mFeatureController.isFeatureEnabled(CarFeatures.FEATURE_CAR_USER_NOTICE_SERVICE)) {
mCarUserNoticeService = constructWithTrace(
t, CarUserNoticeService.class, () -> new CarUserNoticeService(serviceContext),
allServices);
} else {
mCarUserNoticeService = null;
}
if (mFeatureController.isFeatureEnabled(Car.OCCUPANT_AWARENESS_SERVICE)) {
mOccupantAwarenessService = constructWithTrace(t, OccupantAwarenessService.class,
() -> new OccupantAwarenessService(serviceContext), allServices);
} else {
mOccupantAwarenessService = null;
}
mCarPerUserServiceHelper = constructWithTrace(
t, CarPerUserServiceHelper.class,
() -> new CarPerUserServiceHelper(serviceContext, mCarUserService), allServices);
mCarBluetoothService = constructWithTrace(t, CarBluetoothService.class,
() -> new CarBluetoothService(serviceContext, mCarPerUserServiceHelper),
allServices);
mCarInputService = constructWithTrace(t, CarInputService.class,
() -> new CarInputService(serviceContext, mHal.getInputHal(), mCarUserService,
mCarOccupantZoneService, mCarBluetoothService, mCarPowerManagementService,
mSystemInterface), allServices);
mCarProjectionService = constructWithTrace(t, CarProjectionService.class,
() -> new CarProjectionService(serviceContext, null /* handler */, mCarInputService,
mCarBluetoothService), allServices);
if (garageModeService == null) {
mGarageModeService = constructWithTrace(t, GarageModeService.class,
() -> new GarageModeService(serviceContext), allServices);
} else {
mGarageModeService = garageModeService;
allServices.add(mGarageModeService);
}
mAppFocusService = constructWithTrace(t, AppFocusService.class,
() -> new AppFocusService(serviceContext, mSystemActivityMonitoringService),
allServices);
mCarAudioService = constructWithTrace(t, CarAudioService.class,
() -> new CarAudioService(serviceContext), allServices);
mCarNightService = constructWithTrace(t, CarNightService.class,
() -> new CarNightService(serviceContext, mCarPropertyService), allServices);
mFixedActivityService = constructWithTrace(t, FixedActivityService.class,
() -> new FixedActivityService(serviceContext, mCarActivityService), allServices);
mClusterNavigationService = constructWithTrace(
t, ClusterNavigationService.class,
() -> new ClusterNavigationService(serviceContext, mAppFocusService), allServices);
if (mFeatureController.isFeatureEnabled(Car.CAR_INSTRUMENT_CLUSTER_SERVICE)) {
mInstrumentClusterService = constructWithTrace(t, InstrumentClusterService.class,
() -> new InstrumentClusterService(serviceContext,
mClusterNavigationService, mCarInputService), allServices);
} else {
mInstrumentClusterService = null;
}
mCarStatsService = constructWithTrace(t, CarStatsService.class,
() -> new CarStatsService(serviceContext), allServices);
if (mFeatureController.isFeatureEnabled(Car.VEHICLE_MAP_SERVICE)) {
mVmsBrokerService = constructWithTrace(t, VmsBrokerService.class,
() -> new VmsBrokerService(mContext, mCarStatsService), allServices);
} else {
mVmsBrokerService = null;
}
if (mFeatureController.isFeatureEnabled(Car.DIAGNOSTIC_SERVICE)) {
mCarDiagnosticService = constructWithTrace(t, CarDiagnosticService.class,
() -> new CarDiagnosticService(serviceContext,
mHal.getDiagnosticHal()), allServices);
} else {
mCarDiagnosticService = null;
}
if (mFeatureController.isFeatureEnabled(Car.STORAGE_MONITORING_SERVICE)) {
mCarStorageMonitoringService = constructWithTrace(
t, CarStorageMonitoringService.class,
() -> new CarStorageMonitoringService(serviceContext,
systemInterface), allServices);
} else {
mCarStorageMonitoringService = null;
}
mCarLocationService = constructWithTrace(t, CarLocationService.class,
() -> new CarLocationService(serviceContext), allServices);
mCarMediaService = constructWithTrace(t, CarMediaService.class,
() -> new CarMediaService(serviceContext, mCarOccupantZoneService, mCarUserService,
mCarPowerManagementService),
allServices);
mCarBugreportManagerService = constructWithTrace(t, CarBugreportManagerService.class,
() -> new CarBugreportManagerService(serviceContext), allServices);
if (carWatchdogService == null) {
mCarWatchdogService = constructWithTrace(t, CarWatchdogService.class,
() -> new CarWatchdogService(serviceContext, mCarServiceBuiltinPackageContext),
allServices);
} else {
mCarWatchdogService = carWatchdogService;
allServices.add(mCarWatchdogService);
CarLocalServices.addService(CarWatchdogService.class, mCarWatchdogService);
}
if (carPerformanceService == null) {
mCarPerformanceService = constructWithTrace(t, CarPerformanceService.class,
() -> new CarPerformanceService(serviceContext), allServices);
} else {
mCarPerformanceService = carPerformanceService;
allServices.add(mCarPerformanceService);
CarLocalServices.addService(CarPerformanceService.class, mCarPerformanceService);
}
mCarDevicePolicyService = constructWithTrace(
t, CarDevicePolicyService.class, () -> new CarDevicePolicyService(mContext,
mCarServiceBuiltinPackageContext, mCarUserService), allServices);
if (mFeatureController.isFeatureEnabled(Car.CLUSTER_HOME_SERVICE)) {
if (!mFeatureController.isFeatureEnabled(Car.CAR_INSTRUMENT_CLUSTER_SERVICE)) {
mClusterHomeService = constructWithTrace(
t, ClusterHomeService.class,
() -> new ClusterHomeService(serviceContext, mHal.getClusterHal(),
mClusterNavigationService, mCarOccupantZoneService,
mFixedActivityService), allServices);
} else {
Slogf.w(TAG, "Can't init ClusterHomeService, since Old cluster service is running");
mClusterHomeService = null;
}
} else {
mClusterHomeService = null;
}
if (mFeatureController.isFeatureEnabled(Car.CAR_EVS_SERVICE)) {
mCarEvsService = constructWithTrace(t, CarEvsService.class,
() -> new CarEvsService(serviceContext, mCarServiceBuiltinPackageContext,
mHal.getEvsHal(), mCarPropertyService), allServices);
} else {
mCarEvsService = null;
}
if (mFeatureController.isFeatureEnabled(Car.CAR_TELEMETRY_SERVICE)) {
if (carTelemetryService == null) {
mCarTelemetryService = constructWithTrace(t, CarTelemetryService.class,
() -> new CarTelemetryService(
serviceContext, mCarPowerManagementService, mCarPropertyService),
allServices);
} else {
mCarTelemetryService = carTelemetryService;
allServices.add(mCarTelemetryService);
}
} else {
mCarTelemetryService = null;
}
if (mFeatureController.isFeatureEnabled((Car.CAR_REMOTE_ACCESS_SERVICE))) {
if (carRemoteAccessService == null) {
mCarRemoteAccessService = constructWithTrace(t, CarRemoteAccessService.class,
() -> new CarRemoteAccessService(
serviceContext, systemInterface, mHal.getPowerHal()), allServices);
} else {
mCarRemoteAccessService = carRemoteAccessService;
mCarRemoteAccessService.setPowerHal(mHal.getPowerHal());
allServices.add(mCarRemoteAccessService);
}
} else {
mCarRemoteAccessService = null;
}
// Always put mCarExperimentalFeatureServiceController in last.
if (!BuildHelper.isUserBuild()) {
mCarExperimentalFeatureServiceController = constructWithTrace(
t, CarExperimentalFeatureServiceController.class,
() -> new CarExperimentalFeatureServiceController(serviceContext),
allServices);
} else {
mCarExperimentalFeatureServiceController = null;
}
if (mFeatureController.isFeatureEnabled(Car.CAR_OCCUPANT_CONNECTION_SERVICE)
|| mFeatureController.isFeatureEnabled(Car.CAR_REMOTE_DEVICE_SERVICE)) {
mCarRemoteDeviceService = constructWithTrace(
t, CarRemoteDeviceService.class,
() -> new CarRemoteDeviceService(serviceContext, mCarOccupantZoneService,
mCarPowerManagementService, mSystemActivityMonitoringService),
allServices);
mCarOccupantConnectionService = constructWithTrace(
t, CarOccupantConnectionService.class,
() -> new CarOccupantConnectionService(serviceContext, mCarOccupantZoneService,
mCarRemoteDeviceService),
allServices);
} else {
mCarOccupantConnectionService = null;
mCarRemoteDeviceService = null;
}
mAllServicesInInitOrder = allServices.toArray(new CarSystemService[allServices.size()]);
mICarSystemServerClientImpl = new ICarSystemServerClientImpl();
t.traceEnd(); // "ICarImpl.constructor"
}
@MainThread
void init() {
LimitedTimingsTraceLog t = new LimitedTimingsTraceLog(CAR_SERVICE_INIT_TIMING_TAG,
TraceHelper.TRACE_TAG_CAR_SERVICE, CAR_SERVICE_INIT_TIMING_MIN_DURATION_MS);
t.traceBegin("ICarImpl.init");
if (!mDoPriorityInitInConstruction) {
priorityInit();
}
t.traceBegin("CarService.initAllServices");
for (CarSystemService service : mAllServicesInInitOrder) {
t.traceBegin(service.getClass().getSimpleName());
service.init();
t.traceEnd();
}
t.traceBegin("CarOemService.initComplete");
mCarOemService.onInitComplete();
t.traceEnd();
t.traceEnd(); // "CarService.initAllServices"
t.traceEnd(); // "ICarImpl.init"
}
void release() {
// release done in opposite order from init
for (int i = mAllServicesInInitOrder.length - 1; i >= 0; i--) {
mAllServicesInInitOrder[i].release();
}
}
@Override
public void setSystemServerConnections(ICarServiceHelper carServiceHelper,
ICarResultReceiver resultReceiver) {
Bundle bundle;
try {
EventLogHelper.writeCarServiceSetCarServiceHelper(Binder.getCallingPid());
assertCallingFromSystemProcess();
mCarServiceHelperWrapper.setCarServiceHelper(carServiceHelper);
bundle = new Bundle();
bundle.putBinder(ICAR_SYSTEM_SERVER_CLIENT, mICarSystemServerClientImpl.asBinder());
} catch (Exception e) {
// send back a null response
Slogf.w(TAG, "Exception in setSystemServerConnections", e);
bundle = null;
}
try {
resultReceiver.send(/* unused */ 0, bundle);
} catch (RemoteException e) {
Slogf.w(TAG, "RemoteException from CarServiceHelperService", e);
}
}
@Override
public boolean isFeatureEnabled(String featureName) {
return mFeatureController.isFeatureEnabled(featureName);
}
@Override
public int enableFeature(String featureName) {
// permission check inside the controller
return mFeatureController.enableFeature(featureName);
}
@Override
public int disableFeature(String featureName) {
// permission check inside the controller
return mFeatureController.disableFeature(featureName);
}
@Override
public List<String> getAllEnabledFeatures() {
// permission check inside the controller
return mFeatureController.getAllEnabledFeatures();
}
@Override
public List<String> getAllPendingDisabledFeatures() {
// permission check inside the controller
return mFeatureController.getAllPendingDisabledFeatures();
}
@Override
public List<String> getAllPendingEnabledFeatures() {
// permission check inside the controller
return mFeatureController.getAllPendingEnabledFeatures();
}
@Override
@Nullable
public String getCarManagerClassForFeature(String featureName) {
if (mCarExperimentalFeatureServiceController == null) {
return null;
}
return mCarExperimentalFeatureServiceController.getCarManagerClassForFeature(featureName);
}
static void assertCallingFromSystemProcess() {
int uid = Binder.getCallingUid();
if (uid != Process.SYSTEM_UID) {
throw new SecurityException("Only allowed from system");
}
}
@Override
@Nullable
public IBinder getCarService(String serviceName) {
if (!mFeatureController.isFeatureEnabled(serviceName)) {
Slogf.w(CarLog.TAG_SERVICE, "getCarService for disabled service:" + serviceName);
return null;
}
switch (serviceName) {
case Car.AUDIO_SERVICE:
return mCarAudioService;
case Car.APP_FOCUS_SERVICE:
return mAppFocusService;
case Car.PACKAGE_SERVICE:
return mCarPackageManagerService;
case Car.DIAGNOSTIC_SERVICE:
CarServiceUtils.assertAnyDiagnosticPermission(mContext);
return mCarDiagnosticService;
case Car.POWER_SERVICE:
return mCarPowerManagementService;
case Car.CABIN_SERVICE:
case Car.HVAC_SERVICE:
case Car.INFO_SERVICE:
case Car.PROPERTY_SERVICE:
case Car.SENSOR_SERVICE:
case Car.VENDOR_EXTENSION_SERVICE:
return mCarPropertyService;
case Car.CAR_NAVIGATION_SERVICE:
CarServiceUtils.assertNavigationManagerPermission(mContext);
return mClusterNavigationService;
case Car.CAR_INSTRUMENT_CLUSTER_SERVICE:
CarServiceUtils.assertClusterManagerPermission(mContext);
return mInstrumentClusterService.getManagerService();
case Car.PROJECTION_SERVICE:
return mCarProjectionService;
case Car.VEHICLE_MAP_SERVICE:
CarServiceUtils.assertAnyVmsPermission(mContext);
return mVmsBrokerService;
case Car.VMS_SUBSCRIBER_SERVICE:
CarServiceUtils.assertVmsSubscriberPermission(mContext);
return mVmsBrokerService;
case Car.TEST_SERVICE: {
CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE);
synchronized (mLock) {
if (mCarTestService == null) {
mCarTestService = new CarTestService(mContext, this);
}
return mCarTestService;
}
}
case Car.STORAGE_MONITORING_SERVICE:
CarServiceUtils.assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
return mCarStorageMonitoringService;
case Car.CAR_DRIVING_STATE_SERVICE:
CarServiceUtils.assertDrivingStatePermission(mContext);
return mCarDrivingStateService;
case Car.CAR_UX_RESTRICTION_SERVICE:
return mCarUXRestrictionsService;
case Car.OCCUPANT_AWARENESS_SERVICE:
return mOccupantAwarenessService;
case Car.CAR_MEDIA_SERVICE:
return mCarMediaService;
case Car.CAR_OCCUPANT_ZONE_SERVICE:
return mCarOccupantZoneService;
case Car.CAR_BUGREPORT_SERVICE:
return mCarBugreportManagerService;
case Car.CAR_USER_SERVICE:
return mCarUserService;
case Car.EXPERIMENTAL_CAR_USER_SERVICE:
return mExperimentalCarUserService;
case Car.EXPERIMENTAL_CAR_KEYGUARD_SERVICE:
return mExperimentalCarKeyguardService;
case Car.CAR_WATCHDOG_SERVICE:
return mCarWatchdogService;
case Car.CAR_PERFORMANCE_SERVICE:
return mCarPerformanceService;
case Car.CAR_INPUT_SERVICE:
return mCarInputService;
case Car.CAR_DEVICE_POLICY_SERVICE:
return mCarDevicePolicyService;
case Car.CLUSTER_HOME_SERVICE:
return mClusterHomeService;
case Car.CAR_EVS_SERVICE:
return mCarEvsService;
case Car.CAR_TELEMETRY_SERVICE:
return mCarTelemetryService;
case Car.CAR_ACTIVITY_SERVICE:
return mCarActivityService;
case Car.CAR_OCCUPANT_CONNECTION_SERVICE:
return mCarOccupantConnectionService;
case Car.CAR_REMOTE_DEVICE_SERVICE:
return mCarRemoteDeviceService;
case Car.CAR_REMOTE_ACCESS_SERVICE:
return mCarRemoteAccessService;
default:
IBinder service = null;
if (mCarExperimentalFeatureServiceController != null) {
service = mCarExperimentalFeatureServiceController.getCarService(serviceName);
}
if (service == null) {
Slogf.w(CarLog.TAG_SERVICE, "getCarService for unknown service:"
+ serviceName);
}
return service;
}
}
@Override
@ExcludeFromCodeCoverageGeneratedReport(reason = DEPRECATED_CODE)
public int getCarConnectionType() {
return Car.CONNECTION_TYPE_EMBEDDED;
}
@Override
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
writer.println("Permission Denial: can't dump CarService from from pid="
+ Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ " without permission " + android.Manifest.permission.DUMP);
return;
}
try (IndentingPrintWriter pw = new IndentingPrintWriter(writer)) {
dumpIndenting(fd, pw, args);
}
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpIndenting(FileDescriptor fd, IndentingPrintWriter writer, String[] args) {
if (args == null || args.length == 0) {
dumpAll(writer);
return;
}
switch (args[0]) {
case "-a":
dumpAll(writer);
return;
case "--list":
dumpListOfServices(writer);
return;
case "--version":
dumpVersions(writer);
return;
case "--services": {
int length = args.length;
boolean dumpToProto = false;
if (length < 2) {
writer.println("Must pass services to dump when using --services");
return;
}
if (Objects.equals(args[length - 1], "--proto")) {
length -= 2;
dumpToProto = true;
if (length > 1) {
writer.println("Cannot dump multiple services to proto");
return;
}
} else {
length -= 1;
}
String[] services = new String[length];
System.arraycopy(args, 1, services, 0, length);
if (dumpToProto) {
if (!Flags.carDumpToProto()) {
writer.println("Cannot dump " + services[0]
+ " to proto since FLAG_CAR_DUMP_TO_PROTO is disabled");
return;
}
dumpServiceProto(writer, fd, services[0]);
} else {
dumpIndividualServices(writer, services);
}
return;
}
case "--metrics":
// Strip the --metrics flag when passing dumpsys arguments to CarStatsService
// allowing for nested flag selection.
if (args.length == 1 || Arrays.asList(args).contains("--vms-client")) {
mCarStatsService.dump(writer);
}
return;
case "--vms-hal":
mHal.getVmsHal().dumpMetrics(fd);
return;
case "--hal": {
if (args.length == 1) {
dumpAllHals(writer);
return;
}
int length = args.length - 1;
String[] halNames = new String[length];
System.arraycopy(args, 1, halNames, 0, length);
mHal.dumpSpecificHals(writer, halNames);
return;
}
case "--list-hals":
mHal.dumpListHals(writer);
return;
case "--data-dir":
dumpDataDir(writer);
return;
case "--help":
showDumpHelp(writer);
return;
case "--rro":
dumpRROs(writer);
return;
case "--oem-service":
if (args.length > 1 && args[1].equalsIgnoreCase("--name-only")) {
writer.println(getOemServiceName());
} else {
dumpOemService(writer);
}
return;
default:
execShellCmd(args, writer);
}
}
private void dumpOemService(IndentingPrintWriter writer) {
mCarOemService.dump(writer);
}
public String getOemServiceName() {
return mCarOemService.getOemServiceName();
}
private void dumpAll(IndentingPrintWriter writer) {
writer.println("*Dump car service*");
dumpVersions(writer);
dumpAllServices(writer);
dumpAllHals(writer);
dumpRROs(writer);
}
private void dumpRROs(IndentingPrintWriter writer) {
writer.println("*Dump Car Service RROs*");
String packageName = SystemProperties.get(
PROPERTY_CAR_SERVICE_PACKAGE_NAME, /*def= */null);
if (packageName == null) {
writer.println("Car Service updatable package name is null.");
return;
}
OverlayManager manager = mContext.getSystemService(OverlayManager.class);
List<OverlayInfo> installedOverlaysForSystem = manager.getOverlayInfosForTarget(packageName,
UserHandle.SYSTEM);
writer.println("RROs for System User");
for (int i = 0; i < installedOverlaysForSystem.size(); i++) {
OverlayInfo overlayInfo = installedOverlaysForSystem.get(i);
writer.printf("Overlay: %s, Enabled: %b \n", overlayInfo.getPackageName(),
overlayInfo.isEnabled());
}
int currentUser = ActivityManager.getCurrentUser();
writer.printf("RROs for Current User: %d\n", currentUser);
List<OverlayInfo> installedOverlaysForCurrentUser = manager.getOverlayInfosForTarget(
packageName, UserHandle.of(currentUser));
for (int i = 0; i < installedOverlaysForCurrentUser.size(); i++) {
OverlayInfo overlayInfo = installedOverlaysForCurrentUser.get(i);
writer.printf("Overlay: %s, Enabled: %b \n", overlayInfo.getPackageName(),
overlayInfo.isEnabled());
}
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpVersions(IndentingPrintWriter writer) {
writer.println("*Dump versions*");
writer.println("Android SDK_INT: " + Build.VERSION.SDK_INT);
writer.println("Car Version: " + Car.getCarVersion());
writer.println("Platform Version: " + Car.getPlatformVersion());
writer.println("CarBuiltin Platform minor: " + CarBuiltin.PLATFORM_VERSION_MINOR_INT);
writer.println("Legacy versions (might differ from above as they can't be emulated)");
writer.increaseIndent();
writer.println("Car API major: " + Car.API_VERSION_MAJOR_INT);
writer.println("Car API minor: " + Car.API_VERSION_MINOR_INT);
writer.println("Car Platform minor: " + Car.PLATFORM_VERSION_MINOR_INT);
writer.println("VHAL and Car User Service Priority Init: " + mDoPriorityInitInConstruction);
writer.decreaseIndent();
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpAllHals(IndentingPrintWriter writer) {
writer.println("*Dump Vehicle HAL*");
writer.println("Vehicle HAL Interface: " + mVehicleInterfaceName);
try {
// TODO dump all feature flags by creating a dumpable interface
mHal.dump(writer);
} catch (Exception e) {
writer.println("Failed dumping: " + mHal.getClass().getName());
e.printStackTrace(writer);
}
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void showDumpHelp(IndentingPrintWriter writer) {
writer.println("Car service dump usage:");
writer.println("[NO ARG]");
writer.println("\t dumps everything (all services and HALs)");
writer.println("--help");
writer.println("\t shows this help");
writer.println("--version");
writer.println("\t shows the version of all car components");
writer.println("--list");
writer.println("\t lists the name of all services");
writer.println("--list-hals");
writer.println("\t lists the name of all HALs");
writer.println("--services <SVC1> [SVC2] [SVCN]");
writer.println("\t dumps just the specific services, where SVC is just the service class");
writer.println("\t name (like CarUserService)");
writer.println("--vms-hal");
writer.println("\t dumps the VMS HAL metrics");
writer.println("--hal [HAL1] [HAL2] [HALN]");
writer.println("\t dumps just the specified HALs (or all of them if none specified),");
writer.println("\t where HAL is just the class name (like UserHalService)");
writer.println("--user-metrics");
writer.println("\t dumps user switching and stopping metrics");
writer.println("--first-user-metrics");
writer.println("\t dumps how long it took to unlock first user since Android started\n");
writer.println("\t (or -1 if not unlocked)");
writer.println("--data-dir");
writer.println("\t dumps CarService data dir (and whether it exists)");
writer.println("--rro");
writer.println("\t dumps only the RROs");
writer.println("-h");
writer.println("\t shows commands usage (NOTE: commands are not available on USER builds");
writer.println("[ANYTHING ELSE]");
writer.println("\t runs the given command (use --h to see the available commands)");
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpDataDir(IndentingPrintWriter writer) {
File dataDir = mContext.getDataDir();
writer.printf("Data dir: %s Exists: %b\n", dataDir.getAbsolutePath(), dataDir.exists());
}
@Override
public boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
// Shell cmd is handled specially.
if (BinderHelper.onTransactForCmd(code, data, reply, flags, mCmdListener)) {
return true;
}
return super.onTransact(code, data, reply, flags);
}
private CarShellCommand newCarShellCommand() {
Map<Class, CarSystemService> allServicesByClazz = new ArrayMap<>();
for (CarSystemService service : mAllServicesInInitOrder) {
allServicesByClazz.put(service.getClass(), service);
}
return new CarShellCommand(mContext, mHal, mFeatureController, mSystemInterface,
allServicesByClazz);
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpListOfServices(IndentingPrintWriter writer) {
for (CarSystemService service : mAllServicesInInitOrder) {
writer.println(service.getClass().getName());
}
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpAllServices(IndentingPrintWriter writer) {
writer.println("*Dump all services*");
for (CarSystemService service : mAllServicesInInitOrder) {
if (service instanceof CarServiceBase) {
dumpService(service, writer);
}
}
synchronized (mLock) {
if (mCarTestService != null) {
dumpService(mCarTestService, writer);
}
}
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpIndividualServices(IndentingPrintWriter writer, String... serviceNames) {
for (String serviceName : serviceNames) {
writer.printf("** Dumping %s\n\n", serviceName);
CarSystemService service = getCarServiceBySubstring(serviceName);
if (service == null) {
writer.println("No such service!");
} else {
dumpService(service, writer);
}
writer.println();
}
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpServiceProto(IndentingPrintWriter writer, FileDescriptor fd,
String serviceName) {
CarSystemService service = getCarServiceBySubstring(serviceName);
if (service == null) {
writer.println("No such service!");
} else {
if (service instanceof CarServiceBase) {
CarServiceBase carService = (CarServiceBase) service;
try (FileOutputStream fileStream = new FileOutputStream(fd)) {
ProtoOutputStream proto = new ProtoOutputStream(fileStream);
carService.dumpProto(proto);
proto.flush();
} catch (Exception e) {
writer.println("Failed dumping: " + carService.getClass().getName());
e.printStackTrace(writer);
}
} else {
writer.println("Only services that extend CarServiceBase can dump to proto");
}
}
}
@Nullable
private CarSystemService getCarServiceBySubstring(String className) {
return Arrays.asList(mAllServicesInInitOrder).stream()
.filter(s -> s.getClass().getSimpleName().equals(className))
.findFirst().orElse(null);
}
@ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
private void dumpService(CarSystemService service, IndentingPrintWriter writer) {
try {
service.dump(writer);
} catch (Exception e) {
writer.println("Failed dumping: " + service.getClass().getName());
e.printStackTrace(writer);
}
}
void execShellCmd(String[] args, IndentingPrintWriter writer) {
newCarShellCommand().exec(args, writer);
}
private <T extends CarSystemService> T constructWithTrace(LimitedTimingsTraceLog t,
Class<T> cls, Callable<T> callable, List<CarSystemService> allServices) {
t.traceBegin(cls.getSimpleName());
T constructed;
try {
constructed = callable.call();
CarLocalServices.addService(cls, constructed);
} catch (Exception e) {
throw new RuntimeException("Crash while constructing:" + cls.getSimpleName(), e);
} finally {
t.traceEnd();
}
allServices.add(constructed);
return constructed;
}
private final class ICarSystemServerClientImpl extends ICarSystemServerClient.Stub {
@Override
public void onUserLifecycleEvent(int eventType, int fromUserId, int toUserId)
throws RemoteException {
assertCallingFromSystemProcess();
EventLogHelper.writeCarServiceOnUserLifecycle(eventType, fromUserId, toUserId);
if (DBG) {
Slogf.d(TAG,
"onUserLifecycleEvent("
+ CarUserManager.lifecycleEventTypeToString(eventType) + ", "
+ toUserId + ")");
}
mCarUserService.onUserLifecycleEvent(eventType, fromUserId, toUserId);
}
@Override
public void initBootUser() throws RemoteException {
// TODO(b/277271542). Remove this code path.
}
// TODO(235524989): Remove this method as on user removed will now go through
// onUserLifecycleEvent due to changes in CarServiceProxy and CarUserService.
@Override
public void onUserRemoved(UserHandle user) throws RemoteException {
assertCallingFromSystemProcess();
EventLogHelper.writeCarServiceOnUserRemoved(user.getIdentifier());
if (DBG) Slogf.d(TAG, "onUserRemoved(): " + user);
mCarUserService.onUserRemoved(user);
}
@Override
public void onFactoryReset(ICarResultReceiver callback) {
assertCallingFromSystemProcess();
mCarPowerManagementService.setFactoryResetCallback(callback);
BuiltinPackageDependency.createNotificationHelper(mCarServiceBuiltinPackageContext)
.showFactoryResetNotification(callback);
}
@Override
public void setInitialUser(UserHandle user) {
mCarUserService.setInitialUserFromSystemServer(user);
}
}
/* package */ void dumpVhal(ParcelFileDescriptor fd, List<String> options)
throws RemoteException {
mHal.dumpVhal(fd, options);
}
/* package */ boolean hasAidlVhal() {
return mHal.isAidlVhal();
}
/* package */ void priorityInit() {
mHal.priorityInit();
mCarUserService.priorityInit();
}
}