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