• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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