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