1 /* 2 * Copyright (C) 2022 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.android.car.remoteaccess; 18 19 import static android.car.remoteaccess.CarRemoteAccessManager.TASK_TYPE_CUSTOM; 20 import static android.car.remoteaccess.CarRemoteAccessManager.TASK_TYPE_ENTER_GARAGE_MODE; 21 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED; 22 import static android.content.Context.BIND_AUTO_CREATE; 23 import static android.content.Context.RECEIVER_NOT_EXPORTED; 24 25 import static com.android.car.CarServiceUtils.isEventOfType; 26 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE; 27 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO; 28 import static com.android.car.internal.common.CommonConstants.EMPTY_INT_ARRAY; 29 30 import android.annotation.Nullable; 31 import android.app.ActivityManager; 32 import android.car.Car; 33 import android.car.builtin.os.HandlerHelper; 34 import android.car.builtin.util.Slogf; 35 import android.car.feature.FeatureFlags; 36 import android.car.feature.FeatureFlagsImpl; 37 import android.car.hardware.power.CarPowerManager; 38 import android.car.hardware.power.ICarPowerStateListener; 39 import android.car.remoteaccess.CarRemoteAccessManager; 40 import android.car.remoteaccess.ICarRemoteAccessCallback; 41 import android.car.remoteaccess.ICarRemoteAccessService; 42 import android.car.remoteaccess.RemoteTaskClientRegistrationInfo; 43 import android.car.remoteaccess.TaskScheduleInfo; 44 import android.car.user.CarUserManager.UserLifecycleListener; 45 import android.car.user.UserLifecycleEventFilter; 46 import android.content.BroadcastReceiver; 47 import android.content.ComponentName; 48 import android.content.Context; 49 import android.content.Intent; 50 import android.content.IntentFilter; 51 import android.content.ServiceConnection; 52 import android.content.pm.PackageManager; 53 import android.content.pm.PackageManager.PackageInfoFlags; 54 import android.content.pm.ResolveInfo; 55 import android.content.pm.ServiceInfo; 56 import android.content.res.XmlResourceParser; 57 import android.hardware.automotive.remoteaccess.IRemoteAccess; 58 import android.hardware.automotive.remoteaccess.ScheduleInfo; 59 import android.hardware.automotive.remoteaccess.TaskType; 60 import android.net.Uri; 61 import android.os.Binder; 62 import android.os.Handler; 63 import android.os.HandlerThread; 64 import android.os.IBinder; 65 import android.os.Looper; 66 import android.os.Message; 67 import android.os.RemoteException; 68 import android.os.ServiceSpecificException; 69 import android.os.SystemClock; 70 import android.os.UserHandle; 71 import android.os.UserManager; 72 import android.util.ArrayMap; 73 import android.util.ArraySet; 74 import android.util.Log; 75 import android.util.SparseArray; 76 import android.util.proto.ProtoOutputStream; 77 78 import com.android.car.CarLocalServices; 79 import com.android.car.CarLog; 80 import com.android.car.CarServiceBase; 81 import com.android.car.CarServiceUtils; 82 import com.android.car.R; 83 import com.android.car.hal.PowerHalService; 84 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 85 import com.android.car.internal.util.IndentingPrintWriter; 86 import com.android.car.power.CarPowerManagementService; 87 import com.android.car.remoteaccess.RemoteAccessStorage.ClientIdEntry; 88 import com.android.car.remoteaccess.hal.RemoteAccessHalCallback; 89 import com.android.car.remoteaccess.hal.RemoteAccessHalWrapper; 90 import com.android.car.systeminterface.SystemInterface; 91 import com.android.car.user.CarUserService; 92 import com.android.internal.annotations.GuardedBy; 93 import com.android.internal.annotations.VisibleForTesting; 94 import com.android.internal.util.Preconditions; 95 96 import org.xmlpull.v1.XmlPullParser; 97 import org.xmlpull.v1.XmlPullParserException; 98 99 import java.io.IOException; 100 import java.lang.ref.WeakReference; 101 import java.time.Duration; 102 import java.util.ArrayList; 103 import java.util.List; 104 import java.util.Set; 105 import java.util.concurrent.atomic.AtomicLong; 106 import java.util.concurrent.atomic.AtomicReference; 107 108 /** 109 * Service to implement CarRemoteAccessManager API. 110 */ 111 public final class CarRemoteAccessService extends ICarRemoteAccessService.Stub 112 implements CarServiceBase { 113 114 private static final String TAG = CarLog.tagFor(CarRemoteAccessService.class); 115 private static final boolean DEBUG = Slogf.isLoggable(TAG, Log.DEBUG); 116 117 // Tag names for remote_access_serverless_client_map.xml. 118 private static final String XML_TAG_CLIENT_ID = "ClientId"; 119 private static final String XML_TAG_PACKAGE_NAME = "PackageName"; 120 private static final String XML_TAG_SERVERLESS_CLIENT = "ServerlessClient"; 121 private static final String XML_TAG_SERVERLESS_CLIENT_MAP = "ServerlessClientMap"; 122 123 private static final int MILLI_TO_SECOND = 1000; 124 private static final String TASK_PREFIX = "task"; 125 private static final String CLIENT_PREFIX = "client"; 126 private static final int RANDOM_STRING_LENGTH = 12; 127 private static final int MIN_SYSTEM_UPTIME_FOR_REMOTE_ACCESS_IN_SEC = 30; 128 private static final Duration PACKAGE_SEARCH_DELAY = Duration.ofSeconds(1); 129 // Add some randomness to package search delay to avoid thundering herd issue. 130 private static final Duration PACKAGE_SEARCH_DELAY_RAND_RANGE = Duration.ofMillis(100); 131 // Remote task client can use up to 30 seconds to initialize and upload necessary info to the 132 // server. 133 private static final long ALLOWED_TIME_FOR_REMOTE_TASK_CLIENT_INIT_MS = 30_000; 134 private static final long SHUTDOWN_WARNING_MARGIN_IN_MS = 5000; 135 private static final long INVALID_ALLOWED_SYSTEM_UPTIME = -1; 136 private static final int DEFAULT_NOTIFY_AP_STATE_RETRY_SLEEP_IN_MS = 100; 137 private static final int DEFAULT_NOTIFY_AP_STATE_MAX_RETRY = 10; 138 // The buffer time after all the tasks for a specific remote task client service is completed 139 // before we unbind the service. 140 private static final int TASK_UNBIND_DELAY_MS = 1000; 141 // The max time in ms allowed for a task after it is received by the car service, before the 142 // remote task client service is started and it is delivered to that service. This period will 143 // include waiting for the remote task client service to be started if it is not already bound. 144 private static final int MAX_TASK_PENDING_MS = 60_000; 145 146 private final Object mLock = new Object(); 147 private final Context mContext; 148 private final PackageManager mPackageManager; 149 private final HandlerThread mHandlerThread = 150 CarServiceUtils.getHandlerThread(getClass().getSimpleName()); 151 private final RemoteTaskClientServiceHandler mHandler = 152 new RemoteTaskClientServiceHandler(mHandlerThread.getLooper(), this); 153 private long mAllowedTimeForRemoteTaskClientInitMs = 154 ALLOWED_TIME_FOR_REMOTE_TASK_CLIENT_INIT_MS; 155 private long mTaskUnbindDelayMs = TASK_UNBIND_DELAY_MS; 156 private long mMaxTaskPendingMs = MAX_TASK_PENDING_MS; 157 private final AtomicLong mTaskCount = new AtomicLong(/* initialValue= */ 0); 158 private final AtomicLong mClientCount = new AtomicLong(/* initialValue= */ 0); 159 // Whether in vehicle task scheduling is supported by remote access HAL. Only set during init. 160 private boolean mIsHalTaskScheduleSupported; 161 @GuardedBy("mLock") 162 private final ArrayMap<String, String> mUidByClientId = new ArrayMap<>(); 163 @GuardedBy("mLock") 164 private final ArrayMap<String, ArrayList<RemoteTask>> mTasksToBeNotifiedByClientId = 165 new ArrayMap<>(); 166 @GuardedBy("mLock") 167 private final ArrayMap<String, ClientToken> mClientTokenByUidName = new ArrayMap<>(); 168 @GuardedBy("mLock") 169 private final ArrayMap<String, RemoteTaskClientServiceInfo> mClientServiceInfoByUid = 170 new ArrayMap<>(); 171 @GuardedBy("mLock") 172 private boolean mIsReadyForRemoteTask; 173 @GuardedBy("mLock") 174 private boolean mIsWakeupRequired; 175 @GuardedBy("mLock") 176 private int mNotifyApStateChangeRetryCount; 177 @GuardedBy("mLock") 178 private final ArrayMap<String, Integer> mUidByName = new ArrayMap<>(); 179 @GuardedBy("mLock") 180 private final SparseArray<String> mNameByUid = new SparseArray<>(); 181 @GuardedBy("mLock") 182 private ArrayMap<String, String> mServerlessClientIdsByPackageName = new ArrayMap<>(); 183 184 private final RemoteAccessStorage mRemoteAccessStorage; 185 186 private FeatureFlags mFeatureFlags = new FeatureFlagsImpl(); 187 188 /** 189 * Sets fake feature flag for unit testing. 190 */ 191 @VisibleForTesting setFeatureFlags(FeatureFlags fakeFeatureFlags)192 public void setFeatureFlags(FeatureFlags fakeFeatureFlags) { 193 mFeatureFlags = fakeFeatureFlags; 194 } 195 196 private final ICarPowerStateListener mCarPowerStateListener = 197 new ICarPowerStateListener.Stub() { 198 @Override 199 public void onStateChanged(int state, long expirationTimeMs) { 200 // isReadyForRemoteTask and isWakeupRequired are only valid when apStateChangeRequired 201 // is true. 202 Slogf.i(TAG, "power state change, new state: %d", state); 203 boolean apStateChangeRequired = false; 204 boolean isReadyForRemoteTask = false; 205 boolean isWakeupRequired = false; 206 boolean needsComplete = false; 207 208 switch (state) { 209 case CarPowerManager.STATE_SHUTDOWN_PREPARE: 210 apStateChangeRequired = true; 211 isReadyForRemoteTask = false; 212 isWakeupRequired = false; 213 214 needsComplete = true; 215 // If this shutdown is initiated by remote access service, then all remote task 216 // client services should already be unbound and this will do nothing. This is 217 // useful for cases when the shutdown is not initiated by us (e.g. by user). 218 unbindAllServices(); 219 break; 220 case CarPowerManager.STATE_WAIT_FOR_VHAL: 221 case CarPowerManager.STATE_SUSPEND_EXIT: 222 case CarPowerManager.STATE_HIBERNATION_EXIT: 223 apStateChangeRequired = true; 224 isReadyForRemoteTask = true; 225 isWakeupRequired = false; 226 break; 227 case CarPowerManager.STATE_POST_SHUTDOWN_ENTER: 228 case CarPowerManager.STATE_POST_SUSPEND_ENTER: 229 case CarPowerManager.STATE_POST_HIBERNATION_ENTER: 230 apStateChangeRequired = true; 231 isReadyForRemoteTask = false; 232 isWakeupRequired = true; 233 234 needsComplete = true; 235 break; 236 } 237 if (apStateChangeRequired) { 238 synchronized (mLock) { 239 mIsReadyForRemoteTask = isReadyForRemoteTask; 240 mIsWakeupRequired = isWakeupRequired; 241 } 242 mHandler.cancelNotifyApStateChange(); 243 if (!mRemoteAccessHalWrapper.notifyApStateChange( 244 isReadyForRemoteTask, isWakeupRequired)) { 245 Slogf.e(TAG, "Cannot notify AP state change according to power state(%d)", 246 state); 247 } 248 } 249 if (needsComplete) { 250 mPowerService.finished(state, this); 251 } 252 } 253 }; 254 255 @GuardedBy("mLock") isServerlessClientLocked(String clientId)256 private boolean isServerlessClientLocked(String clientId) { 257 for (int i = 0; i < mServerlessClientIdsByPackageName.size(); i++) { 258 if (mServerlessClientIdsByPackageName.valueAt(i).equals(clientId)) { 259 return true; 260 } 261 } 262 return false; 263 } 264 maybeStartNewRemoteTask(String clientId)265 private void maybeStartNewRemoteTask(String clientId) { 266 ICarRemoteAccessCallback callback; 267 List<RemoteTask> remoteTasksToNotify = null; 268 RemoteTaskClientServiceInfo serviceInfo = null; 269 int taskMaxDurationInSec; 270 long taskMaxDurationInMs; 271 String uidName; 272 ClientToken token; 273 274 synchronized (mLock) { 275 if (mTasksToBeNotifiedByClientId.get(clientId) == null) { 276 return; 277 } 278 taskMaxDurationInMs = calcTaskMaxDurationInMsLocked(); 279 taskMaxDurationInSec = (int) (taskMaxDurationInMs / MILLI_TO_SECOND); 280 if (taskMaxDurationInSec <= 0) { 281 Slogf.w(TAG, "onRemoteTaskRequested: system shutdown was supposed to start, " 282 + "but still on: expected shutdown time=%d, current time=%d", 283 mShutdownTimeInMs, SystemClock.uptimeMillis()); 284 // Remove all tasks for this client ID. 285 Slogf.w(TAG, "Removing all the pending tasks for client ID: %s", clientId); 286 mTasksToBeNotifiedByClientId.remove(clientId); 287 return; 288 } 289 // If this clientId has never been stored on this device before, 290 uidName = mUidByClientId.get(clientId); 291 // uidName might be null for serverless remote task client if the device just booted up 292 // and the client has not called addCarRemoteTaskClient yet. For regular remote task 293 // client, the client ID must already be stored in database, so during 294 // populatePackageClientIdMapping the mUidByClientId will contain clientId and uidName 295 // must not be null. 296 if (!isServerlessClientLocked(clientId) && uidName == null) { 297 Slogf.w(TAG, "Cannot notify task: client(%s) is not registered.", clientId); 298 Slogf.w(TAG, "Removing all the pending tasks for client ID: %s", clientId); 299 mTasksToBeNotifiedByClientId.remove(clientId); 300 return; 301 } 302 if (uidName != null) { 303 serviceInfo = mClientServiceInfoByUid.get(uidName); 304 } 305 if (serviceInfo == null) { 306 Slogf.w(TAG, "Notifying task is delayed: the remote client service information " 307 + "for %s is not registered yet", clientId); 308 // We don't have to start the service explicitly because it will be started 309 // after searching for remote task client service is done. 310 return; 311 } 312 // Token must not be null if mUidByClientId contains clientId. 313 token = mClientTokenByUidName.get(uidName); 314 callback = token.getCallback(); 315 if (callback != null) { 316 remoteTasksToNotify = popTasksFromPendingQueueLocked(clientId); 317 } 318 } 319 // Always try to bind the remote task client service. This will starts the service if 320 // it is not active. This will also keep the service alive during the task period. 321 startRemoteTaskClientService(serviceInfo, uidName, taskMaxDurationInMs); 322 323 if (callback == null) { 324 Slogf.w(TAG, "Notifying task is delayed: the callback for token: %s " 325 + "is not registered yet", token); 326 return; 327 } 328 329 if (remoteTasksToNotify != null && !remoteTasksToNotify.isEmpty()) { 330 invokeTaskRequestCallbacks(serviceInfo.getServiceConnection(), callback, clientId, 331 remoteTasksToNotify, taskMaxDurationInSec); 332 } 333 } 334 335 private final RemoteAccessHalCallback mHalCallback = new RemoteAccessHalCallback() { 336 @Override 337 public void onRemoteTaskRequested(String clientId, byte[] data) { 338 if (DEBUG) { 339 Slogf.d(TAG, "Remote task is requested through the HAL to client(%s)", clientId); 340 } 341 String taskId = generateNewTaskId(); 342 long now = SystemClock.uptimeMillis(); 343 long timeoutInMs = now + mMaxTaskPendingMs; 344 synchronized (mLock) { 345 pushTaskToPendingQueueLocked(clientId, new RemoteTask(taskId, data, clientId, 346 timeoutInMs)); 347 } 348 maybeStartNewRemoteTask(clientId); 349 } 350 }; 351 private RemoteAccessHalWrapper mRemoteAccessHalWrapper; 352 private PowerHalService mPowerHalService; 353 private final UserManager mUserManager; 354 private final long mShutdownTimeInMs; 355 private final long mAllowedSystemUptimeMs; 356 private final int mNotifyApStateChangeMaxRetry; 357 private final int mNotifyApStateChangeRetrySleepInMs; 358 private final BroadcastReceiver mPackageRemovedReceiver; 359 360 private String mWakeupServiceName = ""; 361 private String mVehicleId = ""; 362 private String mProcessorId = ""; 363 @GuardedBy("mLock") 364 private int mNextPowerState; 365 @GuardedBy("mLock") 366 private boolean mRunGarageMode; 367 private CarPowerManagementService mPowerService; 368 369 private CarRemoteAccessServiceDep mDep; 370 CarRemoteAccessService(Context context, SystemInterface systemInterface, PowerHalService powerHalService)371 public CarRemoteAccessService(Context context, SystemInterface systemInterface, 372 PowerHalService powerHalService) { 373 this(context, systemInterface, powerHalService, /* dep= */ null, 374 /* remoteAccessHal= */ null, /* remoteAccessStorage= */ null, 375 INVALID_ALLOWED_SYSTEM_UPTIME, /* inMemoryStorage= */ false); 376 } 377 378 /** 379 * Dependencies for stubbing. 380 */ 381 @VisibleForTesting 382 public interface CarRemoteAccessServiceDep { 383 /** 384 * Gets the calling UID. Must be used in a binder context. 385 */ getCallingUid()386 int getCallingUid(); 387 388 /** 389 * Gets the current user. 390 */ getCurrentUser()391 int getCurrentUser(); 392 } 393 394 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE) 395 private static class CarRemoteAccessServiceDepImpl implements CarRemoteAccessServiceDep { getCallingUid()396 public int getCallingUid() { 397 return Binder.getCallingUid(); 398 } 399 getCurrentUser()400 public int getCurrentUser() { 401 return ActivityManager.getCurrentUser(); 402 } 403 } 404 405 @VisibleForTesting CarRemoteAccessService(Context context, SystemInterface systemInterface, PowerHalService powerHalService, @Nullable CarRemoteAccessServiceDep dep, @Nullable IRemoteAccess remoteAccessHal, @Nullable RemoteAccessStorage remoteAccessStorage, long allowedSystemUptimeMs, boolean inMemoryStorage)406 public CarRemoteAccessService(Context context, SystemInterface systemInterface, 407 PowerHalService powerHalService, @Nullable CarRemoteAccessServiceDep dep, 408 @Nullable IRemoteAccess remoteAccessHal, 409 @Nullable RemoteAccessStorage remoteAccessStorage, long allowedSystemUptimeMs, 410 boolean inMemoryStorage) { 411 mContext = context; 412 mUserManager = mContext.getSystemService(UserManager.class); 413 mPowerHalService = powerHalService; 414 mDep = dep != null ? dep : new CarRemoteAccessServiceDepImpl(); 415 mPackageManager = mContext.getPackageManager(); 416 mRemoteAccessHalWrapper = new RemoteAccessHalWrapper(mHalCallback, remoteAccessHal); 417 mAllowedSystemUptimeMs = allowedSystemUptimeMs == INVALID_ALLOWED_SYSTEM_UPTIME 418 ? getAllowedSystemUptimeForRemoteTaskInMs() : allowedSystemUptimeMs; 419 mShutdownTimeInMs = SystemClock.uptimeMillis() + mAllowedSystemUptimeMs; 420 mRemoteAccessStorage = remoteAccessStorage != null ? remoteAccessStorage : 421 new RemoteAccessStorage(context, systemInterface, inMemoryStorage); 422 // TODO(b/263807920): CarService restart should be handled. 423 systemInterface.scheduleActionForBootCompleted(() -> searchForRemoteTaskClientPackages(), 424 PACKAGE_SEARCH_DELAY, PACKAGE_SEARCH_DELAY_RAND_RANGE); 425 mNotifyApStateChangeMaxRetry = getNotifyApStateChangeMaxRetry(); 426 mNotifyApStateChangeRetrySleepInMs = getNotifyApStateChangeRetrySleepInMs(); 427 mPackageRemovedReceiver = new BroadcastReceiver() { 428 @Override 429 public void onReceive(Context context, Intent intent) { 430 onReceiveIntent(context, intent); 431 } 432 }; 433 } 434 435 /** 436 * handles {@code ACTION_PACKAGE_REMOVED} intent. 437 */ 438 @SuppressWarnings("unused") onReceiveIntent(Context context, Intent intent)439 private void onReceiveIntent(Context context, Intent intent) { 440 if (!intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { 441 Slogf.w(TAG, "Received an unknown intent, ignore: " + intent); 442 return; 443 } 444 String packageName = Uri.parse(intent.getDataString()).getSchemeSpecificPart(); 445 String clientId; 446 synchronized (mLock) { 447 if (!mServerlessClientIdsByPackageName.containsKey(packageName)) { 448 // Not a serverless client, ignore. 449 return; 450 } 451 clientId = mServerlessClientIdsByPackageName.get(packageName); 452 } 453 try { 454 mRemoteAccessHalWrapper.unscheduleAllTasks(clientId); 455 } catch (ServiceSpecificException | RemoteException e) { 456 Slogf.e(TAG, e, "failed to unschedule tasks for package: %s when it is removed", 457 packageName); 458 } 459 } 460 461 @VisibleForTesting setRemoteAccessHalWrapper(RemoteAccessHalWrapper remoteAccessHalWrapper)462 public void setRemoteAccessHalWrapper(RemoteAccessHalWrapper remoteAccessHalWrapper) { 463 mRemoteAccessHalWrapper = remoteAccessHalWrapper; 464 } 465 466 @VisibleForTesting setPowerHal(PowerHalService powerHalService)467 public void setPowerHal(PowerHalService powerHalService) { 468 mPowerHalService = powerHalService; 469 } 470 471 @VisibleForTesting setAllowedTimeForRemoteTaskClientInitMs(long allowedTimeForRemoteTaskClientInitMs)472 public void setAllowedTimeForRemoteTaskClientInitMs(long allowedTimeForRemoteTaskClientInitMs) { 473 mAllowedTimeForRemoteTaskClientInitMs = allowedTimeForRemoteTaskClientInitMs; 474 } 475 476 @VisibleForTesting setTaskUnbindDelayMs(long taskUnbindDelayMs)477 public void setTaskUnbindDelayMs(long taskUnbindDelayMs) { 478 mTaskUnbindDelayMs = taskUnbindDelayMs; 479 } 480 481 @VisibleForTesting setMaxTaskPendingMs(long maxTaskPendingMs)482 public void setMaxTaskPendingMs(long maxTaskPendingMs) { 483 mMaxTaskPendingMs = maxTaskPendingMs; 484 } 485 486 @Override init()487 public void init() { 488 mPowerService = CarLocalServices.getService(CarPowerManagementService.class); 489 populatePackageClientIdMapping(); 490 mRemoteAccessHalWrapper.init(); 491 // This must be called after remoteAccessHalWrapper init complete. 492 mIsHalTaskScheduleSupported = mRemoteAccessHalWrapper.isTaskScheduleSupported(); 493 try { 494 mWakeupServiceName = mRemoteAccessHalWrapper.getWakeupServiceName(); 495 mVehicleId = mRemoteAccessHalWrapper.getVehicleId(); 496 mProcessorId = mRemoteAccessHalWrapper.getProcessorId(); 497 } catch (IllegalStateException e) { 498 Slogf.e(TAG, e, "Cannot get vehicle/processor/service info from remote access HAL"); 499 } 500 synchronized (mLock) { 501 mNextPowerState = getLastShutdownState(); 502 mIsReadyForRemoteTask = true; 503 mIsWakeupRequired = false; 504 } 505 506 mPowerService.registerListenerWithCompletion(mCarPowerStateListener); 507 508 long delayForShutdowWarningMs = mAllowedSystemUptimeMs - SHUTDOWN_WARNING_MARGIN_IN_MS; 509 if (delayForShutdowWarningMs > 0) { 510 mHandler.postNotifyShutdownStarting(delayForShutdowWarningMs); 511 } 512 mHandler.postWrapUpRemoteAccessService(mAllowedSystemUptimeMs); 513 mHandler.postNotifyApStateChange(0); 514 515 IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED); 516 filter.addDataScheme("package"); 517 // We are registering receiver for a system broadcast so the flag for NOT_EXPORTED does 518 // not really matter. But we are not expecting intents from other apps, so set it to 519 // NOT_EXPORTED to be safe. 520 mContext.registerReceiver(mPackageRemovedReceiver, filter, RECEIVER_NOT_EXPORTED); 521 } 522 523 @Override release()524 public void release() { 525 Slogf.i(TAG, "release CarRemoteAccessService"); 526 mHandler.cancelAll(); 527 mContext.unregisterReceiver(mPackageRemovedReceiver); 528 mRemoteAccessHalWrapper.release(); 529 mRemoteAccessStorage.release(); 530 } 531 printMap(IndentingPrintWriter writer, ArrayMap<?, ?> map)532 private void printMap(IndentingPrintWriter writer, ArrayMap<?, ?> map) { 533 writer.increaseIndent(); 534 for (int i = 0; i < map.size(); i++) { 535 writer.printf("%d: %s ==> %s\n", i, map.keyAt(i), map.valueAt(i)); 536 } 537 writer.decreaseIndent(); 538 } 539 540 @Override 541 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) dump(IndentingPrintWriter writer)542 public void dump(IndentingPrintWriter writer) { 543 synchronized (mLock) { 544 writer.println("*Car Remote Access Service*"); 545 writer.printf("mShutdownTimeInMs: %d\n", mShutdownTimeInMs); 546 writer.printf("mNextPowerState: %d\n", mNextPowerState); 547 writer.printf("mRunGarageMode: %b\n", mRunGarageMode); 548 writer.printf("mWakeupServiceName: %s\n", mWakeupServiceName); 549 writer.printf("mVehicleId: %s\n", mVehicleId); 550 writer.printf("mProcessorId: %s\n", mProcessorId); 551 writer.println("mClientTokenByUidName:"); 552 printMap(writer, mClientTokenByUidName); 553 writer.println("mClientServiceInfoByUid:"); 554 printMap(writer, mClientServiceInfoByUid); 555 writer.println("mUidAByName:"); 556 printMap(writer, mUidByName); 557 writer.println("mUidByClientId:"); 558 printMap(writer, mUidByClientId); 559 writer.println("mServerlessClientIdsByPackageName:"); 560 printMap(writer, mServerlessClientIdsByPackageName); 561 writer.println("mTasksToBeNotifiedByClientId"); 562 writer.increaseIndent(); 563 for (int i = 0; i < mTasksToBeNotifiedByClientId.size(); i++) { 564 String clientId = mTasksToBeNotifiedByClientId.keyAt(i); 565 List<String> taskIds = new ArrayList<>(); 566 List<RemoteTask> tasks = mTasksToBeNotifiedByClientId.valueAt(i); 567 for (int j = 0; j < tasks.size(); j++) { 568 taskIds.add(tasks.get(j).id); 569 } 570 writer.printf("%d: %s ==> %s\n", i, clientId, taskIds); 571 } 572 writer.decreaseIndent(); 573 writer.println("active task count by Uid:"); 574 writer.increaseIndent(); 575 for (int i = 0; i < mClientServiceInfoByUid.size(); i++) { 576 String uidName = mClientServiceInfoByUid.keyAt(i); 577 RemoteTaskClientServiceInfo serviceInfo = mClientServiceInfoByUid.valueAt(i); 578 int count = 0; 579 if (serviceInfo.getServiceConnection() != null) { 580 count = serviceInfo.getServiceConnection().getActiveTaskCount(); 581 } 582 writer.printf("%d: %s ==> %d\n", i, uidName, count); 583 } 584 writer.decreaseIndent(); 585 } 586 } 587 588 @Override 589 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) dumpProto(ProtoOutputStream proto)590 public void dumpProto(ProtoOutputStream proto) { 591 synchronized (mLock) { 592 for (int i = 0; i < mServerlessClientIdsByPackageName.size(); i++) { 593 long fieldToken = proto.start(CarRemoteAccessDumpProto.SERVERLESS_CLIENTS); 594 proto.write(CarRemoteAccessDumpProto.ServerlessClientInfo.CLIENT_ID, 595 mServerlessClientIdsByPackageName.valueAt(i)); 596 proto.write(CarRemoteAccessDumpProto.ServerlessClientInfo.PACKAGE_NAME, 597 mServerlessClientIdsByPackageName.keyAt(i)); 598 proto.end(fieldToken); 599 } 600 } 601 } 602 getPackageNameForCallingUid(int callingUid)603 private String getPackageNameForCallingUid(int callingUid) { 604 String[] packageNames = mPackageManager.getPackagesForUid(callingUid); 605 if (packageNames.length != 1) { 606 throw new IllegalStateException("Failed to get package name, " 607 + "sharedUserId must not be used by app."); 608 } 609 return packageNames[0]; 610 } 611 612 /** 613 * Registers {@code ICarRemoteAccessCallback}. 614 * 615 * <p>When a callback is registered for a package, calling {@code addCarRemoteTaskClient} will 616 * replace the registered callback with the new one. 617 * 618 * @param callback {@code ICarRemoteAccessCallback} that listens to remote access events. 619 * @throws IllegalArgumentException When {@code callback} is {@code null}. 620 */ 621 @Override addCarRemoteTaskClient(ICarRemoteAccessCallback callback)622 public void addCarRemoteTaskClient(ICarRemoteAccessCallback callback) { 623 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_USE_REMOTE_ACCESS); 624 Preconditions.checkArgument(callback != null, "callback cannot be null"); 625 int callingUid = mDep.getCallingUid(); 626 ClientToken token; 627 String uidName; 628 synchronized (mLock) { 629 uidName = getNameForUidLocked(callingUid); 630 Slogf.i(TAG, "addCarRemoteTaskClient from uid: %s", uidName); 631 632 String packageName = getPackageNameForCallingUid(callingUid); 633 boolean isServerless = mServerlessClientIdsByPackageName.containsKey(packageName); 634 635 if (isServerless) { 636 Slogf.i(TAG, "addCarRemoteTaskClient called from a serverless remote access " 637 + "client: " + packageName); 638 } 639 640 token = mClientTokenByUidName.get(uidName); 641 642 if (isServerless && token != null 643 && !(token.getClientId().equals( 644 mServerlessClientIdsByPackageName.get(packageName)))) { 645 Slogf.w(TAG, "client: " + packageName + " is a serverless remote access client " 646 + "but has a different client ID, clear the previous client ID record"); 647 // In a rare case if the same client was previously not configured as a serverless 648 // client, hence had a different client ID. But now it has become a serverless 649 // remote access client. We must clear the previous record. 650 mUidByClientId.remove(token.getClientId()); 651 mClientTokenByUidName.remove(uidName); 652 if (token.getCallback() != null) { 653 token.getCallback().asBinder().unlinkToDeath(token, /* flags= */ 0); 654 } 655 token = null; 656 } 657 658 if (token != null) { 659 // This is an already registered client. 660 ICarRemoteAccessCallback oldCallback = token.getCallback(); 661 if (oldCallback != null) { 662 oldCallback.asBinder().unlinkToDeath(token, /* flags= */ 0); 663 } 664 } else { 665 // This is a new client. 666 String clientId; 667 if (isServerless) { 668 // This is a serverless remote task client. Use the preconfigured client ID. 669 clientId = mServerlessClientIdsByPackageName.get(packageName); 670 } else { 671 // For regular remote task client, create a new random client ID. 672 clientId = generateNewClientId(); 673 } 674 // Creates a new client token with a null callback. The callback will be registered 675 // in postRegistrationUpdated. 676 token = new ClientToken(clientId, System.currentTimeMillis(), isServerless); 677 mClientTokenByUidName.put(uidName, token); 678 mUidByClientId.put(token.getClientId(), uidName); 679 } 680 try { 681 callback.asBinder().linkToDeath(token, /* flags= */ 0); 682 } catch (RemoteException e) { 683 token.setCallback(null); 684 throw new IllegalStateException("Failed to linkToDeath callback"); 685 } 686 } 687 saveClientIdInDb(token, uidName); 688 postRegistrationUpdated(callback, token); 689 } 690 691 /** 692 * Unregisters {@code ICarRemoteAccessCallback}. 693 * 694 * @param callback {@code ICarRemoteAccessCallback} that listens to remote access events. 695 * @throws IllegalArgumentException When {@code callback} is {@code null}. 696 */ 697 @Override removeCarRemoteTaskClient(ICarRemoteAccessCallback callback)698 public void removeCarRemoteTaskClient(ICarRemoteAccessCallback callback) { 699 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_USE_REMOTE_ACCESS); 700 Preconditions.checkArgument(callback != null, "callback cannot be null"); 701 int callingUid = mDep.getCallingUid(); 702 RemoteTaskClientServiceConnection connection = null; 703 String uidName; 704 synchronized (mLock) { 705 uidName = getNameForUidLocked(callingUid); 706 Slogf.i(TAG, "removeCarRemoteTaskClient from uid: %s", uidName); 707 ClientToken token = mClientTokenByUidName.get(uidName); 708 if (token == null) { 709 Slogf.w(TAG, "Cannot remove callback. Callback has not been registered for %s", 710 uidName); 711 return; 712 } 713 if (token.getCallback() == null) { 714 Slogf.w(TAG, "The callback to remove is already dead, do nothing"); 715 return; 716 } 717 if (token.getCallback().asBinder() != callback.asBinder()) { 718 Slogf.w(TAG, "Cannot remove callback. Provided callback is not the same as the " 719 + "registered callback for %s", uidName); 720 return; 721 } 722 callback.asBinder().unlinkToDeath(token, /* flags= */ 0); 723 token.setCallback(null); 724 connection = getServiceConnectionLocked(uidName); 725 } 726 if (connection == null) { 727 Slogf.w(TAG, "No active service connection for uid: %s", uidName); 728 return; 729 } 730 connection.removeAllActiveTasks(); 731 Slogf.i(TAG, "All active tasks removed for uid: %s, after %d ms, check whether we should " 732 + "shutdown", uidName, mTaskUnbindDelayMs); 733 mHandler.postMaybeShutdown(/* delayMs= */ mTaskUnbindDelayMs); 734 } 735 736 @GuardedBy("mLock") getUidNameForPackageNameLocked(String packageName)737 private String getUidNameForPackageNameLocked(String packageName) { 738 String uidName = ""; 739 try { 740 uidName = getNameForUidLocked(mPackageManager.getPackageUidAsUser( 741 packageName, PackageInfoFlags.of(0), /* uid= */ 0)); 742 } catch (Exception e) { 743 // Do thing. 744 } 745 return uidName; 746 } 747 748 /** 749 * Used in testing only. Clear up the stored client token information for the package. 750 */ 751 @GuardedBy("mLock") clearUpClientTokenForPackageLocked(String packageName)752 private void clearUpClientTokenForPackageLocked(String packageName) { 753 String uidName = getUidNameForPackageNameLocked(packageName); 754 String clientId = ""; 755 for (int i = 0; i < mClientTokenByUidName.size(); i++) { 756 if (!mClientTokenByUidName.keyAt(i).equals(uidName)) { 757 continue; 758 } 759 clientId = mClientTokenByUidName.valueAt(i).getClientId(); 760 break; 761 } 762 if (!clientId.isEmpty()) { 763 Slogf.i(TAG, "Clearing stored client token for uidName: %s because the client is now a " 764 + "serverless remote task client", uidName); 765 mClientTokenByUidName.remove(uidName); 766 mUidByClientId.remove(clientId); 767 } 768 } 769 770 /** 771 * {@link android.car.remoteaccess.CarRemoteAccessManager#addServerlessRemoteTaskClient} 772 */ 773 @Override addServerlessRemoteTaskClient(String packageName, String clientId)774 public void addServerlessRemoteTaskClient(String packageName, String clientId) { 775 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 776 Preconditions.checkArgument(packageName != null, "packageName must not be null"); 777 Preconditions.checkArgument(clientId != null, "clientId must not be null"); 778 synchronized (mLock) { 779 Slogf.i(TAG, "Adding a new test serverless remote task client, packageName: %s, " 780 + "clientId: %s", packageName, clientId); 781 if (mServerlessClientIdsByPackageName.containsKey(packageName)) { 782 String message = "The package: " + packageName 783 + " is already an serverless remote task client"; 784 Slogf.w(TAG, message); 785 throw new IllegalArgumentException(message); 786 } 787 for (int i = 0; i < mServerlessClientIdsByPackageName.size(); i++) { 788 if (mServerlessClientIdsByPackageName.valueAt(i).equals(clientId)) { 789 String message = "The client ID: " + clientId 790 + " is already used, pick a different client ID"; 791 Slogf.w(TAG, message); 792 throw new IllegalArgumentException(message); 793 } 794 } 795 mServerlessClientIdsByPackageName.put(packageName, clientId); 796 clearUpClientTokenForPackageLocked(packageName); 797 } 798 } 799 800 /** 801 * {@link android.car.remoteaccess.CarRemoteAccessManager#removeServerlessRemoteTaskClient} 802 */ 803 @Override removeServerlessRemoteTaskClient(String packageName)804 public void removeServerlessRemoteTaskClient(String packageName) { 805 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 806 Preconditions.checkArgument(packageName != null, "packageName must not be null"); 807 synchronized (mLock) { 808 mServerlessClientIdsByPackageName.remove(packageName); 809 clearUpClientTokenForPackageLocked(packageName); 810 } 811 } 812 813 /** 814 * {@link android.car.remoteaccess.CarRemoteAccessManager#isTaskScheduleSupported} 815 */ 816 @Override isTaskScheduleSupported()817 public boolean isTaskScheduleSupported() { 818 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 819 if (!mIsHalTaskScheduleSupported) { 820 Slogf.i(TAG, "isTaskScheduleSupported returns false because remote access HAL does not" 821 + " support task scheduling"); 822 return false; 823 } 824 int callingUid = mDep.getCallingUid(); 825 String packageName = getPackageNameForCallingUid(callingUid); 826 synchronized (mLock) { 827 if (!mServerlessClientIdsByPackageName.containsKey(packageName)) { 828 Slogf.i(TAG, "isTaskScheduleSupported returns false the client is not a serverless" 829 + " remote task client"); 830 return false; 831 } 832 } 833 Slogf.i(TAG, "isTaskScheduleSupported returns true"); 834 return true; 835 836 } 837 getServerlessCallerClientId()838 private String getServerlessCallerClientId() throws IllegalStateException { 839 if (!mIsHalTaskScheduleSupported) { 840 throw new IllegalStateException("task schedule is not supported by HAL"); 841 } 842 int callingUid = mDep.getCallingUid(); 843 String packageName = getPackageNameForCallingUid(callingUid); 844 synchronized (mLock) { 845 if (mServerlessClientIdsByPackageName.containsKey(packageName)) { 846 return mServerlessClientIdsByPackageName.get(packageName); 847 } 848 } 849 throw new IllegalStateException("Caller is not a serverless remote task client"); 850 } 851 852 /** 853 * {@link android.car.remoteaccess.CarRemoteAccessManager#scheduleTask} 854 */ 855 @Override scheduleTask(TaskScheduleInfo scheduleInfo)856 public void scheduleTask(TaskScheduleInfo scheduleInfo) { 857 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 858 Preconditions.checkArgument(scheduleInfo != null, "scheduleInfo must not be null"); 859 Preconditions.checkArgument(scheduleInfo.scheduleId != null, "scheduleId must not be null"); 860 Preconditions.checkArgument(scheduleInfo.taskData != null, "task data must not be null"); 861 Preconditions.checkArgument(scheduleInfo.count >= 0, "count must >= 0"); 862 Preconditions.checkArgument(scheduleInfo.startTimeInEpochSeconds > 0, 863 "startTimeInEpochSeconds must > 0"); 864 Preconditions.checkArgument(scheduleInfo.periodicInSeconds >= 0, 865 "periodicInSeconds must >= 0"); 866 ScheduleInfo halScheduleInfo = new ScheduleInfo(); 867 String clientId = getServerlessCallerClientId(); 868 halScheduleInfo.clientId = clientId; 869 switch (scheduleInfo.taskType) { 870 case TASK_TYPE_CUSTOM: 871 halScheduleInfo.taskType = TaskType.CUSTOM; 872 break; 873 case TASK_TYPE_ENTER_GARAGE_MODE: 874 halScheduleInfo.taskType = TaskType.ENTER_GARAGE_MODE; 875 break; 876 default: 877 throw new IllegalArgumentException("Unsupported task type: " 878 + scheduleInfo.taskType); 879 } 880 halScheduleInfo.scheduleId = scheduleInfo.scheduleId; 881 halScheduleInfo.taskData = scheduleInfo.taskData; 882 halScheduleInfo.count = scheduleInfo.count; 883 halScheduleInfo.startTimeInEpochSeconds = scheduleInfo.startTimeInEpochSeconds; 884 halScheduleInfo.periodicInSeconds = scheduleInfo.periodicInSeconds; 885 try { 886 mRemoteAccessHalWrapper.scheduleTask(halScheduleInfo); 887 } catch (RemoteException | ServiceSpecificException e) { 888 throw new ServiceSpecificException(SERVICE_ERROR_CODE_GENERAL, 889 "failed to call IRemoteAccess.scheduleTask with scheduleInfo: " 890 + halScheduleInfo + ", error: " + e); 891 } 892 } 893 894 /** 895 * {@link android.car.remoteaccess.CarRemoteAccessManager#unscheduleTask} 896 */ 897 @Override unscheduleTask(String scheduleId)898 public void unscheduleTask(String scheduleId) { 899 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 900 Preconditions.checkArgument(scheduleId != null, "scheduleId must not be null"); 901 String clientId = getServerlessCallerClientId(); 902 try { 903 mRemoteAccessHalWrapper.unscheduleTask(clientId, scheduleId); 904 } catch (RemoteException | ServiceSpecificException e) { 905 throw new ServiceSpecificException(SERVICE_ERROR_CODE_GENERAL, 906 "failed to call IRemoteAccess.unscheduleTask with clientId: " 907 + clientId + ", scheduleId: " + scheduleId+ ", error: " + e); 908 } 909 } 910 911 /** 912 * {@link android.car.remoteaccess.CarRemoteAccessManager#unscheduleAllTasks} 913 */ 914 @Override unscheduleAllTasks()915 public void unscheduleAllTasks() { 916 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 917 String clientId = getServerlessCallerClientId(); 918 try { 919 mRemoteAccessHalWrapper.unscheduleAllTasks(clientId); 920 } catch (RemoteException | ServiceSpecificException e) { 921 throw new ServiceSpecificException(SERVICE_ERROR_CODE_GENERAL, 922 "failed to call IRemoteAccess.unscheduleAllTasks with clientId: " 923 + clientId + ", error: " + e); 924 } 925 } 926 927 /** 928 * {@link android.car.remoteaccess.CarRemoteAccessManager#isTaskScheduled} 929 */ 930 @Override isTaskScheduled(String scheduleId)931 public boolean isTaskScheduled(String scheduleId) { 932 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 933 Preconditions.checkArgument(scheduleId != null, "scheduleId must not be null"); 934 String clientId = getServerlessCallerClientId(); 935 try { 936 return mRemoteAccessHalWrapper.isTaskScheduled(clientId, scheduleId); 937 } catch (RemoteException | ServiceSpecificException e) { 938 throw new ServiceSpecificException(SERVICE_ERROR_CODE_GENERAL, 939 "failed to call IRemoteAccess.isTaskScheduled with clientId: " 940 + clientId + ", scheduleId: " + scheduleId+ ", error: " + e); 941 } 942 } 943 944 /** 945 * {@link android.car.remoteaccess.CarRemoteAccessManager#getAllPendingScheduledTasks} 946 */ 947 @Override getAllPendingScheduledTasks()948 public List<TaskScheduleInfo> getAllPendingScheduledTasks() { 949 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 950 String clientId = getServerlessCallerClientId(); 951 List<TaskScheduleInfo> taskScheduleInfoList = new ArrayList<>(); 952 try { 953 List<ScheduleInfo> halScheduleInfoList = 954 mRemoteAccessHalWrapper.getAllPendingScheduledTasks(clientId); 955 for (int i = 0; i < halScheduleInfoList.size(); i++) { 956 ScheduleInfo halScheduleInfo = halScheduleInfoList.get(i); 957 TaskScheduleInfo taskScheduleInfo = new TaskScheduleInfo(); 958 taskScheduleInfo.scheduleId = halScheduleInfo.scheduleId; 959 taskScheduleInfo.taskData = halScheduleInfo.taskData; 960 taskScheduleInfo.count = halScheduleInfo.count; 961 taskScheduleInfo.startTimeInEpochSeconds = halScheduleInfo.startTimeInEpochSeconds; 962 taskScheduleInfo.periodicInSeconds = halScheduleInfo.periodicInSeconds; 963 switch (halScheduleInfo.taskType) { 964 case TaskType.CUSTOM: 965 taskScheduleInfo.taskType = TASK_TYPE_CUSTOM; 966 break; 967 case TaskType.ENTER_GARAGE_MODE: 968 taskScheduleInfo.taskType = TASK_TYPE_ENTER_GARAGE_MODE; 969 break; 970 default: 971 Slogf.e(TAG, "Unknown task type returned by remote access HAL for: " 972 + taskScheduleInfo + ", default to TASK_TYPE_CUSTOM"); 973 taskScheduleInfo.taskType = TASK_TYPE_CUSTOM; 974 } 975 taskScheduleInfoList.add(taskScheduleInfo); 976 } 977 return taskScheduleInfoList; 978 } catch (RemoteException | ServiceSpecificException e) { 979 throw new ServiceSpecificException(SERVICE_ERROR_CODE_GENERAL, 980 "failed to call IRemoteAccess.getAllPendingScheduledTasks with clientId: " 981 + clientId + ", error: " + e); 982 } 983 } 984 985 @Override getSupportedTaskTypesForScheduling()986 public int[] getSupportedTaskTypesForScheduling() { 987 if (!isTaskScheduleSupported()) { 988 Slogf.i(TAG, "task scheduling is not supported, return empty array for " 989 + "getSupportedTaskTypesForScheduling"); 990 return EMPTY_INT_ARRAY; 991 } 992 int[] supportedHalTaskTypes; 993 try { 994 supportedHalTaskTypes = mRemoteAccessHalWrapper.getSupportedTaskTypesForScheduling(); 995 } catch (RemoteException | ServiceSpecificException e) { 996 throw new ServiceSpecificException(SERVICE_ERROR_CODE_GENERAL, 997 "failed to call IRemoteAccess.getSupportedTaskTypesForScheduling, error: " + e); 998 } 999 ArraySet<Integer> supportedMgrTaskTypes = new ArraySet<>(); 1000 for (int i = 0; i < supportedHalTaskTypes.length; i++) { 1001 switch (supportedHalTaskTypes[i]) { 1002 case TaskType.CUSTOM: 1003 supportedMgrTaskTypes.add(TASK_TYPE_CUSTOM); 1004 break; 1005 case TaskType.ENTER_GARAGE_MODE: 1006 supportedMgrTaskTypes.add(TASK_TYPE_ENTER_GARAGE_MODE); 1007 break; 1008 default: 1009 Slogf.e(TAG, "Unknown supported task type returned from remote access HAL, " 1010 + "ignore: " + supportedHalTaskTypes[i]); 1011 } 1012 } 1013 // Convert to int array. 1014 int[] result = new int[supportedMgrTaskTypes.size()]; 1015 for (int i = 0; i < supportedMgrTaskTypes.size(); i++) { 1016 result[i] = supportedMgrTaskTypes.valueAt(i); 1017 } 1018 return result; 1019 } 1020 1021 @GuardedBy("mLock") getTokenForUidNameAndCheckClientIdLocked(String uidName, String clientId)1022 private ClientToken getTokenForUidNameAndCheckClientIdLocked(String uidName, String clientId) 1023 throws IllegalArgumentException { 1024 ClientToken token = mClientTokenByUidName.get(uidName); 1025 if (token == null) { 1026 throw new IllegalArgumentException("Callback has not been registered"); 1027 } 1028 // TODO(b/252698817): Update the validity checking logic. 1029 if (!clientId.equals(token.getClientId())) { 1030 throw new IllegalArgumentException("Client ID(" + clientId + ") doesn't match the " 1031 + "registered one(" + token.getClientId() + ")"); 1032 } 1033 return token; 1034 } 1035 1036 @GuardedBy("mLock") getServiceConnectionLocked(String uidName)1037 private @Nullable RemoteTaskClientServiceConnection getServiceConnectionLocked(String uidName) { 1038 if (DEBUG) { 1039 Slogf.d(TAG, "getServiceConnectionLocked for uid: %s", uidName); 1040 } 1041 RemoteTaskClientServiceInfo serviceInfo = mClientServiceInfoByUid.get(uidName); 1042 if (serviceInfo == null) { 1043 if (DEBUG) { 1044 Slogf.d(TAG, "the service info for uid: %s is null", uidName); 1045 } 1046 return null; 1047 } 1048 return serviceInfo.getServiceConnection(); 1049 } 1050 1051 /** 1052 * Reports that the task of {@code taskId} is completed. 1053 * 1054 * @param clientId ID of a client that has completed the task. 1055 * @param taskId ID of a task that has been completed. 1056 * @throws IllegalArgumentException When {@code clientId} is not valid, or {@code taskId} is not 1057 * valid. 1058 */ 1059 @Override reportRemoteTaskDone(String clientId, String taskId)1060 public void reportRemoteTaskDone(String clientId, String taskId) { 1061 Slogf.i(TAG, "reportRemoteTaskDone for client: %s, task: %s", clientId, taskId); 1062 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_USE_REMOTE_ACCESS); 1063 Preconditions.checkArgument(clientId != null, "clientId cannot be null"); 1064 Preconditions.checkArgument(taskId != null, "taskId cannot be null"); 1065 int callingUid = mDep.getCallingUid(); 1066 String uidName; 1067 RemoteTaskClientServiceConnection serviceConnection; 1068 synchronized (mLock) { 1069 uidName = getNameForUidLocked(callingUid); 1070 getTokenForUidNameAndCheckClientIdLocked(uidName, clientId); 1071 serviceConnection = getServiceConnectionLocked(uidName); 1072 } 1073 if (serviceConnection == null) { 1074 throw new IllegalArgumentException("No active service connection, uidName: " + uidName 1075 + ", clientId: " + clientId); 1076 } 1077 if (!serviceConnection.removeActiveTasks(new ArraySet<>(Set.of(taskId)))) { 1078 throw new IllegalArgumentException("Task ID(" + taskId + ") is not valid"); 1079 } 1080 if (DEBUG) { 1081 Slogf.d(TAG, "Task: %s complete, after %d ms, check whether we should shutdown", 1082 taskId, mTaskUnbindDelayMs); 1083 } 1084 mHandler.postMaybeShutdown(/* delayMs= */ mTaskUnbindDelayMs); 1085 } 1086 1087 @Override setPowerStatePostTaskExecution(int nextPowerState, boolean runGarageMode)1088 public void setPowerStatePostTaskExecution(int nextPowerState, boolean runGarageMode) { 1089 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 1090 Slogf.i(TAG, "setPowerStatePostTaskExecution, nextPowerState: %d, runGarageMode: %B", 1091 nextPowerState, runGarageMode); 1092 1093 synchronized (mLock) { 1094 mNextPowerState = nextPowerState; 1095 mRunGarageMode = runGarageMode; 1096 } 1097 } 1098 1099 @Override confirmReadyForShutdown(String clientId)1100 public void confirmReadyForShutdown(String clientId) { 1101 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_USE_REMOTE_ACCESS); 1102 Preconditions.checkArgument(clientId != null, "clientId cannot be null"); 1103 int callingUid = mDep.getCallingUid(); 1104 boolean isAllClientReadyForShutDown = true; 1105 synchronized (mLock) { 1106 String uidName = getNameForUidLocked(callingUid); 1107 Slogf.i(TAG, "confirmReadyForShutdown from client: %s, uidName: %s", clientId, uidName); 1108 ClientToken token = getTokenForUidNameAndCheckClientIdLocked(uidName, clientId); 1109 token.setIsReadyForShutdown(); 1110 1111 for (int i = 0; i < mClientTokenByUidName.size(); i++) { 1112 ClientToken clientToken = mClientTokenByUidName.valueAt(i); 1113 if (clientToken.getCallback() == null) { 1114 continue; 1115 } 1116 if (!clientToken.isReadyForShutdown()) { 1117 isAllClientReadyForShutDown = false; 1118 } 1119 } 1120 } 1121 1122 if (isAllClientReadyForShutDown) { 1123 mHandler.postWrapUpRemoteAccessService(/* delayMs= */ 0); 1124 } 1125 } 1126 1127 /** 1128 * Returns whether {@code VEHICLE_IN_USE} is supported and getting it returns a valid value. 1129 */ 1130 @Override isVehicleInUseSupported()1131 public boolean isVehicleInUseSupported() { 1132 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 1133 return mPowerHalService.isVehicleInUseSupported(); 1134 } 1135 1136 /** 1137 * Returns whether {@code SHUTDOWN_REQUEST} is supported. 1138 */ 1139 @Override isShutdownRequestSupported()1140 public boolean isShutdownRequestSupported() { 1141 CarServiceUtils.assertPermission(mContext, Car.PERMISSION_CONTROL_REMOTE_ACCESS); 1142 return mPowerHalService.isShutdownRequestSupported(); 1143 } 1144 1145 @VisibleForTesting getRemoteAccessHalCallback()1146 RemoteAccessHalCallback getRemoteAccessHalCallback() { 1147 return mHalCallback; 1148 } 1149 1150 @VisibleForTesting getAllowedSystemUptimeMs()1151 long getAllowedSystemUptimeMs() { 1152 return mAllowedSystemUptimeMs; 1153 } 1154 1155 @VisibleForTesting getServerlessClientIdsByPackageName()1156 ArrayMap<String, String> getServerlessClientIdsByPackageName() { 1157 synchronized (mLock) { 1158 return mServerlessClientIdsByPackageName; 1159 } 1160 } 1161 parseServerlessClientIdsByPackageName()1162 private ArrayMap<String, String> parseServerlessClientIdsByPackageName() { 1163 ArrayMap<String, String> clientIdsByPackageName = new ArrayMap<>(); 1164 1165 if (!mFeatureFlags.serverlessRemoteAccess()) { 1166 Slogf.i(TAG, "Serverless remote access flag is disabled, skip parsing " 1167 + "remote_access_serverless_client_map.xml"); 1168 return clientIdsByPackageName; 1169 } 1170 1171 try (XmlResourceParser parser = mContext.getResources().getXml( 1172 R.xml.remote_access_serverless_client_map)) { 1173 // Get to the first start tag. 1174 while (parser.getEventType() != XmlPullParser.START_TAG) { 1175 if (parser.next() == XmlPullParser.END_DOCUMENT) { 1176 break; 1177 } 1178 } 1179 1180 // Check the root tag. 1181 parser.require(XmlPullParser.START_TAG, /* namespace= */ null, 1182 XML_TAG_SERVERLESS_CLIENT_MAP); 1183 while (parser.next() != XmlPullParser.END_DOCUMENT) { 1184 if (parser.getEventType() != XmlPullParser.START_TAG) { 1185 continue; 1186 } 1187 String name = parser.getName(); 1188 if (name.equals(XML_TAG_SERVERLESS_CLIENT)) { 1189 readServerlessClient(parser, clientIdsByPackageName); 1190 } else { 1191 skip(parser); 1192 } 1193 } 1194 } catch (Exception e) { 1195 Slogf.e(TAG, "Failed to parse remote_access_serverless_client_map.xml, disabled all " 1196 + "serverless remote task client.", e); 1197 } 1198 1199 return clientIdsByPackageName; 1200 } 1201 readServerlessClient(XmlPullParser parser, ArrayMap<String, String> clientIdsByPackageName)1202 private void readServerlessClient(XmlPullParser parser, 1203 ArrayMap<String, String> clientIdsByPackageName) 1204 throws XmlPullParserException, IOException { 1205 parser.require(XmlPullParser.START_TAG, /* namespace= */ null, XML_TAG_SERVERLESS_CLIENT); 1206 String clientId = null; 1207 String packageName = null; 1208 while (parser.next() != XmlPullParser.END_TAG) { 1209 if (parser.getEventType() != XmlPullParser.START_TAG) { 1210 continue; 1211 } 1212 String name = parser.getName(); 1213 if (name.equals(XML_TAG_CLIENT_ID)) { 1214 clientId = readClientId(parser); 1215 } else if (name.equals(XML_TAG_PACKAGE_NAME)) { 1216 packageName = readPackageName(parser); 1217 } else { 1218 skip(parser); 1219 } 1220 } 1221 if (clientId == null) { 1222 throw new IllegalStateException("Missing ClientId field"); 1223 } 1224 if (packageName == null) { 1225 throw new IllegalStateException("Missing PackageName field"); 1226 } 1227 clientIdsByPackageName.put(packageName, clientId); 1228 } 1229 readClientId(XmlPullParser parser)1230 private String readClientId(XmlPullParser parser) 1231 throws XmlPullParserException, IOException { 1232 parser.require(XmlPullParser.START_TAG, /* namespace= */ null, XML_TAG_CLIENT_ID); 1233 String clientId = readText(parser); 1234 parser.require(XmlPullParser.END_TAG, /* namespace= */ null, XML_TAG_CLIENT_ID); 1235 return clientId; 1236 } 1237 readPackageName(XmlPullParser parser)1238 private String readPackageName(XmlPullParser parser) 1239 throws XmlPullParserException, IOException { 1240 parser.require(XmlPullParser.START_TAG, /* namespace= */ null, XML_TAG_PACKAGE_NAME); 1241 String packageName = readText(parser); 1242 parser.require(XmlPullParser.END_TAG, /* namespace= */ null, XML_TAG_PACKAGE_NAME); 1243 return packageName; 1244 } 1245 1246 // For the tags title and summary, extracts their text values. readText(XmlPullParser parser)1247 private String readText(XmlPullParser parser) throws IOException, XmlPullParserException { 1248 String result = ""; 1249 if (parser.next() == XmlPullParser.TEXT) { 1250 result = parser.getText(); 1251 parser.nextTag(); 1252 } 1253 return result; 1254 } 1255 1256 // Skip uninterested tags. skip(XmlPullParser parser)1257 private void skip(XmlPullParser parser) throws XmlPullParserException, IOException { 1258 if (parser.getEventType() != XmlPullParser.START_TAG) { 1259 throw new IllegalStateException("Invalid xml"); 1260 } 1261 int depth = 1; 1262 while (depth != 0) { 1263 switch (parser.next()) { 1264 case XmlPullParser.END_TAG: 1265 depth--; 1266 break; 1267 case XmlPullParser.START_TAG: 1268 depth++; 1269 break; 1270 } 1271 } 1272 } 1273 populatePackageClientIdMapping()1274 private void populatePackageClientIdMapping() { 1275 List<ClientIdEntry> clientIdEntries = mRemoteAccessStorage.getClientIdEntries(); 1276 ArrayMap<String, String> clientIdsByPackageName = parseServerlessClientIdsByPackageName(); 1277 1278 synchronized (mLock) { 1279 if (clientIdEntries != null) { 1280 for (int i = 0; i < clientIdEntries.size(); i++) { 1281 ClientIdEntry entry = clientIdEntries.get(i); 1282 mUidByClientId.put(entry.clientId, entry.uidName); 1283 mClientTokenByUidName.put(entry.uidName, 1284 new ClientToken(entry.clientId, entry.idCreationTime)); 1285 } 1286 } 1287 mServerlessClientIdsByPackageName = clientIdsByPackageName; 1288 Slogf.i(TAG, "mServerlessClientIdsByPackageName: " + clientIdsByPackageName); 1289 } 1290 } 1291 saveClientIdInDb(ClientToken token, String uidName)1292 private void saveClientIdInDb(ClientToken token, String uidName) { 1293 if (token.isServerless()) { 1294 // This token is static and no need to be stored in db. 1295 return; 1296 } 1297 ClientIdEntry entry = new ClientIdEntry(token.getClientId(), token.getIdCreationTime(), 1298 uidName); 1299 if (!mRemoteAccessStorage.updateClientId(entry)) { 1300 Slogf.e(TAG, "Failed to save %s for %s in the database", token, uidName); 1301 } 1302 } 1303 postRegistrationUpdated(ICarRemoteAccessCallback callback, ClientToken token)1304 private void postRegistrationUpdated(ICarRemoteAccessCallback callback, ClientToken token) { 1305 String clientId = token.getClientId(); 1306 mHandler.post(() -> { 1307 if (DEBUG) { 1308 Slogf.d(TAG, "Calling onClientRegistrationUpdated: serviceName=%s, " 1309 + "vehicleId=%s, processorId=%s, clientId=%s, isServerless=%s", 1310 mWakeupServiceName, mVehicleId, mProcessorId, clientId, 1311 token.isServerless()); 1312 } 1313 if (!token.isServerless()) { 1314 try { 1315 callback.onClientRegistrationUpdated(new RemoteTaskClientRegistrationInfo( 1316 mWakeupServiceName, mVehicleId, mProcessorId, clientId)); 1317 } catch (RemoteException e) { 1318 Slogf.e(TAG, e, "Calling onClientRegistrationUpdated() failed: clientId = %s", 1319 clientId); 1320 } 1321 } else { 1322 try { 1323 callback.onServerlessClientRegistered(clientId); 1324 } catch (RemoteException e) { 1325 Slogf.e(TAG, e, "Calling onServerlessClientRegistered() failed"); 1326 } 1327 } 1328 1329 // After notify the client about the registration info, the callback is registered. 1330 token.setCallback(callback); 1331 1332 // Just after a registration callback is invoked, let's call onRemoteTaskRequested 1333 // callback if there are pending tasks. 1334 maybeStartNewRemoteTask(clientId); 1335 }); 1336 } 1337 shutdownIfNeeded(boolean force)1338 private void shutdownIfNeeded(boolean force) { 1339 if (DEBUG) { 1340 Slogf.d(TAG, "shutdownIfNeeded, force: %B", force); 1341 } 1342 int nextPowerState; 1343 boolean runGarageMode; 1344 synchronized (mLock) { 1345 if (mNextPowerState == CarRemoteAccessManager.NEXT_POWER_STATE_ON) { 1346 Slogf.i(TAG, "Will not shutdown. The next power state is ON."); 1347 return; 1348 } 1349 if (mPowerHalService.isVehicleInUse()) { 1350 Slogf.i(TAG, "Will not shutdown. The vehicle is in use."); 1351 return; 1352 } 1353 int taskCount = getActiveTaskCountLocked(); 1354 if (!force && taskCount > 0) { 1355 Slogf.i(TAG, "Will not shutdown. The activen task count is %d.", taskCount); 1356 return; 1357 } 1358 nextPowerState = mNextPowerState; 1359 runGarageMode = mRunGarageMode; 1360 } 1361 if (DEBUG) { 1362 Slogf.d(TAG, "unbindAllServices before shutdown"); 1363 } 1364 unbindAllServices(); 1365 // Send SHUTDOWN_REQUEST to VHAL. 1366 Slogf.i(TAG, "Requesting shutdown of AP: nextPowerState = %d, runGarageMode = %b", 1367 nextPowerState, runGarageMode); 1368 try { 1369 mPowerService.requestShutdownAp(nextPowerState, runGarageMode); 1370 } catch (Exception e) { 1371 Slogf.e(TAG, e, "Cannot shutdown to %s", nextPowerStateToString(nextPowerState)); 1372 } 1373 } 1374 1375 /** 1376 * Unbinds all the remote task client services. 1377 */ unbindAllServices()1378 public void unbindAllServices() { 1379 Slogf.i(TAG, "unbind all the remote task client services"); 1380 ArrayMap<String, RemoteTaskClientServiceInfo> clientServiceInfoByUid; 1381 synchronized (mLock) { 1382 clientServiceInfoByUid = new ArrayMap<>(mClientServiceInfoByUid); 1383 } 1384 for (int i = 0; i < clientServiceInfoByUid.size(); i++) { 1385 unbindRemoteTaskClientService(clientServiceInfoByUid.valueAt(i), 1386 /* force= */ true); 1387 } 1388 } 1389 1390 @GuardedBy("mLock") calcTaskMaxDurationInMsLocked()1391 private long calcTaskMaxDurationInMsLocked() { 1392 long taskMaxDurationInMs; 1393 if (mNextPowerState == CarRemoteAccessManager.NEXT_POWER_STATE_ON 1394 || mPowerHalService.isVehicleInUse()) { 1395 // If next power state is ON or vehicle is in use, the mShutdownTimeInMs does not make 1396 // sense because shutdown will not happen. We always allow task to execute for 1397 // mAllowedSystemUptimMs. 1398 taskMaxDurationInMs = mAllowedSystemUptimeMs; 1399 } else { 1400 taskMaxDurationInMs = mShutdownTimeInMs - SystemClock.uptimeMillis(); 1401 } 1402 if (DEBUG) { 1403 Slogf.d(TAG, "Task max duration in ms: %d", taskMaxDurationInMs); 1404 } 1405 return taskMaxDurationInMs; 1406 } 1407 1408 @VisibleForTesting getActiveTaskCount()1409 int getActiveTaskCount() { 1410 synchronized (mLock) { 1411 return getActiveTaskCountLocked(); 1412 } 1413 } 1414 1415 @GuardedBy("mLock") getActiveTaskCountLocked()1416 private int getActiveTaskCountLocked() { 1417 int count = 0; 1418 for (int i = 0; i < mClientServiceInfoByUid.size(); i++) { 1419 RemoteTaskClientServiceInfo serviceInfo = mClientServiceInfoByUid.valueAt(i); 1420 if (serviceInfo.getServiceConnection() != null) { 1421 count += serviceInfo.getServiceConnection().getActiveTaskCount(); 1422 } 1423 } 1424 return count; 1425 } 1426 getLastShutdownState()1427 private int getLastShutdownState() { 1428 return mPowerService.getLastShutdownState(); 1429 } 1430 getAllowedSystemUptimeForRemoteTaskInMs()1431 private long getAllowedSystemUptimeForRemoteTaskInMs() { 1432 long timeout = mContext.getResources() 1433 .getInteger(R.integer.config_allowedSystemUptimeForRemoteAccess); 1434 if (timeout < MIN_SYSTEM_UPTIME_FOR_REMOTE_ACCESS_IN_SEC) { 1435 timeout = MIN_SYSTEM_UPTIME_FOR_REMOTE_ACCESS_IN_SEC; 1436 Slogf.w(TAG, "config_allowedSystemUptimeForRemoteAccess(%d) should be no less than %d", 1437 timeout, MIN_SYSTEM_UPTIME_FOR_REMOTE_ACCESS_IN_SEC); 1438 } 1439 return timeout * MILLI_TO_SECOND; 1440 } 1441 getNotifyApStateChangeRetrySleepInMs()1442 private int getNotifyApStateChangeRetrySleepInMs() { 1443 int notifyApStateChangeRetrySleepInMs = mContext.getResources() 1444 .getInteger(R.integer.config_notifyApStateChange_retry_sleep_ms); 1445 if (notifyApStateChangeRetrySleepInMs < 0) { 1446 Slogf.e(TAG, "Invalid config_notifyApStateChange_retry_sleep_ms from RRO: " 1447 + notifyApStateChangeRetrySleepInMs + ", must be a positive integer"); 1448 notifyApStateChangeRetrySleepInMs = DEFAULT_NOTIFY_AP_STATE_RETRY_SLEEP_IN_MS; 1449 } 1450 return notifyApStateChangeRetrySleepInMs; 1451 } 1452 getNotifyApStateChangeMaxRetry()1453 private int getNotifyApStateChangeMaxRetry() { 1454 int notifyApStateChangeMaxRetry = mContext.getResources() 1455 .getInteger(R.integer.config_notifyApStateChange_max_retry); 1456 if (notifyApStateChangeMaxRetry < 0) { 1457 Slogf.e(TAG, "Invalid config_notifyApStateChange_max_retry from RRO: " 1458 + notifyApStateChangeMaxRetry + ", must be a positive integer"); 1459 notifyApStateChangeMaxRetry = DEFAULT_NOTIFY_AP_STATE_MAX_RETRY; 1460 } 1461 return notifyApStateChangeMaxRetry; 1462 } 1463 1464 // Gets the UID name for the specified UID. Read from a cached map if exists. Uses package 1465 // manager to get UID if it does not exist in cached map. 1466 @GuardedBy("mLock") getNameForUidLocked(int uid)1467 private String getNameForUidLocked(int uid) { 1468 String uidName = mNameByUid.get(uid); 1469 if (uidName != null) { 1470 return uidName; 1471 } 1472 uidName = mPackageManager.getNameForUid(uid); 1473 mUidByName.put(uidName, uid); 1474 mNameByUid.put(uid, uidName); 1475 return uidName; 1476 } 1477 1478 // Searchs for all remote task client service packages accroding to the declared intent and 1479 // filter them according to their permissions. 1480 // This will start the found remote task client services (as system user) for init registration. searchForRemoteTaskClientPackages()1481 private void searchForRemoteTaskClientPackages() { 1482 // TODO(b/266129982): Query for all users. 1483 if (DEBUG) { 1484 Slogf.d(TAG, "searchForRemoteTaskClientPackages"); 1485 } 1486 List<ResolveInfo> services = mPackageManager.queryIntentServicesAsUser( 1487 new Intent(Car.CAR_REMOTEACCESS_REMOTE_TASK_CLIENT_SERVICE), /* flags= */ 0, 1488 UserHandle.SYSTEM); 1489 ArrayMap<String, RemoteTaskClientServiceInfo> serviceInfoByUidName = new ArrayMap<>(); 1490 synchronized (mLock) { 1491 for (int i = 0; i < services.size(); i++) { 1492 ServiceInfo info = services.get(i).serviceInfo; 1493 String packageName = info.packageName; 1494 ComponentName componentName = new ComponentName(packageName, info.name); 1495 // We require client to has PERMISSION_CONTROL_REMOTE_ACCESS which is a system API 1496 // so that they can be launched as system user. 1497 if (mPackageManager.checkPermission(Car.PERMISSION_CONTROL_REMOTE_ACCESS, 1498 packageName) != PackageManager.PERMISSION_GRANTED) { 1499 Slogf.w(TAG, "Component(%s) has %s intent but doesn't have %s permission", 1500 componentName.flattenToString(), 1501 Car.CAR_REMOTEACCESS_REMOTE_TASK_CLIENT_SERVICE, 1502 Car.PERMISSION_CONTROL_REMOTE_ACCESS); 1503 continue; 1504 } 1505 // TODO(b/263798644): mClientServiceInfoByUid should be updated when packages 1506 // are added, removed, updated. 1507 RemoteTaskClientServiceInfo serviceInfo = 1508 new RemoteTaskClientServiceInfo(componentName); 1509 String uidName = getNameForUidLocked(info.applicationInfo.uid); 1510 mClientServiceInfoByUid.put(uidName, serviceInfo); 1511 if (DEBUG) { 1512 Slogf.d(TAG, "Package(%s) is found as a remote task client service", 1513 packageName); 1514 } 1515 // Store the service info to be started later outside the lock. 1516 serviceInfoByUidName.put(uidName, serviceInfo); 1517 } 1518 } 1519 // Start the remote task client services outside the lock since binding might be a slow 1520 // operation. 1521 for (int i = 0; i < serviceInfoByUidName.size(); i++) { 1522 startRemoteTaskClientService(serviceInfoByUidName.valueAt(i), 1523 serviceInfoByUidName.keyAt(i), mAllowedTimeForRemoteTaskClientInitMs); 1524 } 1525 } 1526 1527 // Starts the remote task client service if not already started and extends its liftime. startRemoteTaskClientService(RemoteTaskClientServiceInfo serviceInfo, String uidName, long taskDurationMs)1528 private void startRemoteTaskClientService(RemoteTaskClientServiceInfo serviceInfo, 1529 String uidName, long taskDurationMs) { 1530 ComponentName serviceName = serviceInfo.getServiceComponentName(); 1531 1532 // Critical section to protect modification to serviceInfo. 1533 RemoteTaskClientServiceConnection serviceConnection; 1534 synchronized (mLock) { 1535 // TODO(b/266129982): Start a service for the user under which the task needs to be 1536 // executed. 1537 if (serviceInfo.getServiceConnection() != null) { 1538 serviceConnection = serviceInfo.getServiceConnection(); 1539 } else { 1540 int uid = mUidByName.get(uidName); 1541 serviceConnection = new RemoteTaskClientServiceConnection(mContext, mHandler, 1542 mUserManager, serviceName, UserHandle.SYSTEM, uid, mTaskUnbindDelayMs); 1543 serviceInfo.setServiceConnection(serviceConnection); 1544 } 1545 } 1546 long taskTimeoutMs = SystemClock.uptimeMillis() + taskDurationMs; 1547 Slogf.i(TAG, "Service(%s) is bound to give a time to register as a remote task client", 1548 serviceName.flattenToString()); 1549 1550 serviceConnection.bindServiceAndExtendTaskTimeoutMs(taskTimeoutMs); 1551 } 1552 onServiceTimeout(int uid)1553 private void onServiceTimeout(int uid) { 1554 RemoteTaskClientServiceInfo serviceInfo; 1555 synchronized (mLock) { 1556 String uidName = getNameForUidLocked(uid); 1557 serviceInfo = mClientServiceInfoByUid.get(uidName); 1558 if (serviceInfo == null) { 1559 Slogf.e(TAG, "No service connection info for %s, must not happen", uidName); 1560 return; 1561 } 1562 } 1563 Slogf.w(TAG, "The service: %s timeout, clearing all pending tasks and " 1564 + "unbind", serviceInfo.getServiceComponentName()); 1565 unbindRemoteTaskClientService(serviceInfo, /* force= */ false); 1566 } 1567 1568 // Stops the remote task client service. If {@code force} is true, the service will always be 1569 // unbound if it is binding or already bound. If it is false, the service will be unbound if 1570 // the service passed its liftime. unbindRemoteTaskClientService(RemoteTaskClientServiceInfo serviceInfo, boolean force)1571 private void unbindRemoteTaskClientService(RemoteTaskClientServiceInfo serviceInfo, 1572 boolean force) { 1573 if (DEBUG) { 1574 Slogf.d(TAG, "Unbinding remote task client service, force: %B", force); 1575 } 1576 RemoteTaskClientServiceConnection connection = serviceInfo.getServiceConnection(); 1577 if (connection == null) { 1578 Slogf.w(TAG, "Cannot unbind remote task client service: no service connection"); 1579 return; 1580 } 1581 ComponentName serviceName = serviceInfo.getServiceComponentName(); 1582 if (connection.unbindService(force)) { 1583 Slogf.i(TAG, "Service(%s) is unbound from CarRemoteAccessService", serviceName); 1584 } else { 1585 Slogf.w(TAG, "Failed to unbind remote task client service(%s)", serviceName); 1586 } 1587 } 1588 notifyApStateChange()1589 private void notifyApStateChange() { 1590 if (DEBUG) { 1591 Slogf.d(TAG, "notify ap state change"); 1592 } 1593 boolean isReadyForRemoteTask; 1594 boolean isWakeupRequired; 1595 synchronized (mLock) { 1596 isReadyForRemoteTask = mIsReadyForRemoteTask; 1597 isWakeupRequired = mIsWakeupRequired; 1598 mNotifyApStateChangeRetryCount++; 1599 if (mNotifyApStateChangeRetryCount > mNotifyApStateChangeMaxRetry) { 1600 Slogf.e(TAG, "Reached max retry count for trying to notify AP state change, " 1601 + "Failed to notify AP state Change!!!"); 1602 return; 1603 } 1604 } 1605 if (!mRemoteAccessHalWrapper.notifyApStateChange(isReadyForRemoteTask, isWakeupRequired)) { 1606 Slogf.e(TAG, "Cannot notify AP state change, waiting for " 1607 + mNotifyApStateChangeRetrySleepInMs + "ms and retry"); 1608 mHandler.postNotifyApStateChange(mNotifyApStateChangeRetrySleepInMs); 1609 return; 1610 } 1611 synchronized (mLock) { 1612 mNotifyApStateChangeRetryCount = 0; 1613 } 1614 if (DEBUG) { 1615 Slogf.d(TAG, "Notified AP about new state, isReadyForRemoteTask: %B, " 1616 + "isWakeupRequired: %B", isReadyForRemoteTask, isWakeupRequired); 1617 } 1618 } 1619 notifyShutdownStarting()1620 private void notifyShutdownStarting() { 1621 List<ICarRemoteAccessCallback> callbacks = new ArrayList<>(); 1622 Slogf.i(TAG, "notifyShutdownStarting"); 1623 synchronized (mLock) { 1624 if (mNextPowerState == CarRemoteAccessManager.NEXT_POWER_STATE_ON) { 1625 Slogf.i(TAG, "Skipping notifyShutdownStarting because the next power state is ON"); 1626 return; 1627 } 1628 if (mPowerHalService.isVehicleInUse()) { 1629 Slogf.i(TAG, "Skipping notifyShutdownStarting because vehicle is currently in use"); 1630 return; 1631 } 1632 for (int i = 0; i < mClientTokenByUidName.size(); i++) { 1633 ClientToken token = mClientTokenByUidName.valueAt(i); 1634 if (token.getCallback() == null) { 1635 Slogf.w(TAG, "Notifying client(%s) of shutdownStarting is skipped: invalid " 1636 + "client token", token); 1637 continue; 1638 } 1639 callbacks.add(token.getCallback()); 1640 } 1641 } 1642 for (int i = 0; i < callbacks.size(); i++) { 1643 ICarRemoteAccessCallback callback = callbacks.get(i); 1644 try { 1645 callback.onShutdownStarting(); 1646 } catch (RemoteException e) { 1647 Slogf.e(TAG, "Calling onShutdownStarting() failed: package", e); 1648 } 1649 } 1650 } 1651 wrapUpRemoteAccessServiceIfNeeded()1652 private void wrapUpRemoteAccessServiceIfNeeded() { 1653 synchronized (mLock) { 1654 if (mNextPowerState != CarRemoteAccessManager.NEXT_POWER_STATE_ON 1655 && !mPowerHalService.isVehicleInUse()) { 1656 Slogf.i(TAG, "Remote task execution time has expired: wrapping up the service"); 1657 } 1658 } 1659 shutdownIfNeeded(/* force= */ true); 1660 } 1661 1662 @Nullable getRemoteTaskClientServiceInfo(String clientId)1663 RemoteTaskClientServiceInfo getRemoteTaskClientServiceInfo(String clientId) { 1664 synchronized (mLock) { 1665 String uidName = mUidByClientId.get(clientId); 1666 if (uidName == null) { 1667 Slogf.w(TAG, "Cannot get package name for client ID(%s)", clientId); 1668 return null; 1669 } 1670 return mClientServiceInfoByUid.get(uidName); 1671 } 1672 } 1673 invokeTaskRequestCallbacks(RemoteTaskClientServiceConnection serviceConnection, ICarRemoteAccessCallback callback, String clientId, List<RemoteTask> tasks, int taskMaxDurationInSec)1674 private void invokeTaskRequestCallbacks(RemoteTaskClientServiceConnection serviceConnection, 1675 ICarRemoteAccessCallback callback, String clientId, List<RemoteTask> tasks, 1676 int taskMaxDurationInSec) { 1677 ArraySet<String> taskIds = new ArraySet<>(); 1678 for (int i = 0; i < tasks.size(); i++) { 1679 taskIds.add(tasks.get(i).id); 1680 } 1681 serviceConnection.addActiveTasks(taskIds); 1682 1683 ArraySet<String> failedTaskIds = new ArraySet<>(); 1684 for (int i = 0; i < tasks.size(); i++) { 1685 RemoteTask task = tasks.get(i); 1686 try { 1687 Slogf.i(TAG, "Delivering remote task, clientId: %s, taskId: %s, " 1688 + "max duration: %d sec", clientId, task.id, taskMaxDurationInSec); 1689 callback.onRemoteTaskRequested(clientId, task.id, task.data, taskMaxDurationInSec); 1690 } catch (RemoteException e) { 1691 Slogf.e(TAG, e, "Calling onRemoteTaskRequested() failed: clientId = %s, " 1692 + "taskId = %s, data size = %d, taskMaxDurationInSec = %d", clientId, 1693 task.id, task.data != null ? task.data.length : 0, taskMaxDurationInSec); 1694 failedTaskIds.add(task.id); 1695 } 1696 } 1697 if (!failedTaskIds.isEmpty()) { 1698 serviceConnection.removeActiveTasks(failedTaskIds); 1699 } 1700 } 1701 1702 @GuardedBy("mLock") pushTaskToPendingQueueLocked(String clientId, RemoteTask task)1703 private void pushTaskToPendingQueueLocked(String clientId, RemoteTask task) { 1704 if (DEBUG) { 1705 Slogf.d(TAG, "received a new remote task: %s", task); 1706 } 1707 1708 ArrayList remoteTasks = mTasksToBeNotifiedByClientId.get(clientId); 1709 if (remoteTasks == null) { 1710 remoteTasks = new ArrayList<RemoteTask>(); 1711 mTasksToBeNotifiedByClientId.put(clientId, remoteTasks); 1712 } 1713 remoteTasks.add(task); 1714 mHandler.postPendingTaskTimeout(task, task.timeoutInMs); 1715 } 1716 onPendingTaskTimeout(RemoteTask task)1717 private void onPendingTaskTimeout(RemoteTask task) { 1718 long now = SystemClock.uptimeMillis(); 1719 Slogf.w(TAG, "Pending task: %s timeout at %d", task, now); 1720 synchronized (mLock) { 1721 List<RemoteTask> pendingTasks = mTasksToBeNotifiedByClientId.get(task.clientId); 1722 if (pendingTasks == null) { 1723 // The task is already delivered. Do nothing. 1724 return; 1725 } 1726 pendingTasks.remove(task); 1727 } 1728 } 1729 1730 @GuardedBy("mLock") 1731 @Nullable popTasksFromPendingQueueLocked(String clientId)1732 private List<RemoteTask> popTasksFromPendingQueueLocked(String clientId) { 1733 if (DEBUG) { 1734 Slogf.d(TAG, "Pop pending remote tasks from queue for client ID: %s", clientId); 1735 } 1736 List<RemoteTask> pendingTasks = mTasksToBeNotifiedByClientId.get(clientId); 1737 if (pendingTasks == null) { 1738 return null; 1739 } 1740 mTasksToBeNotifiedByClientId.remove(clientId); 1741 for (int i = 0; i < pendingTasks.size(); i++) { 1742 if (DEBUG) { 1743 Slogf.d(TAG, "Prepare to deliver remote task: %s", pendingTasks.get(i)); 1744 } 1745 mHandler.cancelPendingTaskTimeout(pendingTasks.get(i)); 1746 } 1747 return pendingTasks; 1748 } 1749 generateNewTaskId()1750 private String generateNewTaskId() { 1751 return TASK_PREFIX + "_" + mTaskCount.incrementAndGet() + "_" 1752 + CarServiceUtils.generateRandomAlphaNumericString(RANDOM_STRING_LENGTH); 1753 } 1754 generateNewClientId()1755 private String generateNewClientId() { 1756 return CLIENT_PREFIX + "_" + mClientCount.incrementAndGet() + "_" 1757 + CarServiceUtils.generateRandomAlphaNumericString(RANDOM_STRING_LENGTH); 1758 } 1759 1760 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) nextPowerStateToString(int nextPowerState)1761 private static String nextPowerStateToString(int nextPowerState) { 1762 switch (nextPowerState) { 1763 case CarRemoteAccessManager.NEXT_POWER_STATE_ON: 1764 return "ON"; 1765 case CarRemoteAccessManager.NEXT_POWER_STATE_OFF: 1766 return "OFF"; 1767 case CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_RAM: 1768 return "Suspend-to-RAM"; 1769 case CarRemoteAccessManager.NEXT_POWER_STATE_SUSPEND_TO_DISK: 1770 return "Suspend-to-disk"; 1771 default: 1772 return "Unknown(" + nextPowerState + ")"; 1773 } 1774 } 1775 1776 private static final class RemoteTaskClientServiceInfo { 1777 private final ComponentName mServiceComponentName; 1778 private final AtomicReference<RemoteTaskClientServiceConnection> mConnection = 1779 new AtomicReference<>(null); 1780 RemoteTaskClientServiceInfo(ComponentName componentName)1781 private RemoteTaskClientServiceInfo(ComponentName componentName) { 1782 mServiceComponentName = componentName; 1783 } 1784 getServiceComponentName()1785 public ComponentName getServiceComponentName() { 1786 return mServiceComponentName; 1787 } 1788 getServiceConnection()1789 public RemoteTaskClientServiceConnection getServiceConnection() { 1790 return mConnection.get(); 1791 } 1792 setServiceConnection(@ullable RemoteTaskClientServiceConnection connection)1793 public void setServiceConnection(@Nullable RemoteTaskClientServiceConnection connection) { 1794 mConnection.set(connection); 1795 } 1796 1797 @Override toString()1798 public String toString() { 1799 return new StringBuilder() 1800 .append("RemoteTaskClientServiceInfo[") 1801 .append("Component name=") 1802 .append(mServiceComponentName) 1803 .append(", hasConnection=") 1804 .append(mConnection.get() != null) 1805 .append("]") 1806 .toString(); 1807 } 1808 } 1809 1810 private static final class RemoteTask { 1811 public final String id; 1812 public final byte[] data; 1813 public final String clientId; 1814 public final long timeoutInMs; 1815 RemoteTask(String id, byte[] data, String clientId, long timeoutInMs)1816 private RemoteTask(String id, byte[] data, String clientId, long timeoutInMs) { 1817 this.id = id; 1818 this.data = data; 1819 this.clientId = clientId; 1820 this.timeoutInMs = timeoutInMs; 1821 } 1822 1823 @Override toString()1824 public String toString() { 1825 return new StringBuilder() 1826 .append("RemoteTask[") 1827 .append("taskId=") 1828 .append(id) 1829 .append("clientId=") 1830 .append(clientId) 1831 .append("timeoutInMs=") 1832 .append(timeoutInMs) 1833 .append("]") 1834 .toString(); 1835 } 1836 } 1837 1838 private static final class ClientToken implements IBinder.DeathRecipient { 1839 1840 private final Object mTokenLock = new Object(); 1841 private final String mClientId; 1842 private final long mIdCreationTimeInMs; 1843 private final boolean mIsServerless; 1844 1845 @GuardedBy("mTokenLock") 1846 private ICarRemoteAccessCallback mCallback; 1847 @GuardedBy("mTokenLock") 1848 private boolean mIsReadyForShutdown; 1849 ClientToken(String clientId, long idCreationTimeInMs)1850 private ClientToken(String clientId, long idCreationTimeInMs) { 1851 this(clientId, idCreationTimeInMs, /* isServerless= */ false); 1852 } 1853 ClientToken(String clientId, long idCreationTimeInMs, boolean isServerless)1854 private ClientToken(String clientId, long idCreationTimeInMs, boolean isServerless) { 1855 mClientId = clientId; 1856 mIdCreationTimeInMs = idCreationTimeInMs; 1857 mIsServerless = isServerless; 1858 } 1859 isServerless()1860 public boolean isServerless() { 1861 return mIsServerless; 1862 } 1863 getClientId()1864 public String getClientId() { 1865 return mClientId; 1866 } 1867 getIdCreationTime()1868 public long getIdCreationTime() { 1869 return mIdCreationTimeInMs; 1870 } 1871 getCallback()1872 public ICarRemoteAccessCallback getCallback() { 1873 synchronized (mTokenLock) { 1874 return mCallback; 1875 } 1876 } 1877 setCallback(ICarRemoteAccessCallback callback)1878 public void setCallback(ICarRemoteAccessCallback callback) { 1879 synchronized (mTokenLock) { 1880 mCallback = callback; 1881 } 1882 } 1883 setIsReadyForShutdown()1884 public void setIsReadyForShutdown() { 1885 synchronized (mTokenLock) { 1886 mIsReadyForShutdown = true; 1887 } 1888 } 1889 isReadyForShutdown()1890 public boolean isReadyForShutdown() { 1891 synchronized (mTokenLock) { 1892 return mIsReadyForShutdown; 1893 } 1894 } 1895 1896 @Override binderDied()1897 public void binderDied() { 1898 synchronized (mTokenLock) { 1899 Slogf.w(TAG, "Client token callback binder died"); 1900 mCallback.asBinder().unlinkToDeath(this, /* flags= */ 0); 1901 mCallback = null; 1902 } 1903 } 1904 1905 @Override toString()1906 public String toString() { 1907 synchronized (mTokenLock) { 1908 return new StringBuilder() 1909 .append("ClientToken[") 1910 .append("mClientId=").append(mClientId) 1911 .append(", mIdCreationTimeInMs=").append(mIdCreationTimeInMs) 1912 .append(", hasCallback=").append(mCallback != null) 1913 .append(", isServerless=").append(mIsServerless) 1914 .append(']') 1915 .toString(); 1916 } 1917 } 1918 } 1919 1920 private static final class RemoteTaskClientServiceConnection implements ServiceConnection { 1921 1922 private static final String TAG = RemoteTaskClientServiceConnection.class.getSimpleName(); 1923 1924 private final Object mServiceLock = new Object(); 1925 private final Context mContext; 1926 private final Intent mIntent; 1927 private final UserHandle mUser; 1928 private final RemoteTaskClientServiceHandler mHandler; 1929 private final UserManager mUserManager; 1930 private final int mUid; 1931 private final long mTaskUnbindDelayMs; 1932 1933 private final CarUserService mCarUserService; 1934 1935 // The following three variables represent the state machine of this connection: 1936 // 1. Init state (Binding: F, Bound: F, WaitingForUserUnlock: F) 1937 // 2. Waiting for user unlock (Binding: F, Bound: F, WaitingForUserUnlock: T) 1938 // 3. Binding state (Binding: T, Bound: F, WaitingForUserUnlock: F) 1939 // 4. Bound state (Binding: F, Bound: T, WaitingForUserUnlock: F) 1940 // 1941 // 1->2 If user is currently locked 1942 // 2->3 Aftr receiving user unlock intent. 1943 // 1->3 If user is currently unlocked 1944 // 3->4 After onNullBinding callback. 1945 @GuardedBy("mServiceLock") 1946 private boolean mBound; 1947 @GuardedBy("mServiceLock") 1948 private boolean mBinding; 1949 @GuardedBy("mServiceLock") 1950 private boolean mWaitingForUserUnlock; 1951 @GuardedBy("mServiceLock") 1952 private long mTaskTimeoutMs; 1953 @GuardedBy("mServiceLock") 1954 private final Set<String> mActiveTasks = new ArraySet<>(); 1955 1956 private final UserLifecycleListener mUserLifecycleListener; 1957 RemoteTaskClientServiceConnection(Context context, RemoteTaskClientServiceHandler handler, UserManager userManager, ComponentName serviceName, UserHandle user, int uid, long taskUnbindDelayMs)1958 private RemoteTaskClientServiceConnection(Context context, 1959 RemoteTaskClientServiceHandler handler, UserManager userManager, 1960 ComponentName serviceName, UserHandle user, int uid, long taskUnbindDelayMs) { 1961 mContext = context; 1962 mHandler = handler; 1963 mUserManager = userManager; 1964 mIntent = new Intent(); 1965 mIntent.setComponent(serviceName); 1966 mUser = user; 1967 mUid = uid; 1968 mTaskUnbindDelayMs = taskUnbindDelayMs; 1969 mCarUserService = CarLocalServices.getService(CarUserService.class); 1970 mUserLifecycleListener = event -> { 1971 if (!isEventOfType(TAG, event, USER_LIFECYCLE_EVENT_TYPE_UNLOCKED)) { 1972 return; 1973 } 1974 1975 if (event.getUserId() == mUser.getIdentifier()) { 1976 onReceiveUserUnlock(); 1977 } 1978 }; 1979 } 1980 1981 @Override onNullBinding(ComponentName name)1982 public void onNullBinding(ComponentName name) { 1983 synchronized (mServiceLock) { 1984 mBound = true; 1985 mBinding = false; 1986 } 1987 Slogf.i(TAG, "Service(%s) is bound", name.flattenToShortString()); 1988 } 1989 1990 @Override onServiceConnected(ComponentName name, IBinder service)1991 public void onServiceConnected(ComponentName name, IBinder service) { 1992 // Do nothing. 1993 } 1994 1995 @Override onServiceDisconnected(ComponentName name)1996 public void onServiceDisconnected(ComponentName name) { 1997 // Do nothing. 1998 } 1999 2000 @Override onBindingDied(ComponentName name)2001 public void onBindingDied(ComponentName name) { 2002 Slogf.w(TAG, "Service(%s) died", name.flattenToShortString()); 2003 unbindService(/* force= */ true); 2004 } 2005 onReceiveUserUnlock()2006 private void onReceiveUserUnlock() { 2007 synchronized (mServiceLock) { 2008 mWaitingForUserUnlock = false; 2009 Slogf.i(TAG, "received user unlock notification"); 2010 if (mBinding || mBound) { 2011 // bindService is called again after user is unlocked, which caused binding to 2012 // happen, so we don't need to do anything here. 2013 if (DEBUG) { 2014 Slogf.d(TAG, "a binding is already created, ignore the user unlock intent"); 2015 } 2016 return; 2017 } 2018 bindServiceLocked(); 2019 } 2020 } 2021 2022 @GuardedBy("mServiceLock") waitForUserUnlockServiceLocked()2023 private void waitForUserUnlockServiceLocked() { 2024 UserLifecycleEventFilter userUnlockEventFilter = new UserLifecycleEventFilter.Builder() 2025 .addEventType(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED).addUser(mUser).build(); 2026 mCarUserService.addUserLifecycleListener(userUnlockEventFilter, mUserLifecycleListener); 2027 mWaitingForUserUnlock = true; 2028 } 2029 2030 @GuardedBy("mServiceLock") cancelWaitForUserUnlockServiceLocked()2031 private void cancelWaitForUserUnlockServiceLocked() { 2032 mCarUserService.removeUserLifecycleListener(mUserLifecycleListener); 2033 mWaitingForUserUnlock = false; 2034 } 2035 2036 @GuardedBy("mServiceLock") bindServiceLocked()2037 private void bindServiceLocked() { 2038 Slogf.i(TAG, "Bind service %s as user %s", mIntent, mUser); 2039 boolean status = mContext.bindServiceAsUser(mIntent, /* conn= */ this, 2040 BIND_AUTO_CREATE, mUser); 2041 if (!status) { 2042 Slogf.w(TAG, "Failed to bind service %s as user %s", mIntent, mUser); 2043 mContext.unbindService(/* conn= */ this); 2044 return; 2045 } 2046 mBinding = true; 2047 } 2048 2049 @GuardedBy("mServiceLock") bindServiceIfUserUnlockedLocked()2050 private void bindServiceIfUserUnlockedLocked() { 2051 if (DEBUG) { 2052 Slogf.d(TAG, "Try to bind service %s as user %s if unlocked", mIntent, mUser); 2053 } 2054 if (mBinding) { 2055 Slogf.w(TAG, "%s binding is already ongoing, ignore the new bind request", 2056 mIntent); 2057 return; 2058 } 2059 if (mWaitingForUserUnlock) { 2060 Slogf.w(TAG, 2061 "%s binding is waiting for user unlock, ignore the new bind request", 2062 mIntent); 2063 return; 2064 } 2065 if (mBound) { 2066 Slogf.w(TAG, "%s is already bound", mIntent); 2067 return; 2068 } 2069 // Start listening for unlock event before checking so that we don't miss any 2070 // unlock intent. 2071 waitForUserUnlockServiceLocked(); 2072 if (mUserManager.isUserUnlocked(mUser)) { 2073 if (DEBUG) { 2074 Slogf.d(TAG, "User %s is unlocked, start binding", mUser); 2075 } 2076 cancelWaitForUserUnlockServiceLocked(); 2077 } else { 2078 Slogf.w(TAG, "User %s is not unlocked, waiting for it to be unlocked", mUser); 2079 return; 2080 } 2081 bindServiceLocked(); 2082 } 2083 unbindService(boolean force)2084 public boolean unbindService(boolean force) { 2085 synchronized (mServiceLock) { 2086 return unbindServiceLocked(force); 2087 } 2088 } 2089 2090 @GuardedBy("mServiceLock") unbindServiceLocked(boolean force)2091 private boolean unbindServiceLocked(boolean force) { 2092 long currentTimeMs = SystemClock.uptimeMillis(); 2093 if (!force && currentTimeMs < mTaskTimeoutMs) { 2094 Slogf.w(TAG, "Unbind request is out-dated and is ignored"); 2095 return false; 2096 } 2097 Slogf.i(TAG, "unbindServiceLocked"); 2098 mActiveTasks.clear(); 2099 mHandler.cancelServiceTimeout(mUid); 2100 if (mWaitingForUserUnlock) { 2101 cancelWaitForUserUnlockServiceLocked(); 2102 Slogf.w(TAG, "Still waiting for user unlock and bind has not started, " 2103 + "ignore unbind"); 2104 return false; 2105 } 2106 if (!mBound && !mBinding) { 2107 // If we do not have an active bounding. 2108 Slogf.w(TAG, "No active binding, ignore unbind"); 2109 return false; 2110 } 2111 mBinding = false; 2112 mBound = false; 2113 try { 2114 mContext.unbindService(/* conn= */ this); 2115 } catch (Exception e) { 2116 Slogf.e(TAG, e, "failed to unbind service"); 2117 } 2118 return true; 2119 } 2120 2121 // Bind the service if user is unlocked or waiting for user unlock. Extend the task timeout 2122 // to be taskTimeoutMs. bindServiceAndExtendTaskTimeoutMs(long taskTimeoutMs)2123 public void bindServiceAndExtendTaskTimeoutMs(long taskTimeoutMs) { 2124 Slogf.i(TAG, "Try to bind service %s as user %s if unlocked, timeout: %d", mIntent, 2125 mUser, taskTimeoutMs); 2126 synchronized (mServiceLock) { 2127 // Always bind the service to extend its lifetime. If the service is already bound, 2128 // it will do nothing. 2129 bindServiceIfUserUnlockedLocked(); 2130 if (mTaskTimeoutMs >= taskTimeoutMs) { 2131 if (DEBUG) { 2132 Slogf.d(TAG, "The service: %s new task timeout: %d ms is <= existing" 2133 + " task timeout: %d ms, ignore", mIntent, taskTimeoutMs, 2134 mTaskTimeoutMs); 2135 } 2136 return; 2137 } 2138 mTaskTimeoutMs = taskTimeoutMs; 2139 mHandler.postServiceTimeout(mUid, taskTimeoutMs); 2140 } 2141 } 2142 getActiveTaskCount()2143 public int getActiveTaskCount() { 2144 synchronized (mServiceLock) { 2145 return mActiveTasks.size(); 2146 } 2147 } 2148 addActiveTasks(ArraySet<String> tasks)2149 public void addActiveTasks(ArraySet<String> tasks) { 2150 if (DEBUG) { 2151 Slogf.d(TAG, "Add active tasks: %s for service %s", tasks, mIntent); 2152 } 2153 synchronized (mServiceLock) { 2154 for (int i = 0; i < tasks.size(); i++) { 2155 mActiveTasks.add(tasks.valueAt(i)); 2156 } 2157 } 2158 } 2159 2160 // Remove the task IDs from the active tasks list for this connection. Return false if 2161 // one of the provided task is not in the list. removeActiveTasks(ArraySet<String> tasks)2162 public boolean removeActiveTasks(ArraySet<String> tasks) { 2163 synchronized (mServiceLock) { 2164 if (DEBUG) { 2165 Slogf.d(TAG, "Remove active tasks: %s for service %s, current active tasks %s", 2166 tasks, mIntent, mActiveTasks); 2167 } 2168 for (int i = 0; i < tasks.size(); i++) { 2169 if (!mActiveTasks.contains(tasks.valueAt(i))) { 2170 return false; 2171 } 2172 mActiveTasks.remove(tasks.valueAt(i)); 2173 } 2174 if (mActiveTasks.isEmpty()) { 2175 handleAllTasksCompletionLocked(); 2176 } 2177 } 2178 return true; 2179 } 2180 removeAllActiveTasks()2181 public void removeAllActiveTasks() { 2182 synchronized (mServiceLock) { 2183 mActiveTasks.clear(); 2184 handleAllTasksCompletionLocked(); 2185 } 2186 } 2187 2188 @GuardedBy("mServiceLock") handleAllTasksCompletionLocked()2189 private void handleAllTasksCompletionLocked() { 2190 // All active tasks are completed for this package, we can now unbind the service after 2191 // mTaskUnbindDelayMs. 2192 Slogf.i(TAG, "All tasks completed for service: %s", mIntent); 2193 long currentTimeMs = SystemClock.uptimeMillis(); 2194 if (DEBUG) { 2195 Slogf.d(TAG, "Unbind remote task client service: %s after %d ms, " 2196 + "current time: %d ms", mIntent, mTaskUnbindDelayMs, 2197 currentTimeMs); 2198 } 2199 mTaskTimeoutMs = currentTimeMs + mTaskUnbindDelayMs; 2200 mHandler.postServiceTimeout(mUid, mTaskTimeoutMs); 2201 } 2202 } 2203 2204 private static final class RemoteTaskClientServiceHandler extends Handler { 2205 2206 private static final String TAG = RemoteTaskClientServiceHandler.class.getSimpleName(); 2207 private static final int MSG_SERVICE_TIMEOUT = 1; 2208 private static final int MSG_WRAP_UP_REMOTE_ACCESS_SERVICE = 2; 2209 private static final int MSG_NOTIFY_SHUTDOWN_STARTING = 3; 2210 private static final int MSG_NOTIFY_AP_STATE_CHANGE = 4; 2211 private static final int MSG_MAYBE_SHUTDOWN = 5; 2212 private static final int MSG_PENDING_TASK_TIMEOUT = 6; 2213 2214 // Lock to synchronize remove messages and add messages. 2215 private final Object mHandlerLock = new Object(); 2216 private final WeakReference<CarRemoteAccessService> mService; 2217 RemoteTaskClientServiceHandler(Looper looper, CarRemoteAccessService service)2218 private RemoteTaskClientServiceHandler(Looper looper, CarRemoteAccessService service) { 2219 super(looper); 2220 mService = new WeakReference<>(service); 2221 } 2222 2223 // Must use uid instead of uidName here because message object is compared using "==" 2224 // instead fo equals, so two same string might not "==" each other. postServiceTimeout(Integer uid, long msgTimeMs)2225 private void postServiceTimeout(Integer uid, long msgTimeMs) { 2226 synchronized (mHandlerLock) { 2227 HandlerHelper.removeEqualMessages(this, MSG_SERVICE_TIMEOUT, uid); 2228 Message msg = obtainMessage(MSG_SERVICE_TIMEOUT, uid); 2229 sendMessageAtTime(msg, msgTimeMs); 2230 } 2231 } 2232 postNotifyShutdownStarting(long delayMs)2233 private void postNotifyShutdownStarting(long delayMs) { 2234 synchronized (mHandlerLock) { 2235 removeMessages(MSG_NOTIFY_SHUTDOWN_STARTING); 2236 Message msg = obtainMessage(MSG_NOTIFY_SHUTDOWN_STARTING); 2237 sendMessageDelayed(msg, delayMs); 2238 } 2239 } 2240 postWrapUpRemoteAccessService(long delayMs)2241 private void postWrapUpRemoteAccessService(long delayMs) { 2242 synchronized (mHandlerLock) { 2243 removeMessages(MSG_WRAP_UP_REMOTE_ACCESS_SERVICE); 2244 Message msg = obtainMessage(MSG_WRAP_UP_REMOTE_ACCESS_SERVICE); 2245 sendMessageDelayed(msg, delayMs); 2246 } 2247 } 2248 postNotifyApStateChange(long delayMs)2249 private void postNotifyApStateChange(long delayMs) { 2250 synchronized (mHandlerLock) { 2251 removeMessages(MSG_NOTIFY_AP_STATE_CHANGE); 2252 Message msg = obtainMessage(MSG_NOTIFY_AP_STATE_CHANGE); 2253 sendMessageDelayed(msg, delayMs); 2254 } 2255 } 2256 postMaybeShutdown(long delayMs)2257 private void postMaybeShutdown(long delayMs) { 2258 synchronized (mHandlerLock) { 2259 removeMessages(MSG_MAYBE_SHUTDOWN); 2260 Message msg = obtainMessage(MSG_MAYBE_SHUTDOWN); 2261 sendMessageDelayed(msg, delayMs); 2262 } 2263 } 2264 postPendingTaskTimeout(RemoteTask task, long msgTimeMs)2265 private void postPendingTaskTimeout(RemoteTask task, long msgTimeMs) { 2266 Message msg = obtainMessage(MSG_PENDING_TASK_TIMEOUT, task); 2267 sendMessageAtTime(msg, msgTimeMs); 2268 } 2269 cancelServiceTimeout(int uid)2270 private void cancelServiceTimeout(int uid) { 2271 HandlerHelper.removeEqualMessages(this, MSG_SERVICE_TIMEOUT, uid); 2272 } 2273 cancelAllServiceTimeout()2274 private void cancelAllServiceTimeout() { 2275 removeMessages(MSG_SERVICE_TIMEOUT); 2276 } 2277 cancelNotifyShutdownStarting()2278 private void cancelNotifyShutdownStarting() { 2279 removeMessages(MSG_NOTIFY_SHUTDOWN_STARTING); 2280 } 2281 cancelWrapUpRemoteAccessService()2282 private void cancelWrapUpRemoteAccessService() { 2283 removeMessages(MSG_WRAP_UP_REMOTE_ACCESS_SERVICE); 2284 } 2285 cancelNotifyApStateChange()2286 private void cancelNotifyApStateChange() { 2287 removeMessages(MSG_NOTIFY_AP_STATE_CHANGE); 2288 } 2289 cancelMaybeShutdown()2290 private void cancelMaybeShutdown() { 2291 removeMessages(MSG_MAYBE_SHUTDOWN); 2292 } 2293 cancelPendingTaskTimeout(RemoteTask task)2294 private void cancelPendingTaskTimeout(RemoteTask task) { 2295 removeMessages(MSG_PENDING_TASK_TIMEOUT, task); 2296 } 2297 cancelAllPendingTaskTimeout()2298 private void cancelAllPendingTaskTimeout() { 2299 removeMessages(MSG_PENDING_TASK_TIMEOUT); 2300 } 2301 cancelAll()2302 private void cancelAll() { 2303 cancelAllServiceTimeout(); 2304 cancelNotifyShutdownStarting(); 2305 cancelWrapUpRemoteAccessService(); 2306 cancelNotifyApStateChange(); 2307 cancelMaybeShutdown(); 2308 cancelAllPendingTaskTimeout(); 2309 } 2310 2311 @Override handleMessage(Message msg)2312 public void handleMessage(Message msg) { 2313 CarRemoteAccessService service = mService.get(); 2314 if (service == null) { 2315 Slogf.w(TAG, "CarRemoteAccessService is not available"); 2316 return; 2317 } 2318 switch (msg.what) { 2319 case MSG_SERVICE_TIMEOUT: 2320 service.onServiceTimeout((Integer) msg.obj); 2321 break; 2322 case MSG_WRAP_UP_REMOTE_ACCESS_SERVICE: 2323 service.wrapUpRemoteAccessServiceIfNeeded(); 2324 break; 2325 case MSG_NOTIFY_SHUTDOWN_STARTING: 2326 service.notifyShutdownStarting(); 2327 break; 2328 case MSG_NOTIFY_AP_STATE_CHANGE: 2329 service.notifyApStateChange(); 2330 break; 2331 case MSG_MAYBE_SHUTDOWN: 2332 service.shutdownIfNeeded(/* force= */ false); 2333 break; 2334 case MSG_PENDING_TASK_TIMEOUT: 2335 service.onPendingTaskTimeout((RemoteTask) msg.obj); 2336 break; 2337 default: 2338 Slogf.w(TAG, "Unknown(%d) message", msg.what); 2339 } 2340 } 2341 } 2342 } 2343