1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.android.car.kitchensink; 18 19 import android.car.Car; 20 import android.car.CarOccupantZoneManager; 21 import android.car.CarProjectionManager; 22 import android.car.hardware.CarSensorManager; 23 import android.car.hardware.hvac.CarHvacManager; 24 import android.car.hardware.power.CarPowerManager; 25 import android.car.hardware.property.CarPropertyManager; 26 import android.car.os.CarPerformanceManager; 27 import android.car.telemetry.CarTelemetryManager; 28 import android.car.watchdog.CarWatchdogManager; 29 import android.content.Context; 30 import android.content.pm.PackageManager; 31 import android.os.Handler; 32 import android.util.Log; 33 34 import androidx.annotation.GuardedBy; 35 36 import java.util.ArrayList; 37 import java.util.List; 38 39 public class KitchenSinkHelperImpl implements KitchenSinkHelper { 40 private static final String TAG = "KitchenSinkHelperImpl"; 41 42 private final Object mLock = new Object(); 43 @GuardedBy("mLock") 44 private Car mCarApi; 45 @GuardedBy("mLock") 46 private CarHvacManager mHvacManager; 47 @GuardedBy("mLock") 48 private CarOccupantZoneManager mOccupantZoneManager; 49 @GuardedBy("mLock") 50 private CarPowerManager mPowerManager; 51 @GuardedBy("mLock") 52 private CarPropertyManager mPropertyManager; 53 @GuardedBy("mLock") 54 private CarSensorManager mSensorManager; 55 @GuardedBy("mLock") 56 private CarProjectionManager mCarProjectionManager; 57 @GuardedBy("mLock") 58 private CarTelemetryManager mCarTelemetryManager; 59 @GuardedBy("mLock") 60 private CarWatchdogManager mCarWatchdogManager; 61 @GuardedBy("mLock") 62 private CarPerformanceManager mCarPerformanceManager; 63 @GuardedBy("mLock") 64 private boolean mCarReady = false; 65 HandlerRunnable(Handler h, Runnable r)66 private record HandlerRunnable(Handler h, Runnable r) {} 67 68 // A list of callbacks that would be posted to handlers every time car service is connected 69 // or reconnected. 70 @GuardedBy("mLock") 71 private final List<HandlerRunnable> mCarReadyCallbacks = new ArrayList<>(); 72 73 @Override getCar()74 public Car getCar() { 75 synchronized (mLock) { 76 return mCarApi; 77 } 78 } 79 80 @Override requestRefreshManager(final Runnable r, final Handler h)81 public void requestRefreshManager(final Runnable r, final Handler h) { 82 synchronized (mLock) { 83 mCarReadyCallbacks.add(new HandlerRunnable(h, r)); 84 85 if (mCarReady) { 86 // If car service is already ready, we already missed the initial callback so 87 // we invoke the runnable now. 88 h.post(r); 89 } 90 } 91 } 92 93 @Override getPropertyManager()94 public CarPropertyManager getPropertyManager() { 95 synchronized (mLock) { 96 if (mPropertyManager == null) { 97 mPropertyManager = (CarPropertyManager) mCarApi.getCarManager( 98 android.car.Car.PROPERTY_SERVICE); 99 } 100 return mPropertyManager; 101 } 102 } 103 104 @Override getHvacManager()105 public CarHvacManager getHvacManager() { 106 synchronized (mLock) { 107 if (mHvacManager == null) { 108 mHvacManager = (CarHvacManager) mCarApi.getCarManager(android.car.Car.HVAC_SERVICE); 109 } 110 return mHvacManager; 111 } 112 } 113 114 @Override getOccupantZoneManager()115 public CarOccupantZoneManager getOccupantZoneManager() { 116 synchronized (mLock) { 117 if (mOccupantZoneManager == null) { 118 mOccupantZoneManager = (CarOccupantZoneManager) mCarApi.getCarManager( 119 android.car.Car.CAR_OCCUPANT_ZONE_SERVICE); 120 } 121 return mOccupantZoneManager; 122 } 123 } 124 125 @Override getPowerManager()126 public CarPowerManager getPowerManager() { 127 synchronized (mLock) { 128 if (mPowerManager == null) { 129 mPowerManager = (CarPowerManager) mCarApi.getCarManager( 130 android.car.Car.POWER_SERVICE); 131 } 132 return mPowerManager; 133 } 134 } 135 136 @Override getSensorManager()137 public CarSensorManager getSensorManager() { 138 synchronized (mLock) { 139 if (mSensorManager == null) { 140 mSensorManager = (CarSensorManager) mCarApi.getCarManager( 141 android.car.Car.SENSOR_SERVICE); 142 } 143 return mSensorManager; 144 } 145 } 146 147 @Override getProjectionManager()148 public CarProjectionManager getProjectionManager() { 149 synchronized (mLock) { 150 if (mCarProjectionManager == null) { 151 mCarProjectionManager = 152 (CarProjectionManager) mCarApi.getCarManager(Car.PROJECTION_SERVICE); 153 } 154 return mCarProjectionManager; 155 } 156 } 157 158 @Override getCarTelemetryManager()159 public CarTelemetryManager getCarTelemetryManager() { 160 synchronized (mLock) { 161 if (mCarTelemetryManager == null) { 162 mCarTelemetryManager = 163 (CarTelemetryManager) mCarApi.getCarManager(Car.CAR_TELEMETRY_SERVICE); 164 } 165 return mCarTelemetryManager; 166 } 167 } 168 169 @Override getCarWatchdogManager()170 public CarWatchdogManager getCarWatchdogManager() { 171 synchronized (mLock) { 172 if (mCarWatchdogManager == null) { 173 mCarWatchdogManager = 174 (CarWatchdogManager) mCarApi.getCarManager(Car.CAR_WATCHDOG_SERVICE); 175 } 176 return mCarWatchdogManager; 177 } 178 } 179 180 @Override getPerformanceManager()181 public CarPerformanceManager getPerformanceManager() { 182 synchronized (mLock) { 183 if (mCarPerformanceManager == null) { 184 mCarPerformanceManager = 185 (CarPerformanceManager) mCarApi.getCarManager(Car.CAR_PERFORMANCE_SERVICE); 186 } 187 return mCarPerformanceManager; 188 } 189 } 190 191 /** 192 * Initialized Car API if in automotive. Must be called during onCreate. 193 */ initCarApiIfAutomotive(Context context)194 public void initCarApiIfAutomotive(Context context) { 195 // Connection to Car Service does not work for non-automotive yet. 196 if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 197 initCarApi(context); 198 } 199 } 200 201 /** 202 * Disconnects from car service. Must be called during onDestroy. 203 */ disconnect()204 public void disconnect() { 205 synchronized (mLock) { 206 if (mCarApi != null) { 207 mCarApi.disconnect(); 208 mCarApi = null; 209 } 210 } 211 } 212 initCarApi(Context context)213 private void initCarApi(Context context) { 214 synchronized (mLock) { 215 if (mCarApi != null && mCarApi.isConnected()) { 216 mCarApi.disconnect(); 217 mCarApi = null; 218 } 219 } 220 Car.createCar(context, null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER, 221 (Car car, boolean ready) -> { 222 synchronized (mLock) { 223 mCarApi = car; 224 mCarReady = ready; 225 if (!mCarReady) { 226 return; 227 } 228 229 Log.d(TAG, "Car service connected"); 230 231 mHvacManager = null; 232 mOccupantZoneManager = null; 233 mPowerManager = null; 234 mPropertyManager = null; 235 mSensorManager = null; 236 mCarProjectionManager = null; 237 mCarTelemetryManager = null; 238 mCarWatchdogManager = null; 239 mCarPerformanceManager = null; 240 241 for (int i = 0; i < mCarReadyCallbacks.size(); i++) { 242 var handlerRunnable = mCarReadyCallbacks.get(i); 243 handlerRunnable.h.post(handlerRunnable.r); 244 } 245 } 246 }); 247 } 248 } 249