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.server.sdksandbox; 18 19 import static android.app.sdksandbox.SdkSandboxManager.REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED; 20 import static android.app.sdksandbox.SdkSandboxManager.SDK_SANDBOX_PROCESS_NOT_AVAILABLE; 21 22 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE; 23 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__UNLOAD_SDK; 24 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__STAGE_UNSPECIFIED; 25 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX; 26 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP; 27 28 import android.annotation.IntDef; 29 import android.annotation.Nullable; 30 import android.app.sdksandbox.ILoadSdkCallback; 31 import android.app.sdksandbox.IRequestSurfacePackageCallback; 32 import android.app.sdksandbox.LoadSdkException; 33 import android.app.sdksandbox.LogUtil; 34 import android.app.sdksandbox.SandboxedSdk; 35 import android.app.sdksandbox.SdkSandboxManager; 36 import android.content.Context; 37 import android.content.pm.ApplicationInfo; 38 import android.content.pm.PackageManager; 39 import android.content.pm.PackageManager.ApplicationInfoFlags; 40 import android.content.pm.SharedLibraryInfo; 41 import android.os.Bundle; 42 import android.os.DeadObjectException; 43 import android.os.IBinder; 44 import android.os.RemoteException; 45 import android.os.UserHandle; 46 import android.text.TextUtils; 47 import android.util.ArraySet; 48 import android.util.Log; 49 import android.view.SurfaceControlViewHost; 50 51 import com.android.internal.annotations.GuardedBy; 52 import com.android.sdksandbox.ILoadSdkInSandboxCallback; 53 import com.android.sdksandbox.IRequestSurfacePackageFromSdkCallback; 54 import com.android.sdksandbox.ISdkSandboxManagerToSdkSandboxCallback; 55 import com.android.sdksandbox.ISdkSandboxService; 56 import com.android.sdksandbox.IUnloadSdkCallback; 57 import com.android.sdksandbox.SandboxLatencyInfo; 58 import com.android.sdksandbox.service.stats.SdkSandboxStatsLog; 59 60 import java.lang.annotation.Retention; 61 import java.lang.annotation.RetentionPolicy; 62 import java.util.List; 63 64 /** 65 * Represents the lifecycle of a single request to load an SDK for a specific app. 66 * 67 * <p>A new instance of this class must be created for every load request of an SDK. This class also 68 * maintains a link to the remote SDK loaded in the sandbox if any, and communicates with it. 69 */ 70 class LoadSdkSession { 71 72 private static final String TAG = "SdkSandboxManager"; 73 private static final String PROPERTY_SDK_PROVIDER_CLASS_NAME = 74 "android.sdksandbox.PROPERTY_SDK_PROVIDER_CLASS_NAME"; 75 76 /** @hide */ 77 @IntDef(value = {LOAD_PENDING, LOADED, LOAD_FAILED, UNLOADED}) 78 @Retention(RetentionPolicy.SOURCE) 79 public @interface LoadStatus {} 80 81 /** 82 * Represents the initial state of the SDK, when a request to load it has arrived but not yet 83 * been completed. 84 * 85 * <p>Once the state of an SDK transitions out of LOAD_PENDING, it cannot be reset to 86 * LOAD_PENDING as this state is the representation of a specific load request for an SDK. 87 * 88 * <ul> 89 * <li>LOAD_PENDING --> onLoadSdkSuccess() --> LOADED 90 * <li>LOAD_PENDING --> onLoadSdkError() --> LOAD_FAILED 91 * <li>LOAD_PENDING --> unload() --> IllegalArgumentException 92 * <li>LOAD_PENDING --> onSandboxDeath() --> LOAD_FAILED 93 * </ul> 94 */ 95 public static final int LOAD_PENDING = 1; 96 97 /** 98 * Represents the state when the SDK has been successfully loaded into the sandbox. 99 * 100 * <ul> 101 * <li>LOADED --> load() --> IllegalArgumentException 102 * <li>LOADED --> unload() --> UNLOADED 103 * <li>LOADED --> onSandboxDeath() --> UNLOADED 104 * </ul> 105 */ 106 public static final int LOADED = 2; 107 108 /** 109 * Represents the state when the SDK has failed to load into the sandbox. 110 * 111 * <p>The state can be LOAD_FAILED if the sandbox could not properly initialize the SDK, SDK is 112 * invalid, the sandbox died while in the middle of loading etc. If the SDK load failed, this 113 * same session cannot be used to load the SDK again. 114 * 115 * <ul> 116 * <li>LOAD_FAILED --> load() --> IllegalArgumentException 117 * <li>LOAD_FAILED --> unload() --> LOAD_FAILED 118 * <li>LOAD_FAILED --> onSandboxDeath() --> LOAD_FAILED 119 * </ul> 120 */ 121 public static final int LOAD_FAILED = 3; 122 123 /** 124 * Represents the state when the SDK has either been unloaded from the sandbox, or the sandbox 125 * has died. 126 * 127 * <ul> 128 * <li>UNLOADED --> load() --> IllegalArgumentException 129 * <li>UNLOADED --> unload() --> UNLOADED 130 * <li>UNLOADED --> onSandboxDeath() --> UNLOADED 131 * </ul> 132 */ 133 public static final int UNLOADED = 4; 134 135 private final Object mLock = new Object(); 136 137 private final Context mContext; 138 private final SdkSandboxManagerService mSdkSandboxManagerService; 139 private final SdkSandboxManagerService.Injector mInjector; 140 141 final String mSdkName; 142 final CallingInfo mCallingInfo; 143 144 // The params used to load this SDK. 145 private final Bundle mLoadParams; 146 // The callback used to load this SDK. 147 private final ILoadSdkCallback mLoadCallback; 148 149 final SdkProviderInfo mSdkProviderInfo; 150 151 /** 152 * The initial status is LOAD_PENDING. Once the loading is complete, the status is set to LOADED 153 * or LOAD_FAILED depending on the success of loading. If the SDK is unloaded at any point or 154 * the sandbox dies, the status is set to UNLOADED. 155 * 156 * <p>The status cannot be reset to LOAD_PENDING as this class is meant to represent a single 157 * load request. 158 */ 159 @GuardedBy("mLock") 160 @LoadStatus 161 private int mStatus = LOAD_PENDING; 162 163 // The sandbox in which this SDK is supposed to be loaded. 164 @GuardedBy("mLock") 165 private ISdkSandboxService mSandboxService = null; 166 167 // Used for communication with the remotely loaded SDK in the sandbox. 168 private final RemoteSdkLink mRemoteSdkLink; 169 170 // Maintain all surface package requests whose callbacks have not been invoked yet. 171 @GuardedBy("mLock") 172 private final ArraySet<IRequestSurfacePackageCallback> mPendingRequestSurfacePackageCallbacks = 173 new ArraySet<>(); 174 LoadSdkSession( Context context, SdkSandboxManagerService service, SdkSandboxManagerService.Injector injector, String sdkName, CallingInfo callingInfo, Bundle loadParams, ILoadSdkCallback loadCallback)175 LoadSdkSession( 176 Context context, 177 SdkSandboxManagerService service, 178 SdkSandboxManagerService.Injector injector, 179 String sdkName, 180 CallingInfo callingInfo, 181 Bundle loadParams, 182 ILoadSdkCallback loadCallback) { 183 mContext = context; 184 mSdkSandboxManagerService = service; 185 mInjector = injector; 186 mSdkName = sdkName; 187 mCallingInfo = callingInfo; 188 mLoadParams = loadParams; 189 mLoadCallback = loadCallback; 190 191 mSdkProviderInfo = createSdkProviderInfo(); 192 mRemoteSdkLink = new RemoteSdkLink(); 193 } 194 195 @LoadStatus getStatus()196 int getStatus() { 197 synchronized (mLock) { 198 return mStatus; 199 } 200 } 201 202 @Nullable getSandboxedSdk()203 SandboxedSdk getSandboxedSdk() { 204 return mRemoteSdkLink.mSandboxedSdk; 205 } 206 207 // Asks the given sandbox service to load this SDK. load( ISdkSandboxService service, String ceDataDir, String deDataDir, long timeSystemServerCalledSandbox, long timeSystemServerReceivedCallFromApp)208 void load( 209 ISdkSandboxService service, 210 String ceDataDir, 211 String deDataDir, 212 long timeSystemServerCalledSandbox, 213 long timeSystemServerReceivedCallFromApp) { 214 final SandboxLatencyInfo sandboxLatencyInfo = 215 new SandboxLatencyInfo(timeSystemServerCalledSandbox); 216 217 // TODO(b/258679084): If a second load request comes here, while the first is pending, it 218 // will go through. SdkSandboxManagerService already has a check for this, but we should 219 // have it here as well. 220 synchronized (mLock) { 221 if (getStatus() != LOAD_PENDING) { 222 // If the status is not the initial pending load, that means that this load request 223 // had already been performed before and completed (either successfully or 224 // unsuccessfully). Therefore, do not invoke any callback here. 225 throw new IllegalArgumentException("Invalid request to load SDK " + mSdkName); 226 } 227 mSandboxService = service; 228 } 229 230 if (service == null) { 231 handleLoadFailure( 232 new LoadSdkException( 233 SDK_SANDBOX_PROCESS_NOT_AVAILABLE, "Sandbox is not available"), 234 /*startTimeOfErrorStage=*/ -1, 235 SANDBOX_API_CALLED__STAGE__STAGE_UNSPECIFIED, 236 /*successAtStage=*/ false); 237 } 238 239 try { 240 service.loadSdk( 241 mCallingInfo.getPackageName(), 242 mSdkProviderInfo.getApplicationInfo(), 243 mSdkProviderInfo.getSdkInfo().getName(), 244 mSdkProviderInfo.getSdkProviderClassName(), 245 ceDataDir, 246 deDataDir, 247 mLoadParams, 248 mRemoteSdkLink, 249 sandboxLatencyInfo); 250 } catch (DeadObjectException e) { 251 handleLoadFailure( 252 new LoadSdkException( 253 SDK_SANDBOX_PROCESS_NOT_AVAILABLE, 254 "Failed to load SDK as sandbox is dead"), 255 /*startTimeOfErrorStage=*/ -1, 256 SANDBOX_API_CALLED__STAGE__STAGE_UNSPECIFIED, 257 /*successAtStage=*/ false); 258 } catch (RemoteException e) { 259 String errorMsg = "Failed to load sdk"; 260 handleLoadFailure( 261 new LoadSdkException(SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR, errorMsg), 262 /*startTimeOfErrorStage=*/ timeSystemServerReceivedCallFromApp, 263 /*stage*/ SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, 264 /*successAtStage=*/ false); 265 } 266 } 267 handleLoadSuccess(long timeSystemServerReceivedCallFromSandbox)268 void handleLoadSuccess(long timeSystemServerReceivedCallFromSandbox) { 269 final long timeSystemServerCalledApp = mInjector.getCurrentTime(); 270 SdkSandboxStatsLog.write( 271 SdkSandboxStatsLog.SANDBOX_API_CALLED, 272 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK, 273 (int) (timeSystemServerCalledApp - timeSystemServerReceivedCallFromSandbox), 274 /*success=*/ true, 275 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP, 276 mCallingInfo.getUid()); 277 278 synchronized (mLock) { 279 if (getStatus() == LOAD_PENDING) { 280 mStatus = LOADED; 281 } else { 282 // If the SDK is not pending a load, something has happened to it - for example, the 283 // sandbox might have died and the status is now LOAD_FAILED. Either way, since it 284 // is not waiting to be loaded, the LoadSdkCallback would have already been invoked. 285 // Just log and return. 286 LogUtil.d( 287 TAG, 288 "Could not successfully load " 289 + mSdkName 290 + " as its status is " 291 + getStatus()); 292 return; 293 } 294 } 295 try { 296 mLoadCallback.onLoadSdkSuccess(getSandboxedSdk(), timeSystemServerCalledApp); 297 } catch (RemoteException e) { 298 Log.w(TAG, "Failed to send onLoadCodeSuccess", e); 299 } 300 } 301 handleLoadFailure( LoadSdkException exception, long startTimeOfErrorStage, int stage, boolean successAtStage)302 void handleLoadFailure( 303 LoadSdkException exception, 304 long startTimeOfErrorStage, 305 int stage, 306 boolean successAtStage) { 307 final long timeSystemServerCalledApp = mInjector.getCurrentTime(); 308 if (stage != SANDBOX_API_CALLED__STAGE__STAGE_UNSPECIFIED) { 309 SdkSandboxStatsLog.write( 310 SdkSandboxStatsLog.SANDBOX_API_CALLED, 311 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK, 312 (int) (timeSystemServerCalledApp - startTimeOfErrorStage), 313 successAtStage, 314 stage, 315 mCallingInfo.getUid()); 316 } 317 318 synchronized (mLock) { 319 if (getStatus() == LOAD_PENDING) { 320 mStatus = LOAD_FAILED; 321 } else { 322 // If the SDK is not pending a load, something has happened to it - for example, the 323 // sandbox might have died and the status is now LOAD_FAILED. Either way, since it 324 // is not waiting to be loaded, the LoadSdkCallback would have already been invoked. 325 // Just log and return. 326 LogUtil.d( 327 TAG, 328 "Could not complete load failure for " 329 + mSdkName 330 + " as its status is " 331 + getStatus()); 332 return; 333 } 334 } 335 try { 336 mLoadCallback.onLoadSdkFailure(exception, timeSystemServerCalledApp); 337 } catch (RemoteException e) { 338 Log.w(TAG, "Failed to send onLoadCodeFailure", e); 339 } 340 } 341 unload(long timeSystemServerReceivedCallFromApp)342 void unload(long timeSystemServerReceivedCallFromApp) { 343 SandboxLatencyInfo sandboxLatencyInfo = new SandboxLatencyInfo(mInjector.getCurrentTime()); 344 IUnloadSdkCallback unloadCallback = 345 new IUnloadSdkCallback.Stub() { 346 @Override 347 public void onUnloadSdk(SandboxLatencyInfo sandboxLatencyInfo) { 348 logLatencyMetricsForCallback( 349 /*timeSystemServerReceivedCallFromSandbox=*/ mInjector 350 .getCurrentTime(), 351 SANDBOX_API_CALLED__METHOD__UNLOAD_SDK, 352 sandboxLatencyInfo); 353 } 354 }; 355 356 ISdkSandboxService service = null; 357 synchronized (mLock) { 358 switch (getStatus()) { 359 case LOAD_PENDING: 360 // If load is pending, unloading should fail. 361 throw new IllegalArgumentException( 362 "SDK " 363 + mSdkName 364 + " is currently being loaded for " 365 + mCallingInfo 366 + " - wait till onLoadSdkSuccess() to unload"); 367 case LOADED: 368 // Set status as unloaded right away, so that it is treated as unloaded even if 369 // the actual unloading hasn't completed. 370 mStatus = UNLOADED; 371 break; 372 default: 373 // Unloading an SDK that is not loaded is a no-op, return. Don't throw any 374 // exception here since the sandbox can die at any time and the SDK becomes 375 // unloaded. 376 Log.i(TAG, "SDK " + mSdkName + " is not loaded for " + mCallingInfo); 377 return; 378 } 379 380 service = mSandboxService; 381 } 382 383 if (service == null) { 384 // Sandbox could have died, just ignore. 385 Log.i(TAG, "Cannot unload SDK " + mSdkName + " - could not find sandbox service"); 386 return; 387 } 388 389 SdkSandboxStatsLog.write( 390 SdkSandboxStatsLog.SANDBOX_API_CALLED, 391 SANDBOX_API_CALLED__METHOD__UNLOAD_SDK, 392 (int) 393 (sandboxLatencyInfo.getTimeSystemServerCalledSandbox() 394 - timeSystemServerReceivedCallFromApp), 395 /*success=*/ true, 396 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, 397 mCallingInfo.getUid()); 398 399 try { 400 service.unloadSdk(mSdkName, unloadCallback, sandboxLatencyInfo); 401 } catch (DeadObjectException e) { 402 Log.i( 403 TAG, 404 "Sdk sandbox for " + mCallingInfo + " is dead, cannot unload SDK " + mSdkName); 405 } catch (RemoteException e) { 406 Log.w(TAG, "Failed to unload SDK: ", e); 407 } 408 } 409 requestSurfacePackage( IBinder hostToken, int displayId, int width, int height, long timeSystemServerReceivedCallFromApp, Bundle params, IRequestSurfacePackageCallback callback)410 void requestSurfacePackage( 411 IBinder hostToken, 412 int displayId, 413 int width, 414 int height, 415 long timeSystemServerReceivedCallFromApp, 416 Bundle params, 417 IRequestSurfacePackageCallback callback) { 418 synchronized (mLock) { 419 mPendingRequestSurfacePackageCallbacks.add(callback); 420 421 if (getStatus() != LOADED) { 422 handleSurfacePackageError( 423 REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED, 424 "SDK " + mSdkName + " is not loaded", 425 timeSystemServerReceivedCallFromApp, 426 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, 427 /*successAtStage*/ false, 428 callback); 429 return; 430 } 431 } 432 mRemoteSdkLink.requestSurfacePackage( 433 hostToken, 434 displayId, 435 width, 436 height, 437 timeSystemServerReceivedCallFromApp, 438 params, 439 callback); 440 } 441 handleSurfacePackageReady( SurfaceControlViewHost.SurfacePackage surfacePackage, int surfacePackageId, Bundle params, long timeSystemServerReceivedCallFromSandbox, IRequestSurfacePackageCallback callback)442 void handleSurfacePackageReady( 443 SurfaceControlViewHost.SurfacePackage surfacePackage, 444 int surfacePackageId, 445 Bundle params, 446 long timeSystemServerReceivedCallFromSandbox, 447 IRequestSurfacePackageCallback callback) { 448 synchronized (mLock) { 449 mPendingRequestSurfacePackageCallbacks.remove(callback); 450 } 451 final long timeSystemServerCalledApp = mInjector.getCurrentTime(); 452 SdkSandboxStatsLog.write( 453 SdkSandboxStatsLog.SANDBOX_API_CALLED, 454 SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, 455 (int) (timeSystemServerCalledApp - timeSystemServerReceivedCallFromSandbox), 456 /*success=*/ true, 457 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP, 458 mCallingInfo.getUid()); 459 try { 460 callback.onSurfacePackageReady( 461 surfacePackage, surfacePackageId, params, timeSystemServerCalledApp); 462 } catch (RemoteException e) { 463 Log.w(TAG, "Failed to send onSurfacePackageReady callback", e); 464 } 465 } 466 handleSurfacePackageError( int errorCode, String errorMsg, long startTimeOfStageWhereErrorOccurred, int stage, boolean successAtStage, IRequestSurfacePackageCallback callback)467 void handleSurfacePackageError( 468 int errorCode, 469 String errorMsg, 470 long startTimeOfStageWhereErrorOccurred, 471 int stage, 472 boolean successAtStage, 473 IRequestSurfacePackageCallback callback) { 474 synchronized (mLock) { 475 mPendingRequestSurfacePackageCallbacks.remove(callback); 476 } 477 final long timeSystemServerCalledApp = mInjector.getCurrentTime(); 478 if (stage != SANDBOX_API_CALLED__STAGE__STAGE_UNSPECIFIED) { 479 SdkSandboxStatsLog.write( 480 SdkSandboxStatsLog.SANDBOX_API_CALLED, 481 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, 482 (int) (timeSystemServerCalledApp - startTimeOfStageWhereErrorOccurred), 483 successAtStage, 484 stage, 485 mCallingInfo.getUid()); 486 } 487 try { 488 callback.onSurfacePackageError(errorCode, errorMsg, timeSystemServerCalledApp); 489 } catch (RemoteException e) { 490 Log.w(TAG, "Failed to send onSurfacePackageError", e); 491 } 492 } 493 onSandboxDeath()494 void onSandboxDeath() { 495 synchronized (mLock) { 496 mSandboxService = null; 497 498 // If load status was pending, then the callback need to be notified. 499 if (getStatus() == LOAD_PENDING) { 500 handleLoadFailure( 501 new LoadSdkException( 502 SDK_SANDBOX_PROCESS_NOT_AVAILABLE, 503 "Could not load SDK, sandbox has died"), 504 /*startTimeOfErrorStage=*/ -1, 505 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__METHOD_UNSPECIFIED, 506 /*successAtStage=*/ false); 507 } 508 509 // Clear all pending request surface package callbacks. 510 notifyPendingRequestSurfacePackageCallbacksLocked(); 511 512 // Set status to unloaded on sandbox death. 513 if (getStatus() == LOADED) { 514 mStatus = UNLOADED; 515 } 516 } 517 } 518 519 @GuardedBy("mLock") notifyPendingRequestSurfacePackageCallbacksLocked()520 private void notifyPendingRequestSurfacePackageCallbacksLocked() { 521 for (int i = 0; i < mPendingRequestSurfacePackageCallbacks.size(); i++) { 522 IRequestSurfacePackageCallback callback = 523 mPendingRequestSurfacePackageCallbacks.valueAt(i); 524 handleSurfacePackageError( 525 REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED, 526 "Sandbox died - could not request surface package", 527 -1, 528 SANDBOX_API_CALLED__STAGE__STAGE_UNSPECIFIED, 529 /*successAtStage*/ false, 530 callback); 531 } 532 mPendingRequestSurfacePackageCallbacks.clear(); 533 } 534 535 /** 536 * A callback object to establish a link between the manager service and the remote SDK being 537 * loaded in SdkSandbox. 538 * 539 * <p>Overview of communication: 540 * 541 * <ol> 542 * <li>RemoteSdk to ManagerService: {@link RemoteSdkLink} extends {@link 543 * ILoadSdkInSandboxCallback} interface. We pass on this object to {@link 544 * ISdkSandboxService} so that remote SDK can call back into ManagerService. 545 * <li>ManagerService to RemoteSdk: When the SDK is loaded for the first time and remote SDK 546 * calls back with successful result, it also sends reference to {@link 547 * ISdkSandboxManagerToSdkSandboxCallback} callback object. ManagerService uses this to 548 * callback into the remote SDK. 549 * </ol> 550 * 551 * <p>We maintain a link for each unique {app, remoteSdk} pair, which is identified with {@code 552 * sdkName}. 553 */ 554 private class RemoteSdkLink extends ILoadSdkInSandboxCallback.Stub { 555 @Nullable private volatile SandboxedSdk mSandboxedSdk; 556 557 @GuardedBy("this") 558 @Nullable 559 private ISdkSandboxManagerToSdkSandboxCallback mManagerToSdkCallback; 560 561 @Override onLoadSdkSuccess( SandboxedSdk sandboxedSdk, ISdkSandboxManagerToSdkSandboxCallback callback, SandboxLatencyInfo sandboxLatencyInfo)562 public void onLoadSdkSuccess( 563 SandboxedSdk sandboxedSdk, 564 ISdkSandboxManagerToSdkSandboxCallback callback, 565 SandboxLatencyInfo sandboxLatencyInfo) { 566 final long timeSystemServerReceivedCallFromSandbox = mInjector.getCurrentTime(); 567 logLatencyMetricsForCallback( 568 timeSystemServerReceivedCallFromSandbox, 569 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK, 570 sandboxLatencyInfo); 571 572 synchronized (this) { 573 // Keep reference to callback so that manager service can 574 // callback to remote SDK loaded. 575 mManagerToSdkCallback = callback; 576 577 // Attach the SharedLibraryInfo for the loaded SDK to the SandboxedSdk. 578 sandboxedSdk.attachSharedLibraryInfo(mSdkProviderInfo.getSdkInfo()); 579 580 // Keep reference to SandboxedSdk so that manager service can 581 // keep log of all loaded SDKs and their binders for communication. 582 mSandboxedSdk = sandboxedSdk; 583 } 584 585 handleLoadSuccess(timeSystemServerReceivedCallFromSandbox); 586 } 587 588 @Override onLoadSdkError( LoadSdkException exception, SandboxLatencyInfo sandboxLatencyInfo)589 public void onLoadSdkError( 590 LoadSdkException exception, SandboxLatencyInfo sandboxLatencyInfo) { 591 final long timeSystemServerReceivedCallFromSandbox = mInjector.getCurrentTime(); 592 logLatencyMetricsForCallback( 593 timeSystemServerReceivedCallFromSandbox, 594 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK, 595 sandboxLatencyInfo); 596 597 if (exception.getLoadSdkErrorCode() 598 == ILoadSdkInSandboxCallback.LOAD_SDK_INSTANTIATION_ERROR) { 599 mSdkSandboxManagerService.handleFailedSandboxInitialization(mCallingInfo); 600 } 601 handleLoadFailure( 602 updateLoadSdkErrorCode(exception), 603 /*startTimeOfErrorStage=*/ timeSystemServerReceivedCallFromSandbox, 604 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP, 605 /*successAtStage=*/ true); 606 } 607 updateLoadSdkErrorCode(LoadSdkException exception)608 private LoadSdkException updateLoadSdkErrorCode(LoadSdkException exception) { 609 @SdkSandboxManager.LoadSdkErrorCode 610 int newErrorCode = toSdkSandboxManagerLoadSdkErrorCode(exception.getLoadSdkErrorCode()); 611 return new LoadSdkException( 612 newErrorCode, 613 exception.getMessage(), 614 exception.getCause(), 615 exception.getExtraInformation()); 616 } 617 618 @SdkSandboxManager.LoadSdkErrorCode toSdkSandboxManagerLoadSdkErrorCode(int sdkSandboxErrorCode)619 private int toSdkSandboxManagerLoadSdkErrorCode(int sdkSandboxErrorCode) { 620 switch (sdkSandboxErrorCode) { 621 case ILoadSdkInSandboxCallback.LOAD_SDK_ALREADY_LOADED: 622 return SdkSandboxManager.LOAD_SDK_ALREADY_LOADED; 623 case ILoadSdkInSandboxCallback.LOAD_SDK_NOT_FOUND: 624 return SdkSandboxManager.LOAD_SDK_NOT_FOUND; 625 case ILoadSdkInSandboxCallback.LOAD_SDK_PROVIDER_INIT_ERROR: 626 case ILoadSdkInSandboxCallback.LOAD_SDK_INSTANTIATION_ERROR: 627 case ILoadSdkInSandboxCallback.LOAD_SDK_INTERNAL_ERROR: 628 return SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR; 629 case SdkSandboxManager.LOAD_SDK_SDK_DEFINED_ERROR: 630 return sdkSandboxErrorCode; 631 default: 632 Log.e( 633 TAG, 634 "Error code " 635 + sdkSandboxErrorCode 636 + " has no mapping to the SdkSandboxManager error codes"); 637 return SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR; 638 } 639 } 640 requestSurfacePackage( IBinder hostToken, int displayId, int width, int height, long timeSystemServerReceivedCallFromApp, Bundle params, IRequestSurfacePackageCallback callback)641 public void requestSurfacePackage( 642 IBinder hostToken, 643 int displayId, 644 int width, 645 int height, 646 long timeSystemServerReceivedCallFromApp, 647 Bundle params, 648 IRequestSurfacePackageCallback callback) { 649 final long timeSystemServerCalledSandbox = mInjector.getCurrentTime(); 650 SdkSandboxStatsLog.write( 651 SdkSandboxStatsLog.SANDBOX_API_CALLED, 652 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, 653 (int) (timeSystemServerCalledSandbox - timeSystemServerReceivedCallFromApp), 654 /*success=*/ true, 655 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX, 656 mCallingInfo.getUid()); 657 final SandboxLatencyInfo sandboxLatencyInfo = 658 new SandboxLatencyInfo(timeSystemServerCalledSandbox); 659 try { 660 synchronized (this) { 661 mManagerToSdkCallback.onSurfacePackageRequested( 662 hostToken, 663 displayId, 664 width, 665 height, 666 params, 667 sandboxLatencyInfo, 668 new IRequestSurfacePackageFromSdkCallback.Stub() { 669 @Override 670 public void onSurfacePackageReady( 671 SurfaceControlViewHost.SurfacePackage surfacePackage, 672 int surfacePackageId, 673 Bundle params, 674 SandboxLatencyInfo sandboxLatencyInfo) { 675 final long timeSystemServerReceivedCallFromSandbox = 676 mInjector.getCurrentTime(); 677 678 LogUtil.d(TAG, "onSurfacePackageReady received"); 679 680 logLatencyMetricsForCallback( 681 timeSystemServerReceivedCallFromSandbox, 682 SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, 683 sandboxLatencyInfo); 684 685 handleSurfacePackageReady( 686 surfacePackage, 687 surfacePackageId, 688 params, 689 timeSystemServerReceivedCallFromSandbox, 690 callback); 691 } 692 693 @Override 694 public void onSurfacePackageError( 695 int errorCode, 696 String errorMsg, 697 SandboxLatencyInfo sandboxLatencyInfo) { 698 final long timeSystemServerReceivedCallFromSandbox = 699 mInjector.getCurrentTime(); 700 701 logLatencyMetricsForCallback( 702 timeSystemServerReceivedCallFromSandbox, 703 SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE, 704 sandboxLatencyInfo); 705 706 int sdkSandboxManagerErrorCode = 707 toSdkSandboxManagerRequestSurfacePackageErrorCode( 708 errorCode); 709 710 handleSurfacePackageError( 711 sdkSandboxManagerErrorCode, 712 errorMsg, 713 timeSystemServerReceivedCallFromSandbox, 714 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP, 715 /*successAtStage=*/ true, 716 callback); 717 } 718 }); 719 } 720 } catch (DeadObjectException e) { 721 LogUtil.d( 722 TAG, 723 mCallingInfo 724 + " requested surface package from SDK " 725 + mSdkName 726 + " but sandbox is not alive"); 727 handleSurfacePackageError( 728 REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED, 729 "SDK " + mSdkName + " is not loaded", 730 /*startTimeOfStageWhereErrorOccurred=*/ -1, 731 SANDBOX_API_CALLED__STAGE__STAGE_UNSPECIFIED, 732 /*successAtStage=*/ false, 733 callback); 734 } catch (RemoteException e) { 735 String errorMsg = "Failed to requestSurfacePackage"; 736 Log.w(TAG, errorMsg, e); 737 handleSurfacePackageError( 738 SdkSandboxManager.REQUEST_SURFACE_PACKAGE_INTERNAL_ERROR, 739 errorMsg + ": " + e, 740 /*startTimeOfStageWhereErrorOccurred=*/ -1, 741 SANDBOX_API_CALLED__STAGE__STAGE_UNSPECIFIED, 742 /*successAtStage=*/ false, 743 callback); 744 } 745 } 746 747 @SdkSandboxManager.RequestSurfacePackageErrorCode toSdkSandboxManagerRequestSurfacePackageErrorCode(int sdkSandboxErrorCode)748 private int toSdkSandboxManagerRequestSurfacePackageErrorCode(int sdkSandboxErrorCode) { 749 if (sdkSandboxErrorCode 750 == IRequestSurfacePackageFromSdkCallback.SURFACE_PACKAGE_INTERNAL_ERROR) { 751 return SdkSandboxManager.REQUEST_SURFACE_PACKAGE_INTERNAL_ERROR; 752 } 753 Log.e( 754 TAG, 755 "Error code" 756 + sdkSandboxErrorCode 757 + "has no mapping to the SdkSandboxManager error codes"); 758 return SdkSandboxManager.REQUEST_SURFACE_PACKAGE_INTERNAL_ERROR; 759 } 760 } 761 logLatencyMetricsForCallback( long timeSystemServerReceivedCallFromSandbox, int method, SandboxLatencyInfo sandboxLatencyInfo)762 private void logLatencyMetricsForCallback( 763 long timeSystemServerReceivedCallFromSandbox, 764 int method, 765 SandboxLatencyInfo sandboxLatencyInfo) { 766 final int appUid = mCallingInfo.getUid(); 767 768 SdkSandboxStatsLog.write( 769 SdkSandboxStatsLog.SANDBOX_API_CALLED, 770 method, 771 sandboxLatencyInfo.getLatencySystemServerToSandbox(), 772 /*success=*/ true, 773 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX, 774 appUid); 775 776 SdkSandboxStatsLog.write( 777 SdkSandboxStatsLog.SANDBOX_API_CALLED, 778 method, 779 sandboxLatencyInfo.getSandboxLatency(), 780 sandboxLatencyInfo.isSuccessfulAtSandbox(), 781 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX, 782 appUid); 783 784 final int latencySdk = sandboxLatencyInfo.getSdkLatency(); 785 if (latencySdk != -1) { 786 SdkSandboxStatsLog.write( 787 SdkSandboxStatsLog.SANDBOX_API_CALLED, 788 method, 789 latencySdk, 790 sandboxLatencyInfo.isSuccessfulAtSdk(), 791 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SDK, 792 appUid); 793 } 794 795 SdkSandboxStatsLog.write( 796 SdkSandboxStatsLog.SANDBOX_API_CALLED, 797 method, 798 /*latency=*/ (int) 799 (timeSystemServerReceivedCallFromSandbox 800 - sandboxLatencyInfo.getTimeSandboxCalledSystemServer()), 801 /*success=*/ true, 802 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX_TO_SYSTEM_SERVER, 803 appUid); 804 } 805 806 // Returns an empty string if there is no issue getting information the SDK provider, else the 807 // error message. getSdkProviderErrorIfExists()808 String getSdkProviderErrorIfExists() { 809 if (mSdkProviderInfo == null) { 810 return mSdkName + " not found for loading"; 811 } 812 if (TextUtils.isEmpty(mSdkProviderInfo.getSdkProviderClassName())) { 813 return mSdkName + " did not set " + PROPERTY_SDK_PROVIDER_CLASS_NAME; 814 } 815 return ""; 816 } 817 createSdkProviderInfo()818 private SdkProviderInfo createSdkProviderInfo() { 819 try { 820 UserHandle userHandle = UserHandle.getUserHandleForUid(mCallingInfo.getUid()); 821 Context userContext = mContext.createContextAsUser(userHandle, /* flags= */ 0); 822 PackageManager pm = userContext.getPackageManager(); 823 ApplicationInfo info = 824 pm.getApplicationInfo( 825 mCallingInfo.getPackageName(), 826 ApplicationInfoFlags.of(PackageManager.GET_SHARED_LIBRARY_FILES)); 827 List<SharedLibraryInfo> sharedLibraries = info.getSharedLibraryInfos(); 828 for (int j = 0; j < sharedLibraries.size(); j++) { 829 SharedLibraryInfo sharedLibrary = sharedLibraries.get(j); 830 if (sharedLibrary.getType() != SharedLibraryInfo.TYPE_SDK_PACKAGE) { 831 continue; 832 } 833 834 if (!mSdkName.equals(sharedLibrary.getName())) { 835 continue; 836 } 837 838 String sdkProviderClassName = 839 pm.getProperty( 840 PROPERTY_SDK_PROVIDER_CLASS_NAME, 841 sharedLibrary.getDeclaringPackage().getPackageName()) 842 .getString(); 843 ApplicationInfo applicationInfo = 844 pm.getPackageInfo( 845 sharedLibrary.getDeclaringPackage(), 846 PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES 847 | PackageManager.MATCH_ANY_USER) 848 .applicationInfo; 849 return new SdkProviderInfo(applicationInfo, sharedLibrary, sdkProviderClassName); 850 } 851 return null; 852 } catch (PackageManager.NameNotFoundException e) { 853 return null; 854 } 855 } 856 857 /** Class which retrieves and stores the sdkName, sdkProviderClassName, and ApplicationInfo */ 858 static class SdkProviderInfo { 859 860 private final ApplicationInfo mApplicationInfo; 861 private final SharedLibraryInfo mSdkInfo; 862 private final String mSdkProviderClassName; 863 SdkProviderInfo( ApplicationInfo applicationInfo, SharedLibraryInfo sdkInfo, String sdkProviderClassName)864 private SdkProviderInfo( 865 ApplicationInfo applicationInfo, 866 SharedLibraryInfo sdkInfo, 867 String sdkProviderClassName) { 868 mApplicationInfo = applicationInfo; 869 mSdkInfo = sdkInfo; 870 mSdkProviderClassName = sdkProviderClassName; 871 } 872 getSdkInfo()873 public SharedLibraryInfo getSdkInfo() { 874 return mSdkInfo; 875 } 876 getSdkProviderClassName()877 public String getSdkProviderClassName() { 878 return mSdkProviderClassName; 879 } 880 getApplicationInfo()881 public ApplicationInfo getApplicationInfo() { 882 return mApplicationInfo; 883 } 884 } 885 } 886