blob: be888d304c9d984e65cfd2dc13671d7e6a6aa027 [file] [log] [blame]
Eric Jeong38ae8212020-01-14 10:25:10 -08001/*
2 * Copyright (C) 2020 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
17package com.android.car.watchdog;
18
Eric Jeong01a28aa2020-03-27 16:43:19 -070019import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING;
20import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STOPPED;
Eric Jeongae2c04c2020-02-21 09:18:31 -080021
Eric Jeong09657562020-03-20 16:02:39 -070022import static com.android.car.CarLog.TAG_WATCHDOG;
Eric Jeong09657562020-03-20 16:02:39 -070023
24import android.annotation.NonNull;
Lakshman Annadorai8a67df12021-06-29 19:33:37 -070025import android.automotive.watchdog.internal.GarageMode;
Lakshman Annadoraid26098a2020-11-10 14:05:04 -080026import android.automotive.watchdog.internal.ICarWatchdogServiceForSystem;
Lakshman Annadorai8dfeeaf2020-12-15 14:10:53 -080027import android.automotive.watchdog.internal.PackageInfo;
Lakshman Annadoraidd4a4e42021-02-19 14:22:06 -080028import android.automotive.watchdog.internal.PackageIoOveruseStats;
Lakshman Annadorai967b21e2020-10-30 09:35:29 -070029import android.automotive.watchdog.internal.PowerCycle;
30import android.automotive.watchdog.internal.StateType;
Lakshman Annadorai03cbd1f2021-10-08 18:39:10 +000031import android.automotive.watchdog.internal.UserPackageIoUsageStats;
Lakshman Annadorai967b21e2020-10-30 09:35:29 -070032import android.automotive.watchdog.internal.UserState;
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -080033import android.car.Car;
Eric Jeong27a178f2020-03-24 16:39:39 -070034import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -070035import android.car.hardware.power.CarPowerPolicy;
36import android.car.hardware.power.CarPowerPolicyFilter;
37import android.car.hardware.power.ICarPowerPolicyListener;
Eric Jeong27a178f2020-03-24 16:39:39 -070038import android.car.hardware.power.ICarPowerStateListener;
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -070039import android.car.hardware.power.PowerComponent;
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -080040import android.car.watchdog.CarWatchdogManager;
Eric Jeong38ae8212020-01-14 10:25:10 -080041import android.car.watchdog.ICarWatchdogService;
Eric Jeong4e111e92020-06-23 19:50:55 -070042import android.car.watchdog.ICarWatchdogServiceCallback;
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -080043import android.car.watchdog.IResourceOveruseListener;
44import android.car.watchdog.PackageKillableState;
45import android.car.watchdog.ResourceOveruseConfiguration;
46import android.car.watchdog.ResourceOveruseStats;
Eric Jeong6df075f2020-03-11 16:12:23 -070047import android.car.watchdoglib.CarWatchdogDaemonHelper;
Lakshman Annadorai8a67df12021-06-29 19:33:37 -070048import android.content.BroadcastReceiver;
Eric Jeongae2c04c2020-02-21 09:18:31 -080049import android.content.Context;
Lakshman Annadorai8a67df12021-06-29 19:33:37 -070050import android.content.Intent;
51import android.content.IntentFilter;
Eric Jeong01a28aa2020-03-27 16:43:19 -070052import android.content.pm.UserInfo;
Eric Jeongae2c04c2020-02-21 09:18:31 -080053import android.os.RemoteException;
Eric Jeong01a28aa2020-03-27 16:43:19 -070054import android.os.UserHandle;
55import android.os.UserManager;
Lakshman Annadoraiec4d08a2021-04-30 08:29:10 -070056import android.util.ArraySet;
Felipe Leme176a5fd2021-01-20 15:48:33 -080057import android.util.IndentingPrintWriter;
Eric Jeongae2c04c2020-02-21 09:18:31 -080058
Eric Jeong27a178f2020-03-24 16:39:39 -070059import com.android.car.CarLocalServices;
Mayank Garg72c71d22021-02-03 23:54:45 -080060import com.android.car.CarLog;
Eric Jeong38ae8212020-01-14 10:25:10 -080061import com.android.car.CarServiceBase;
Eric Jeong7e481702021-05-14 11:14:06 -070062import com.android.car.CarServiceUtils;
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -080063import com.android.car.ICarImpl;
Eric Jeongbc351e22020-07-31 13:54:17 -070064import com.android.car.power.CarPowerManagementService;
Eric Jeong01a28aa2020-03-27 16:43:19 -070065import com.android.car.user.CarUserService;
Eric Jeong7e481702021-05-14 11:14:06 -070066import com.android.internal.annotations.GuardedBy;
Eric Jeong0ee72812020-04-21 15:23:54 -070067import com.android.internal.annotations.VisibleForTesting;
Lakshman Annadoraie17cba72020-12-17 14:03:36 -080068import com.android.internal.util.ArrayUtils;
Lakshman Annadorai54e10542021-03-16 15:36:04 -070069import com.android.server.utils.Slogf;
Eric Jeong38ae8212020-01-14 10:25:10 -080070
Eric Jeong38ae8212020-01-14 10:25:10 -080071import java.lang.ref.WeakReference;
Lakshman Annadorai282c3ce2021-08-17 09:08:27 -070072import java.time.Instant;
Eric Jeong01a28aa2020-03-27 16:43:19 -070073import java.util.List;
Eric Jeong38ae8212020-01-14 10:25:10 -080074
75/**
76 * Service to implement CarWatchdogManager API.
Eric Jeong38ae8212020-01-14 10:25:10 -080077 */
78public final class CarWatchdogService extends ICarWatchdogService.Stub implements CarServiceBase {
Lakshman Annadoraid7b8a032021-04-20 12:31:05 -070079 static final boolean DEBUG = false; // STOPSHIP if true
80 static final String TAG = CarLog.tagFor(CarWatchdogService.class);
Lakshman Annadorai8a67df12021-06-29 19:33:37 -070081 static final String ACTION_GARAGE_MODE_ON =
82 "com.android.server.jobscheduler.GARAGE_MODE_ON";
83 static final String ACTION_GARAGE_MODE_OFF =
84 "com.android.server.jobscheduler.GARAGE_MODE_OFF";
Jahdiel Alvarez9de7aa52021-09-10 04:39:23 +000085 static final int MISSING_ARG_VALUE = -1;
Lakshman Annadorai282c3ce2021-08-17 09:08:27 -070086 static final TimeSourceInterface SYSTEM_INSTANCE = new TimeSourceInterface() {
87 @Override
88 public Instant now() {
89 return Instant.now();
90 }
91
92 @Override
93 public String toString() {
94 return "System time instance";
95 }
96 };
Eric Jeong09657562020-03-20 16:02:39 -070097
Eric Jeongae2c04c2020-02-21 09:18:31 -080098 private final Context mContext;
Lakshman Annadoraid26098a2020-11-10 14:05:04 -080099 private final ICarWatchdogServiceForSystemImpl mWatchdogServiceForSystem;
Lakshman Annadorai5f1181b2021-04-01 16:03:07 -0700100 private final PackageInfoHandler mPackageInfoHandler;
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700101 private final WatchdogStorage mWatchdogStorage;
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700102 private final WatchdogProcessHandler mWatchdogProcessHandler;
103 private final WatchdogPerfHandler mWatchdogPerfHandler;
Eric Jeong09657562020-03-20 16:02:39 -0700104 private final CarWatchdogDaemonHelper mCarWatchdogDaemonHelper;
Lakshman Annadorai8ee56ec2021-04-27 11:51:08 -0700105 private final CarWatchdogDaemonHelper.OnConnectionChangeListener mConnectionListener;
Lakshman Annadorai8a67df12021-06-29 19:33:37 -0700106 /*
107 * TODO(b/192481350): Listen for GarageMode change notification rather than depending on the
108 * system_server broadcast when the CarService internal API for listening GarageMode change is
109 * implemented.
110 */
111 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
112 @Override
113 public void onReceive(Context context, Intent intent) {
114 final String action = intent.getAction();
Jahdiel Alvarez9de7aa52021-09-10 04:39:23 +0000115 switch (action) {
116 case ACTION_GARAGE_MODE_ON:
117 case ACTION_GARAGE_MODE_OFF:
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000118 int garageMode;
119 synchronized (mLock) {
120 garageMode = mCurrentGarageMode = action.equals(ACTION_GARAGE_MODE_ON)
121 ? GarageMode.GARAGE_MODE_ON : GarageMode.GARAGE_MODE_OFF;
122 }
Lakshman Annadorai678feda2021-10-25 16:23:46 -0700123 mWatchdogPerfHandler.onGarageModeChange(garageMode);
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000124 if (garageMode == GarageMode.GARAGE_MODE_ON) {
125 mWatchdogStorage.shrinkDatabase();
126 }
127 notifyGarageModeChange(garageMode);
128 return;
Jahdiel Alvarez9de7aa52021-09-10 04:39:23 +0000129 case Intent.ACTION_USER_REMOVED:
130 UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
131 mWatchdogPerfHandler.deleteUser(user.getIdentifier());
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000132 return;
Lakshman Annadorai8a67df12021-06-29 19:33:37 -0700133 }
134 }
135 };
136
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700137 private final ICarPowerStateListener mCarPowerStateListener =
138 new ICarPowerStateListener.Stub() {
139 @Override
140 public void onStateChanged(int state) {
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000141 CarPowerManagementService powerService =
142 CarLocalServices.getService(CarPowerManagementService.class);
143 if (powerService == null) {
144 return;
145 }
146 int powerCycle = carPowerStateToPowerCycle(powerService.getPowerState());
147 switch (powerCycle) {
148 case PowerCycle.POWER_CYCLE_SHUTDOWN_ENTER:
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700149 mWatchdogPerfHandler.writeToDatabase();
150 break;
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000151 // ON covers resume.
152 case PowerCycle.POWER_CYCLE_RESUME:
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700153 // There might be outdated & incorrect info. We should reset them before
154 // starting to do health check.
155 mWatchdogProcessHandler.prepareHealthCheck();
156 break;
157 default:
158 return;
159 }
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000160 notifyPowerCycleChange(powerCycle);
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700161 }
162 };
163
164 private final ICarPowerPolicyListener mCarDisplayPowerPolicyListener =
165 new ICarPowerPolicyListener.Stub() {
166 @Override
167 public void onPolicyChanged(CarPowerPolicy appliedPolicy,
168 CarPowerPolicy accumulatedPolicy) {
Lakshman Annadorai04416132021-10-18 16:35:34 +0000169 boolean isDisplayEnabled =
170 appliedPolicy.isComponentEnabled(PowerComponent.DISPLAY);
171 boolean didStateChange = false;
172 synchronized (mLock) {
173 didStateChange = mIsDisplayEnabled != isDisplayEnabled;
174 mIsDisplayEnabled = isDisplayEnabled;
175 }
176 if (didStateChange) {
177 mWatchdogPerfHandler.onDisplayStateChanged(isDisplayEnabled);
178 }
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700179 }
180 };
181
Eric Jeong7e481702021-05-14 11:14:06 -0700182 private final Object mLock = new Object();
183 @GuardedBy("mLock")
184 private boolean mReadyToRespond;
185 @GuardedBy("mLock")
186 private boolean mIsConnected;
Lakshman Annadorai04416132021-10-18 16:35:34 +0000187 @GuardedBy("mLock")
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000188 private @GarageMode int mCurrentGarageMode;
189 @GuardedBy("mLock")
Lakshman Annadorai04416132021-10-18 16:35:34 +0000190 private boolean mIsDisplayEnabled;
Eric Jeong09657562020-03-20 16:02:39 -0700191
Eric Jeong0ee72812020-04-21 15:23:54 -0700192 public CarWatchdogService(Context context) {
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700193 this(context, new WatchdogStorage(context));
194 }
195
196 @VisibleForTesting
197 CarWatchdogService(Context context, WatchdogStorage watchdogStorage) {
Eric Jeongae2c04c2020-02-21 09:18:31 -0800198 mContext = context;
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700199 mWatchdogStorage = watchdogStorage;
Lakshman Annadorai5f1181b2021-04-01 16:03:07 -0700200 mPackageInfoHandler = new PackageInfoHandler(mContext.getPackageManager());
Eric Jeong0ee72812020-04-21 15:23:54 -0700201 mCarWatchdogDaemonHelper = new CarWatchdogDaemonHelper(TAG_WATCHDOG);
Lakshman Annadoraid26098a2020-11-10 14:05:04 -0800202 mWatchdogServiceForSystem = new ICarWatchdogServiceForSystemImpl(this);
Lakshman Annadoraicf5f3a92021-04-02 15:26:16 -0700203 mWatchdogProcessHandler = new WatchdogProcessHandler(mWatchdogServiceForSystem,
Lakshman Annadoraid7b8a032021-04-20 12:31:05 -0700204 mCarWatchdogDaemonHelper);
Lakshman Annadoraicf5f3a92021-04-02 15:26:16 -0700205 mWatchdogPerfHandler = new WatchdogPerfHandler(mContext, mCarWatchdogDaemonHelper,
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700206 mPackageInfoHandler, mWatchdogStorage);
Lakshman Annadorai8ee56ec2021-04-27 11:51:08 -0700207 mConnectionListener = (isConnected) -> {
Lakshman Annadorai8ee56ec2021-04-27 11:51:08 -0700208 mWatchdogPerfHandler.onDaemonConnectionChange(isConnected);
Eric Jeong7e481702021-05-14 11:14:06 -0700209 synchronized (mLock) {
210 mIsConnected = isConnected;
211 }
212 registerToDaemon();
Lakshman Annadorai8ee56ec2021-04-27 11:51:08 -0700213 };
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000214 mCurrentGarageMode = GarageMode.GARAGE_MODE_OFF;
Lakshman Annadorai04416132021-10-18 16:35:34 +0000215 mIsDisplayEnabled = true;
Eric Jeong38ae8212020-01-14 10:25:10 -0800216 }
217
218 @Override
219 public void init() {
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700220 mWatchdogProcessHandler.init();
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700221 mWatchdogPerfHandler.init();
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700222 subscribePowerManagementService();
Eric Jeong01a28aa2020-03-27 16:43:19 -0700223 subscribeUserStateChange();
Lakshman Annadorai8a67df12021-06-29 19:33:37 -0700224 subscribeBroadcastReceiver();
Eric Jeong6df075f2020-03-11 16:12:23 -0700225 mCarWatchdogDaemonHelper.addOnConnectionChangeListener(mConnectionListener);
226 mCarWatchdogDaemonHelper.connect();
Eric Jeong7e481702021-05-14 11:14:06 -0700227 // To make sure the main handler is ready for responding to car watchdog daemon, registering
228 // to the daemon is done through the main handler. Once the registration is completed, we
229 // can assume that the main handler is not too busy handling other stuffs.
230 postRegisterToDaemonMessage();
Eric Jeong09657562020-03-20 16:02:39 -0700231 if (DEBUG) {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700232 Slogf.d(TAG, "CarWatchdogService is initialized");
Eric Jeong09657562020-03-20 16:02:39 -0700233 }
Eric Jeong38ae8212020-01-14 10:25:10 -0800234 }
235
236 @Override
237 public void release() {
Lakshman Annadorai8a67df12021-06-29 19:33:37 -0700238 mContext.unregisterReceiver(mBroadcastReceiver);
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700239 unsubscribePowerManagementService();
240 mWatchdogPerfHandler.release();
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700241 mWatchdogStorage.release();
Eric Jeong6df075f2020-03-11 16:12:23 -0700242 unregisterFromDaemon();
243 mCarWatchdogDaemonHelper.disconnect();
Eric Jeong38ae8212020-01-14 10:25:10 -0800244 }
245
246 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -0800247 public void dump(IndentingPrintWriter writer) {
Lakshman Annadorai593672d2021-10-21 17:00:43 -0700248 writer.println("*" + getClass().getSimpleName() + "*");
249 writer.increaseIndent();
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000250 synchronized (mLock) {
251 writer.println("Current garage mode: " + toGarageModeString(mCurrentGarageMode));
252 }
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700253 mWatchdogProcessHandler.dump(writer);
254 mWatchdogPerfHandler.dump(writer);
Lakshman Annadorai593672d2021-10-21 17:00:43 -0700255 writer.decreaseIndent();
Eric Jeong38ae8212020-01-14 10:25:10 -0800256 }
257
Eric Jeong09657562020-03-20 16:02:39 -0700258 /**
Eric Jeong4e111e92020-06-23 19:50:55 -0700259 * Registers {@link android.car.watchdog.ICarWatchdogServiceCallback} to
Eric Jeong09657562020-03-20 16:02:39 -0700260 * {@link CarWatchdogService}.
261 */
Eric Jeong38ae8212020-01-14 10:25:10 -0800262 @Override
Eric Jeong4e111e92020-06-23 19:50:55 -0700263 public void registerClient(ICarWatchdogServiceCallback client, int timeout) {
Jahdiel Alvarez4537c082021-05-25 21:34:20 +0000264 ICarImpl.assertPermission(mContext, Car.PERMISSION_USE_CAR_WATCHDOG);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700265 mWatchdogProcessHandler.registerClient(client, timeout);
Eric Jeong38ae8212020-01-14 10:25:10 -0800266 }
267
Eric Jeong09657562020-03-20 16:02:39 -0700268 /**
Eric Jeong4e111e92020-06-23 19:50:55 -0700269 * Unregisters {@link android.car.watchdog.ICarWatchdogServiceCallback} from
Eric Jeong09657562020-03-20 16:02:39 -0700270 * {@link CarWatchdogService}.
271 */
Eric Jeong38ae8212020-01-14 10:25:10 -0800272 @Override
Eric Jeong4e111e92020-06-23 19:50:55 -0700273 public void unregisterClient(ICarWatchdogServiceCallback client) {
Jahdiel Alvarez4537c082021-05-25 21:34:20 +0000274 ICarImpl.assertPermission(mContext, Car.PERMISSION_USE_CAR_WATCHDOG);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700275 mWatchdogProcessHandler.unregisterClient(client);
Eric Jeong38ae8212020-01-14 10:25:10 -0800276 }
277
Eric Jeong09657562020-03-20 16:02:39 -0700278 /**
279 * Tells {@link CarWatchdogService} that the client is alive.
280 */
Eric Jeong38ae8212020-01-14 10:25:10 -0800281 @Override
Eric Jeong4e111e92020-06-23 19:50:55 -0700282 public void tellClientAlive(ICarWatchdogServiceCallback client, int sessionId) {
Jahdiel Alvarez4537c082021-05-25 21:34:20 +0000283 ICarImpl.assertPermission(mContext, Car.PERMISSION_USE_CAR_WATCHDOG);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700284 mWatchdogProcessHandler.tellClientAlive(client, sessionId);
285 }
286
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800287 /** Returns {@link android.car.watchdog.ResourceOveruseStats} for the calling package. */
288 @Override
289 @NonNull
290 public ResourceOveruseStats getResourceOveruseStats(
291 @CarWatchdogManager.ResourceOveruseFlag int resourceOveruseFlag,
292 @CarWatchdogManager.StatsPeriod int maxStatsPeriod) {
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700293 return mWatchdogPerfHandler.getResourceOveruseStats(resourceOveruseFlag, maxStatsPeriod);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800294 }
295
296 /**
297 * Returns {@link android.car.watchdog.ResourceOveruseStats} for all packages for the maximum
298 * specified period, and the specified resource types with stats greater than or equal to the
299 * minimum specified stats.
300 */
301 @Override
302 @NonNull
303 public List<ResourceOveruseStats> getAllResourceOveruseStats(
304 @CarWatchdogManager.ResourceOveruseFlag int resourceOveruseFlag,
305 @CarWatchdogManager.MinimumStatsFlag int minimumStatsFlag,
306 @CarWatchdogManager.StatsPeriod int maxStatsPeriod) {
307 ICarImpl.assertPermission(mContext, Car.PERMISSION_COLLECT_CAR_WATCHDOG_METRICS);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700308 return mWatchdogPerfHandler.getAllResourceOveruseStats(resourceOveruseFlag,
309 minimumStatsFlag, maxStatsPeriod);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800310 }
311
312 /** Returns {@link android.car.watchdog.ResourceOveruseStats} for the specified user package. */
313 @Override
314 @NonNull
315 public ResourceOveruseStats getResourceOveruseStatsForUserPackage(
316 @NonNull String packageName, @NonNull UserHandle userHandle,
317 @CarWatchdogManager.ResourceOveruseFlag int resourceOveruseFlag,
318 @CarWatchdogManager.StatsPeriod int maxStatsPeriod) {
319 ICarImpl.assertPermission(mContext, Car.PERMISSION_COLLECT_CAR_WATCHDOG_METRICS);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700320 return mWatchdogPerfHandler.getResourceOveruseStatsForUserPackage(packageName, userHandle,
321 resourceOveruseFlag, maxStatsPeriod);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800322 }
323
324 /**
325 * Adds {@link android.car.watchdog.IResourceOveruseListener} for the calling package's resource
326 * overuse notifications.
327 */
328 @Override
329 public void addResourceOveruseListener(
330 @CarWatchdogManager.ResourceOveruseFlag int resourceOveruseFlag,
331 @NonNull IResourceOveruseListener listener) {
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700332 mWatchdogPerfHandler.addResourceOveruseListener(resourceOveruseFlag, listener);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800333 }
334
335 /**
336 * Removes the previously added {@link android.car.watchdog.IResourceOveruseListener} for the
337 * calling package's resource overuse notifications.
338 */
339 @Override
340 public void removeResourceOveruseListener(@NonNull IResourceOveruseListener listener) {
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700341 mWatchdogPerfHandler.removeResourceOveruseListener(listener);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800342 }
343
344 /**
345 * Adds {@link android.car.watchdog.IResourceOveruseListener} for all packages' resource overuse
346 * notifications.
347 */
348 @Override
349 public void addResourceOveruseListenerForSystem(
350 @CarWatchdogManager.ResourceOveruseFlag int resourceOveruseFlag,
351 @NonNull IResourceOveruseListener listener) {
352 ICarImpl.assertPermission(mContext, Car.PERMISSION_COLLECT_CAR_WATCHDOG_METRICS);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700353 mWatchdogPerfHandler.addResourceOveruseListenerForSystem(resourceOveruseFlag, listener);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800354 }
355
356 /**
357 * Removes the previously added {@link android.car.watchdog.IResourceOveruseListener} for all
358 * packages' resource overuse notifications.
359 */
360 @Override
361 public void removeResourceOveruseListenerForSystem(@NonNull IResourceOveruseListener listener) {
362 ICarImpl.assertPermission(mContext, Car.PERMISSION_COLLECT_CAR_WATCHDOG_METRICS);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700363 mWatchdogPerfHandler.removeResourceOveruseListenerForSystem(listener);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800364 }
365
366 /** Sets whether or not a user package is killable on resource overuse. */
367 @Override
368 public void setKillablePackageAsUser(String packageName, UserHandle userHandle,
369 boolean isKillable) {
370 ICarImpl.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700371 mWatchdogPerfHandler.setKillablePackageAsUser(packageName, userHandle, isKillable);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800372 }
373
374 /**
375 * Returns all {@link android.car.watchdog.PackageKillableState} on resource overuse for
376 * the specified user.
377 */
378 @Override
379 @NonNull
380 public List<PackageKillableState> getPackageKillableStatesAsUser(UserHandle userHandle) {
381 ICarImpl.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700382 return mWatchdogPerfHandler.getPackageKillableStatesAsUser(userHandle);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800383 }
384
385 /**
386 * Sets {@link android.car.watchdog.ResourceOveruseConfiguration} for the specified resources.
387 */
388 @Override
Lakshman Annadorai8ee56ec2021-04-27 11:51:08 -0700389 @CarWatchdogManager.ReturnCode
390 public int setResourceOveruseConfigurations(
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800391 List<ResourceOveruseConfiguration> configurations,
Lakshman Annadorai94323ff2021-04-29 12:14:34 -0700392 @CarWatchdogManager.ResourceOveruseFlag int resourceOveruseFlag)
393 throws RemoteException {
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800394 ICarImpl.assertPermission(mContext, Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG);
Lakshman Annadorai8ee56ec2021-04-27 11:51:08 -0700395 return mWatchdogPerfHandler.setResourceOveruseConfigurations(configurations,
396 resourceOveruseFlag);
Lakshman Annadoraiec1944b2021-03-03 16:18:34 -0800397 }
398
399 /** Returns the available {@link android.car.watchdog.ResourceOveruseConfiguration}. */
400 @Override
401 @NonNull
402 public List<ResourceOveruseConfiguration> getResourceOveruseConfigurations(
403 @CarWatchdogManager.ResourceOveruseFlag int resourceOveruseFlag) {
404 ICarImpl.assertAnyPermission(mContext, Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG,
405 Car.PERMISSION_COLLECT_CAR_WATCHDOG_METRICS);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700406 return mWatchdogPerfHandler.getResourceOveruseConfigurations(resourceOveruseFlag);
Eric Jeong0ee72812020-04-21 15:23:54 -0700407 }
408
Jahdiel Alvarezc29893b2021-07-12 21:31:01 +0000409 /**
410 * Enables/disables the watchdog daemon client health check process.
411 */
412 public void controlProcessHealthCheck(boolean disable) {
413 ICarImpl.assertPermission(mContext, Car.PERMISSION_USE_CAR_WATCHDOG);
414 mWatchdogProcessHandler.controlProcessHealthCheck(disable);
415 }
416
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700417 @VisibleForTesting
418 int getClientCount(int timeout) {
419 return mWatchdogProcessHandler.getClientCount(timeout);
420 }
421
422 @VisibleForTesting
423 void setTimeSource(TimeSourceInterface timeSource) {
424 mWatchdogPerfHandler.setTimeSource(timeSource);
425 }
426
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700427 @VisibleForTesting
428 void setOveruseHandlingDelay(long millis) {
429 mWatchdogPerfHandler.setOveruseHandlingDelay(millis);
430 }
431
432 @VisibleForTesting
433 void setRecurringOveruseThreshold(int threshold) {
434 mWatchdogPerfHandler.setRecurringOveruseThreshold(threshold);
435 }
436
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000437 private void notifyAllUserStates() {
438 UserManager userManager = UserManager.get(mContext);
439 List<UserInfo> users = userManager.getUsers();
Jahdiel Alvarez9de7aa52021-09-10 04:39:23 +0000440 try {
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000441 // TODO(b/152780162): reduce the number of RPC calls(isUserRunning).
442 for (int i = 0; i < users.size(); ++i) {
443 UserInfo info = users.get(i);
444 int userState = userManager.isUserRunning(info.id)
445 ? UserState.USER_STATE_STARTED
446 : UserState.USER_STATE_STOPPED;
447 mCarWatchdogDaemonHelper.notifySystemStateChange(StateType.USER_STATE, info.id,
448 userState);
449 mWatchdogProcessHandler.updateUserState(info.id,
450 userState == UserState.USER_STATE_STOPPED);
451 }
Jahdiel Alvarez9de7aa52021-09-10 04:39:23 +0000452 if (DEBUG) {
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000453 Slogf.d(TAG, "Notified car watchdog daemon of user states");
Jahdiel Alvarez9de7aa52021-09-10 04:39:23 +0000454 }
455 } catch (RemoteException | RuntimeException e) {
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000456 Slogf.w(TAG, "Notifying latest user states failed: %s", e);
Jahdiel Alvarez9de7aa52021-09-10 04:39:23 +0000457 }
458 }
459
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000460 private void notifyPowerCycleChange(@PowerCycle int powerCycle) {
461 if (powerCycle == PowerCycle.NUM_POWER_CYLES) {
462 Slogf.e(TAG, "Skipping notifying invalid power cycle (%d)", powerCycle);
463 return;
464 }
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700465 try {
466 mCarWatchdogDaemonHelper.notifySystemStateChange(
467 StateType.POWER_CYCLE, powerCycle, MISSING_ARG_VALUE);
468 if (DEBUG) {
469 Slogf.d(TAG, "Notified car watchdog daemon of power cycle(%d)", powerCycle);
470 }
471 } catch (RemoteException | RuntimeException e) {
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000472 Slogf.w(TAG, e, "Notifying power cycle change to %d failed", powerCycle);
473 }
474 }
475
476 private void notifyGarageModeChange(@GarageMode int garageMode) {
477 try {
478 mCarWatchdogDaemonHelper.notifySystemStateChange(
479 StateType.GARAGE_MODE, garageMode, MISSING_ARG_VALUE);
480 if (DEBUG) {
481 Slogf.d(TAG, "Notified car watchdog daemon of garage mode(%d)", garageMode);
482 }
483 } catch (RemoteException | RuntimeException e) {
484 Slogf.w(TAG, e, "Notifying garage mode change to %d failed", garageMode);
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700485 }
486 }
487
Eric Jeong7e481702021-05-14 11:14:06 -0700488 private void postRegisterToDaemonMessage() {
489 CarServiceUtils.runOnMain(() -> {
490 synchronized (mLock) {
491 mReadyToRespond = true;
492 }
493 registerToDaemon();
494 });
495 }
496
Eric Jeong6df075f2020-03-11 16:12:23 -0700497 private void registerToDaemon() {
Eric Jeong7e481702021-05-14 11:14:06 -0700498 synchronized (mLock) {
499 if (!mIsConnected || !mReadyToRespond) {
500 return;
501 }
502 }
Eric Jeongae2c04c2020-02-21 09:18:31 -0800503 try {
Lakshman Annadoraid26098a2020-11-10 14:05:04 -0800504 mCarWatchdogDaemonHelper.registerCarWatchdogService(mWatchdogServiceForSystem);
Eric Jeong09657562020-03-20 16:02:39 -0700505 if (DEBUG) {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700506 Slogf.d(TAG, "CarWatchdogService registers to car watchdog daemon");
Eric Jeong09657562020-03-20 16:02:39 -0700507 }
Eric Jeong4825ca32020-04-13 18:07:44 -0700508 } catch (RemoteException | RuntimeException e) {
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700509 Slogf.w(TAG, "Cannot register to car watchdog daemon: %s", e);
Eric Jeong6df075f2020-03-11 16:12:23 -0700510 }
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000511 notifyAllUserStates();
512 CarPowerManagementService powerService =
513 CarLocalServices.getService(CarPowerManagementService.class);
514 if (powerService != null) {
515 int powerState = powerService.getPowerState();
516 int powerCycle = carPowerStateToPowerCycle(powerState);
517 if (powerCycle != PowerCycle.NUM_POWER_CYLES) {
518 notifyPowerCycleChange(powerCycle);
519 } else {
520 Slogf.i(TAG, "Skipping notifying %d power state", powerState);
Eric Jeong01a28aa2020-03-27 16:43:19 -0700521 }
Eric Jeong01a28aa2020-03-27 16:43:19 -0700522 }
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000523 int garageMode;
524 synchronized (mLock) {
525 // To avoid race condition, fetch {@link mCurrentGarageMode} just before
526 // the {@link notifyGarageModeChange} call. For instance, if {@code mCurrentGarageMode}
527 // changes before the above {@link notifyPowerCycleChange} call returns,
528 // the {@link garageMode}'s value will be out of date.
529 garageMode = mCurrentGarageMode;
530 }
531 notifyGarageModeChange(garageMode);
Eric Jeong6df075f2020-03-11 16:12:23 -0700532 }
533
534 private void unregisterFromDaemon() {
535 try {
Lakshman Annadoraid26098a2020-11-10 14:05:04 -0800536 mCarWatchdogDaemonHelper.unregisterCarWatchdogService(mWatchdogServiceForSystem);
Eric Jeong09657562020-03-20 16:02:39 -0700537 if (DEBUG) {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700538 Slogf.d(TAG, "CarWatchdogService unregisters from car watchdog daemon");
Eric Jeong09657562020-03-20 16:02:39 -0700539 }
Eric Jeong4825ca32020-04-13 18:07:44 -0700540 } catch (RemoteException | RuntimeException e) {
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700541 Slogf.w(TAG, "Cannot unregister from car watchdog daemon: %s", e);
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700542 }
543 }
544
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700545 private void subscribePowerManagementService() {
Eric Jeong27a178f2020-03-24 16:39:39 -0700546 CarPowerManagementService powerService =
547 CarLocalServices.getService(CarPowerManagementService.class);
548 if (powerService == null) {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700549 Slogf.w(TAG, "Cannot get CarPowerManagementService");
Eric Jeong27a178f2020-03-24 16:39:39 -0700550 return;
551 }
Lakshman Annadorai64d0e1f2021-10-06 12:19:41 -0700552 powerService.registerListener(mCarPowerStateListener);
553 powerService.addPowerPolicyListener(
554 new CarPowerPolicyFilter.Builder().setComponents(PowerComponent.DISPLAY).build(),
555 mCarDisplayPowerPolicyListener);
556 }
557
558 private void unsubscribePowerManagementService() {
559 CarPowerManagementService powerService =
560 CarLocalServices.getService(CarPowerManagementService.class);
561 if (powerService == null) {
562 Slogf.w(TAG, "Cannot get CarPowerManagementService");
563 return;
564 }
565 powerService.unregisterListener(mCarPowerStateListener);
566 powerService.removePowerPolicyListener(mCarDisplayPowerPolicyListener);
Eric Jeong27a178f2020-03-24 16:39:39 -0700567 }
568
Eric Jeong01a28aa2020-03-27 16:43:19 -0700569 private void subscribeUserStateChange() {
570 CarUserService userService = CarLocalServices.getService(CarUserService.class);
571 if (userService == null) {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700572 Slogf.w(TAG, "Cannot get CarUserService");
Eric Jeong01a28aa2020-03-27 16:43:19 -0700573 return;
574 }
575 userService.addUserLifecycleListener((event) -> {
576 int userId = event.getUserHandle().getIdentifier();
577 int userState;
578 String userStateDesc;
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700579 switch (event.getEventType()) {
580 case USER_LIFECYCLE_EVENT_TYPE_STARTING:
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700581 mWatchdogProcessHandler.updateUserState(userId, /*isStopped=*/ false);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700582 userState = UserState.USER_STATE_STARTED;
583 userStateDesc = "STARTING";
584 break;
585 case USER_LIFECYCLE_EVENT_TYPE_STOPPED:
Lakshman Annadorai0d3b1992021-08-17 09:11:24 -0700586 mWatchdogProcessHandler.updateUserState(userId, /*isStopped=*/ true);
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700587 userState = UserState.USER_STATE_STOPPED;
588 userStateDesc = "STOPPING";
589 break;
590 default:
591 return;
Eric Jeong01a28aa2020-03-27 16:43:19 -0700592 }
593 try {
594 mCarWatchdogDaemonHelper.notifySystemStateChange(StateType.USER_STATE, userId,
595 userState);
Eric Jeong4825ca32020-04-13 18:07:44 -0700596 if (DEBUG) {
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700597 Slogf.d(TAG, "Notified car watchdog daemon user %d's user state, %s",
598 userId, userStateDesc);
Eric Jeong4825ca32020-04-13 18:07:44 -0700599 }
600 } catch (RemoteException | RuntimeException e) {
Lakshman Annadorai8a67df12021-06-29 19:33:37 -0700601 Slogf.w(TAG, "Notifying user state change failed: %s", e);
Eric Jeong01a28aa2020-03-27 16:43:19 -0700602 }
Eric Jeong01a28aa2020-03-27 16:43:19 -0700603 });
604 }
605
Lakshman Annadorai8a67df12021-06-29 19:33:37 -0700606 private void subscribeBroadcastReceiver() {
607 IntentFilter filter = new IntentFilter();
608 filter.addAction(ACTION_GARAGE_MODE_ON);
609 filter.addAction(ACTION_GARAGE_MODE_OFF);
Jahdiel Alvarez9de7aa52021-09-10 04:39:23 +0000610 filter.addAction(Intent.ACTION_USER_REMOVED);
Lakshman Annadorai8a67df12021-06-29 19:33:37 -0700611
612 mContext.registerReceiverForAllUsers(mBroadcastReceiver, filter, null, null);
613 }
614
Lakshman Annadorai42185d82021-10-15 23:55:14 +0000615 private static @PowerCycle int carPowerStateToPowerCycle(int powerState) {
616 switch (powerState) {
617 // SHUTDOWN_PREPARE covers suspend and shutdown.
618 case CarPowerStateListener.SHUTDOWN_PREPARE:
619 return PowerCycle.POWER_CYCLE_SHUTDOWN_PREPARE;
620 case CarPowerStateListener.SHUTDOWN_ENTER:
621 case CarPowerStateListener.SUSPEND_ENTER:
622 return PowerCycle.POWER_CYCLE_SHUTDOWN_ENTER;
623 // ON covers resume.
624 case CarPowerStateListener.ON:
625 return PowerCycle.POWER_CYCLE_RESUME;
626 }
627 return PowerCycle.NUM_POWER_CYLES;
628 }
629
630 private static String toGarageModeString(@GarageMode int garageMode) {
631 switch (garageMode) {
632 case GarageMode.GARAGE_MODE_OFF:
633 return "GARAGE_MODE_OFF";
634 case GarageMode.GARAGE_MODE_ON:
635 return "GARAGE_MODE_ON";
636 }
637 return "INVALID";
638 }
Jahdiel Alvarez8bf64ce2021-07-21 01:03:42 +0000639
Lakshman Annadoraid26098a2020-11-10 14:05:04 -0800640 private static final class ICarWatchdogServiceForSystemImpl
641 extends ICarWatchdogServiceForSystem.Stub {
Eric Jeong38ae8212020-01-14 10:25:10 -0800642 private final WeakReference<CarWatchdogService> mService;
643
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700644 ICarWatchdogServiceForSystemImpl(CarWatchdogService service) {
Eric Jeong38ae8212020-01-14 10:25:10 -0800645 mService = new WeakReference<>(service);
646 }
647
648 @Override
649 public void checkIfAlive(int sessionId, int timeout) {
Eric Jeongae2c04c2020-02-21 09:18:31 -0800650 CarWatchdogService service = mService.get();
651 if (service == null) {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700652 Slogf.w(TAG, "CarWatchdogService is not available");
Eric Jeongae2c04c2020-02-21 09:18:31 -0800653 return;
654 }
Lakshman Annadorai016127e2021-03-18 09:11:43 -0700655 service.mWatchdogProcessHandler.postHealthCheckMessage(sessionId);
Eric Jeong09657562020-03-20 16:02:39 -0700656 }
Jeongik Cha1d04bdd2020-04-08 22:19:52 +0900657
658 @Override
Eric Jeong515009b2020-04-10 17:23:56 -0700659 public void prepareProcessTermination() {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700660 Slogf.w(TAG, "CarWatchdogService is about to be killed by car watchdog daemon");
Eric Jeong515009b2020-04-10 17:23:56 -0700661 }
Lakshman Annadorai8dfeeaf2020-12-15 14:10:53 -0800662
663 @Override
Lakshman Annadoraie17cba72020-12-17 14:03:36 -0800664 public List<PackageInfo> getPackageInfosForUids(
665 int[] uids, List<String> vendorPackagePrefixes) {
666 if (ArrayUtils.isEmpty(uids)) {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700667 Slogf.w(TAG, "UID list is empty");
Lakshman Annadoraie17cba72020-12-17 14:03:36 -0800668 return null;
669 }
670 CarWatchdogService service = mService.get();
671 if (service == null) {
Lakshman Annadorai54e10542021-03-16 15:36:04 -0700672 Slogf.w(TAG, "CarWatchdogService is not available");
Lakshman Annadoraie17cba72020-12-17 14:03:36 -0800673 return null;
674 }
Lakshman Annadorai5f1181b2021-04-01 16:03:07 -0700675 return service.mPackageInfoHandler.getPackageInfosForUids(uids, vendorPackagePrefixes);
Lakshman Annadorai8dfeeaf2020-12-15 14:10:53 -0800676 }
Lakshman Annadoraidd4a4e42021-02-19 14:22:06 -0800677
678 @Override
Lakshman Annadorai9ed47322021-03-11 16:09:28 -0800679 public void latestIoOveruseStats(List<PackageIoOveruseStats> packageIoOveruseStats) {
Lakshman Annadoraicf5f3a92021-04-02 15:26:16 -0700680 if (packageIoOveruseStats.isEmpty()) {
681 Slogf.w(TAG, "Latest I/O overuse stats is empty");
682 return;
683 }
684 CarWatchdogService service = mService.get();
685 if (service == null) {
686 Slogf.w(TAG, "CarWatchdogService is not available");
687 return;
688 }
689 service.mWatchdogPerfHandler.latestIoOveruseStats(packageIoOveruseStats);
Lakshman Annadoraidd4a4e42021-02-19 14:22:06 -0800690 }
Lakshman Annadoraiec4d08a2021-04-30 08:29:10 -0700691
692 @Override
693 public void resetResourceOveruseStats(List<String> packageNames) {
694 if (packageNames.isEmpty()) {
695 Slogf.w(TAG, "Provided an empty package name to reset resource overuse stats");
696 return;
697 }
698 CarWatchdogService service = mService.get();
699 if (service == null) {
700 Slogf.w(TAG, "CarWatchdogService is not available");
701 return;
702 }
703 service.mWatchdogPerfHandler.resetResourceOveruseStats(new ArraySet<>(packageNames));
704 }
Lakshman Annadorai03cbd1f2021-10-08 18:39:10 +0000705
706 @Override
707 public List<UserPackageIoUsageStats> getTodayIoUsageStats() {
708 CarWatchdogService service = mService.get();
709 if (service == null) {
710 Slogf.w(TAG, "CarWatchdogService is not available");
711 return null;
712 }
713 return service.mWatchdogPerfHandler.getTodayIoUsageStats();
714 }
Eric Jeong09657562020-03-20 16:02:39 -0700715 }
Eric Jeong38ae8212020-01-14 10:25:10 -0800716}