• 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.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
20 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
21 import static android.app.adservices.AdServicesManager.AD_SERVICES_SYSTEM_SERVICE;
22 import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_ACTIVITY;
23 import static android.app.sdksandbox.SdkSandboxManager.EXTRA_SANDBOXED_ACTIVITY_HANDLER;
24 import static android.app.sdksandbox.SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR;
25 import static android.app.sdksandbox.SdkSandboxManager.LOAD_SDK_SDK_SANDBOX_DISABLED;
26 import static android.app.sdksandbox.SdkSandboxManager.REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED;
27 import static android.app.sdksandbox.SdkSandboxManager.SDK_SANDBOX_PROCESS_NOT_AVAILABLE;
28 import static android.app.sdksandbox.SdkSandboxManager.SDK_SANDBOX_SERVICE;
29 
30 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE;
31 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__UNLOAD_SDK;
32 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX;
33 import static com.android.server.sdksandbox.SdkSandboxStorageManager.StorageDirInfo;
34 import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_SDK_SANDBOX_ORDER_ID;
35 
36 import android.annotation.NonNull;
37 import android.annotation.Nullable;
38 import android.annotation.RequiresPermission;
39 import android.annotation.WorkerThread;
40 import android.app.ActivityManager;
41 import android.app.sdksandbox.ILoadSdkCallback;
42 import android.app.sdksandbox.IRequestSurfacePackageCallback;
43 import android.app.sdksandbox.ISdkSandboxManager;
44 import android.app.sdksandbox.ISdkSandboxProcessDeathCallback;
45 import android.app.sdksandbox.ISdkToServiceCallback;
46 import android.app.sdksandbox.ISharedPreferencesSyncCallback;
47 import android.app.sdksandbox.LoadSdkException;
48 import android.app.sdksandbox.LogUtil;
49 import android.app.sdksandbox.SandboxedSdk;
50 import android.app.sdksandbox.SdkSandboxManager;
51 import android.app.sdksandbox.SharedPreferencesUpdate;
52 import android.app.sdksandbox.sdkprovider.SdkSandboxController;
53 import android.content.BroadcastReceiver;
54 import android.content.ComponentName;
55 import android.content.Context;
56 import android.content.Intent;
57 import android.content.IntentFilter;
58 import android.content.ServiceConnection;
59 import android.content.pm.ActivityInfo;
60 import android.content.pm.ApplicationInfo;
61 import android.content.pm.PackageManager;
62 import android.content.pm.ProviderInfo;
63 import android.content.pm.ResolveInfo;
64 import android.content.pm.ServiceInfo;
65 import android.os.Binder;
66 import android.os.Build;
67 import android.os.Bundle;
68 import android.os.Handler;
69 import android.os.HandlerThread;
70 import android.os.IBinder;
71 import android.os.ParcelFileDescriptor;
72 import android.os.Process;
73 import android.os.RemoteCallbackList;
74 import android.os.RemoteException;
75 import android.os.SystemProperties;
76 import android.os.UserHandle;
77 import android.provider.DeviceConfig;
78 import android.text.TextUtils;
79 import android.util.ArrayMap;
80 import android.util.ArraySet;
81 import android.util.Log;
82 import android.webkit.WebViewUpdateService;
83 
84 import androidx.annotation.RequiresApi;
85 
86 import com.android.adservices.AdServicesCommon;
87 import com.android.internal.annotations.GuardedBy;
88 import com.android.internal.annotations.VisibleForTesting;
89 import com.android.modules.utils.BackgroundThread;
90 import com.android.modules.utils.build.SdkLevel;
91 import com.android.sdksandbox.IComputeSdkStorageCallback;
92 import com.android.sdksandbox.IRequestSurfacePackageFromSdkCallback;
93 import com.android.sdksandbox.ISdkSandboxDisabledCallback;
94 import com.android.sdksandbox.ISdkSandboxService;
95 import com.android.sdksandbox.service.stats.SdkSandboxStatsLog;
96 import com.android.server.LocalManagerRegistry;
97 import com.android.server.SystemService;
98 import com.android.server.am.ActivityManagerLocal;
99 import com.android.server.pm.PackageManagerLocal;
100 import com.android.server.wm.ActivityInterceptorCallback;
101 import com.android.server.wm.ActivityInterceptorCallbackRegistry;
102 
103 import java.io.FileDescriptor;
104 import java.io.PrintWriter;
105 import java.util.ArrayList;
106 import java.util.List;
107 import java.util.Set;
108 import java.util.concurrent.CountDownLatch;
109 import java.util.concurrent.TimeUnit;
110 
111 /**
112  * Implementation of {@link SdkSandboxManager}.
113  *
114  * @hide
115  */
116 public class SdkSandboxManagerService extends ISdkSandboxManager.Stub {
117 
118     private static final String TAG = "SdkSandboxManager";
119 
120     private static final String STOP_SDK_SANDBOX_PERMISSION =
121             "com.android.app.sdksandbox.permission.STOP_SDK_SANDBOX";
122 
123     private static final String SANDBOX_NOT_AVAILABLE_MSG = "Sandbox is unavailable";
124     private static final String SANDBOX_DISABLED_MSG = "SDK sandbox is disabled";
125 
126     private static final String DUMP_ARG_AD_SERVICES = "--AdServices";
127 
128     private final Context mContext;
129 
130     private final ActivityManager mActivityManager;
131     private final ActivityManagerLocal mActivityManagerLocal;
132     private final Handler mHandler;
133     private final SdkSandboxStorageManager mSdkSandboxStorageManager;
134     private final SdkSandboxServiceProvider mServiceProvider;
135 
136     @GuardedBy("mLock")
137     private IBinder mAdServicesManager;
138 
139     // TODO(b/282239822): temporary guard to define if dump() should handle the --AdServices otpion
140     @GuardedBy("mLock")
141     private boolean mAdServicesManagerPublished;
142 
143     private final Object mLock = new Object();
144 
145     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
146 
147     /**
148      * For each app, keep a mapping from SDK name to it's corresponding LoadSdkSession. This can
149      * contain all SDKs that are pending load, have been loaded, unloaded etc. Therefore, it is
150      * important to filter out by the type needed.
151      */
152     @GuardedBy("mLock")
153     private final ArrayMap<CallingInfo, ArrayMap<String, LoadSdkSession>> mLoadSdkSessions =
154             new ArrayMap<>();
155 
156     @GuardedBy("mLock")
157     private final ArrayMap<CallingInfo, IBinder> mCallingInfosWithDeathRecipients =
158             new ArrayMap<>();
159 
160     @GuardedBy("mLock")
161     private final Set<CallingInfo> mRunningInstrumentations = new ArraySet<>();
162 
163     @GuardedBy("mLock")
164     private final ArrayMap<CallingInfo, RemoteCallbackList<ISdkSandboxProcessDeathCallback>>
165             mSandboxLifecycleCallbacks = new ArrayMap<>();
166 
167     // Callbacks that need to be invoked when the sandbox binding has occurred (either successfully
168     // or unsuccessfully).
169     @GuardedBy("mLock")
170     private final ArrayMap<CallingInfo, ArrayList<SandboxBindingCallback>>
171             mSandboxBindingCallbacks = new ArrayMap<>();
172 
173     @GuardedBy("mLock")
174     private final ArrayMap<CallingInfo, ISharedPreferencesSyncCallback> mSyncDataCallbacks =
175             new ArrayMap<>();
176 
177     @GuardedBy("mLock")
178     private final UidImportanceListener mUidImportanceListener = new UidImportanceListener();
179 
180     private final String mAdServicesPackageName;
181 
182     private Injector mInjector;
183 
184     private final SdkSandboxPulledAtoms mSdkSandboxPulledAtoms;
185 
186     // All U devices have the visibility patch, so we can consider it already checked on U+ devices.
187     private static final boolean DEFAULT_VALUE_VISIBILITY_PATCH_CHECKED = SdkLevel.isAtLeastU();
188 
189     // The device must have a change that allows the Webview provider to be visible in order for the
190     // sandbox to be enabled. This change is present on all U+ devices, but not all T devices.
191     @GuardedBy("mLock")
192     private boolean mHasVisibilityPatch = DEFAULT_VALUE_VISIBILITY_PATCH_CHECKED;
193 
194     @GuardedBy("mLock")
195     private boolean mCheckedVisibilityPatch = DEFAULT_VALUE_VISIBILITY_PATCH_CHECKED;
196 
197     private SdkSandboxSettingsListener mSdkSandboxSettingsListener;
198 
199     private static final String PROPERTY_DISABLE_SDK_SANDBOX = "disable_sdk_sandbox";
200     private static final String PROPERTY_CUSTOMIZED_SDK_CONTEXT_ENABLED =
201             "sdksandbox_customized_sdk_context_enabled";
202     private static final boolean DEFAULT_VALUE_DISABLE_SDK_SANDBOX = true;
203     private static final boolean DEFAULT_VALUE_CUSTOMIZED_SDK_CONTEXT_ENABLED = false;
204 
205     /**
206      * Property to enforce broadcast receiver restrictions for SDK sandbox processes. If the value
207      * of this property is {@code true}, the restrictions will be enforced.
208      */
209     private static final String PROPERTY_ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS =
210             "enforce_broadcast_receiver_restrictions";
211 
212     private static final boolean DEFAULT_VALUE_ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS = false;
213 
214     /**
215      * Property to enforce content provider restrictions for SDK sandbox processes. If the value of
216      * this property is {@code true}, the restrictions will be enforced.
217      */
218     private static final String PROPERTY_ENFORCE_CONTENT_PROVIDER_RESTRICTIONS =
219             "enforce_content_provider_restrictions";
220 
221     private static final boolean DEFAULT_VALUE_ENFORCE_CONTENT_PROVIDER_RESTRICTIONS = false;
222 
223     // On UDC, AdServicesManagerService.Lifecycle implements dumpable so it's dumped as part of
224     // SystemServer.
225     // If AdServices register itself as binder service, dump() will ignore the --AdServices option
226     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
227     static final String DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_AD_SERVICES_ITSELF =
228             "Don't need to dump AdServices as it's available as " + AD_SERVICES_SYSTEM_SERVICE;
229 
230     // On UDC, if AdServices register itself as binder service, dump() will ignore the --AdServices
231     // option because AdServices could be dumped as part of SystemService
232     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
233     static final String DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_SYSTEM_SERVICE =
234             "Don't need to dump AdServices on UDC+ - use "
235                     + "'dumpsys system_server_dumper --name AdServices instead'";
236 
237     static class Injector {
238         private final Context mContext;
239         private SdkSandboxManagerLocal mLocalManager;
240         private final SdkSandboxServiceProvider mServiceProvider;
241 
Injector(Context context)242         Injector(Context context) {
243             mContext = context;
244             mServiceProvider = new SdkSandboxServiceProviderImpl(mContext);
245         }
246 
247         private static final boolean IS_EMULATOR =
248                 SystemProperties.getBoolean("ro.boot.qemu", false);
249 
getCurrentTime()250         long getCurrentTime() {
251             return System.currentTimeMillis();
252         }
253 
createShellCommand( SdkSandboxManagerService service, Context context)254         SdkSandboxShellCommand createShellCommand(
255                 SdkSandboxManagerService service, Context context) {
256             return new SdkSandboxShellCommand(service, context);
257         }
258 
isEmulator()259         boolean isEmulator() {
260             return IS_EMULATOR;
261         }
262 
getSdkSandboxServiceProvider()263         SdkSandboxServiceProvider getSdkSandboxServiceProvider() {
264             return mServiceProvider;
265         }
266 
getSdkSandboxPulledAtoms()267         SdkSandboxPulledAtoms getSdkSandboxPulledAtoms() {
268             return new SdkSandboxPulledAtoms();
269         }
270 
getPackageManagerLocal()271         PackageManagerLocal getPackageManagerLocal() {
272             return LocalManagerRegistry.getManager(PackageManagerLocal.class);
273         }
274 
getSdkSandboxStorageManager()275         SdkSandboxStorageManager getSdkSandboxStorageManager() {
276             return new SdkSandboxStorageManager(mContext, mLocalManager, getPackageManagerLocal());
277         }
278 
setLocalManager(SdkSandboxManagerLocal localManager)279         void setLocalManager(SdkSandboxManagerLocal localManager) {
280             mLocalManager = localManager;
281         }
282 
getLocalManager()283         SdkSandboxManagerLocal getLocalManager() {
284             return mLocalManager;
285         }
286     }
287 
SdkSandboxManagerService(Context context)288     SdkSandboxManagerService(Context context) {
289         this(context, new Injector(context));
290     }
291 
292     @VisibleForTesting
SdkSandboxManagerService(Context context, Injector injector)293     SdkSandboxManagerService(Context context, Injector injector) {
294         mContext = context;
295         mInjector = injector;
296         mInjector.setLocalManager(new LocalImpl());
297         mServiceProvider = mInjector.getSdkSandboxServiceProvider();
298         mActivityManager = mContext.getSystemService(ActivityManager.class);
299         mActivityManagerLocal = LocalManagerRegistry.getManager(ActivityManagerLocal.class);
300         mSdkSandboxPulledAtoms = mInjector.getSdkSandboxPulledAtoms();
301         PackageManagerLocal packageManagerLocal =
302                 LocalManagerRegistry.getManager(PackageManagerLocal.class);
303         mSdkSandboxStorageManager = mInjector.getSdkSandboxStorageManager();
304 
305         // Start the handler thread.
306         HandlerThread handlerThread = new HandlerThread("SdkSandboxManagerServiceHandler");
307         handlerThread.start();
308         mHandler = new Handler(handlerThread.getLooper());
309 
310         // Start a background handler thread.
311         HandlerThread backgroundHandlerThread =
312                 new HandlerThread(
313                         "SdkSandboxManagerServiceHandler", Process.THREAD_PRIORITY_BACKGROUND);
314         backgroundHandlerThread.start();
315 
316         registerBroadcastReceivers();
317 
318         mAdServicesPackageName = resolveAdServicesPackage();
319         mSdkSandboxSettingsListener = new SdkSandboxSettingsListener(mContext);
320         mSdkSandboxSettingsListener.registerObserver();
321         mSdkSandboxPulledAtoms.initialize(mContext);
322 
323         if (SdkLevel.isAtLeastU()) {
324             registerSandboxActivityInterceptor();
325         }
326     }
327 
registerBroadcastReceivers()328     private void registerBroadcastReceivers() {
329         registerPackageUpdateBroadcastReceiver();
330         registerVerifierBroadcastReceiver();
331     }
332 
registerPackageUpdateBroadcastReceiver()333     private void registerPackageUpdateBroadcastReceiver() {
334         // Register for package addition and update
335         final IntentFilter packageAddedIntentFilter = new IntentFilter();
336         packageAddedIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
337         packageAddedIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
338         packageAddedIntentFilter.addDataScheme("package");
339         BroadcastReceiver packageAddedIntentReceiver =
340                 new BroadcastReceiver() {
341                     @Override
342                     public void onReceive(Context context, Intent intent) {
343                         final String packageName = intent.getData().getSchemeSpecificPart();
344                         final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
345                         final CallingInfo callingInfo = new CallingInfo(uid, packageName);
346                         mHandler.post(
347                                 () ->
348                                         mSdkSandboxStorageManager.onPackageAddedOrUpdated(
349                                                 callingInfo));
350                     }
351                 };
352         mContext.registerReceiver(
353                 packageAddedIntentReceiver,
354                 packageAddedIntentFilter,
355                 /*broadcastPermission=*/ null,
356                 mHandler);
357     }
358 
registerVerifierBroadcastReceiver()359     private void registerVerifierBroadcastReceiver() {
360         final IntentFilter packageNeedsVerificationIntentFilter = new IntentFilter();
361         try {
362             packageNeedsVerificationIntentFilter.addDataType(PACKAGE_MIME_TYPE);
363             packageNeedsVerificationIntentFilter.addAction(
364                     Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
365             mContext.registerReceiverForAllUsers(
366                     new SdkSandboxVerifierReceiver(),
367                     packageNeedsVerificationIntentFilter,
368                     /*broadcastPermission=*/ null,
369                     /*scheduler=*/ null,
370                     Context.RECEIVER_EXPORTED);
371         } catch (IntentFilter.MalformedMimeTypeException e) {
372             Log.e(TAG, "Could not register verifier");
373         }
374     }
375 
376     @Override
getSandboxedSdks( String callingPackageName, long timeAppCalledSystemServer)377     public List<SandboxedSdk> getSandboxedSdks(
378             String callingPackageName, long timeAppCalledSystemServer) {
379         final long timeSystemServerReceivedCallFromApp = mInjector.getCurrentTime();
380 
381         final int callingUid = Binder.getCallingUid();
382         final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName);
383 
384         SdkSandboxStatsLog.write(
385                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
386                 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__GET_SANDBOXED_SDKS,
387                 /*latency=*/ (int)
388                         (timeSystemServerReceivedCallFromApp - timeAppCalledSystemServer),
389                 /*success=*/ true,
390                 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER,
391                 callingUid);
392 
393         final List<SandboxedSdk> sandboxedSdks = new ArrayList<>();
394         synchronized (mLock) {
395             ArrayList<LoadSdkSession> loadedSdks = getLoadedSdksForApp(callingInfo);
396             for (int i = 0; i < loadedSdks.size(); i++) {
397                 LoadSdkSession sdk = loadedSdks.get(i);
398                 SandboxedSdk sandboxedSdk = sdk.getSandboxedSdk();
399                 if (sandboxedSdk != null) {
400                     sandboxedSdks.add(sandboxedSdk);
401                 } else {
402                     Log.w(
403                             TAG,
404                             "SandboxedSdk is null for SDK "
405                                     + sdk.mSdkName
406                                     + " despite being loaded");
407                 }
408             }
409         }
410         SdkSandboxStatsLog.write(
411                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
412                 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__GET_SANDBOXED_SDKS,
413                 /*latency=*/ (int)
414                         (mInjector.getCurrentTime() - timeSystemServerReceivedCallFromApp),
415                 /*success=*/ true,
416                 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
417                 callingUid);
418         return sandboxedSdks;
419     }
420 
421     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
registerSandboxActivityInterceptor()422     private void registerSandboxActivityInterceptor() {
423         final ActivityInterceptorCallback mActivityInterceptorCallback =
424                 info -> {
425                     final Intent intent = info.getIntent();
426                     final String sdkSandboxPackageName =
427                             mContext.getPackageManager().getSdkSandboxPackageName();
428                     // Only intercept if action and package are both defined and refer to the
429                     // sandbox activity.
430                     if (intent == null
431                             || intent.getPackage() == null
432                             || !intent.getPackage().equals(sdkSandboxPackageName)
433                             || intent.getAction() == null
434                             || !intent.getAction().equals(ACTION_START_SANDBOXED_ACTIVITY)) {
435                         return null;
436                     }
437 
438                     // If component is set, it should refer to the sandbox package to intercept.
439                     if (intent.getComponent() != null) {
440                         final String componentPackageName = intent.getComponent().getPackageName();
441                         if (!componentPackageName.equals(sdkSandboxPackageName)) {
442                             return null;
443                         }
444                     }
445 
446                     final String sandboxProcessName =
447                             this.mInjector
448                                     .getSdkSandboxServiceProvider()
449                                     .toSandboxProcessName(info.getCallingPackage());
450                     final int sandboxUid = Process.toSdkSandboxUid(info.getCallingUid());
451 
452                     // Update process name and uid to match sandbox process for the calling app.
453                     ActivityInfo activityInfo = info.getActivityInfo();
454                     activityInfo.applicationInfo.uid = sandboxUid;
455                     activityInfo.processName = sandboxProcessName;
456 
457                     return new ActivityInterceptorCallback.ActivityInterceptResult(
458                             info.getIntent(), info.getCheckedOptions(), true);
459                 };
460         ActivityInterceptorCallbackRegistry registry =
461                 ActivityInterceptorCallbackRegistry.getInstance();
462         registry.registerActivityInterceptorCallback(
463                 MAINLINE_SDK_SANDBOX_ORDER_ID, mActivityInterceptorCallback);
464     }
465 
getLoadedSdksForApp(CallingInfo callingInfo)466     private ArrayList<LoadSdkSession> getLoadedSdksForApp(CallingInfo callingInfo) {
467         ArrayList<LoadSdkSession> loadedSdks = new ArrayList<>();
468         synchronized (mLock) {
469             if (mLoadSdkSessions.containsKey(callingInfo)) {
470                 ArrayList<LoadSdkSession> loadSessions =
471                         new ArrayList<>(mLoadSdkSessions.get(callingInfo).values());
472                 for (int i = 0; i < loadSessions.size(); i++) {
473                     LoadSdkSession sdk = loadSessions.get(i);
474                     if (sdk.getStatus() == LoadSdkSession.LOADED) {
475                         loadedSdks.add(sdk);
476                     }
477                 }
478             }
479         }
480         return loadedSdks;
481     }
482 
483     @Override
addSdkSandboxProcessDeathCallback( String callingPackageName, long timeAppCalledSystemServer, ISdkSandboxProcessDeathCallback callback)484     public void addSdkSandboxProcessDeathCallback(
485             String callingPackageName,
486             long timeAppCalledSystemServer,
487             ISdkSandboxProcessDeathCallback callback) {
488         final long timeSystemServerReceivedCallFromApp = mInjector.getCurrentTime();
489 
490         final int callingUid = Binder.getCallingUid();
491         final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName);
492 
493         SdkSandboxStatsLog.write(
494                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
495                 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__ADD_SDK_SANDBOX_LIFECYCLE_CALLBACK,
496                 /*latency=*/ (int)
497                         (timeSystemServerReceivedCallFromApp - timeAppCalledSystemServer),
498                 /*success=*/ true,
499                 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER,
500                 callingUid);
501 
502         synchronized (mLock) {
503             if (mSandboxLifecycleCallbacks.containsKey(callingInfo)) {
504                 mSandboxLifecycleCallbacks.get(callingInfo).register(callback);
505             } else {
506                 RemoteCallbackList<ISdkSandboxProcessDeathCallback> sandboxLifecycleCallbacks =
507                         new RemoteCallbackList<>();
508                 sandboxLifecycleCallbacks.register(callback);
509                 mSandboxLifecycleCallbacks.put(callingInfo, sandboxLifecycleCallbacks);
510             }
511         }
512 
513         // addSdkSandboxProcessDeathCallback() can be called without calling loadSdk(). Register for
514         // app death to make sure cleanup occurs.
515         registerForAppDeath(callingInfo, callback.asBinder());
516 
517         SdkSandboxStatsLog.write(
518                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
519                 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__ADD_SDK_SANDBOX_LIFECYCLE_CALLBACK,
520                 /*latency=*/ (int)
521                         (mInjector.getCurrentTime() - timeSystemServerReceivedCallFromApp),
522                 /*success=*/ true,
523                 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
524                 callingUid);
525     }
526 
527     // Register a handler for app death using any binder object originating from the app. Returns
528     // true if registering the handle succeeded and false if it failed (because the app died by
529     // then).
registerForAppDeath(CallingInfo callingInfo, IBinder appBinderObject)530     private boolean registerForAppDeath(CallingInfo callingInfo, IBinder appBinderObject) {
531         // Register a death recipient to clean up app related state and unbind its service after
532         // the app dies.
533         try {
534             synchronized (mLock) {
535                 if (!mCallingInfosWithDeathRecipients.containsKey(callingInfo)) {
536                     Log.d(TAG, "Registering " + callingInfo + " for death notification");
537                     appBinderObject.linkToDeath(() -> onAppDeath(callingInfo), 0);
538                     mCallingInfosWithDeathRecipients.put(callingInfo, appBinderObject);
539                 }
540             }
541         } catch (RemoteException re) {
542             // App has already died, cleanup sdk link, and unbind its service
543             onAppDeath(callingInfo);
544             return false;
545         }
546 
547         return true;
548     }
549 
550     @Override
removeSdkSandboxProcessDeathCallback( String callingPackageName, long timeAppCalledSystemServer, ISdkSandboxProcessDeathCallback callback)551     public void removeSdkSandboxProcessDeathCallback(
552             String callingPackageName,
553             long timeAppCalledSystemServer,
554             ISdkSandboxProcessDeathCallback callback) {
555         final long timeSystemServerReceivedCallFromApp = mInjector.getCurrentTime();
556 
557         final int callingUid = Binder.getCallingUid();
558         final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName);
559 
560         SdkSandboxStatsLog.write(
561                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
562                 SdkSandboxStatsLog
563                         .SANDBOX_API_CALLED__METHOD__REMOVE_SDK_SANDBOX_LIFECYCLE_CALLBACK,
564                 /*latency=*/ (int)
565                         (timeSystemServerReceivedCallFromApp - timeAppCalledSystemServer),
566                 /*success=*/ true,
567                 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER,
568                 callingUid);
569 
570         synchronized (mLock) {
571             RemoteCallbackList<ISdkSandboxProcessDeathCallback> sandboxLifecycleCallbacks =
572                     mSandboxLifecycleCallbacks.get(callingInfo);
573             if (sandboxLifecycleCallbacks != null) {
574                 sandboxLifecycleCallbacks.unregister(callback);
575             }
576         }
577         SdkSandboxStatsLog.write(
578                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
579                 SdkSandboxStatsLog
580                         .SANDBOX_API_CALLED__METHOD__REMOVE_SDK_SANDBOX_LIFECYCLE_CALLBACK,
581                 /*latency=*/ (int)
582                         (mInjector.getCurrentTime() - timeSystemServerReceivedCallFromApp),
583                 /*success=*/ true,
584                 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
585                 callingUid);
586     }
587 
588     @Override
loadSdk( String callingPackageName, IBinder callingAppProcessToken, String sdkName, long timeAppCalledSystemServer, Bundle params, ILoadSdkCallback callback)589     public void loadSdk(
590             String callingPackageName,
591             IBinder callingAppProcessToken,
592             String sdkName,
593             long timeAppCalledSystemServer,
594             Bundle params,
595             ILoadSdkCallback callback) {
596         try {
597             // Log the IPC latency from app to system server
598             final long timeSystemServerReceivedCallFromApp = mInjector.getCurrentTime();
599 
600             final int callingUid = Binder.getCallingUid();
601             final CallingInfo callingInfo =
602                     CallingInfo.fromBinderWithApplicationThread(
603                             mContext, callingPackageName, callingAppProcessToken);
604             enforceCallerHasNetworkAccess(callingPackageName);
605             enforceCallerOrItsSandboxRunInForeground(callingInfo);
606             synchronized (mLock) {
607                 if (mRunningInstrumentations.contains(callingInfo)) {
608                     throw new SecurityException(
609                             "Currently running instrumentation of this sdk sandbox process");
610                 }
611             }
612 
613             SdkSandboxStatsLog.write(
614                     SdkSandboxStatsLog.SANDBOX_API_CALLED,
615                     SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK,
616                     /*latency=*/ (int)
617                             (timeSystemServerReceivedCallFromApp - timeAppCalledSystemServer),
618                     /*success=*/ true,
619                     SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER,
620                     callingUid);
621 
622             final long token = Binder.clearCallingIdentity();
623             try {
624                 loadSdkWithClearIdentity(
625                         callingInfo,
626                         sdkName,
627                         params,
628                         callback,
629                         timeSystemServerReceivedCallFromApp);
630             } finally {
631                 Binder.restoreCallingIdentity(token);
632             }
633         } catch (Throwable e) {
634             try {
635                 Log.e(TAG, "Failed to load SDK " + sdkName, e);
636                 callback.onLoadSdkFailure(
637                         new LoadSdkException(LOAD_SDK_INTERNAL_ERROR, e.getMessage(), e),
638                         System.currentTimeMillis());
639             } catch (RemoteException ex) {
640                 Log.e(TAG, "Failed to send onLoadCodeFailure", e);
641             }
642         }
643     }
644 
loadSdkWithClearIdentity( CallingInfo callingInfo, String sdkName, Bundle params, ILoadSdkCallback callback, long timeSystemServerReceivedCallFromApp)645     private void loadSdkWithClearIdentity(
646             CallingInfo callingInfo,
647             String sdkName,
648             Bundle params,
649             ILoadSdkCallback callback,
650             long timeSystemServerReceivedCallFromApp) {
651         LoadSdkSession loadSdkSession =
652                 new LoadSdkSession(
653                         mContext, this, mInjector, sdkName, callingInfo, params, callback);
654 
655         // SDK provider was invalid. This load request should fail.
656         String errorMsg = loadSdkSession.getSdkProviderErrorIfExists();
657         if (!TextUtils.isEmpty(errorMsg)) {
658             Log.w(TAG, errorMsg);
659             loadSdkSession.handleLoadFailure(
660                     new LoadSdkException(SdkSandboxManager.LOAD_SDK_NOT_FOUND, errorMsg),
661                     /*startTimeOfErrorStage=*/ timeSystemServerReceivedCallFromApp,
662                     SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
663                     /*successAtStage=*/ false);
664             return;
665         }
666 
667         // Ensure we are not already loading this sdk. That's determined by checking if we already
668         // have a completed LoadSdkSession with the same SDK name for the calling info.
669         synchronized (mLock) {
670             LoadSdkSession prevLoadSession = null;
671             // Get any previous load session for this SDK if exists.
672             if (mLoadSdkSessions.containsKey(callingInfo)) {
673                 prevLoadSession = mLoadSdkSessions.get(callingInfo).get(sdkName);
674             }
675 
676             // If there was a previous load session and the status is loaded, this new load request
677             // should fail.
678             if (prevLoadSession != null && prevLoadSession.getStatus() == LoadSdkSession.LOADED) {
679                 loadSdkSession.handleLoadFailure(
680                         new LoadSdkException(
681                                 SdkSandboxManager.LOAD_SDK_ALREADY_LOADED,
682                                 sdkName + " has been loaded already"),
683                         /*startTimeOfErrorStage=*/ timeSystemServerReceivedCallFromApp,
684                         SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
685                         /*successAtStage=*/ false);
686                 return;
687             }
688 
689             // If there was an ongoing load session for this SDK, this new load request should fail.
690             if (prevLoadSession != null
691                     && prevLoadSession.getStatus() == LoadSdkSession.LOAD_PENDING) {
692                 loadSdkSession.handleLoadFailure(
693                         new LoadSdkException(
694                                 SdkSandboxManager.LOAD_SDK_ALREADY_LOADED,
695                                 sdkName + " is currently being loaded"),
696                         /*startTimeOfErrorStage=*/ timeSystemServerReceivedCallFromApp,
697                         SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
698                         /*successAtStage=*/ false);
699                 return;
700             }
701 
702             // If there was no previous load session (or there was one but its load status was
703             // unloaded or failed), it should be replaced by the new load session.
704             mLoadSdkSessions.computeIfAbsent(callingInfo, k -> new ArrayMap<>());
705             mLoadSdkSessions.get(callingInfo).put(sdkName, loadSdkSession);
706         }
707 
708         synchronized (mLock) {
709             mUidImportanceListener.startListening();
710             if (!registerForAppDeath(callingInfo, callback.asBinder())) {
711                 // Log the time taken in System Server before the exception occurred
712                 SdkSandboxStatsLog.write(
713                         SdkSandboxStatsLog.SANDBOX_API_CALLED,
714                         SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK,
715                         /*latency=*/ (int)
716                                 (mInjector.getCurrentTime() - timeSystemServerReceivedCallFromApp),
717                         /*success=*/ false,
718                         SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
719                         callingInfo.getUid());
720                 // App has already died and there is no point in loading the SDK.
721                 return;
722             }
723         }
724 
725         // Callback to be invoked once the sandbox has been created;
726         SandboxBindingCallback sandboxBindingCallback =
727                 createSdkLoadCallback(loadSdkSession, timeSystemServerReceivedCallFromApp);
728         startSdkSandboxIfNeeded(callingInfo, sandboxBindingCallback);
729     }
730 
createSdkLoadCallback( LoadSdkSession loadSdkSession, long timeSystemServerReceivedCallFromApp)731     private SandboxBindingCallback createSdkLoadCallback(
732             LoadSdkSession loadSdkSession, long timeSystemServerReceivedCallFromApp) {
733         return new SandboxBindingCallback() {
734             @Override
735             public void onBindingSuccessful(ISdkSandboxService service, int timeToLoadSandbox) {
736                 loadSdkForService(
737                         loadSdkSession,
738                         timeToLoadSandbox,
739                         timeSystemServerReceivedCallFromApp,
740                         service);
741             }
742 
743             @Override
744             public void onBindingFailed(
745                     LoadSdkException exception, long startTimeForLoadingSandbox) {
746                 loadSdkSession.handleLoadFailure(
747                         exception,
748                         /*startTimeOfErrorStage=*/ startTimeForLoadingSandbox,
749                         /*stage*/ SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__LOAD_SANDBOX,
750                         /*successAtStage=*/ false);
751             }
752         };
753     }
754 
755     void startSdkSandboxIfNeeded(CallingInfo callingInfo, SandboxBindingCallback callback) {
756 
757         boolean isSandboxStartRequired = false;
758         synchronized (mLock) {
759             @SdkSandboxServiceProvider.SandboxStatus
760             int sandboxStatus = mServiceProvider.getSandboxStatusForApp(callingInfo);
761 
762             // Check if service is already created for the app.
763             if (sandboxStatus == SdkSandboxServiceProvider.NON_EXISTENT
764                     || sandboxStatus == SdkSandboxServiceProvider.CREATE_PENDING) {
765                 addSandboxBindingCallback(callingInfo, callback);
766                 if (sandboxStatus == SdkSandboxServiceProvider.NON_EXISTENT) {
767                     isSandboxStartRequired = true;
768                 } else {
769                     // The sandbox is in the process of being brought up. Nothing more to do here.
770                     return;
771                 }
772             }
773         }
774 
775         final long startTimeForLoadingSandbox = mInjector.getCurrentTime();
776 
777         if (!isSandboxStartRequired) {
778             ISdkSandboxService service = mServiceProvider.getSdkSandboxServiceForApp(callingInfo);
779             if (service == null) {
780                 LoadSdkException exception =
781                         new LoadSdkException(
782                                 SDK_SANDBOX_PROCESS_NOT_AVAILABLE, SANDBOX_NOT_AVAILABLE_MSG);
783                 callback.onBindingFailed(exception, startTimeForLoadingSandbox);
784             }
785             callback.onBindingSuccessful(service, -1);
786             return;
787         }
788 
789         // Prepare sdk data directories before starting the sandbox. If sdk data package directory
790         // is missing, starting the sandbox process would crash as we will fail to mount data_mirror
791         // for sdk-data isolation.
792         mSdkSandboxStorageManager.prepareSdkDataOnLoad(callingInfo);
793         mServiceProvider.bindService(
794                 callingInfo,
795                 new SandboxServiceConnection(
796                         mServiceProvider, callingInfo, startTimeForLoadingSandbox));
797     }
798 
799     private void addSandboxBindingCallback(
800             CallingInfo callingInfo, SandboxBindingCallback callback) {
801         synchronized (mLock) {
802             mSandboxBindingCallbacks.computeIfAbsent(callingInfo, k -> new ArrayList<>());
803             mSandboxBindingCallbacks.get(callingInfo).add(callback);
804         }
805     }
806 
807     @Override
808     public void unloadSdk(
809             String callingPackageName, String sdkName, long timeAppCalledSystemServer) {
810         final long timeSystemServerReceivedCallFromApp = mInjector.getCurrentTime();
811 
812         final int callingUid = Binder.getCallingUid();
813         final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName);
814         enforceCallerOrItsSandboxRunInForeground(callingInfo);
815 
816         SdkSandboxStatsLog.write(
817                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
818                 SANDBOX_API_CALLED__METHOD__UNLOAD_SDK,
819                 /*latency=*/ (int)
820                         (timeSystemServerReceivedCallFromApp - timeAppCalledSystemServer),
821                 /*success=*/ true,
822                 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER,
823                 callingUid);
824 
825         final long token = Binder.clearCallingIdentity();
826         try {
827             unloadSdkWithClearIdentity(callingInfo, sdkName, timeSystemServerReceivedCallFromApp);
828         } finally {
829             Binder.restoreCallingIdentity(token);
830         }
831     }
832 
833     private void unloadSdkWithClearIdentity(
834             CallingInfo callingInfo, String sdkName, long timeSystemServerReceivedCallFromApp) {
835         LoadSdkSession prevLoadSession = null;
836         long timeSystemServerReceivedCallFromSandbox;
837         synchronized (mLock) {
838             // TODO(b/254657226): Add a callback or return value for unloadSdk() to indicate
839             // success of unload.
840 
841             // Get any previous load session for this SDK if exists.
842             if (mLoadSdkSessions.containsKey(callingInfo)) {
843                 prevLoadSession = mLoadSdkSessions.get(callingInfo).get(sdkName);
844             }
845         }
846 
847         // If there was no previous load session or the SDK is not loaded, there is nothing to
848         // unload.
849         if (prevLoadSession == null) {
850             // Unloading SDK that is not loaded is a no-op, return.
851             Log.w(TAG, "SDK " + sdkName + " is not loaded for " + callingInfo);
852             return;
853         }
854 
855         prevLoadSession.unload(timeSystemServerReceivedCallFromApp);
856         timeSystemServerReceivedCallFromSandbox = mInjector.getCurrentTime();
857 
858         ArrayList<LoadSdkSession> loadedSdks = getLoadedSdksForApp(callingInfo);
859         if (loadedSdks.isEmpty()) {
860             stopSdkSandboxService(
861                     callingInfo, "Caller " + callingInfo + " has no remaining SDKS loaded.");
862         }
863         SdkSandboxStatsLog.write(
864                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
865                 SANDBOX_API_CALLED__METHOD__UNLOAD_SDK,
866                 (int) (mInjector.getCurrentTime() - timeSystemServerReceivedCallFromSandbox),
867                 /*success=*/ true,
868                 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_SANDBOX_TO_APP,
869                 callingInfo.getUid());
870     }
871 
872     private void enforceCallingPackageBelongsToUid(CallingInfo callingInfo) {
873         int callingUid = callingInfo.getUid();
874         String callingPackage = callingInfo.getPackageName();
875         int packageUid;
876         PackageManager pm = mContext.createContextAsUser(
877                 UserHandle.getUserHandleForUid(callingUid), 0).getPackageManager();
878         try {
879             packageUid = pm.getPackageUid(callingPackage, 0);
880         } catch (PackageManager.NameNotFoundException e) {
881             throw new SecurityException(callingPackage + " not found");
882         }
883         if (packageUid != callingUid) {
884             throw new SecurityException(callingPackage + " does not belong to uid " + callingUid);
885         }
886     }
887 
888     private void enforceCallerOrItsSandboxRunInForeground(CallingInfo callingInfo) {
889         String callingPackage = callingInfo.getPackageName();
890         final long token = Binder.clearCallingIdentity();
891         try {
892             int importance =
893                     Math.min(
894                             mActivityManager.getUidImportance(callingInfo.getUid()),
895                             mActivityManager.getUidImportance(
896                                     Process.toSdkSandboxUid(callingInfo.getUid())));
897             if (importance > IMPORTANCE_FOREGROUND) {
898                 throw new SecurityException(callingPackage + " does not run in the foreground");
899             }
900         } finally {
901             Binder.restoreCallingIdentity(token);
902         }
903     }
904 
905     private void enforceCallerHasNetworkAccess(String callingPackage) {
906         mContext.enforceCallingPermission(android.Manifest.permission.INTERNET,
907                 callingPackage + " does not hold INTERNET permission");
908         mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
909                 callingPackage + " does not hold ACCESS_NETWORK_STATE permission");
910     }
911 
912     private void onAppDeath(CallingInfo callingInfo) {
913         synchronized (mLock) {
914             Log.d(TAG, "App " + callingInfo + " has died, cleaning up associated sandbox info");
915             mSandboxLifecycleCallbacks.remove(callingInfo);
916             mSandboxBindingCallbacks.remove(callingInfo);
917             mCallingInfosWithDeathRecipients.remove(callingInfo);
918             if (mCallingInfosWithDeathRecipients.size() == 0) {
919                 mUidImportanceListener.stopListening();
920             }
921             mSyncDataCallbacks.remove(callingInfo);
922             mLoadSdkSessions.remove(callingInfo);
923             stopSdkSandboxService(callingInfo, "Caller " + callingInfo + " has died");
924             mServiceProvider.onAppDeath(callingInfo);
925         }
926     }
927 
928     @Override
929     public void requestSurfacePackage(
930             String callingPackageName,
931             String sdkName,
932             IBinder hostToken,
933             int displayId,
934             int width,
935             int height,
936             long timeAppCalledSystemServer,
937             Bundle params,
938             IRequestSurfacePackageCallback callback) {
939         try {
940             final long timeSystemServerReceivedCallFromApp = mInjector.getCurrentTime();
941 
942             LogUtil.d(
943                     TAG,
944                     "requestSurfacePackage call received. callingPackageName: "
945                             + callingPackageName);
946 
947             final int callingUid = Binder.getCallingUid();
948             final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName);
949             enforceCallerOrItsSandboxRunInForeground(callingInfo);
950 
951             SdkSandboxStatsLog.write(
952                     SdkSandboxStatsLog.SANDBOX_API_CALLED,
953                     SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE,
954                     /*latency=*/ (int)
955                             (timeSystemServerReceivedCallFromApp - timeAppCalledSystemServer),
956                     /*success=*/ true,
957                     SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER,
958                     callingUid);
959 
960             final long token = Binder.clearCallingIdentity();
961             try {
962                 requestSurfacePackageWithClearIdentity(
963                         callingInfo,
964                         sdkName,
965                         hostToken,
966                         displayId,
967                         width,
968                         height,
969                         timeSystemServerReceivedCallFromApp,
970                         params,
971                         callback);
972             } finally {
973                 Binder.restoreCallingIdentity(token);
974             }
975         } catch (Throwable e) {
976             try {
977                 callback.onSurfacePackageError(
978                         IRequestSurfacePackageFromSdkCallback.SURFACE_PACKAGE_INTERNAL_ERROR,
979                         e.getMessage(),
980                         mInjector.getCurrentTime());
981             } catch (RemoteException ex) {
982                 Log.e(TAG, "Failed to send onLoadCodeFailure", e);
983             }
984         }
985     }
986 
987     private void requestSurfacePackageWithClearIdentity(
988             CallingInfo callingInfo,
989             String sdkName,
990             IBinder hostToken,
991             int displayId,
992             int width,
993             int height,
994             long timeSystemServerReceivedCallFromApp,
995             Bundle params,
996             IRequestSurfacePackageCallback callback) {
997         LoadSdkSession loadSdkSession = null;
998         synchronized (mLock) {
999             if (mLoadSdkSessions.containsKey(callingInfo)) {
1000                 loadSdkSession = mLoadSdkSessions.get(callingInfo).get(sdkName);
1001             }
1002         }
1003         if (loadSdkSession == null) {
1004             LogUtil.d(
1005                     TAG,
1006                     callingInfo + " requested surface package, but could not find SDK " + sdkName);
1007 
1008             final long timeSystemServerCalledApp = mInjector.getCurrentTime();
1009             SdkSandboxStatsLog.write(
1010                     SdkSandboxStatsLog.SANDBOX_API_CALLED,
1011                     SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE,
1012                     (int) (timeSystemServerCalledApp - timeSystemServerReceivedCallFromApp),
1013                     /*successAtStage*/ false,
1014                     SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
1015                     callingInfo.getUid());
1016 
1017             try {
1018                 callback.onSurfacePackageError(
1019                         REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED,
1020                         "SDK " + sdkName + " is not loaded",
1021                         timeSystemServerCalledApp);
1022             } catch (RemoteException e) {
1023                 Log.w(TAG, "Failed to send onSurfacePackageError", e);
1024             }
1025             return;
1026         }
1027 
1028         loadSdkSession.requestSurfacePackage(
1029                 hostToken,
1030                 displayId,
1031                 width,
1032                 height,
1033                 timeSystemServerReceivedCallFromApp,
1034                 params,
1035                 callback);
1036     }
1037 
1038     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1039     void onUserUnlocking(int userId) {
1040         Log.i(TAG, "onUserUnlocking " + userId);
1041         // using postDelayed to wait for other volumes to mount
1042         mHandler.postDelayed(() -> mSdkSandboxStorageManager.onUserUnlocking(userId), 20000);
1043     }
1044 
1045     @Override
1046     @RequiresPermission(android.Manifest.permission.DUMP)
1047     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1048         mContext.enforceCallingPermission(android.Manifest.permission.DUMP,
1049                 "Can't dump " + TAG);
1050 
1051         if (args != null && args.length > 0 && args[0].equals(DUMP_ARG_AD_SERVICES)) {
1052             dumpAdServices(fd, writer, args, /* quiet= */ false);
1053             return;
1054         }
1055 
1056         // TODO(b/211575098): Use IndentingPrintWriter for better formatting
1057         synchronized (mLock) {
1058             writer.println("Checked Webview visibility patch exists: " + mCheckedVisibilityPatch);
1059             if (mCheckedVisibilityPatch) {
1060                 writer.println("Build contains Webview visibility patch: " + mHasVisibilityPatch);
1061             }
1062             writer.println(
1063                     "Killswitch enabled: " + mSdkSandboxSettingsListener.isKillSwitchEnabled());
1064             writer.println(
1065                     "Customized Sdk Context enabled: "
1066                             + mSdkSandboxSettingsListener.isCustomizedSdkContextEnabled());
1067             writer.println("mLoadSdkSessions size: " + mLoadSdkSessions.size());
1068             for (CallingInfo callingInfo : mLoadSdkSessions.keySet()) {
1069                 writer.printf("Caller: %s has following SDKs", callingInfo);
1070                 writer.println();
1071                 ArrayList<LoadSdkSession> loadSessions =
1072                         new ArrayList<>(mLoadSdkSessions.get(callingInfo).values());
1073                 for (int i = 0; i < loadSessions.size(); i++) {
1074                     LoadSdkSession sdk = loadSessions.get(i);
1075                     writer.printf("SDK: %s Status: %s", sdk.mSdkName, sdk.getStatus());
1076                     writer.println();
1077                 }
1078             }
1079             writer.println();
1080 
1081             writer.println("AdServicesManager binder published: " + mAdServicesManagerPublished);
1082         }
1083 
1084         writer.println("mServiceProvider:");
1085         mServiceProvider.dump(writer);
1086         writer.println();
1087 
1088         dumpAdServices(fd, writer, args, /* quiet= */ true);
1089     }
1090 
1091     private void dumpAdServices(
1092             @Nullable FileDescriptor fd, PrintWriter writer, String[] args, boolean quiet) {
1093 
1094         synchronized (mLock) {
1095             if (mAdServicesManagerPublished) {
1096                 // AdServices registered itself as binder service
1097                 if (quiet) {
1098                     Log.d(TAG, DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_AD_SERVICES_ITSELF);
1099                 } else {
1100                     writer.println(DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_AD_SERVICES_ITSELF);
1101                 }
1102                 return;
1103             }
1104         }
1105 
1106         if (SdkLevel.isAtLeastU()) {
1107             // AdServices didn't register itself as binder service, but
1108             // AdServicesManagerService.Lifecycle implements Dumpable so it's dumped as
1109             // part of SystemServer
1110             if (quiet) {
1111                 Log.d(TAG, DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_SYSTEM_SERVICE);
1112             } else {
1113                 writer.println(DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_SYSTEM_SERVICE);
1114             }
1115             return;
1116         }
1117         writer.print("AdServices:");
1118         IBinder adServicesManager = getAdServicesManager();
1119         if (adServicesManager == null) {
1120             // Should not happen on "real life", but it could on unit tests.
1121             Log.e(TAG, "dumpAdServices(): mAdServicesManager not set");
1122             writer.println(" N/A");
1123             return;
1124         }
1125         writer.println();
1126         writer.println();
1127         writer.flush(); // must flush, other raw dump on fd below will be printed before it
1128         try {
1129             adServicesManager.dump(fd, args);
1130         } catch (RemoteException e) {
1131             Log.e(TAG, "Failed to dump AdServices", e);
1132             // Shouldn't happen, but it doesn't hurt to catch
1133             writer.printf("Failed to dump Adservices: %s\n", e);
1134         }
1135         writer.println();
1136     }
1137 
1138     @Override
1139     public void syncDataFromClient(
1140             String callingPackageName,
1141             long timeAppCalledSystemServer,
1142             SharedPreferencesUpdate update,
1143             ISharedPreferencesSyncCallback callback) {
1144         try {
1145             final long timeSystemServerReceivedCallFromApp = mInjector.getCurrentTime();
1146 
1147             final int callingUid = Binder.getCallingUid();
1148             final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName);
1149             enforceCallingPackageBelongsToUid(callingInfo);
1150 
1151             SdkSandboxStatsLog.write(
1152                     SdkSandboxStatsLog.SANDBOX_API_CALLED,
1153                     SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__SYNC_DATA_FROM_CLIENT,
1154                     /*latency=*/ (int)
1155                             (timeSystemServerReceivedCallFromApp - timeAppCalledSystemServer),
1156                     /*success=*/ true,
1157                     SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__APP_TO_SYSTEM_SERVER,
1158                     callingUid);
1159 
1160             final long token = Binder.clearCallingIdentity();
1161             try {
1162                 syncDataFromClientInternal(callingInfo, update, callback);
1163             } finally {
1164                 Binder.restoreCallingIdentity(token);
1165             }
1166         } catch (Throwable e) {
1167             try {
1168                 callback.onError(
1169                         ISharedPreferencesSyncCallback.PREFERENCES_SYNC_INTERNAL_ERROR,
1170                         e.getMessage());
1171             } catch (RemoteException ex) {
1172                 Log.e(TAG, "Failed to send onLoadCodeFailure", e);
1173             }
1174         }
1175     }
1176 
1177     private void syncDataFromClientInternal(
1178             CallingInfo callingInfo,
1179             SharedPreferencesUpdate update,
1180             ISharedPreferencesSyncCallback callback) {
1181         // check first if service already bound
1182         ISdkSandboxService service = mServiceProvider.getSdkSandboxServiceForApp(callingInfo);
1183         if (service != null) {
1184             try {
1185                 service.syncDataFromClient(update);
1186             } catch (RemoteException e) {
1187                 syncDataOnError(callingInfo, callback, e.getMessage());
1188             }
1189         } else {
1190             syncDataOnError(callingInfo, callback, "Sandbox not available");
1191         }
1192     }
1193 
1194     private void syncDataOnError(
1195             CallingInfo callingInfo, ISharedPreferencesSyncCallback callback, String errorMsg) {
1196         // Store reference to the callback so that we can notify SdkSandboxManager when sandbox
1197         // starts
1198         synchronized (mLock) {
1199             mSyncDataCallbacks.put(callingInfo, callback);
1200         }
1201         try {
1202             callback.onError(ISharedPreferencesSyncCallback.SANDBOX_NOT_AVAILABLE, errorMsg);
1203         } catch (RemoteException ignore) {
1204             // App died. Sync will be re-established again by app later.
1205         }
1206     }
1207 
1208     @Override
1209     public void logLatencyFromSystemServerToApp(String method, int latency) {
1210         SdkSandboxStatsLog.write(
1211                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
1212                 convertToStatsLogMethodCode(method),
1213                 latency,
1214                 /*success=*/ true,
1215                 SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_APP,
1216                 Binder.getCallingUid());
1217     }
1218 
1219     private int convertToStatsLogMethodCode(String method) {
1220         switch (method) {
1221             case ISdkSandboxManager.REQUEST_SURFACE_PACKAGE:
1222                 return SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__REQUEST_SURFACE_PACKAGE;
1223             case ISdkSandboxManager.LOAD_SDK:
1224                 return SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK;
1225             default:
1226                 return SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__METHOD_UNSPECIFIED;
1227         }
1228     }
1229 
1230     interface SandboxBindingCallback {
1231         void onBindingSuccessful(ISdkSandboxService service, int timeToLoadSandbox);
1232 
1233         void onBindingFailed(LoadSdkException exception, long startTimeForLoadingSandbox);
1234     }
1235 
1236     class SandboxServiceConnection implements ServiceConnection {
1237 
1238         private final SdkSandboxServiceProvider mServiceProvider;
1239         private final CallingInfo mCallingInfo;
1240         private boolean mHasConnectedBefore = false;
1241         private long mStartTimeForLoadingSandbox;
1242 
1243 
1244         SandboxServiceConnection(
1245                 SdkSandboxServiceProvider serviceProvider,
1246                 CallingInfo callingInfo,
1247                 long startTimeForLoadingSandbox) {
1248             mServiceProvider = serviceProvider;
1249             mCallingInfo = callingInfo;
1250             mStartTimeForLoadingSandbox = startTimeForLoadingSandbox;
1251         }
1252 
1253         @Override
1254         public void onServiceConnected(ComponentName name, IBinder service) {
1255             final ISdkSandboxService mService = ISdkSandboxService.Stub.asInterface(service);
1256 
1257             // Perform actions needed after every sandbox restart.
1258             if (!onSandboxConnected(mService)) {
1259                 // We don't need to call sandboxBindingCallback.onBindingFailed() in this case since
1260                 // onSdkSandboxDeath() will take care of iterating through LoadSdkSessions and
1261                 // informing SDKs about load failure.
1262                 return;
1263             }
1264 
1265             // Set connected service for app once all initialization has finished. This needs to be
1266             // set after every sandbox restart as well.
1267             mServiceProvider.onServiceConnected(mCallingInfo, mService);
1268 
1269             // Once bound service has been set, sync manager is notified.
1270             notifySyncManagerSandboxStarted(mCallingInfo);
1271 
1272             BackgroundThread.getExecutor()
1273                     .execute(
1274                             () -> {
1275                                 computeSdkStorage(mCallingInfo, mService);
1276                             });
1277 
1278             final int timeToLoadSandbox =
1279                     (int) (mInjector.getCurrentTime() - mStartTimeForLoadingSandbox);
1280             if (!mHasConnectedBefore) {
1281                 logSandboxStart(timeToLoadSandbox);
1282                 mHasConnectedBefore = true;
1283             }
1284 
1285             ArrayList<SandboxBindingCallback> sandboxBindingCallbacksForApp =
1286                     clearAndGetSandboxBindingCallbacks();
1287             for (int i = 0; i < sandboxBindingCallbacksForApp.size(); i++) {
1288                 SandboxBindingCallback callback = sandboxBindingCallbacksForApp.get(i);
1289                 callback.onBindingSuccessful(mService, timeToLoadSandbox);
1290             }
1291         }
1292 
1293         @Override
1294         public void onServiceDisconnected(ComponentName name) {
1295             // Sdk sandbox crashed or killed, system will start it again.
1296             Log.d(TAG, "Sandbox service for " + mCallingInfo + " has been disconnected");
1297             mServiceProvider.onServiceDisconnected(mCallingInfo);
1298         }
1299 
1300         @Override
1301         public void onBindingDied(ComponentName name) {
1302             Log.d(TAG, "Sandbox service for " + mCallingInfo + " : died on binding");
1303             mServiceProvider.unbindService(mCallingInfo);
1304         }
1305 
1306         @Override
1307         public void onNullBinding(ComponentName name) {
1308             Log.d(TAG, "Sandbox service failed to bind for " + mCallingInfo + " : service is null");
1309             LoadSdkException exception =
1310                     new LoadSdkException(
1311                             SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR,
1312                             "Failed to bind the service");
1313             ArrayList<SandboxBindingCallback> sandboxBindingCallbacksForApp =
1314                     clearAndGetSandboxBindingCallbacks();
1315             for (int i = 0; i < sandboxBindingCallbacksForApp.size(); i++) {
1316                 SandboxBindingCallback callback = sandboxBindingCallbacksForApp.get(i);
1317                 callback.onBindingFailed(exception, mStartTimeForLoadingSandbox);
1318             }
1319         }
1320 
1321         /**
1322          * Actions to be performed every time the sandbox connects for a particular app, such as the
1323          * first time the sandbox is brought up and every time it restarts.
1324          *
1325          * @return true if all actions were performed successfully, false otherwise.
1326          */
1327         private boolean onSandboxConnected(ISdkSandboxService service) {
1328             Log.i(
1329                     TAG,
1330                     String.format(
1331                             "Sdk sandbox has been bound for app package %s with uid %d",
1332                             mCallingInfo.getPackageName(), mCallingInfo.getUid()));
1333             try {
1334                 service.asBinder().linkToDeath(() -> onSdkSandboxDeath(mCallingInfo), 0);
1335             } catch (RemoteException e) {
1336                 // Sandbox had already died, cleanup sdk links, notify app etc.
1337                 onSdkSandboxDeath(mCallingInfo);
1338                 return false;
1339             }
1340 
1341             try {
1342                 service.initialize(
1343                         new SdkToServiceLink(),
1344                         mSdkSandboxSettingsListener.isCustomizedSdkContextEnabled());
1345             } catch (Throwable e) {
1346                 handleFailedSandboxInitialization(mCallingInfo);
1347                 return false;
1348             }
1349 
1350             return true;
1351         }
1352 
1353         private void logSandboxStart(int timeToLoadSandbox) {
1354             // Log the latency for loading the Sandbox process
1355             SdkSandboxStatsLog.write(
1356                     SdkSandboxStatsLog.SANDBOX_API_CALLED,
1357                     SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK,
1358                     timeToLoadSandbox,
1359                     /* success=*/ true,
1360                     SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__LOAD_SANDBOX,
1361                     mCallingInfo.getUid());
1362         }
1363 
1364         private ArrayList<SandboxBindingCallback> clearAndGetSandboxBindingCallbacks() {
1365             ArrayList<SandboxBindingCallback> sandboxBindingCallbacksForApp;
1366             synchronized (mLock) {
1367                 sandboxBindingCallbacksForApp = mSandboxBindingCallbacks.get(mCallingInfo);
1368                 mSandboxBindingCallbacks.remove(mCallingInfo);
1369             }
1370             if (sandboxBindingCallbacksForApp == null) {
1371                 sandboxBindingCallbacksForApp = new ArrayList<>();
1372             }
1373             return sandboxBindingCallbacksForApp;
1374         }
1375     }
1376 
1377     void handleFailedSandboxInitialization(CallingInfo callingInfo) {
1378         final String errorMsg = "Failed to initialize sandbox";
1379         Log.e(TAG, errorMsg + " for " + callingInfo);
1380         // Kill the sandbox if it failed to initialize as it might not be properly usable.
1381         stopSdkSandboxService(callingInfo, errorMsg);
1382     }
1383 
1384     private void onSdkSandboxDeath(CallingInfo callingInfo) {
1385         synchronized (mLock) {
1386             killAppOnSandboxDeathIfNeededLocked(callingInfo);
1387             handleSandboxLifecycleCallbacksLocked(callingInfo);
1388             mSandboxBindingCallbacks.remove(callingInfo);
1389             mServiceProvider.onSandboxDeath(callingInfo);
1390             // All SDK state is lost on death.
1391             if (mLoadSdkSessions.containsKey(callingInfo)) {
1392                 ArrayList<LoadSdkSession> loadSessions =
1393                         new ArrayList<>(mLoadSdkSessions.get(callingInfo).values());
1394                 for (int i = 0; i < loadSessions.size(); i++) {
1395                     LoadSdkSession loadSdkSession = loadSessions.get(i);
1396                     loadSdkSession.onSandboxDeath();
1397                 }
1398                 mLoadSdkSessions.remove(callingInfo);
1399             }
1400         }
1401     }
1402 
1403     @GuardedBy("mLock")
1404     private void killAppOnSandboxDeathIfNeededLocked(CallingInfo callingInfo) {
1405         if (!SdkLevel.isAtLeastU()
1406                 || !mCallingInfosWithDeathRecipients.containsKey(callingInfo)
1407                 || mSandboxLifecycleCallbacks.containsKey(callingInfo)
1408                 || getLoadedSdksForApp(callingInfo).size() == 0) {
1409             /* The app should not be killed in any one of the following cases:
1410                1) The SDK level is not U+ (as app kill API is not supported in that case).
1411                2) The app is already dead.
1412                3) The app has registered at least one callback to deal with sandbox death.
1413                4) The app has no SDKs loaded.
1414             */
1415             return;
1416         }
1417 
1418         // TODO(b/261442377): Only the processes that loaded some SDK should be killed. For now,
1419         // kill the process that loaded the first SDK.
1420         mActivityManagerLocal.killSdkSandboxClientAppProcess(callingInfo.getAppProcessToken());
1421     }
1422 
1423     @GuardedBy("mLock")
1424     private void handleSandboxLifecycleCallbacksLocked(CallingInfo callingInfo) {
1425         RemoteCallbackList<ISdkSandboxProcessDeathCallback> sandboxLifecycleCallbacks;
1426         sandboxLifecycleCallbacks = mSandboxLifecycleCallbacks.get(callingInfo);
1427 
1428         if (sandboxLifecycleCallbacks == null) {
1429             return;
1430         }
1431 
1432         int size = sandboxLifecycleCallbacks.beginBroadcast();
1433         for (int i = 0; i < size; ++i) {
1434             try {
1435                 sandboxLifecycleCallbacks.getBroadcastItem(i).onSdkSandboxDied();
1436             } catch (RemoteException e) {
1437                 Log.w(TAG, "Unable to send sdk sandbox death event to app", e);
1438             }
1439         }
1440         sandboxLifecycleCallbacks.finishBroadcast();
1441     }
1442 
1443     @Override
1444     public void stopSdkSandbox(String callingPackageName) {
1445         final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName);
1446 
1447         mContext.enforceCallingPermission(
1448                 STOP_SDK_SANDBOX_PERMISSION,
1449                 callingPackageName + " does not have permission to stop their sandbox");
1450 
1451         final long token = Binder.clearCallingIdentity();
1452         try {
1453             stopSdkSandboxService(callingInfo, "App requesting sandbox kill");
1454         } finally {
1455             Binder.restoreCallingIdentity(token);
1456         }
1457     }
1458 
1459     @Override
1460     public IBinder getAdServicesManager() {
1461         synchronized (mLock) {
1462             return mAdServicesManager;
1463         }
1464     }
1465 
1466     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1467     void registerAdServicesManagerService(IBinder iBinder, boolean published) {
1468         Log.d(TAG, "registerAdServicesManagerService(): published=" + published);
1469         synchronized (mLock) {
1470             mAdServicesManager = iBinder;
1471             mAdServicesManagerPublished = published;
1472         }
1473     }
1474 
1475     boolean isSdkSandboxDisabled(ISdkSandboxService boundService) {
1476         synchronized (mLock) {
1477             if (!mCheckedVisibilityPatch) {
1478                 SdkSandboxDisabledCallback callback = new SdkSandboxDisabledCallback();
1479                 try {
1480                     boundService.isDisabled(callback);
1481                     boolean isDisabled = callback.getIsDisabled();
1482                     mCheckedVisibilityPatch = true;
1483                     mHasVisibilityPatch = !isDisabled;
1484                 } catch (Exception e) {
1485                     Log.w(TAG, "Could not verify SDK sandbox state", e);
1486                     return true;
1487                 }
1488             }
1489 
1490             // Disable immediately if visibility patch is missing
1491             if (!mHasVisibilityPatch) {
1492                 return true;
1493             }
1494 
1495             // Ignore killswitch if the device is an emulator
1496             if (mInjector.isEmulator()) {
1497                 return false;
1498             }
1499 
1500             return getSdkSandboxSettingsListener().isKillSwitchEnabled();
1501         }
1502     }
1503 
1504     /**
1505      * Clears the SDK sandbox state. This will result in the state being checked again the next time
1506      * an SDK is loaded.
1507      */
1508     void clearSdkSandboxState() {
1509         synchronized (mLock) {
1510             mCheckedVisibilityPatch = DEFAULT_VALUE_VISIBILITY_PATCH_CHECKED;
1511             getSdkSandboxSettingsListener().setKillSwitchState(DEFAULT_VALUE_DISABLE_SDK_SANDBOX);
1512         }
1513     }
1514 
1515     /**
1516      * Enables the sandbox for testing purposes. Note that the sandbox can still be disabled by
1517      * setting the killswitch.
1518      */
1519     void forceEnableSandbox() {
1520         synchronized (mLock) {
1521             mCheckedVisibilityPatch = true;
1522             mHasVisibilityPatch = true;
1523             getSdkSandboxSettingsListener().setKillSwitchState(false);
1524         }
1525     }
1526 
1527     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1528     SdkSandboxSettingsListener getSdkSandboxSettingsListener() {
1529         synchronized (mLock) {
1530             return mSdkSandboxSettingsListener;
1531         }
1532     }
1533 
1534     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1535     void setSdkSandboxSettingsListener(SdkSandboxSettingsListener listener) {
1536         synchronized (mLock) {
1537             mSdkSandboxSettingsListener = listener;
1538         }
1539     }
1540 
1541     class SdkSandboxSettingsListener implements DeviceConfig.OnPropertiesChangedListener {
1542 
1543         private final Context mContext;
1544         private final Object mLock = new Object();
1545 
1546         @GuardedBy("mLock")
1547         private boolean mKillSwitchEnabled =
1548                 DeviceConfig.getBoolean(
1549                         DeviceConfig.NAMESPACE_ADSERVICES,
1550                         PROPERTY_DISABLE_SDK_SANDBOX,
1551                         DEFAULT_VALUE_DISABLE_SDK_SANDBOX);
1552 
1553         @GuardedBy("mLock")
1554         private boolean mEnforceBroadcastReceiverRestrictions =
1555                 DeviceConfig.getBoolean(
1556                         DeviceConfig.NAMESPACE_ADSERVICES,
1557                         PROPERTY_ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS,
1558                         DEFAULT_VALUE_ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS);
1559 
1560         @GuardedBy("mLock")
1561         private boolean mEnforceContentProviderRestrictions =
1562                 DeviceConfig.getBoolean(
1563                         DeviceConfig.NAMESPACE_ADSERVICES,
1564                         PROPERTY_ENFORCE_CONTENT_PROVIDER_RESTRICTIONS,
1565                         DEFAULT_VALUE_ENFORCE_CONTENT_PROVIDER_RESTRICTIONS);
1566 
1567         SdkSandboxSettingsListener(Context context) {
1568             mContext = context;
1569         }
1570 
1571         private void registerObserver() {
1572             DeviceConfig.addOnPropertiesChangedListener(
1573                     DeviceConfig.NAMESPACE_ADSERVICES, mContext.getMainExecutor(), this);
1574         }
1575 
1576         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1577         boolean isKillSwitchEnabled() {
1578             synchronized (mLock) {
1579                 return mKillSwitchEnabled;
1580             }
1581         }
1582 
1583         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1584         void setKillSwitchState(boolean enabled) {
1585             synchronized (mLock) {
1586                 DeviceConfig.setProperty(
1587                         DeviceConfig.NAMESPACE_ADSERVICES,
1588                         PROPERTY_DISABLE_SDK_SANDBOX,
1589                         Boolean.toString(enabled),
1590                         false);
1591                 mKillSwitchEnabled = enabled;
1592             }
1593         }
1594 
1595         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1596         void unregisterPropertiesListener() {
1597             DeviceConfig.removeOnPropertiesChangedListener(this);
1598         }
1599 
1600         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1601         boolean isCustomizedSdkContextEnabled() {
1602             // Can only be enabled on U+ devices
1603             if (!SdkLevel.isAtLeastU()) {
1604                 return false;
1605             }
1606             return DeviceConfig.getBoolean(
1607                     DeviceConfig.NAMESPACE_ADSERVICES,
1608                     PROPERTY_CUSTOMIZED_SDK_CONTEXT_ENABLED,
1609                     DEFAULT_VALUE_CUSTOMIZED_SDK_CONTEXT_ENABLED);
1610         }
1611 
1612         boolean isBroadcastReceiverRestrictionsEnforced() {
1613             synchronized (mLock) {
1614                 return mEnforceBroadcastReceiverRestrictions;
1615             }
1616         }
1617 
1618         boolean areContentProviderRestrictionsEnforced() {
1619             synchronized (mLock) {
1620                 return mEnforceContentProviderRestrictions;
1621             }
1622         }
1623 
1624         @Override
1625         public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
1626             synchronized (mLock) {
1627                 if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_ADSERVICES)) {
1628                     return;
1629                 }
1630                 for (String name : properties.getKeyset()) {
1631                     if (name == null) {
1632                         continue;
1633                     }
1634 
1635                     switch (name) {
1636                         case PROPERTY_DISABLE_SDK_SANDBOX:
1637                             boolean killSwitchPreviouslyEnabled = mKillSwitchEnabled;
1638                             mKillSwitchEnabled =
1639                                     properties.getBoolean(
1640                                             PROPERTY_DISABLE_SDK_SANDBOX,
1641                                             DEFAULT_VALUE_DISABLE_SDK_SANDBOX);
1642                             if (mKillSwitchEnabled && !killSwitchPreviouslyEnabled) {
1643                                 Log.i(TAG, "SDK sandbox killswitch has become enabled");
1644                                 synchronized (SdkSandboxManagerService.this.mLock) {
1645                                     stopAllSandboxesLocked();
1646                                 }
1647                             }
1648                             break;
1649                         case PROPERTY_ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS:
1650                             mEnforceBroadcastReceiverRestrictions =
1651                                     properties.getBoolean(
1652                                             PROPERTY_ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS,
1653                                             DEFAULT_VALUE_ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS);
1654                             break;
1655                         case PROPERTY_ENFORCE_CONTENT_PROVIDER_RESTRICTIONS:
1656                             mEnforceContentProviderRestrictions =
1657                                     properties.getBoolean(
1658                                             PROPERTY_ENFORCE_CONTENT_PROVIDER_RESTRICTIONS,
1659                                             DEFAULT_VALUE_ENFORCE_CONTENT_PROVIDER_RESTRICTIONS);
1660                             break;
1661                         default:
1662                     }
1663                 }
1664             }
1665         }
1666     }
1667 
1668     static class SdkSandboxDisabledCallback extends ISdkSandboxDisabledCallback.Stub {
1669         CountDownLatch mLatch;
1670         boolean mIsDisabled = false;
1671 
1672         SdkSandboxDisabledCallback() {
1673             mLatch = new CountDownLatch(1);
1674         }
1675 
1676         @Override
1677         public void onResult(boolean isDisabled) {
1678             mIsDisabled = isDisabled;
1679             mLatch.countDown();
1680         }
1681 
1682         boolean getIsDisabled() {
1683             try {
1684                 if (mLatch.await(1, TimeUnit.SECONDS)) {
1685                     return mIsDisabled;
1686                 }
1687                 return true;
1688             } catch (InterruptedException e) {
1689                 Log.w(TAG, "Interrupted while waiting for SDK sandbox state", e);
1690                 return true;
1691             }
1692         }
1693     }
1694 
1695     /** Stops all running sandboxes in the case that the killswitch is triggered. */
1696     @GuardedBy("mLock")
1697     private void stopAllSandboxesLocked() {
1698         for (int i = mLoadSdkSessions.size() - 1; i >= 0; --i) {
1699             stopSdkSandboxService(mLoadSdkSessions.keyAt(i), "SDK sandbox killswitch enabled");
1700         }
1701     }
1702 
1703     void stopSdkSandboxService(CallingInfo currentCallingInfo, String reason) {
1704         if (!isSdkSandboxServiceRunning(currentCallingInfo)) {
1705             Log.d(TAG, "Cannot kill sandbox for " + currentCallingInfo + ", already dead");
1706             return;
1707         }
1708 
1709         mServiceProvider.unbindService(currentCallingInfo);
1710 
1711         // For T, we kill the sandbox by uid. For U, we kill a specific sandbox process.
1712         if (SdkLevel.isAtLeastU()) {
1713             mServiceProvider.stopSandboxService(currentCallingInfo);
1714         } else {
1715             // For apps with shared uid, unbind the sandboxes for all the remaining apps since we
1716             // kill the sandbox by uid.
1717             synchronized (mLock) {
1718                 for (int i = 0; i < mCallingInfosWithDeathRecipients.size(); i++) {
1719                     final CallingInfo callingInfo = mCallingInfosWithDeathRecipients.keyAt(i);
1720                     if (callingInfo.getUid() == currentCallingInfo.getUid()) {
1721                         mServiceProvider.unbindService(callingInfo);
1722                     }
1723                 }
1724             }
1725             final int sdkSandboxUid = Process.toSdkSandboxUid(currentCallingInfo.getUid());
1726             Log.i(TAG, "Killing sdk sandbox/s with uid " + sdkSandboxUid);
1727             mActivityManager.killUid(sdkSandboxUid, reason);
1728         }
1729     }
1730 
1731     boolean isSdkSandboxServiceRunning(CallingInfo callingInfo) {
1732         int sandboxStatus = mServiceProvider.getSandboxStatusForApp(callingInfo);
1733         return sandboxStatus == SdkSandboxServiceProvider.CREATED
1734                 || sandboxStatus == SdkSandboxServiceProvider.CREATE_PENDING;
1735     }
1736 
1737     @WorkerThread
1738     private void computeSdkStorage(CallingInfo callingInfo, ISdkSandboxService service) {
1739         final List<StorageDirInfo> sharedStorageDirsInfo =
1740                 mSdkSandboxStorageManager.getInternalStorageDirInfo(callingInfo);
1741         final List<StorageDirInfo> sdkStorageDirsInfo =
1742                 mSdkSandboxStorageManager.getSdkStorageDirInfo(callingInfo);
1743 
1744         try {
1745             service.computeSdkStorage(
1746                     getListOfStoragePaths(sharedStorageDirsInfo),
1747                     getListOfStoragePaths(sdkStorageDirsInfo),
1748                     new IComputeSdkStorageCallback.Stub() {
1749                         @Override
1750                         public void onStorageInfoComputed(int sharedStorageKb, int sdkStorageKb) {
1751                             mSdkSandboxPulledAtoms.logStorage(
1752                                     callingInfo.getUid(), sharedStorageKb, sdkStorageKb);
1753                         }
1754                     });
1755         } catch (RemoteException e) {
1756             Log.e(TAG, "Error while computing sdk storage for CallingInfo: " + callingInfo);
1757         }
1758     }
1759 
1760     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1761     List<String> getListOfStoragePaths(List<StorageDirInfo> storageDirInfos) {
1762         final List<String> paths = new ArrayList<>();
1763 
1764         for (int i = 0; i < storageDirInfos.size(); i++) {
1765             paths.add(storageDirInfos.get(i).getCeDataDir());
1766             paths.add(storageDirInfos.get(i).getDeDataDir());
1767         }
1768         return paths;
1769     }
1770 
1771     private void notifySyncManagerSandboxStarted(CallingInfo callingInfo) {
1772         ISharedPreferencesSyncCallback syncManagerCallback = null;
1773         synchronized (mLock) {
1774             syncManagerCallback = mSyncDataCallbacks.get(callingInfo);
1775             if (syncManagerCallback != null) {
1776                 try {
1777                     syncManagerCallback.onSandboxStart();
1778                 } catch (RemoteException ignore) {
1779                     // App died.
1780                 }
1781             }
1782             mSyncDataCallbacks.remove(callingInfo);
1783         }
1784     }
1785 
1786     private void loadSdkForService(
1787             LoadSdkSession loadSdkSession,
1788             int timeToLoadSandbox,
1789             long timeSystemServerReceivedCallFromApp,
1790             ISdkSandboxService service) {
1791         CallingInfo callingInfo = loadSdkSession.mCallingInfo;
1792 
1793         if (isSdkSandboxDisabled(service)) {
1794             Log.e(TAG, "SDK cannot be loaded because SDK sandbox is disabled");
1795             loadSdkSession.handleLoadFailure(
1796                     new LoadSdkException(LOAD_SDK_SDK_SANDBOX_DISABLED, SANDBOX_DISABLED_MSG),
1797                     -1,
1798                     SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__METHOD_UNSPECIFIED,
1799                     false);
1800             return;
1801         }
1802         // Gather sdk storage information
1803         final StorageDirInfo sdkDataInfo =
1804                 mSdkSandboxStorageManager.getSdkStorageDirInfo(
1805                         callingInfo, loadSdkSession.mSdkProviderInfo.getSdkInfo().getName());
1806 
1807         final long timeSystemServerCalledSandbox = mInjector.getCurrentTime();
1808         int latencySystemServerAppToSandbox =
1809                 (int) (timeSystemServerCalledSandbox - timeSystemServerReceivedCallFromApp);
1810         if (timeToLoadSandbox != -1) {
1811             latencySystemServerAppToSandbox -= timeToLoadSandbox;
1812         }
1813 
1814         SdkSandboxStatsLog.write(
1815                 SdkSandboxStatsLog.SANDBOX_API_CALLED,
1816                 SdkSandboxStatsLog.SANDBOX_API_CALLED__METHOD__LOAD_SDK,
1817                 latencySystemServerAppToSandbox,
1818                 /*success=*/ true,
1819                 SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_APP_TO_SANDBOX,
1820                 callingInfo.getUid());
1821 
1822         loadSdkSession.load(
1823                 service,
1824                 sdkDataInfo.getCeDataDir(),
1825                 sdkDataInfo.getDeDataDir(),
1826                 timeSystemServerCalledSandbox,
1827                 timeSystemServerReceivedCallFromApp);
1828     }
1829 
1830     private void failStartOrBindService(Intent intent) {
1831         throw new SecurityException(
1832                 "SDK sandbox uid may not bind to or start to this service: " + intent.toString());
1833     }
1834 
1835     private void enforceAllowedToStartOrBindService(Intent intent) {
1836         ComponentName component = intent.getComponent();
1837         if (component == null) {
1838             failStartOrBindService(intent);
1839         }
1840         String componentPackageName = component.getPackageName();
1841         if (componentPackageName == null) {
1842             failStartOrBindService(intent);
1843         }
1844         if (componentPackageName.equals(WebViewUpdateService.getCurrentWebViewPackageName())
1845                 || componentPackageName.equals(getAdServicesPackageName())) {
1846             return;
1847         }
1848 
1849         // Default disallow.
1850         failStartOrBindService(intent);
1851     }
1852 
1853     @Override
1854     public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
1855             ParcelFileDescriptor err, String[] args) {
1856         return mInjector
1857                 .createShellCommand(this, mContext)
1858                 .exec(
1859                         this,
1860                         in.getFileDescriptor(),
1861                         out.getFileDescriptor(),
1862                         err.getFileDescriptor(),
1863                         args);
1864     }
1865 
1866     private String resolveAdServicesPackage() {
1867         PackageManager pm = mContext.getPackageManager();
1868         Intent serviceIntent = new Intent(AdServicesCommon.ACTION_TOPICS_SERVICE);
1869         List<ResolveInfo> resolveInfos =
1870                 pm.queryIntentServicesAsUser(
1871                         serviceIntent,
1872                         PackageManager.GET_SERVICES
1873                                 | PackageManager.MATCH_SYSTEM_ONLY
1874                                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
1875                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1876                         UserHandle.SYSTEM);
1877         final ServiceInfo serviceInfo =
1878                 AdServicesCommon.resolveAdServicesService(resolveInfos, serviceIntent.getAction());
1879         if (serviceInfo != null) {
1880             return serviceInfo.packageName;
1881         }
1882         return null;
1883     }
1884 
1885     @VisibleForTesting
1886     String getAdServicesPackageName() {
1887         return mAdServicesPackageName;
1888     }
1889 
1890     /**
1891      * A callback object to establish a link between the sdk in sandbox calling into manager
1892      * service.
1893      *
1894      * <p>When a sandbox is initialized, a callback object of {@link SdkToServiceLink} is passed to
1895      * be used as a part of {@link SdkSandboxController}. The Controller can then can call APIs on
1896      * the link object to get data from the manager service.
1897      */
1898     // TODO(b/268043836): Move SdkToServiceLink out of SdkSandboxManagerService
1899     private class SdkToServiceLink extends ISdkToServiceCallback.Stub {
1900 
1901         /**
1902          * Fetches {@link SandboxedSdk} for all SDKs that are loaded in the sandbox.
1903          *
1904          * <p>This provides the information on the library that is currently loaded in the sandbox
1905          * and also channels to communicate with loaded SDK.
1906          *
1907          * @param clientPackageName package name of the app for which the sdk was loaded in the
1908          *     sandbox
1909          * @return List of {@link SandboxedSdk} containing all currently loaded sdks
1910          */
1911         @Override
1912         public List<SandboxedSdk> getSandboxedSdks(String clientPackageName)
1913                 throws RemoteException {
1914             // TODO(b/258195148): Write multiuser tests
1915             // TODO(b/242039497): Add authorisation checks to make sure only the sandbox calls this
1916             //  API.
1917             int uid = Binder.getCallingUid();
1918             if (Process.isSdkSandboxUid(uid)) {
1919                 uid = Process.getAppUidForSdkSandboxUid(uid);
1920             }
1921             CallingInfo callingInfo = new CallingInfo(uid, clientPackageName);
1922             final List<SandboxedSdk> sandboxedSdks = new ArrayList<>();
1923             synchronized (mLock) {
1924                 List<LoadSdkSession> loadedSdks = getLoadedSdksForApp(callingInfo);
1925                 for (int i = 0; i < loadedSdks.size(); i++) {
1926                     LoadSdkSession sdk = loadedSdks.get(i);
1927                     SandboxedSdk sandboxedSdk = sdk.getSandboxedSdk();
1928                     if (sandboxedSdk != null) {
1929                         sandboxedSdks.add(sandboxedSdk);
1930                     } else {
1931                         Log.e(
1932                                 TAG,
1933                                 "SandboxedSdk is null for SDK "
1934                                         + sdk.mSdkName
1935                                         + " despite being loaded");
1936                     }
1937                 }
1938             }
1939             return sandboxedSdks;
1940         }
1941 
1942         @Override
1943         public void logLatenciesFromSandbox(
1944                 int latencyFromSystemServerToSandboxMillis,
1945                 int latencySandboxMillis,
1946                 int method,
1947                 boolean success) {
1948             final int appUid = Process.getAppUidForSdkSandboxUid(Binder.getCallingUid());
1949             /**
1950              * In case system server is not involved and the API call is just concerned with sandbox
1951              * process, there will be no call to system server, and we will not log that information
1952              */
1953             if (latencyFromSystemServerToSandboxMillis != -1) {
1954                 SdkSandboxStatsLog.write(
1955                         SdkSandboxStatsLog.SANDBOX_API_CALLED,
1956                         method,
1957                         latencyFromSystemServerToSandboxMillis,
1958                         success,
1959                         SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SYSTEM_SERVER_TO_SANDBOX,
1960                         appUid);
1961             }
1962             SdkSandboxStatsLog.write(
1963                     SdkSandboxStatsLog.SANDBOX_API_CALLED,
1964                     method,
1965                     latencySandboxMillis,
1966                     /*success=*/ true,
1967                     SdkSandboxStatsLog.SANDBOX_API_CALLED__STAGE__SANDBOX,
1968                     appUid);
1969         }
1970     }
1971 
1972     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
1973     SdkSandboxManagerLocal getLocalManager() {
1974         return mInjector.getLocalManager();
1975     }
1976 
1977     private void notifyInstrumentationStarted(CallingInfo callingInfo) {
1978         Log.d(TAG, "notifyInstrumentationStarted: clientApp = " + callingInfo.getPackageName()
1979                 + " clientAppUid = " + callingInfo.getUid());
1980         synchronized (mLock) {
1981             mServiceProvider.unbindService(callingInfo);
1982             int sdkSandboxUid = Process.toSdkSandboxUid(callingInfo.getUid());
1983             mActivityManager.killUid(sdkSandboxUid, "instrumentation started");
1984             mRunningInstrumentations.add(callingInfo);
1985         }
1986         // TODO(b/223386213): we need to check if there is reconcileSdkData task already enqueued
1987         //  because the instrumented client app was just installed.
1988         mSdkSandboxStorageManager.notifyInstrumentationStarted(callingInfo);
1989     }
1990 
1991     private void notifyInstrumentationFinished(CallingInfo callingInfo) {
1992         Log.d(TAG, "notifyInstrumentationFinished: clientApp = " + callingInfo.getPackageName()
1993                 + " clientAppUid = " + callingInfo.getUid());
1994         synchronized (mLock) {
1995             mRunningInstrumentations.remove(callingInfo);
1996         }
1997     }
1998 
1999     private boolean isInstrumentationRunning(CallingInfo callingInfo) {
2000         synchronized (mLock) {
2001             return mRunningInstrumentations.contains(callingInfo);
2002         }
2003     }
2004 
2005     /** @hide */
2006     public static class Lifecycle extends SystemService {
2007         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
2008         SdkSandboxManagerService mService;
2009 
2010         public Lifecycle(Context context) {
2011             super(context);
2012             mService = new SdkSandboxManagerService(getContext());
2013         }
2014 
2015         @Override
2016         public void onStart() {
2017             publishBinderService(SDK_SANDBOX_SERVICE, mService);
2018 
2019             LocalManagerRegistry.addManager(
2020                     SdkSandboxManagerLocal.class, mService.getLocalManager());
2021         }
2022 
2023         @Override
2024         public void onUserUnlocking(TargetUser user) {
2025             final int userId = user.getUserHandle().getIdentifier();
2026             mService.onUserUnlocking(userId);
2027         }
2028     }
2029 
2030     private class UidImportanceListener implements ActivityManager.OnUidImportanceListener {
2031 
2032         private static final int IMPORTANCE_CUTPOINT = IMPORTANCE_VISIBLE;
2033 
2034         public boolean isListening = false;
2035 
2036         public void startListening() {
2037             synchronized (mLock) {
2038                 if (isListening) {
2039                     return;
2040                 }
2041                 mActivityManager.addOnUidImportanceListener(this, IMPORTANCE_CUTPOINT);
2042                 isListening = true;
2043             }
2044         }
2045 
2046         public void stopListening() {
2047             synchronized (mLock) {
2048                 if (!isListening) {
2049                     return;
2050                 }
2051                 mActivityManager.removeOnUidImportanceListener(this);
2052                 isListening = false;
2053             }
2054         }
2055 
2056         @Override
2057         public void onUidImportance(int uid, int importance) {
2058             if (importance <= IMPORTANCE_CUTPOINT) {
2059                 // The lower the importance value, the more "important" the process is. We
2060                 // are only interested when the process is no longer in the foreground.
2061                 return;
2062             }
2063             if (SdkLevel.isAtLeastU()) {
2064                 // On U+, the priority of the sandbox is matched with the calling app, no need to
2065                 // unbind.
2066                 return;
2067             }
2068             synchronized (mLock) {
2069                 for (int i = 0; i < mCallingInfosWithDeathRecipients.size(); i++) {
2070                     final CallingInfo callingInfo = mCallingInfosWithDeathRecipients.keyAt(i);
2071                     if (callingInfo.getUid() == uid) {
2072                         LogUtil.d(
2073                                 TAG,
2074                                 "App with uid "
2075                                         + uid
2076                                         + " has gone to the background, unbinding sandbox");
2077                         // Unbind the sandbox when the app goes to the background to lower its
2078                         // priority.
2079                         mServiceProvider.unbindService(callingInfo);
2080                     }
2081                 }
2082             }
2083         }
2084     }
2085 
2086     // For testing as SANDBOXED_ACTIVITY_HANDLER_KEY is hidden from
2087     // SdkSandboxManagerServiceUnitTests
2088     @NonNull
2089     public String getSandboxedActivityHandlerKey() {
2090         return EXTRA_SANDBOXED_ACTIVITY_HANDLER;
2091     }
2092 
2093     private class LocalImpl implements SdkSandboxManagerLocal {
2094         @Override
2095         public void registerAdServicesManagerService(IBinder iBinder, boolean published) {
2096             SdkSandboxManagerService.this.registerAdServicesManagerService(iBinder, published);
2097         }
2098 
2099         @NonNull
2100         @Override
2101         public String getSdkSandboxProcessNameForInstrumentation(
2102                 @NonNull ApplicationInfo clientAppInfo) {
2103             return clientAppInfo.processName + "_sdk_sandbox_instr";
2104         }
2105 
2106         @Override
2107         public void notifyInstrumentationStarted(
2108                 @NonNull String clientAppPackageName, int clientAppUid) {
2109             SdkSandboxManagerService.this.notifyInstrumentationStarted(
2110                     new CallingInfo(clientAppUid, clientAppPackageName));
2111         }
2112 
2113         @Override
2114         public void notifyInstrumentationFinished(
2115                 @NonNull String clientAppPackageName, int clientAppUid) {
2116             SdkSandboxManagerService.this.notifyInstrumentationFinished(
2117                     new CallingInfo(clientAppUid, clientAppPackageName));
2118         }
2119 
2120         @Override
2121         public boolean isInstrumentationRunning(
2122                 @NonNull String clientAppPackageName, int clientAppUid) {
2123             return SdkSandboxManagerService.this.isInstrumentationRunning(
2124                     new CallingInfo(clientAppUid, clientAppPackageName));
2125         }
2126 
2127         @Override
2128         public void enforceAllowedToSendBroadcast(@NonNull Intent intent) {
2129             if (!canSendBroadcast(intent)) {
2130                 throw new SecurityException(
2131                         "Intent "
2132                                 + intent.getAction()
2133                                 + " may not be broadcast from an SDK sandbox uid");
2134             }
2135         }
2136 
2137         @Override
2138         public boolean canSendBroadcast(@NonNull Intent intent) {
2139             return false;
2140         }
2141 
2142         @Override
2143         public void enforceAllowedToStartActivity(@NonNull Intent intent) {
2144             if (intent.getAction() != null) {
2145                 if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
2146                     throw new SecurityException(
2147                             "Intent "
2148                                     + intent.getAction()
2149                                     + " may not be started from an SDK sandbox uid.");
2150                 }
2151             }
2152         }
2153 
2154         @Override
2155         public void enforceAllowedToStartOrBindService(@NonNull Intent intent) {
2156             SdkSandboxManagerService.this.enforceAllowedToStartOrBindService(intent);
2157         }
2158 
2159         @Override
2160         public boolean canAccessContentProviderFromSdkSandbox(@NonNull ProviderInfo providerInfo) {
2161             // TODO(b/229200204): Implement a starter set of restrictions
2162             if (!Process.isSdkSandboxUid(Binder.getCallingUid())) {
2163                 return true;
2164             }
2165 
2166             /**
2167              * By clearing the calling identity, system server identity is set which allows us to
2168              * call {@DeviceConfig.getBoolean}
2169              */
2170             final long token = Binder.clearCallingIdentity();
2171 
2172             try {
2173                 return !mSdkSandboxSettingsListener.areContentProviderRestrictionsEnforced();
2174             } finally {
2175                 Binder.restoreCallingIdentity(token);
2176             }
2177         }
2178 
2179         @Override
2180         public void enforceAllowedToHostSandboxedActivity(
2181                 @NonNull Intent intent, int clientAppUid, @NonNull String clientAppPackageName) {
2182             if (Process.isSdkSandboxUid(clientAppUid)) {
2183                 throw new SecurityException(
2184                         "Sandbox process is not allowed to start sandbox activities.");
2185             }
2186             if (intent == null) {
2187                 throw new SecurityException("Intent to start sandbox activity is null.");
2188             }
2189             if (intent.getAction() == null
2190                     || !intent.getAction().equals(ACTION_START_SANDBOXED_ACTIVITY)) {
2191                 throw new SecurityException(
2192                         "Sandbox activity intent must have an action ("
2193                                 + ACTION_START_SANDBOXED_ACTIVITY
2194                                 + ").");
2195             }
2196             String sandboxPackageName = mContext.getPackageManager().getSdkSandboxPackageName();
2197             if (intent.getPackage() == null || !intent.getPackage().equals(sandboxPackageName)) {
2198                 throw new SecurityException(
2199                         "Sandbox activity intent's package must be set to the sandbox package");
2200             }
2201             if (intent.getComponent() != null) {
2202                 final String componentPackageName = intent.getComponent().getPackageName();
2203                 if (!componentPackageName.equals(sandboxPackageName)) {
2204                     throw new SecurityException(
2205                             "Sandbox activity intent's component must refer to the sandbox"
2206                                     + " package");
2207                 }
2208             }
2209             final CallingInfo callingInfo = new CallingInfo(clientAppUid, clientAppPackageName);
2210             if (mServiceProvider.getSdkSandboxServiceForApp(callingInfo) == null) {
2211                 throw new SecurityException(
2212                         "There is no sandbox process running for the caller uid"
2213                                 + ": "
2214                                 + clientAppUid
2215                                 + ".");
2216             }
2217 
2218             Bundle extras = intent.getExtras();
2219             if (extras == null || extras.getBinder(getSandboxedActivityHandlerKey()) == null) {
2220                 throw new IllegalArgumentException(
2221                         "Intent should contain an extra params with key = "
2222                                 + getSandboxedActivityHandlerKey()
2223                                 + " and value is an IBinder that identifies a registered "
2224                                 + "SandboxedActivityHandler.");
2225             }
2226         }
2227 
2228         @Override
2229         // TODO(b/265647873): Add enforcement around onlyProtectedBroadcasts parameter
2230         public boolean canRegisterBroadcastReceiver(
2231                 @NonNull IntentFilter intentFilter, int flags, boolean onlyProtectedBroadcasts) {
2232             if (!Process.isSdkSandboxUid(Binder.getCallingUid())) {
2233                 return true;
2234             }
2235 
2236             if (intentFilter.countActions() == 0) {
2237                 return false;
2238             }
2239 
2240             /**
2241              * By clearing the calling identity, system server identity is set which allows us to
2242              * call {@DeviceConfig.getBoolean}
2243              */
2244             final long token = Binder.clearCallingIdentity();
2245 
2246             try {
2247                 final boolean enforceRestrictions =
2248                         mSdkSandboxSettingsListener.isBroadcastReceiverRestrictionsEnforced();
2249                 final boolean exported = (flags & Context.RECEIVER_NOT_EXPORTED) == 0;
2250                 return !enforceRestrictions || !exported;
2251             } finally {
2252                 Binder.restoreCallingIdentity(token);
2253             }
2254         }
2255     }
2256 }
2257