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.flags.Flags.sandboxActivitySdkBasedContext; 31 import static com.android.sdksandbox.service.stats.SdkSandboxStatsLog.SANDBOX_ACTIVITY_EVENT_OCCURRED__CALL_RESULT__FAILURE_SECURITY_EXCEPTION; 32 import static com.android.server.sdksandbox.SdkSandboxStorageManager.StorageDirInfo; 33 import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_SDK_SANDBOX_ORDER_ID; 34 35 import android.annotation.NonNull; 36 import android.annotation.Nullable; 37 import android.annotation.RequiresPermission; 38 import android.annotation.WorkerThread; 39 import android.app.ActivityManager; 40 import android.app.sdksandbox.AppOwnedSdkSandboxInterface; 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.IUnloadSdkCallback; 48 import android.app.sdksandbox.LoadSdkException; 49 import android.app.sdksandbox.LogUtil; 50 import android.app.sdksandbox.SandboxLatencyInfo; 51 import android.app.sdksandbox.SandboxedSdk; 52 import android.app.sdksandbox.SdkSandboxManager; 53 import android.app.sdksandbox.SharedPreferencesUpdate; 54 import android.app.sdksandbox.sandboxactivity.SdkSandboxActivityAuthority; 55 import android.app.sdksandbox.sdkprovider.SdkSandboxController; 56 import android.content.BroadcastReceiver; 57 import android.content.ComponentName; 58 import android.content.Context; 59 import android.content.Intent; 60 import android.content.IntentFilter; 61 import android.content.ServiceConnection; 62 import android.content.pm.ActivityInfo; 63 import android.content.pm.ApplicationInfo; 64 import android.content.pm.PackageManager; 65 import android.content.pm.ProviderInfo; 66 import android.content.pm.ResolveInfo; 67 import android.content.pm.ServiceInfo; 68 import android.os.Binder; 69 import android.os.Build; 70 import android.os.Bundle; 71 import android.os.Handler; 72 import android.os.HandlerThread; 73 import android.os.IBinder; 74 import android.os.ParcelFileDescriptor; 75 import android.os.Process; 76 import android.os.RemoteCallbackList; 77 import android.os.RemoteException; 78 import android.os.SystemClock; 79 import android.os.SystemProperties; 80 import android.os.UserHandle; 81 import android.provider.Settings; 82 import android.util.ArrayMap; 83 import android.util.ArraySet; 84 import android.util.Log; 85 import android.webkit.WebViewUpdateService; 86 87 import androidx.annotation.RequiresApi; 88 89 import com.android.adservices.AdServicesCommon; 90 import com.android.internal.annotations.GuardedBy; 91 import com.android.internal.annotations.VisibleForTesting; 92 import com.android.modules.utils.BackgroundThread; 93 import com.android.modules.utils.build.SdkLevel; 94 import com.android.sdksandbox.IComputeSdkStorageCallback; 95 import com.android.sdksandbox.IRequestSurfacePackageFromSdkCallback; 96 import com.android.sdksandbox.ISdkSandboxService; 97 import com.android.sdksandbox.service.stats.SdkSandboxStatsLog; 98 import com.android.server.LocalManagerRegistry; 99 import com.android.server.SystemService; 100 import com.android.server.am.ActivityManagerLocal; 101 import com.android.server.pm.PackageManagerLocal; 102 import com.android.server.sdksandbox.helpers.StringHelper; 103 import com.android.server.sdksandbox.proto.Services.AllowedService; 104 import com.android.server.sdksandbox.proto.Services.AllowedServices; 105 import com.android.server.wm.ActivityInterceptorCallback; 106 import com.android.server.wm.ActivityInterceptorCallbackRegistry; 107 108 import java.io.FileDescriptor; 109 import java.io.PrintWriter; 110 import java.util.ArrayList; 111 import java.util.Arrays; 112 import java.util.List; 113 import java.util.Objects; 114 import java.util.Set; 115 116 /** 117 * Implementation of {@link SdkSandboxManager}. 118 * 119 * @hide 120 */ 121 public class SdkSandboxManagerService extends ISdkSandboxManager.Stub { 122 123 private static final String TAG = "SdkSandboxManager"; 124 125 private static final String STOP_SDK_SANDBOX_PERMISSION = 126 "com.android.app.sdksandbox.permission.STOP_SDK_SANDBOX"; 127 128 private static final String SANDBOX_NOT_AVAILABLE_MSG = "Sandbox is unavailable"; 129 private static final String SANDBOX_DISABLED_MSG = "SDK sandbox is disabled"; 130 131 private static final String DUMP_ARG_AD_SERVICES = "--AdServices"; 132 133 private final Context mContext; 134 135 private final ActivityManager mActivityManager; 136 private final ActivityManagerLocal mActivityManagerLocal; 137 private final Handler mHandler; 138 private final SdkSandboxStorageManager mSdkSandboxStorageManager; 139 private final SdkSandboxServiceProvider mServiceProvider; 140 private final SdkSandboxStatsdLogger mSdkSandboxStatsdLogger; 141 private final SdkSandboxRestrictionManager mSdkSandboxRestrictionManager; 142 143 @GuardedBy("mLock") 144 private IBinder mAdServicesManager; 145 146 // TODO(b/282239822): temporary guard to define if dump() should handle the --AdServices otpion 147 @GuardedBy("mLock") 148 private boolean mAdServicesManagerPublished; 149 150 private final Object mLock = new Object(); 151 152 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 153 154 /** 155 * For each app, keep a mapping from SDK name to it's corresponding LoadSdkSession. This can 156 * contain all SDKs that are pending load, have been loaded, unloaded etc. Therefore, it is 157 * important to filter out by the type needed. 158 */ 159 @GuardedBy("mLock") 160 private final ArrayMap<CallingInfo, ArrayMap<String, LoadSdkSession>> mLoadSdkSessions = 161 new ArrayMap<>(); 162 163 /** 164 * For each app, keep a mapping from {@link AppOwnedSdkSandboxInterface} name to its 165 * corresponding {@link AppOwnedSdkSandboxInterface}. This contains all 166 * AppOwnedSdkSandboxInterfaces that are registered. 167 */ 168 @GuardedBy("mLock") 169 private final ArrayMap<CallingInfo, ArrayMap<String, AppOwnedSdkSandboxInterface>> 170 mHeldInterfaces = new ArrayMap<>(); 171 172 @GuardedBy("mLock") 173 private final ArrayMap<CallingInfo, IBinder> mCallingInfosWithDeathRecipients = 174 new ArrayMap<>(); 175 176 @GuardedBy("mLock") 177 private final Set<CallingInfo> mRunningInstrumentations = new ArraySet<>(); 178 179 @GuardedBy("mLock") 180 private final ArrayMap<CallingInfo, RemoteCallbackList<ISdkSandboxProcessDeathCallback>> 181 mSandboxLifecycleCallbacks = new ArrayMap<>(); 182 183 // Callbacks that need to be invoked when the sandbox binding has occurred (either successfully 184 // or unsuccessfully). 185 @GuardedBy("mLock") 186 private final ArrayMap<CallingInfo, ArrayList<SandboxBindingCallback>> 187 mSandboxBindingCallbacks = new ArrayMap<>(); 188 189 @GuardedBy("mLock") 190 private final ArrayMap<CallingInfo, ISharedPreferencesSyncCallback> mSyncDataCallbacks = 191 new ArrayMap<>(); 192 193 @GuardedBy("mLock") 194 private final UidImportanceListener mUidImportanceListener = new UidImportanceListener(); 195 196 private Injector mInjector; 197 198 private final SdkSandboxPulledAtoms mSdkSandboxPulledAtoms; 199 200 private final SdkSandboxSettingsListener mSdkSandboxSettingsListener; 201 202 private static final boolean DEFAULT_VALUE_DISABLE_SDK_SANDBOX = true; 203 204 /** 205 * Property to enforce restrictions for SDK sandbox processes. If the value of this property is 206 * {@code true}, the restrictions will be enforced. 207 */ 208 static final String PROPERTY_ENFORCE_RESTRICTIONS = "sdksandbox_enforce_restrictions"; 209 210 static final boolean DEFAULT_VALUE_ENFORCE_RESTRICTIONS = true; 211 212 private static final String WEBVIEW_DEVELOPER_MODE_CONTENT_PROVIDER = 213 "DeveloperModeContentProvider"; 214 215 private static final String WEBVIEW_SAFE_MODE_CONTENT_PROVIDER = "SafeModeContentProvider"; 216 217 // If AdServices register itself as binder service, dump() will ignore the --AdServices option 218 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 219 static final String DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_AD_SERVICES_ITSELF = 220 "Don't need to dump AdServices as it's available as " + AD_SERVICES_SYSTEM_SERVICE; 221 222 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 223 static final ArraySet<String> DEFAULT_ACTIVITY_ALLOWED_ACTIONS = 224 new ArraySet<>( 225 Arrays.asList( 226 Intent.ACTION_VIEW, 227 Intent.ACTION_DIAL, 228 Intent.ACTION_EDIT, 229 Intent.ACTION_INSERT)); 230 231 static final ArraySet<String> DEFAULT_CONTENTPROVIDER_ALLOWED_AUTHORITIES = 232 new ArraySet<>( 233 Arrays.asList( 234 Settings.AUTHORITY, "com.android.textclassifier.icons", "downloads")); 235 236 static class Injector { 237 private final Context mContext; 238 private SdkSandboxManagerLocal mLocalManager; 239 private final SdkSandboxServiceProvider mServiceProvider; 240 private final @Nullable String mAdServicesPackageName; 241 private final SdkSandboxStatsdLogger mSdkSandboxStatsdLogger; 242 Injector(Context context)243 Injector(Context context) { 244 mContext = context; 245 mServiceProvider = new SdkSandboxServiceProviderImpl(mContext); 246 mAdServicesPackageName = resolveAdServicesPackage(mContext); 247 mSdkSandboxStatsdLogger = new SdkSandboxStatsdLogger(); 248 } 249 250 private static final boolean IS_EMULATOR = 251 SystemProperties.getBoolean("ro.boot.qemu", false); 252 resolveAdServicesPackage(Context context)253 private static String resolveAdServicesPackage(Context context) { 254 PackageManager pm = context.getPackageManager(); 255 Intent serviceIntent = new Intent(AdServicesCommon.ACTION_TOPICS_SERVICE); 256 List<ResolveInfo> resolveInfos = 257 pm.queryIntentServices( 258 serviceIntent, 259 PackageManager.GET_SERVICES 260 | PackageManager.MATCH_SYSTEM_ONLY 261 | PackageManager.MATCH_DIRECT_BOOT_AWARE 262 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 263 ServiceInfo serviceInfo = 264 AdServicesCommon.resolveAdServicesService( 265 resolveInfos, serviceIntent.getAction()); 266 return serviceInfo != null ? serviceInfo.packageName : null; 267 } 268 elapsedRealtime()269 long elapsedRealtime() { 270 return SystemClock.elapsedRealtime(); 271 } 272 createShellCommand( SdkSandboxManagerService service, Context context, boolean supportsAdServicesShellCmd)273 SdkSandboxShellCommand createShellCommand( 274 SdkSandboxManagerService service, 275 Context context, 276 boolean supportsAdServicesShellCmd) { 277 return new SdkSandboxShellCommand(service, context, supportsAdServicesShellCmd); 278 } 279 isEmulator()280 boolean isEmulator() { 281 return IS_EMULATOR; 282 } 283 getSdkSandboxServiceProvider()284 SdkSandboxServiceProvider getSdkSandboxServiceProvider() { 285 return mServiceProvider; 286 } 287 getSdkSandboxPulledAtoms()288 SdkSandboxPulledAtoms getSdkSandboxPulledAtoms() { 289 return new SdkSandboxPulledAtoms(); 290 } 291 getPackageManagerLocal()292 PackageManagerLocal getPackageManagerLocal() { 293 return LocalManagerRegistry.getManager(PackageManagerLocal.class); 294 } 295 getSdkSandboxStorageManager()296 SdkSandboxStorageManager getSdkSandboxStorageManager() { 297 return new SdkSandboxStorageManager(mContext, mLocalManager, getPackageManagerLocal()); 298 } 299 setLocalManager(SdkSandboxManagerLocal localManager)300 void setLocalManager(SdkSandboxManagerLocal localManager) { 301 mLocalManager = localManager; 302 } 303 getLocalManager()304 SdkSandboxManagerLocal getLocalManager() { 305 return mLocalManager; 306 } 307 getAdServicesPackageName()308 String getAdServicesPackageName() { 309 return mAdServicesPackageName; 310 } 311 isAdServiceApkPresent()312 boolean isAdServiceApkPresent() { 313 return mAdServicesPackageName != null; 314 } 315 getSdkSandboxStatsdLogger()316 SdkSandboxStatsdLogger getSdkSandboxStatsdLogger() { 317 return mSdkSandboxStatsdLogger; 318 } 319 } 320 SdkSandboxManagerService(Context context)321 SdkSandboxManagerService(Context context) { 322 this(context, new Injector(context)); 323 } 324 325 @VisibleForTesting SdkSandboxManagerService(Context context, Injector injector)326 SdkSandboxManagerService(Context context, Injector injector) { 327 mContext = context; 328 mInjector = injector; 329 mInjector.setLocalManager(new LocalImpl()); 330 mServiceProvider = mInjector.getSdkSandboxServiceProvider(); 331 mActivityManager = mContext.getSystemService(ActivityManager.class); 332 mActivityManagerLocal = LocalManagerRegistry.getManager(ActivityManagerLocal.class); 333 mSdkSandboxPulledAtoms = mInjector.getSdkSandboxPulledAtoms(); 334 mSdkSandboxStorageManager = mInjector.getSdkSandboxStorageManager(); 335 mSdkSandboxStatsdLogger = mInjector.getSdkSandboxStatsdLogger(); 336 mSdkSandboxRestrictionManager = new SdkSandboxRestrictionManager(mContext); 337 338 // Start the handler thread. 339 HandlerThread handlerThread = new HandlerThread("SdkSandboxManagerServiceHandler"); 340 handlerThread.start(); 341 mHandler = new Handler(handlerThread.getLooper()); 342 343 registerBroadcastReceivers(); 344 345 mSdkSandboxSettingsListener = new SdkSandboxSettingsListener(mContext, this); 346 mSdkSandboxPulledAtoms.initialize(mContext); 347 348 if (SdkLevel.isAtLeastU()) { 349 registerSandboxActivityInterceptor(); 350 } 351 } 352 registerBroadcastReceivers()353 private void registerBroadcastReceivers() { 354 registerPackageUpdateBroadcastReceiver(); 355 registerVerifierBroadcastReceiver(); 356 } 357 registerPackageUpdateBroadcastReceiver()358 private void registerPackageUpdateBroadcastReceiver() { 359 // Register for package addition and update 360 final IntentFilter packageAddedIntentFilter = new IntentFilter(); 361 packageAddedIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 362 packageAddedIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); 363 packageAddedIntentFilter.addDataScheme("package"); 364 BroadcastReceiver packageAddedIntentReceiver = 365 new BroadcastReceiver() { 366 @Override 367 public void onReceive(Context context, Intent intent) { 368 final String packageName = intent.getData().getSchemeSpecificPart(); 369 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 370 final CallingInfo callingInfo = new CallingInfo(uid, packageName); 371 mHandler.post( 372 () -> 373 mSdkSandboxStorageManager.onPackageAddedOrUpdated( 374 callingInfo)); 375 } 376 }; 377 mContext.registerReceiver( 378 packageAddedIntentReceiver, 379 packageAddedIntentFilter, 380 /*broadcastPermission=*/ null, 381 mHandler); 382 } 383 registerVerifierBroadcastReceiver()384 private void registerVerifierBroadcastReceiver() { 385 final IntentFilter packageNeedsVerificationIntentFilter = new IntentFilter(); 386 try { 387 packageNeedsVerificationIntentFilter.addDataType(PACKAGE_MIME_TYPE); 388 packageNeedsVerificationIntentFilter.addAction( 389 Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); 390 mContext.registerReceiverForAllUsers( 391 new SdkSandboxVerifierReceiver(), 392 packageNeedsVerificationIntentFilter, 393 /*broadcastPermission=*/ null, 394 /*scheduler=*/ null, 395 Context.RECEIVER_EXPORTED); 396 } catch (IntentFilter.MalformedMimeTypeException e) { 397 Log.e(TAG, "Could not register verifier"); 398 } 399 } 400 401 @Override getSandboxedSdks( String callingPackageName, SandboxLatencyInfo sandboxLatencyInfo)402 public List<SandboxedSdk> getSandboxedSdks( 403 String callingPackageName, SandboxLatencyInfo sandboxLatencyInfo) { 404 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 405 406 final int callingUid = Binder.getCallingUid(); 407 CallingInfo callingInfo; 408 if (Process.isSdkSandboxUid(callingUid)) { 409 callingInfo = 410 CallingInfo.fromExternal( 411 mContext, 412 Process.getAppUidForSdkSandboxUid(callingUid), 413 callingPackageName); 414 } else { 415 callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 416 } 417 418 final List<SandboxedSdk> sandboxedSdks = new ArrayList<>(); 419 synchronized (mLock) { 420 ArrayList<LoadSdkSession> loadedSdks = getLoadedSdksForApp(callingInfo); 421 for (int i = 0; i < loadedSdks.size(); i++) { 422 LoadSdkSession sdk = loadedSdks.get(i); 423 SandboxedSdk sandboxedSdk = sdk.getSandboxedSdk(); 424 if (sandboxedSdk != null) { 425 sandboxedSdks.add(sandboxedSdk); 426 } else { 427 Log.w( 428 TAG, 429 "SandboxedSdk is null for SDK " 430 + sdk.mSdkName 431 + " despite being loaded"); 432 } 433 } 434 } 435 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 436 logSandboxApiLatency(sandboxLatencyInfo); 437 return sandboxedSdks; 438 } 439 440 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) registerSandboxActivityInterceptor()441 private void registerSandboxActivityInterceptor() { 442 final ActivityInterceptorCallback mActivityInterceptorCallback = 443 new SdkSandboxInterceptorCallback(); 444 ActivityInterceptorCallbackRegistry registry = 445 ActivityInterceptorCallbackRegistry.getInstance(); 446 registry.registerActivityInterceptorCallback( 447 MAINLINE_SDK_SANDBOX_ORDER_ID, mActivityInterceptorCallback); 448 } 449 getRegisteredAppOwnedSdkSandboxInterfacesForApp( CallingInfo callingInfo)450 private ArrayList<AppOwnedSdkSandboxInterface> getRegisteredAppOwnedSdkSandboxInterfacesForApp( 451 CallingInfo callingInfo) { 452 synchronized (mLock) { 453 if (!mHeldInterfaces.containsKey(callingInfo)) { 454 return new ArrayList<>(); 455 } 456 return new ArrayList<>(mHeldInterfaces.get(callingInfo).values()); 457 } 458 } 459 getLoadedSdksForApp(CallingInfo callingInfo)460 private ArrayList<LoadSdkSession> getLoadedSdksForApp(CallingInfo callingInfo) { 461 ArrayList<LoadSdkSession> loadedSdks = new ArrayList<>(); 462 synchronized (mLock) { 463 if (mLoadSdkSessions.containsKey(callingInfo)) { 464 ArrayList<LoadSdkSession> loadSessions = 465 new ArrayList<>(mLoadSdkSessions.get(callingInfo).values()); 466 for (int i = 0; i < loadSessions.size(); i++) { 467 LoadSdkSession sdk = loadSessions.get(i); 468 if (sdk.getStatus() == LoadSdkSession.LOADED) { 469 loadedSdks.add(sdk); 470 } 471 } 472 } 473 } 474 return loadedSdks; 475 } 476 477 @Override addSdkSandboxProcessDeathCallback( String callingPackageName, SandboxLatencyInfo sandboxLatencyInfo, ISdkSandboxProcessDeathCallback callback)478 public void addSdkSandboxProcessDeathCallback( 479 String callingPackageName, 480 SandboxLatencyInfo sandboxLatencyInfo, 481 ISdkSandboxProcessDeathCallback callback) { 482 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 483 484 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 485 synchronized (mLock) { 486 if (mSandboxLifecycleCallbacks.containsKey(callingInfo)) { 487 mSandboxLifecycleCallbacks.get(callingInfo).register(callback); 488 } else { 489 RemoteCallbackList<ISdkSandboxProcessDeathCallback> sandboxLifecycleCallbacks = 490 new RemoteCallbackList<>(); 491 sandboxLifecycleCallbacks.register(callback); 492 mSandboxLifecycleCallbacks.put(callingInfo, sandboxLifecycleCallbacks); 493 } 494 } 495 496 // addSdkSandboxProcessDeathCallback() can be called without calling loadSdk(). Register for 497 // app death to make sure cleanup occurs. 498 registerForAppDeath(callingInfo, callback.asBinder()); 499 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 500 logSandboxApiLatency(sandboxLatencyInfo); 501 } 502 503 // Register a handler for app death using any binder object originating from the app. Returns 504 // true if registering the handle succeeded and false if it failed (because the app died by 505 // then). registerForAppDeath(CallingInfo callingInfo, IBinder appBinderObject)506 private boolean registerForAppDeath(CallingInfo callingInfo, IBinder appBinderObject) { 507 // Register a death recipient to clean up app related state and unbind its service after 508 // the app dies. 509 try { 510 synchronized (mLock) { 511 if (!mCallingInfosWithDeathRecipients.containsKey(callingInfo)) { 512 Log.d(TAG, "Registering " + callingInfo + " for death notification"); 513 appBinderObject.linkToDeath(() -> onAppDeath(callingInfo), 0); 514 mCallingInfosWithDeathRecipients.put(callingInfo, appBinderObject); 515 } 516 } 517 } catch (RemoteException re) { 518 // App has already died, cleanup sdk link, and unbind its service 519 onAppDeath(callingInfo); 520 return false; 521 } 522 523 return true; 524 } 525 526 @Override removeSdkSandboxProcessDeathCallback( String callingPackageName, SandboxLatencyInfo sandboxLatencyInfo, ISdkSandboxProcessDeathCallback callback)527 public void removeSdkSandboxProcessDeathCallback( 528 String callingPackageName, 529 SandboxLatencyInfo sandboxLatencyInfo, 530 ISdkSandboxProcessDeathCallback callback) { 531 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 532 533 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 534 synchronized (mLock) { 535 RemoteCallbackList<ISdkSandboxProcessDeathCallback> sandboxLifecycleCallbacks = 536 mSandboxLifecycleCallbacks.get(callingInfo); 537 if (sandboxLifecycleCallbacks != null) { 538 sandboxLifecycleCallbacks.unregister(callback); 539 } 540 } 541 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 542 logSandboxApiLatency(sandboxLatencyInfo); 543 } 544 545 @Override getAppOwnedSdkSandboxInterfaces( String callingPackageName, SandboxLatencyInfo sandboxLatencyInfo)546 public List<AppOwnedSdkSandboxInterface> getAppOwnedSdkSandboxInterfaces( 547 String callingPackageName, SandboxLatencyInfo sandboxLatencyInfo) { 548 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 549 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 550 List<AppOwnedSdkSandboxInterface> appOwnedSdkSandboxInterfaces = 551 getRegisteredAppOwnedSdkSandboxInterfacesForApp(callingInfo); 552 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 553 logSandboxApiLatency(sandboxLatencyInfo); 554 return appOwnedSdkSandboxInterfaces; 555 } 556 557 @Override registerAppOwnedSdkSandboxInterface( String callingPackageName, AppOwnedSdkSandboxInterface appOwnedSdkSandboxInterface, SandboxLatencyInfo sandboxLatencyInfo)558 public void registerAppOwnedSdkSandboxInterface( 559 String callingPackageName, 560 AppOwnedSdkSandboxInterface appOwnedSdkSandboxInterface, 561 SandboxLatencyInfo sandboxLatencyInfo) { 562 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 563 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 564 565 synchronized (mLock) { 566 if (mHeldInterfaces.containsKey(callingInfo)) { 567 if (mHeldInterfaces 568 .get(callingInfo) 569 .containsKey(appOwnedSdkSandboxInterface.getName())) { 570 throw new IllegalStateException( 571 "Already registered interface of name " 572 + appOwnedSdkSandboxInterface.getName()); 573 } 574 } 575 mHeldInterfaces.computeIfAbsent(callingInfo, k -> new ArrayMap<>()); 576 mHeldInterfaces 577 .get(callingInfo) 578 .put(appOwnedSdkSandboxInterface.getName(), appOwnedSdkSandboxInterface); 579 } 580 // registerAppOwnedSdkSandboxInterface() can be called without calling loadSdk(). Register 581 // for app death to make sure cleanup occurs. 582 boolean isRegistrationForAppDeathSuccessful = 583 registerForAppDeath(callingInfo, appOwnedSdkSandboxInterface.getInterface()); 584 585 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 586 if (!isRegistrationForAppDeathSuccessful) { 587 sandboxLatencyInfo.setSandboxStatus( 588 SandboxLatencyInfo.SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX); 589 } 590 logSandboxApiLatency(sandboxLatencyInfo); 591 } 592 593 @Override unregisterAppOwnedSdkSandboxInterface( String callingPackageName, String name, SandboxLatencyInfo sandboxLatencyInfo)594 public void unregisterAppOwnedSdkSandboxInterface( 595 String callingPackageName, String name, SandboxLatencyInfo sandboxLatencyInfo) { 596 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 597 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 598 599 synchronized (mLock) { 600 if (mHeldInterfaces.containsKey(callingInfo)) { 601 mHeldInterfaces.get(callingInfo).remove(name); 602 } 603 } 604 605 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 606 logSandboxApiLatency(sandboxLatencyInfo); 607 } 608 609 @Override loadSdk( String callingPackageName, IBinder callingAppProcessToken, String sdkName, SandboxLatencyInfo sandboxLatencyInfo, Bundle params, ILoadSdkCallback callback)610 public void loadSdk( 611 String callingPackageName, 612 IBinder callingAppProcessToken, 613 String sdkName, 614 SandboxLatencyInfo sandboxLatencyInfo, 615 Bundle params, 616 ILoadSdkCallback callback) { 617 try { 618 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 619 620 final int callingUid = Binder.getCallingUid(); 621 CallingInfo callingInfo; 622 if (Process.isSdkSandboxUid(callingUid)) { 623 callingInfo = 624 CallingInfo.fromExternal( 625 mContext, 626 Process.getAppUidForSdkSandboxUid(callingUid), 627 callingPackageName); 628 } else { 629 callingInfo = 630 CallingInfo.fromBinderWithApplicationThread( 631 mContext, callingPackageName, callingAppProcessToken); 632 } 633 enforceCallerHasNetworkAccess(callingPackageName); 634 enforceCallerOrItsSandboxRunInForeground(callingInfo); 635 synchronized (mLock) { 636 if (mRunningInstrumentations.contains(callingInfo)) { 637 throw new SecurityException( 638 "Currently running instrumentation of this sdk sandbox process"); 639 } 640 } 641 642 if (isSdkSandboxDisabled()) { 643 Log.i(TAG, "Not loading an SDK as the SDK sandbox is disabled"); 644 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 645 sandboxLatencyInfo.setSandboxStatus( 646 SandboxLatencyInfo.SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX); 647 sandboxLatencyInfo.setTimeSystemServerCalledApp(mInjector.elapsedRealtime()); 648 callback.onLoadSdkFailure( 649 new LoadSdkException(LOAD_SDK_SDK_SANDBOX_DISABLED, SANDBOX_DISABLED_MSG), 650 sandboxLatencyInfo); 651 return; 652 } 653 654 final long token = Binder.clearCallingIdentity(); 655 try { 656 loadSdkWithClearIdentity( 657 callingInfo, 658 sdkName, 659 params, 660 callback, 661 sandboxLatencyInfo); 662 } finally { 663 Binder.restoreCallingIdentity(token); 664 } 665 } catch (Throwable e) { 666 try { 667 Log.e(TAG, "Failed to load SDK " + sdkName, e); 668 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 669 sandboxLatencyInfo.setSandboxStatus( 670 SandboxLatencyInfo.SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX); 671 sandboxLatencyInfo.setTimeSystemServerCalledApp(mInjector.elapsedRealtime()); 672 callback.onLoadSdkFailure( 673 new LoadSdkException(LOAD_SDK_INTERNAL_ERROR, e.getMessage(), e), 674 sandboxLatencyInfo); 675 } catch (RemoteException ex) { 676 Log.e(TAG, "Failed to send onLoadSdkFailure", e); 677 } 678 } 679 } 680 loadSdkWithClearIdentity( CallingInfo callingInfo, String sdkName, Bundle params, ILoadSdkCallback callback, SandboxLatencyInfo sandboxLatencyInfo)681 private void loadSdkWithClearIdentity( 682 CallingInfo callingInfo, 683 String sdkName, 684 Bundle params, 685 ILoadSdkCallback callback, 686 SandboxLatencyInfo sandboxLatencyInfo) { 687 LoadSdkSession loadSdkSession; 688 689 try { 690 loadSdkSession = 691 new LoadSdkSession( 692 mContext, this, mInjector, sdkName, callingInfo, params, callback); 693 } catch (PackageManager.NameNotFoundException e) { 694 Log.w(TAG, e.getMessage(), e); 695 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 696 sandboxLatencyInfo.setSandboxStatus( 697 SandboxLatencyInfo.SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX); 698 699 LoadSdkException loadSdkException = 700 new LoadSdkException( 701 SdkSandboxManager.LOAD_SDK_NOT_FOUND, e.getMessage() + " not found"); 702 sandboxLatencyInfo.setTimeSystemServerCalledApp(mInjector.elapsedRealtime()); 703 try { 704 callback.onLoadSdkFailure(loadSdkException, sandboxLatencyInfo); 705 } catch (RemoteException remoteException) { 706 Log.w(TAG, "Failed to send onLoadSdkFailure", remoteException); 707 } 708 return; 709 } 710 711 // Ensure we are not already loading this sdk. That's determined by checking if we already 712 // have a completed LoadSdkSession with the same SDK name for the calling info. 713 synchronized (mLock) { 714 LoadSdkSession prevLoadSession = null; 715 // Get any previous load session for this SDK if exists. 716 if (mLoadSdkSessions.containsKey(callingInfo)) { 717 prevLoadSession = mLoadSdkSessions.get(callingInfo).get(sdkName); 718 } 719 720 // If there was a previous load session and the status is loaded, this new load request 721 // should fail. 722 if (prevLoadSession != null && prevLoadSession.getStatus() == LoadSdkSession.LOADED) { 723 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 724 sandboxLatencyInfo.setSandboxStatus( 725 SandboxLatencyInfo.SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX); 726 loadSdkSession.handleLoadFailure( 727 new LoadSdkException( 728 SdkSandboxManager.LOAD_SDK_ALREADY_LOADED, 729 sdkName + " has been loaded already"), 730 sandboxLatencyInfo); 731 return; 732 } 733 734 // If there was an ongoing load session for this SDK, this new load request should fail. 735 if (prevLoadSession != null 736 && prevLoadSession.getStatus() == LoadSdkSession.LOAD_PENDING) { 737 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 738 sandboxLatencyInfo.setSandboxStatus( 739 SandboxLatencyInfo.SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX); 740 loadSdkSession.handleLoadFailure( 741 new LoadSdkException( 742 SdkSandboxManager.LOAD_SDK_ALREADY_LOADED, 743 sdkName + " is currently being loaded"), 744 sandboxLatencyInfo); 745 return; 746 } 747 748 // If there was no previous load session (or there was one but its load status was 749 // unloaded or failed), it should be replaced by the new load session. 750 mLoadSdkSessions.computeIfAbsent(callingInfo, k -> new ArrayMap<>()); 751 mLoadSdkSessions.get(callingInfo).put(sdkName, loadSdkSession); 752 } 753 754 synchronized (mLock) { 755 if (!callingInfo.isCallFromSdkSandbox()) { 756 // The code is used to be able to detect app death and app foreground state. 757 // Hence, it is of no use for the call from sandbox. 758 mUidImportanceListener.startListening(); 759 if (!registerForAppDeath(callingInfo, callback.asBinder())) { 760 sandboxLatencyInfo.setTimeSystemServerCallFinished(mInjector.elapsedRealtime()); 761 sandboxLatencyInfo.setSandboxStatus( 762 SandboxLatencyInfo 763 .SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX); 764 // App has already died and there is no point in loading the SDK. 765 return; 766 } 767 } 768 } 769 770 // Callback to be invoked once the sandbox has been created; 771 SandboxBindingCallback sandboxBindingCallback = createSdkLoadCallback(loadSdkSession); 772 startSdkSandboxIfNeeded(callingInfo, sandboxBindingCallback, sandboxLatencyInfo); 773 } 774 createSdkLoadCallback(LoadSdkSession loadSdkSession)775 private SandboxBindingCallback createSdkLoadCallback(LoadSdkSession loadSdkSession) { 776 return new SandboxBindingCallback() { 777 @Override 778 public void onBindingSuccessful( 779 ISdkSandboxService service, SandboxLatencyInfo sandboxLatencyInfo) { 780 loadSdkForService(loadSdkSession, service, sandboxLatencyInfo); 781 } 782 783 @Override 784 public void onBindingFailed( 785 LoadSdkException exception, SandboxLatencyInfo sandboxLatencyInfo) { 786 sandboxLatencyInfo.setTimeSandboxLoaded(mInjector.elapsedRealtime()); 787 sandboxLatencyInfo.setSandboxStatus( 788 SandboxLatencyInfo.SANDBOX_STATUS_FAILED_AT_LOAD_SANDBOX); 789 loadSdkSession.handleLoadFailure( 790 exception, 791 sandboxLatencyInfo); 792 } 793 }; 794 } 795 796 void startSdkSandboxIfNeeded( 797 CallingInfo callingInfo, 798 SandboxBindingCallback callback, 799 SandboxLatencyInfo sandboxLatencyInfo) { 800 801 boolean isSandboxStartRequired = false; 802 synchronized (mLock) { 803 @SdkSandboxServiceProvider.SandboxStatus 804 int sandboxStatus = mServiceProvider.getSandboxStatusForApp(callingInfo); 805 806 // Check if service is already created for the app. 807 if (sandboxStatus == SdkSandboxServiceProvider.NON_EXISTENT) { 808 // We do not want to start sandbox if the call is from sandbox 809 // and sandbox is dead/non-existent since SDK loading the other 810 // SDK itself will be unloaded if sandbox dies after the loadSdk call. 811 if (callingInfo.isCallFromSdkSandbox()) { 812 return; 813 } 814 addSandboxBindingCallback(callingInfo, callback); 815 isSandboxStartRequired = true; 816 } else if (sandboxStatus == SdkSandboxServiceProvider.CREATE_PENDING) { 817 addSandboxBindingCallback(callingInfo, callback); 818 // The sandbox is in the process of being brought up. Nothing more to do here. 819 return; 820 } 821 } 822 823 if (!isSandboxStartRequired) { 824 ISdkSandboxService service = mServiceProvider.getSdkSandboxServiceForApp(callingInfo); 825 if (service == null) { 826 LoadSdkException exception = 827 new LoadSdkException( 828 SDK_SANDBOX_PROCESS_NOT_AVAILABLE, SANDBOX_NOT_AVAILABLE_MSG); 829 callback.onBindingFailed(exception, sandboxLatencyInfo); 830 } 831 callback.onBindingSuccessful(service, sandboxLatencyInfo); 832 return; 833 } 834 835 // Prepare sdk data directories before starting the sandbox. If sdk data package directory 836 // is missing, starting the sandbox process would crash as we will fail to mount data_mirror 837 // for sdk-data isolation. 838 mSdkSandboxStorageManager.prepareSdkDataOnLoad(callingInfo); 839 sandboxLatencyInfo.setTimeLoadSandboxStarted(mInjector.elapsedRealtime()); 840 mServiceProvider.bindService( 841 callingInfo, 842 new SandboxServiceConnection(mServiceProvider, callingInfo, sandboxLatencyInfo)); 843 } 844 845 private void addSandboxBindingCallback( 846 CallingInfo callingInfo, SandboxBindingCallback callback) { 847 synchronized (mLock) { 848 mSandboxBindingCallbacks.computeIfAbsent(callingInfo, k -> new ArrayList<>()); 849 mSandboxBindingCallbacks.get(callingInfo).add(callback); 850 } 851 } 852 853 @Override 854 public void unloadSdk( 855 String callingPackageName, String sdkName, SandboxLatencyInfo sandboxLatencyInfo) { 856 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 857 858 final int callingUid = Binder.getCallingUid(); 859 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 860 enforceCallerOrItsSandboxRunInForeground(callingInfo); 861 862 final long token = Binder.clearCallingIdentity(); 863 try { 864 unloadSdkWithClearIdentity(callingInfo, sdkName, sandboxLatencyInfo); 865 } finally { 866 Binder.restoreCallingIdentity(token); 867 } 868 } 869 870 private void unloadSdkWithClearIdentity( 871 CallingInfo callingInfo, String sdkName, SandboxLatencyInfo sandboxLatencyInfo) { 872 LoadSdkSession prevLoadSession = null; 873 synchronized (mLock) { 874 // TODO(b/254657226): Add a callback or return value for unloadSdk() to indicate 875 // success of unload. 876 877 // Get any previous load session for this SDK if exists. 878 if (mLoadSdkSessions.containsKey(callingInfo)) { 879 prevLoadSession = mLoadSdkSessions.get(callingInfo).get(sdkName); 880 } 881 } 882 883 // If there was no previous load session or the SDK is not loaded, there is nothing to 884 // unload. 885 if (prevLoadSession == null) { 886 // Unloading SDK that is not loaded is a no-op, return. 887 Log.w(TAG, "SDK " + sdkName + " is not loaded for " + callingInfo); 888 return; 889 } 890 891 IUnloadSdkCallback unloadSdkCallback = 892 new IUnloadSdkCallback.Stub() { 893 @Override 894 public void onUnloadSdk(SandboxLatencyInfo sandboxLatencyInfo) 895 throws RemoteException { 896 sandboxLatencyInfo.setTimeSystemServerCalledApp( 897 mInjector.elapsedRealtime()); 898 logSandboxApiLatency(sandboxLatencyInfo); 899 } 900 }; 901 prevLoadSession.unload(sandboxLatencyInfo, unloadSdkCallback); 902 903 ArrayList<LoadSdkSession> loadedSdks = getLoadedSdksForApp(callingInfo); 904 if (loadedSdks.isEmpty()) { 905 stopSdkSandboxService( 906 callingInfo, "Caller " + callingInfo + " has no remaining SDKS loaded."); 907 } 908 } 909 910 private void enforceCallingPackageBelongsToUid(CallingInfo callingInfo) { 911 int callingUid = callingInfo.getUid(); 912 String callingPackage = callingInfo.getPackageName(); 913 int packageUid; 914 PackageManager pm = mContext.createContextAsUser( 915 UserHandle.getUserHandleForUid(callingUid), 0).getPackageManager(); 916 try { 917 packageUid = pm.getPackageUid(callingPackage, 0); 918 } catch (PackageManager.NameNotFoundException e) { 919 throw new SecurityException(callingPackage + " not found"); 920 } 921 if (packageUid != callingUid) { 922 throw new SecurityException(callingPackage + " does not belong to uid " + callingUid); 923 } 924 } 925 926 private void enforceCallerOrItsSandboxRunInForeground(CallingInfo callingInfo) { 927 String callingPackage = callingInfo.getPackageName(); 928 final long token = Binder.clearCallingIdentity(); 929 try { 930 int importance = 931 Math.min( 932 mActivityManager.getUidImportance(callingInfo.getUid()), 933 mActivityManager.getUidImportance( 934 Process.toSdkSandboxUid(callingInfo.getUid()))); 935 if (importance > IMPORTANCE_FOREGROUND) { 936 throw new SecurityException(callingPackage + " does not run in the foreground"); 937 } 938 } finally { 939 Binder.restoreCallingIdentity(token); 940 } 941 } 942 943 private void enforceCallerHasNetworkAccess(String callingPackage) { 944 mContext.enforceCallingPermission(android.Manifest.permission.INTERNET, 945 callingPackage + " does not hold INTERNET permission"); 946 mContext.enforceCallingPermission(android.Manifest.permission.ACCESS_NETWORK_STATE, 947 callingPackage + " does not hold ACCESS_NETWORK_STATE permission"); 948 } 949 950 private void onAppDeath(CallingInfo callingInfo) { 951 synchronized (mLock) { 952 Log.d(TAG, "App " + callingInfo + " has died, cleaning up associated sandbox info"); 953 mSandboxLifecycleCallbacks.remove(callingInfo); 954 mSandboxBindingCallbacks.remove(callingInfo); 955 mCallingInfosWithDeathRecipients.remove(callingInfo); 956 if (mCallingInfosWithDeathRecipients.size() == 0) { 957 mUidImportanceListener.stopListening(); 958 } 959 mSyncDataCallbacks.remove(callingInfo); 960 mLoadSdkSessions.remove(callingInfo); 961 mHeldInterfaces.remove(callingInfo); 962 stopSdkSandboxService(callingInfo, "Caller " + callingInfo + " has died"); 963 mServiceProvider.onAppDeath(callingInfo); 964 } 965 } 966 967 @Override 968 public void requestSurfacePackage( 969 String callingPackageName, 970 String sdkName, 971 IBinder hostToken, 972 int displayId, 973 int width, 974 int height, 975 SandboxLatencyInfo sandboxLatencyInfo, 976 Bundle params, 977 IRequestSurfacePackageCallback callback) { 978 try { 979 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 980 981 LogUtil.d( 982 TAG, 983 "requestSurfacePackage call received. callingPackageName: " 984 + callingPackageName); 985 986 final int callingUid = Binder.getCallingUid(); 987 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 988 enforceCallerOrItsSandboxRunInForeground(callingInfo); 989 990 final long token = Binder.clearCallingIdentity(); 991 try { 992 requestSurfacePackageWithClearIdentity( 993 callingInfo, 994 sdkName, 995 hostToken, 996 displayId, 997 width, 998 height, 999 sandboxLatencyInfo, 1000 params, 1001 callback); 1002 } finally { 1003 Binder.restoreCallingIdentity(token); 1004 } 1005 } catch (Throwable e) { 1006 try { 1007 callback.onSurfacePackageError( 1008 IRequestSurfacePackageFromSdkCallback.SURFACE_PACKAGE_INTERNAL_ERROR, 1009 e.getMessage(), 1010 sandboxLatencyInfo); 1011 } catch (RemoteException ex) { 1012 Log.e(TAG, "Failed to send onRequestSurfacePackageError", e); 1013 } 1014 } 1015 } 1016 1017 private void requestSurfacePackageWithClearIdentity( 1018 CallingInfo callingInfo, 1019 String sdkName, 1020 IBinder hostToken, 1021 int displayId, 1022 int width, 1023 int height, 1024 SandboxLatencyInfo sandboxLatencyInfo, 1025 Bundle params, 1026 IRequestSurfacePackageCallback callback) { 1027 LoadSdkSession loadSdkSession = null; 1028 synchronized (mLock) { 1029 if (mLoadSdkSessions.containsKey(callingInfo)) { 1030 loadSdkSession = mLoadSdkSessions.get(callingInfo).get(sdkName); 1031 } 1032 } 1033 if (loadSdkSession == null) { 1034 LogUtil.d( 1035 TAG, 1036 callingInfo + " requested surface package, but could not find SDK " + sdkName); 1037 1038 final long timeSystemServerProcessedCall = mInjector.elapsedRealtime(); 1039 sandboxLatencyInfo.setTimeSystemServerCallFinished(timeSystemServerProcessedCall); 1040 sandboxLatencyInfo.setTimeSystemServerCalledApp(timeSystemServerProcessedCall); 1041 sandboxLatencyInfo.setSandboxStatus( 1042 SandboxLatencyInfo.SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX); 1043 1044 try { 1045 callback.onSurfacePackageError( 1046 REQUEST_SURFACE_PACKAGE_SDK_NOT_LOADED, 1047 "SDK " + sdkName + " is not loaded", 1048 sandboxLatencyInfo); 1049 } catch (RemoteException e) { 1050 Log.w(TAG, "Failed to send onSurfacePackageError", e); 1051 } 1052 return; 1053 } 1054 1055 loadSdkSession.requestSurfacePackage( 1056 hostToken, displayId, width, height, sandboxLatencyInfo, params, callback); 1057 } 1058 1059 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1060 void onUserUnlocking(int userId) { 1061 Log.i(TAG, "onUserUnlocking " + userId); 1062 // using postDelayed to wait for other volumes to mount 1063 BackgroundThread.getHandler() 1064 .postDelayed(() -> mSdkSandboxStorageManager.onUserUnlocking(userId), 20000); 1065 } 1066 1067 @Override 1068 @RequiresPermission(android.Manifest.permission.DUMP) 1069 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1070 mContext.enforceCallingPermission(android.Manifest.permission.DUMP, 1071 "Can't dump " + TAG); 1072 1073 if (args != null && args.length > 0 && args[0].equals(DUMP_ARG_AD_SERVICES)) { 1074 dumpAdServices(fd, writer, args, /* quiet= */ false); 1075 return; 1076 } 1077 1078 // TODO(b/211575098): Use IndentingPrintWriter for better formatting 1079 synchronized (mLock) { 1080 writer.println( 1081 "Killswitch enabled: " + mSdkSandboxSettingsListener.isKillSwitchEnabled()); 1082 writer.println("mLoadSdkSessions size: " + mLoadSdkSessions.size()); 1083 for (CallingInfo callingInfo : mLoadSdkSessions.keySet()) { 1084 writer.printf("Caller: %s has following SDKs", callingInfo); 1085 writer.println(); 1086 ArrayList<LoadSdkSession> loadSessions = 1087 new ArrayList<>(mLoadSdkSessions.get(callingInfo).values()); 1088 for (int i = 0; i < loadSessions.size(); i++) { 1089 LoadSdkSession sdk = loadSessions.get(i); 1090 writer.printf("SDK: %s Status: %s", sdk.mSdkName, sdk.getStatus()); 1091 writer.println(); 1092 } 1093 } 1094 writer.println(); 1095 1096 writer.println("AdServicesManager binder published: " + mAdServicesManagerPublished); 1097 } 1098 if (mInjector.isAdServiceApkPresent()) { 1099 writer.println("AdService package name: " + mInjector.getAdServicesPackageName()); 1100 } else { 1101 writer.println("AdService apk not present."); 1102 } 1103 writer.println(); 1104 1105 writer.println("mServiceProvider:"); 1106 mServiceProvider.dump(writer); 1107 writer.println(); 1108 1109 dumpAdServices(fd, writer, args, /* quiet= */ true); 1110 } 1111 1112 private void dumpAdServices( 1113 @Nullable FileDescriptor fd, PrintWriter writer, String[] args, boolean quiet) { 1114 1115 synchronized (mLock) { 1116 if (mAdServicesManagerPublished) { 1117 // AdServices registered itself as binder service 1118 if (quiet) { 1119 Log.d(TAG, DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_AD_SERVICES_ITSELF); 1120 } else { 1121 writer.println(DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_AD_SERVICES_ITSELF); 1122 } 1123 return; 1124 } 1125 } 1126 1127 writer.print("AdServices:"); 1128 IBinder adServicesManager = getAdServicesManager(); 1129 if (adServicesManager == null) { 1130 // Should not happen on "real life", but it could on unit tests. 1131 Log.e(TAG, "dumpAdServices(): mAdServicesManager not set"); 1132 writer.println(" N/A"); 1133 return; 1134 } 1135 writer.println(); 1136 writer.println(); 1137 writer.flush(); // must flush, other raw dump on fd below will be printed before it 1138 try { 1139 adServicesManager.dump(fd, args); 1140 } catch (RemoteException e) { 1141 Log.e(TAG, "Failed to dump AdServices", e); 1142 // Shouldn't happen, but it doesn't hurt to catch 1143 writer.printf("Failed to dump Adservices: %s\n", e); 1144 } 1145 writer.println(); 1146 } 1147 1148 @Override 1149 public void syncDataFromClient( 1150 String callingPackageName, 1151 SandboxLatencyInfo sandboxLatencyInfo, 1152 SharedPreferencesUpdate update, 1153 ISharedPreferencesSyncCallback callback) { 1154 try { 1155 sandboxLatencyInfo.setTimeSystemServerReceivedCallFromApp(mInjector.elapsedRealtime()); 1156 logSandboxApiLatency(sandboxLatencyInfo); 1157 1158 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 1159 enforceCallingPackageBelongsToUid(callingInfo); 1160 1161 final long token = Binder.clearCallingIdentity(); 1162 try { 1163 syncDataFromClientInternal(callingInfo, update, callback); 1164 } finally { 1165 Binder.restoreCallingIdentity(token); 1166 } 1167 } catch (Throwable e) { 1168 try { 1169 callback.onError( 1170 ISharedPreferencesSyncCallback.PREFERENCES_SYNC_INTERNAL_ERROR, 1171 e.getMessage()); 1172 } catch (RemoteException ex) { 1173 Log.e(TAG, "Failed to send ISharedPreferencesSyncCallback.onError", e); 1174 } 1175 } 1176 } 1177 1178 private void syncDataFromClientInternal( 1179 CallingInfo callingInfo, 1180 SharedPreferencesUpdate update, 1181 ISharedPreferencesSyncCallback callback) { 1182 // check first if service already bound 1183 ISdkSandboxService service = mServiceProvider.getSdkSandboxServiceForApp(callingInfo); 1184 if (service != null) { 1185 try { 1186 service.syncDataFromClient(update); 1187 } catch (RemoteException e) { 1188 syncDataOnError(callingInfo, callback, e.getMessage()); 1189 } 1190 } else { 1191 syncDataOnError(callingInfo, callback, "Sandbox not available"); 1192 } 1193 } 1194 1195 private void syncDataOnError( 1196 CallingInfo callingInfo, ISharedPreferencesSyncCallback callback, String errorMsg) { 1197 // Store reference to the callback so that we can notify SdkSandboxManager when sandbox 1198 // starts 1199 synchronized (mLock) { 1200 mSyncDataCallbacks.put(callingInfo, callback); 1201 } 1202 try { 1203 callback.onError(ISharedPreferencesSyncCallback.SANDBOX_NOT_AVAILABLE, errorMsg); 1204 } catch (RemoteException ignore) { 1205 // App died. Sync will be re-established again by app later. 1206 } 1207 } 1208 1209 @Override 1210 public void logSandboxApiLatency(SandboxLatencyInfo sandboxLatencyInfo) { 1211 mSdkSandboxStatsdLogger.logSandboxApiLatency(sandboxLatencyInfo); 1212 } 1213 1214 @Override 1215 public void logSandboxActivityApiLatency(int method, int callResult, int latencyMillis) { 1216 int clientUid = Binder.getCallingUid(); 1217 if (Process.isSdkSandboxUid(clientUid)) { 1218 clientUid = Process.getAppUidForSdkSandboxUid(clientUid); 1219 } 1220 logSandboxActivityApiLatency(method, callResult, latencyMillis, clientUid); 1221 } 1222 1223 private void logSandboxActivityApiLatency( 1224 int method, int callResult, int latencyMillis, int clientUid) { 1225 // TODO(b/321974997): log SDK package name in addition to existing data. 1226 mSdkSandboxStatsdLogger.logSandboxActivityApiLatency( 1227 method, callResult, latencyMillis, clientUid); 1228 } 1229 1230 interface SandboxBindingCallback { 1231 void onBindingSuccessful( 1232 ISdkSandboxService service, 1233 SandboxLatencyInfo sandboxLatencyInfo); 1234 1235 void onBindingFailed( 1236 LoadSdkException exception, 1237 SandboxLatencyInfo sandboxLatencyInfo); 1238 } 1239 1240 class SandboxServiceConnection implements ServiceConnection { 1241 1242 private final SdkSandboxServiceProvider mServiceProvider; 1243 private final CallingInfo mCallingInfo; 1244 private boolean mHasConnectedBefore = false; 1245 private SandboxLatencyInfo mSandboxLatencyInfo; 1246 1247 SandboxServiceConnection( 1248 SdkSandboxServiceProvider serviceProvider, 1249 CallingInfo callingInfo, 1250 SandboxLatencyInfo sandboxLatencyInfo) { 1251 mServiceProvider = serviceProvider; 1252 mCallingInfo = callingInfo; 1253 mSandboxLatencyInfo = sandboxLatencyInfo; 1254 } 1255 1256 @Override 1257 public void onServiceConnected(ComponentName name, IBinder service) { 1258 final ISdkSandboxService mService = ISdkSandboxService.Stub.asInterface(service); 1259 1260 // Perform actions needed after every sandbox restart. 1261 if (!onSandboxConnected(mService)) { 1262 // We don't need to call sandboxBindingCallback.onBindingFailed() in this case since 1263 // onSdkSandboxDeath() will take care of iterating through LoadSdkSessions and 1264 // informing SDKs about load failure. 1265 return; 1266 } 1267 1268 // Set connected service for app once all initialization has finished. This needs to be 1269 // set after every sandbox restart as well. 1270 mServiceProvider.onServiceConnected(mCallingInfo, mService); 1271 1272 // Once bound service has been set, sync manager is notified. 1273 notifySyncManagerSandboxStarted(mCallingInfo); 1274 1275 BackgroundThread.getExecutor() 1276 .execute( 1277 () -> { 1278 computeSdkStorage(mCallingInfo, mService); 1279 }); 1280 1281 mSandboxLatencyInfo.setTimeSandboxLoaded(mInjector.elapsedRealtime()); 1282 if (!mHasConnectedBefore) { 1283 mHasConnectedBefore = true; 1284 } 1285 1286 ArrayList<SandboxBindingCallback> sandboxBindingCallbacksForApp = 1287 clearAndGetSandboxBindingCallbacks(); 1288 for (int i = 0; i < sandboxBindingCallbacksForApp.size(); i++) { 1289 SandboxBindingCallback callback = sandboxBindingCallbacksForApp.get(i); 1290 callback.onBindingSuccessful(mService, mSandboxLatencyInfo); 1291 } 1292 } 1293 1294 @Override 1295 public void onServiceDisconnected(ComponentName name) { 1296 // Sdk sandbox crashed or killed, system will start it again. 1297 Log.d(TAG, "Sandbox service for " + mCallingInfo + " has been disconnected"); 1298 mServiceProvider.onServiceDisconnected(mCallingInfo); 1299 } 1300 1301 @Override 1302 public void onBindingDied(ComponentName name) { 1303 Log.d(TAG, "Sandbox service for " + mCallingInfo + " : died on binding"); 1304 // We call the lifecycle callback only after service is unbound to avoid a race 1305 // condition with a new binding, if the app immediately reloads the SDK. 1306 synchronized (mLock) { 1307 mServiceProvider.unbindService(mCallingInfo); 1308 handleSandboxLifecycleCallbacksLocked(mCallingInfo); 1309 } 1310 } 1311 1312 @Override 1313 public void onNullBinding(ComponentName name) { 1314 Log.d(TAG, "Sandbox service failed to bind for " + mCallingInfo + " : service is null"); 1315 LoadSdkException exception = 1316 new LoadSdkException( 1317 SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR, 1318 "Failed to bind the service"); 1319 ArrayList<SandboxBindingCallback> sandboxBindingCallbacksForApp = 1320 clearAndGetSandboxBindingCallbacks(); 1321 for (int i = 0; i < sandboxBindingCallbacksForApp.size(); i++) { 1322 SandboxBindingCallback callback = sandboxBindingCallbacksForApp.get(i); 1323 callback.onBindingFailed(exception, mSandboxLatencyInfo); 1324 } 1325 } 1326 1327 /** 1328 * Actions to be performed every time the sandbox connects for a particular app, such as the 1329 * first time the sandbox is brought up and every time it restarts. 1330 * 1331 * @return true if all actions were performed successfully, false otherwise. 1332 */ 1333 private boolean onSandboxConnected(ISdkSandboxService service) { 1334 Log.i( 1335 TAG, 1336 String.format( 1337 "Sdk sandbox has been bound for app package %s with uid %d", 1338 mCallingInfo.getPackageName(), mCallingInfo.getUid())); 1339 try { 1340 service.asBinder().linkToDeath(() -> onSdkSandboxDeath(mCallingInfo), 0); 1341 } catch (RemoteException e) { 1342 // Sandbox had already died, cleanup sdk links. 1343 onSdkSandboxDeath(mCallingInfo); 1344 return false; 1345 } 1346 1347 try { 1348 service.initialize(new SdkToServiceLink()); 1349 } catch (Throwable e) { 1350 handleFailedSandboxInitialization(mCallingInfo); 1351 return false; 1352 } 1353 1354 return true; 1355 } 1356 1357 private ArrayList<SandboxBindingCallback> clearAndGetSandboxBindingCallbacks() { 1358 ArrayList<SandboxBindingCallback> sandboxBindingCallbacksForApp; 1359 synchronized (mLock) { 1360 sandboxBindingCallbacksForApp = mSandboxBindingCallbacks.get(mCallingInfo); 1361 mSandboxBindingCallbacks.remove(mCallingInfo); 1362 } 1363 if (sandboxBindingCallbacksForApp == null) { 1364 sandboxBindingCallbacksForApp = new ArrayList<>(); 1365 } 1366 return sandboxBindingCallbacksForApp; 1367 } 1368 } 1369 1370 void handleFailedSandboxInitialization(CallingInfo callingInfo) { 1371 final String errorMsg = "Failed to initialize sandbox"; 1372 Log.e(TAG, errorMsg + " for " + callingInfo); 1373 // Kill the sandbox if it failed to initialize as it might not be properly usable. 1374 stopSdkSandboxService(callingInfo, errorMsg); 1375 } 1376 1377 private void onSdkSandboxDeath(CallingInfo callingInfo) { 1378 synchronized (mLock) { 1379 killAppOnSandboxDeathIfNeededLocked(callingInfo); 1380 mSandboxBindingCallbacks.remove(callingInfo); 1381 // If SDK sandbox is already unbound then we can invoke callbacks immediately, 1382 // otherwise we defer until onBindingDied is called. 1383 if (mServiceProvider.getSandboxStatusForApp(callingInfo) 1384 != SdkSandboxServiceProvider.NON_EXISTENT 1385 && !mServiceProvider.isSandboxBoundForApp(callingInfo)) { 1386 handleSandboxLifecycleCallbacksLocked(callingInfo); 1387 } 1388 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 boolean isSdkSandboxServiceRunning(String callingPackageName) { 1445 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 1446 1447 final long token = Binder.clearCallingIdentity(); 1448 try { 1449 return isSdkSandboxServiceRunning(callingInfo); 1450 } finally { 1451 Binder.restoreCallingIdentity(token); 1452 } 1453 } 1454 1455 @Override 1456 public void stopSdkSandbox(String callingPackageName) { 1457 final CallingInfo callingInfo = CallingInfo.fromBinder(mContext, callingPackageName); 1458 1459 mContext.enforceCallingPermission( 1460 STOP_SDK_SANDBOX_PERMISSION, 1461 callingPackageName + " does not have permission to stop their sandbox"); 1462 1463 final long token = Binder.clearCallingIdentity(); 1464 try { 1465 stopSdkSandboxService(callingInfo, "App requesting sandbox kill"); 1466 } finally { 1467 Binder.restoreCallingIdentity(token); 1468 } 1469 } 1470 1471 @Override 1472 public IBinder getAdServicesManager() { 1473 synchronized (mLock) { 1474 return mAdServicesManager; 1475 } 1476 } 1477 1478 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1479 void registerAdServicesManagerService(IBinder iBinder, boolean published) { 1480 Log.d(TAG, "registerAdServicesManagerService(): published=" + published); 1481 synchronized (mLock) { 1482 mAdServicesManager = iBinder; 1483 mAdServicesManagerPublished = published; 1484 } 1485 } 1486 1487 boolean isSdkSandboxDisabled() { 1488 if (!SdkLevel.isAtLeastU()) { 1489 return true; 1490 } 1491 1492 synchronized (mLock) { 1493 if (!mInjector.isAdServiceApkPresent()) { 1494 return true; 1495 } 1496 1497 // Ignore killswitch if the device is an emulator 1498 if (mInjector.isEmulator()) { 1499 return false; 1500 } 1501 1502 return getSdkSandboxSettingsListener().isKillSwitchEnabled(); 1503 } 1504 } 1505 1506 /** 1507 * Clears the SDK sandbox state. This will result in the state being checked again the next time 1508 * an SDK is loaded. 1509 */ 1510 void clearSdkSandboxState() { 1511 synchronized (mLock) { 1512 getSdkSandboxSettingsListener().setKillSwitchState(DEFAULT_VALUE_DISABLE_SDK_SANDBOX); 1513 } 1514 } 1515 1516 /** 1517 * Enables the sandbox for testing purposes. Note that the sandbox can still be disabled by 1518 * setting the killswitch. 1519 */ 1520 void forceEnableSandbox() { 1521 synchronized (mLock) { 1522 getSdkSandboxSettingsListener().setKillSwitchState(false); 1523 } 1524 } 1525 1526 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1527 SdkSandboxSettingsListener getSdkSandboxSettingsListener() { 1528 synchronized (mLock) { 1529 return mSdkSandboxSettingsListener; 1530 } 1531 } 1532 1533 void stopAllSandboxes() { 1534 synchronized (mLock) { 1535 stopAllSandboxesLocked(); 1536 } 1537 } 1538 1539 /** Stops all running sandboxes in the case that the killswitch is triggered. */ 1540 @GuardedBy("mLock") 1541 void stopAllSandboxesLocked() { 1542 for (int i = mLoadSdkSessions.size() - 1; i >= 0; --i) { 1543 stopSdkSandboxService(mLoadSdkSessions.keyAt(i), "SDK sandbox killswitch enabled"); 1544 } 1545 } 1546 1547 void stopSdkSandboxService(CallingInfo currentCallingInfo, String reason) { 1548 if (!isSdkSandboxServiceRunning(currentCallingInfo)) { 1549 Log.d(TAG, "Cannot kill sandbox for " + currentCallingInfo + ", already dead"); 1550 return; 1551 } 1552 1553 mServiceProvider.unbindService(currentCallingInfo); 1554 1555 // For T, we kill the sandbox by uid. For U, we kill a specific sandbox process. 1556 if (SdkLevel.isAtLeastU()) { 1557 mServiceProvider.stopSandboxService(currentCallingInfo); 1558 } else { 1559 // For apps with shared uid, unbind the sandboxes for all the remaining apps since we 1560 // kill the sandbox by uid. 1561 synchronized (mLock) { 1562 for (int i = 0; i < mCallingInfosWithDeathRecipients.size(); i++) { 1563 final CallingInfo callingInfo = mCallingInfosWithDeathRecipients.keyAt(i); 1564 if (callingInfo.getUid() == currentCallingInfo.getUid()) { 1565 mServiceProvider.unbindService(callingInfo); 1566 } 1567 } 1568 } 1569 final int sdkSandboxUid = Process.toSdkSandboxUid(currentCallingInfo.getUid()); 1570 Log.i(TAG, "Killing sdk sandbox/s with uid " + sdkSandboxUid); 1571 mActivityManager.killUid(sdkSandboxUid, reason); 1572 } 1573 } 1574 1575 boolean isSdkSandboxServiceRunning(CallingInfo callingInfo) { 1576 int sandboxStatus = mServiceProvider.getSandboxStatusForApp(callingInfo); 1577 return sandboxStatus == SdkSandboxServiceProvider.CREATED 1578 || sandboxStatus == SdkSandboxServiceProvider.CREATE_PENDING; 1579 } 1580 1581 @WorkerThread 1582 private void computeSdkStorage(CallingInfo callingInfo, ISdkSandboxService service) { 1583 final List<StorageDirInfo> sharedStorageDirsInfo = 1584 mSdkSandboxStorageManager.getInternalStorageDirInfo(callingInfo); 1585 final List<StorageDirInfo> sdkStorageDirsInfo = 1586 mSdkSandboxStorageManager.getSdkStorageDirInfo(callingInfo); 1587 1588 try { 1589 service.computeSdkStorage( 1590 getListOfStoragePaths(sharedStorageDirsInfo), 1591 getListOfStoragePaths(sdkStorageDirsInfo), 1592 new IComputeSdkStorageCallback.Stub() { 1593 @Override 1594 public void onStorageInfoComputed(int sharedStorageKb, int sdkStorageKb) { 1595 mSdkSandboxPulledAtoms.logStorage( 1596 callingInfo.getUid(), sharedStorageKb, sdkStorageKb); 1597 } 1598 }); 1599 } catch (RemoteException e) { 1600 Log.e(TAG, "Error while computing sdk storage for CallingInfo: " + callingInfo); 1601 } 1602 } 1603 1604 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1605 List<String> getListOfStoragePaths(List<StorageDirInfo> storageDirInfos) { 1606 final List<String> paths = new ArrayList<>(); 1607 1608 for (int i = 0; i < storageDirInfos.size(); i++) { 1609 paths.add(storageDirInfos.get(i).getCeDataDir()); 1610 paths.add(storageDirInfos.get(i).getDeDataDir()); 1611 } 1612 return paths; 1613 } 1614 1615 private void notifySyncManagerSandboxStarted(CallingInfo callingInfo) { 1616 ISharedPreferencesSyncCallback syncManagerCallback = null; 1617 synchronized (mLock) { 1618 syncManagerCallback = mSyncDataCallbacks.get(callingInfo); 1619 if (syncManagerCallback != null) { 1620 try { 1621 syncManagerCallback.onSandboxStart(); 1622 } catch (RemoteException ignore) { 1623 // App died. 1624 } 1625 } 1626 mSyncDataCallbacks.remove(callingInfo); 1627 } 1628 } 1629 1630 private void loadSdkForService( 1631 LoadSdkSession loadSdkSession, 1632 ISdkSandboxService service, 1633 SandboxLatencyInfo sandboxLatencyInfo) { 1634 CallingInfo callingInfo = loadSdkSession.mCallingInfo; 1635 // Gather sdk storage information 1636 final StorageDirInfo sdkDataInfo = 1637 mSdkSandboxStorageManager.getSdkStorageDirInfo( 1638 callingInfo, loadSdkSession.mSdkProviderInfo.getSdkInfo().getName()); 1639 1640 ApplicationInfo customizedInfo = 1641 createCustomizedApplicationInfo(loadSdkSession.getApplicationInfo(), sdkDataInfo); 1642 1643 loadSdkSession.load(service, customizedInfo, sandboxLatencyInfo); 1644 } 1645 1646 /** The customized ApplicationInfo is used to create CustomizedSdkContext for sdks. */ 1647 ApplicationInfo createCustomizedApplicationInfo( 1648 ApplicationInfo original, StorageDirInfo dirInfo) { 1649 ApplicationInfo custom = new ApplicationInfo(original); 1650 1651 // Assign per-sdk storage path as data dir 1652 custom.dataDir = dirInfo.getCeDataDir(); 1653 custom.credentialProtectedDataDir = dirInfo.getCeDataDir(); 1654 custom.deviceProtectedDataDir = dirInfo.getDeDataDir(); 1655 1656 // Package name still needs to be that of the sandbox because permissions are defined 1657 // for the sandbox app. 1658 custom.packageName = mContext.getPackageManager().getSdkSandboxPackageName(); 1659 1660 return custom; 1661 } 1662 1663 private void failStartOrBindService(Intent intent) { 1664 throw new SecurityException( 1665 "SDK sandbox uid may not bind to or start to this service: " + intent.toString()); 1666 } 1667 1668 private void enforceAllowedToStartOrBindService(Intent intent) { 1669 if (!Process.isSdkSandboxUid(Binder.getCallingUid()) 1670 || !mSdkSandboxSettingsListener.areRestrictionsEnforced()) { 1671 return; 1672 } 1673 ComponentName component = intent.getComponent(); 1674 1675 if (component != null) { 1676 String componentPackageName = component.getPackageName(); 1677 if ((componentPackageName != null) 1678 && (componentPackageName.equals( 1679 WebViewUpdateService.getCurrentWebViewPackageName()) 1680 || componentPackageName.equals(mInjector.getAdServicesPackageName()))) { 1681 return; 1682 } 1683 } 1684 1685 if (requestAllowedPerAllowlist( 1686 intent.getAction(), 1687 intent.getPackage(), 1688 /*componentClassName=*/ (component == null) ? null : component.getClassName(), 1689 /*componentPackageName=*/ (component == null) 1690 ? null 1691 : component.getPackageName())) { 1692 return; 1693 } 1694 1695 // Default disallow. 1696 failStartOrBindService(intent); 1697 } 1698 1699 @Override 1700 public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, 1701 ParcelFileDescriptor err, String[] args) { 1702 boolean supportsAdServicesShellCmd = !mAdServicesManagerPublished; 1703 return mInjector 1704 .createShellCommand(this, mContext, supportsAdServicesShellCmd) 1705 .exec( 1706 this, 1707 in.getFileDescriptor(), 1708 out.getFileDescriptor(), 1709 err.getFileDescriptor(), 1710 args); 1711 } 1712 1713 private ApplicationInfo getSdkSandboxApplicationInfoForInstrumentation( 1714 ApplicationInfo clientAppInfo, boolean isSdkInSandbox) 1715 throws PackageManager.NameNotFoundException { 1716 int uid = clientAppInfo.uid; 1717 PackageManager pm = mContext.getPackageManager(); 1718 ApplicationInfo sdkSandboxInfo = 1719 pm.getApplicationInfoAsUser( 1720 pm.getSdkSandboxPackageName(), 1721 /* flags= */ 0, 1722 UserHandle.getUserHandleForUid(uid)); 1723 ApplicationInfo sdkSandboxInfoForInstrumentation = 1724 (isSdkInSandbox) 1725 ? createCustomizedApplicationInfo( 1726 clientAppInfo, 1727 new StorageDirInfo( 1728 sdkSandboxInfo.dataDir, 1729 sdkSandboxInfo.deviceProtectedDataDir)) 1730 : sdkSandboxInfo; 1731 1732 // Required to allow adopt shell permissions in tests. 1733 sdkSandboxInfoForInstrumentation.uid = Process.toSdkSandboxUid(uid); 1734 // We want to use a predictable process name during testing. 1735 sdkSandboxInfoForInstrumentation.processName = 1736 getLocalManager().getSdkSandboxProcessNameForInstrumentation(clientAppInfo); 1737 1738 return sdkSandboxInfoForInstrumentation; 1739 } 1740 1741 /** 1742 * A callback object to establish a link between the sdk in sandbox calling into manager 1743 * service. 1744 * 1745 * <p>When a sandbox is initialized, a callback object of {@link SdkToServiceLink} is passed to 1746 * be used as a part of {@link SdkSandboxController}. The Controller can then can call APIs on 1747 * the link object to get data from the manager service. 1748 */ 1749 // TODO(b/268043836): Move SdkToServiceLink out of SdkSandboxManagerService 1750 private class SdkToServiceLink extends ISdkToServiceCallback.Stub { 1751 1752 /** 1753 * Fetches a list of {@link AppOwnedSdkSandboxInterface} registered for an app 1754 * 1755 * <p>This provides the information on the interfaces that are currently registered in the 1756 * app. 1757 * 1758 * @param clientPackageName of the client package 1759 * @return empty list if callingInfo not found in map otherwise a list of {@link 1760 * AppOwnedSdkSandboxInterface} 1761 */ 1762 @Override 1763 public List<AppOwnedSdkSandboxInterface> getAppOwnedSdkSandboxInterfaces( 1764 String clientPackageName) throws RemoteException { 1765 int uid = Binder.getCallingUid(); 1766 if (Process.isSdkSandboxUid(uid)) { 1767 uid = Process.getAppUidForSdkSandboxUid(uid); 1768 } 1769 CallingInfo callingInfo = new CallingInfo(uid, clientPackageName); 1770 return getRegisteredAppOwnedSdkSandboxInterfacesForApp(callingInfo); 1771 } 1772 1773 /** 1774 * Fetches {@link SandboxedSdk} for all SDKs that are loaded in the sandbox. 1775 * 1776 * <p>This provides the information on the library that is currently loaded in the sandbox 1777 * and also channels to communicate with loaded SDK. 1778 * 1779 * @param clientPackageName package name of the app for which the sdk was loaded in the 1780 * sandbox 1781 * @param sandboxLatencyInfo object containing the information of latency metrics for the 1782 * api 1783 * @return List of {@link SandboxedSdk} containing all currently loaded sdks 1784 */ 1785 @Override 1786 public List<SandboxedSdk> getSandboxedSdks( 1787 String clientPackageName, SandboxLatencyInfo sandboxLatencyInfo) 1788 throws RemoteException { 1789 // TODO(b/258195148): Write multiuser tests 1790 // TODO(b/242039497): Add authorisation checks to make sure only the sandbox calls this 1791 // API. 1792 return SdkSandboxManagerService.this.getSandboxedSdks( 1793 clientPackageName, sandboxLatencyInfo); 1794 } 1795 1796 @Override 1797 public void loadSdk( 1798 String callingPackageName, 1799 String sdkName, 1800 SandboxLatencyInfo sandboxLatencyInfo, 1801 Bundle params, 1802 ILoadSdkCallback callback) 1803 throws RemoteException { 1804 // The process token is only used to kill the app process when the 1805 // sandbox dies (for U+, not available on T), so a sandbox process token 1806 // is not needed here. This is taken care of when the first SDK is loaded 1807 // by the app. 1808 SdkSandboxManagerService.this.loadSdk( 1809 callingPackageName, 1810 /*callingAppProcessToken=*/ null, 1811 sdkName, 1812 sandboxLatencyInfo, 1813 params, 1814 callback); 1815 } 1816 1817 @Override 1818 public void logLatenciesFromSandbox(SandboxLatencyInfo sandboxLatencyInfo) { 1819 logSandboxApiLatency(sandboxLatencyInfo); 1820 } 1821 1822 @Override 1823 public void logSandboxActivityApiLatencyFromSandbox( 1824 int method, int callResult, int latencyMillis) { 1825 SdkSandboxManagerService.this.logSandboxActivityApiLatency( 1826 method, callResult, latencyMillis); 1827 } 1828 } 1829 1830 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 1831 SdkSandboxManagerLocal getLocalManager() { 1832 return mInjector.getLocalManager(); 1833 } 1834 1835 private void notifyInstrumentationStarted(CallingInfo callingInfo) { 1836 Log.d( 1837 TAG, 1838 "notifyInstrumentationStarted: clientApp = " 1839 + callingInfo.getPackageName() 1840 + " clientAppUid = " 1841 + callingInfo.getUid()); 1842 synchronized (mLock) { 1843 mServiceProvider.unbindService(callingInfo); 1844 int sdkSandboxUid = Process.toSdkSandboxUid(callingInfo.getUid()); 1845 mActivityManager.killUid(sdkSandboxUid, "instrumentation started"); 1846 mRunningInstrumentations.add(callingInfo); 1847 } 1848 // TODO(b/223386213): we need to check if there is reconcileSdkData task already enqueued 1849 // because the instrumented client app was just installed. 1850 mSdkSandboxStorageManager.notifyInstrumentationStarted(callingInfo); 1851 } 1852 1853 private void notifyInstrumentationFinished(CallingInfo callingInfo) { 1854 Log.d(TAG, "notifyInstrumentationFinished: clientApp = " + callingInfo.getPackageName() 1855 + " clientAppUid = " + callingInfo.getUid()); 1856 synchronized (mLock) { 1857 mRunningInstrumentations.remove(callingInfo); 1858 } 1859 } 1860 1861 private boolean isInstrumentationRunning(CallingInfo callingInfo) { 1862 synchronized (mLock) { 1863 return mRunningInstrumentations.contains(callingInfo); 1864 } 1865 } 1866 1867 private boolean isSdkSandboxAllowedToStartActivities(int pid, int uid) { 1868 return mContext.checkPermission( 1869 "android.permission.START_ACTIVITIES_FROM_SDK_SANDBOX", pid, uid) 1870 == PackageManager.PERMISSION_GRANTED; 1871 } 1872 1873 // TODO(b/300059435): remove once the {@link 1874 // SdkSandboxActivityAuthority#isSdkSandboxActivityIntent} API is stable. 1875 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1876 boolean isSdkSandboxActivity(Intent intent) { 1877 if (intent == null) { 1878 return false; 1879 } 1880 if (intent.getAction() != null 1881 && intent.getAction().equals(ACTION_START_SANDBOXED_ACTIVITY)) { 1882 return true; 1883 } 1884 final String sandboxPackageName = mContext.getPackageManager().getSdkSandboxPackageName(); 1885 if (intent.getPackage() != null && intent.getPackage().equals(sandboxPackageName)) { 1886 return true; 1887 } 1888 if (intent.getComponent() != null 1889 && intent.getComponent().getPackageName().equals(sandboxPackageName)) { 1890 return true; 1891 } 1892 return false; 1893 } 1894 1895 /** @hide */ 1896 public static class Lifecycle extends SystemService { 1897 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1898 SdkSandboxManagerService mService; 1899 1900 public Lifecycle(Context context) { 1901 super(context); 1902 mService = new SdkSandboxManagerService(getContext()); 1903 } 1904 1905 @Override 1906 public void onStart() { 1907 publishBinderService(SDK_SANDBOX_SERVICE, mService); 1908 1909 LocalManagerRegistry.addManager( 1910 SdkSandboxManagerLocal.class, mService.getLocalManager()); 1911 } 1912 1913 @Override 1914 public void onUserUnlocking(TargetUser user) { 1915 final int userId = user.getUserHandle().getIdentifier(); 1916 mService.onUserUnlocking(userId); 1917 } 1918 } 1919 1920 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1921 private class SdkSandboxInterceptorCallback implements ActivityInterceptorCallback { 1922 1923 private enum InterceptCase { 1924 SANDBOXED_ACTIVITY, 1925 INSTRUMENTATION_ACTIVITY, 1926 NO_INTERCEPT 1927 } 1928 1929 private InterceptCase shouldIntercept(ActivityInterceptorInfo info) { 1930 final Intent intent = info.getIntent(); 1931 if (intent == null) { 1932 return InterceptCase.NO_INTERCEPT; 1933 } 1934 1935 boolean isSdkSandboxActivity = 1936 (sandboxActivitySdkBasedContext()) 1937 ? SdkSandboxActivityAuthority.isSdkSandboxActivityIntent( 1938 mContext, intent) 1939 : isSdkSandboxActivity(intent); 1940 if (isSdkSandboxActivity) { 1941 final String sdkSandboxPackageName = 1942 mContext.getPackageManager().getSdkSandboxPackageName(); 1943 // Only intercept if action and package are both defined and refer to the 1944 // sandbox activity. 1945 if (intent.getPackage() == null 1946 || !intent.getPackage().equals(sdkSandboxPackageName) 1947 || intent.getAction() == null 1948 || !intent.getAction().equals(ACTION_START_SANDBOXED_ACTIVITY)) { 1949 return InterceptCase.NO_INTERCEPT; 1950 } 1951 1952 // If component is set, it should refer to the sandbox package to intercept. 1953 if (intent.getComponent() != null) { 1954 if (!intent.getComponent().getPackageName().equals(sdkSandboxPackageName)) { 1955 return InterceptCase.NO_INTERCEPT; 1956 } 1957 } 1958 return InterceptCase.SANDBOXED_ACTIVITY; 1959 } 1960 1961 if (info.getActivityInfo() == null 1962 || !Process.isSdkSandboxUid(info.getCallingUid()) 1963 || !SdkLevel.isAtLeastV()) { 1964 return InterceptCase.NO_INTERCEPT; 1965 } 1966 final ApplicationInfo applicationInfo = info.getActivityInfo().applicationInfo; 1967 synchronized (mLock) { 1968 if (applicationInfo.packageName != null 1969 && mRunningInstrumentations.contains( 1970 new CallingInfo(applicationInfo.uid, applicationInfo.packageName)) 1971 && isSdkSandboxAllowedToStartActivities( 1972 info.getCallingPid(), info.getCallingUid())) { 1973 return InterceptCase.INSTRUMENTATION_ACTIVITY; 1974 } 1975 } 1976 1977 return InterceptCase.NO_INTERCEPT; 1978 } 1979 1980 @Override 1981 public ActivityInterceptResult onInterceptActivityLaunch( 1982 @NonNull ActivityInterceptorInfo info) { 1983 final ActivityInfo activityInfo = info.getActivityInfo(); 1984 ActivityInterceptorCallback.ActivityInterceptResult activityInterceptResult = null; 1985 long timeEventStarted = mInjector.elapsedRealtime(); 1986 int callingUid = info.getCallingUid(); 1987 1988 // Do not add any lines before checking if interception should apply, this interception 1989 // happens for every single activity and adding logic might add significant performance 1990 // overhead. 1991 switch (shouldIntercept(info)) { 1992 case SANDBOXED_ACTIVITY: 1993 // Update process name and uid to match sandbox process for the calling app. 1994 activityInfo.applicationInfo.uid = Process.toSdkSandboxUid(callingUid); 1995 CallingInfo callingInfo = new CallingInfo(callingUid, info.getCallingPackage()); 1996 try { 1997 activityInfo.processName = 1998 mInjector 1999 .getSdkSandboxServiceProvider() 2000 .toSandboxProcessName(callingInfo); 2001 } catch (PackageManager.NameNotFoundException e) { 2002 SdkSandboxManagerService.this.logSandboxActivityApiLatency( 2003 SdkSandboxStatsLog 2004 .SANDBOX_ACTIVITY_EVENT_OCCURRED__METHOD__INTERCEPT_SANDBOX_ACTIVITY, 2005 SANDBOX_ACTIVITY_EVENT_OCCURRED__CALL_RESULT__FAILURE_SECURITY_EXCEPTION, 2006 (int) (mInjector.elapsedRealtime() - timeEventStarted), 2007 callingUid); 2008 Log.e( 2009 TAG, 2010 "onInterceptActivityLaunch failed for: " + callingInfo.toString(), 2011 e); 2012 throw new SecurityException(e.toString()); 2013 } 2014 activityInterceptResult = 2015 new ActivityInterceptorCallback.ActivityInterceptResult( 2016 info.getIntent(), info.getCheckedOptions(), true); 2017 SdkSandboxManagerService.this.logSandboxActivityApiLatency( 2018 SdkSandboxStatsLog 2019 .SANDBOX_ACTIVITY_EVENT_OCCURRED__METHOD__INTERCEPT_SANDBOX_ACTIVITY, 2020 SdkSandboxStatsLog 2021 .SANDBOX_ACTIVITY_EVENT_OCCURRED__CALL_RESULT__SUCCESS, 2022 (int) (mInjector.elapsedRealtime() - timeEventStarted), 2023 callingUid); 2024 break; 2025 case INSTRUMENTATION_ACTIVITY: 2026 // Tests instrumented to run in the Sandbox already use a sandbox Uid. 2027 activityInfo.applicationInfo.uid = callingUid; 2028 callingInfo = 2029 new CallingInfo(callingUid, activityInfo.applicationInfo.packageName); 2030 activityInterceptResult = 2031 new ActivityInterceptorCallback.ActivityInterceptResult( 2032 info.getIntent(), info.getCheckedOptions(), true); 2033 try { 2034 activityInfo.processName = 2035 mInjector 2036 .getSdkSandboxServiceProvider() 2037 .toSandboxProcessNameForInstrumentation(callingInfo); 2038 } catch (PackageManager.NameNotFoundException e) { 2039 Log.e( 2040 TAG, 2041 "onInterceptActivityLaunch failed for: " + callingInfo.toString(), 2042 e); 2043 throw new SecurityException(e.toString()); 2044 } 2045 break; 2046 default: // NO_INTERCEPT 2047 return null; 2048 } 2049 2050 return activityInterceptResult; 2051 } 2052 } 2053 2054 private class UidImportanceListener implements ActivityManager.OnUidImportanceListener { 2055 2056 private final int mImportanceCutpoint; 2057 2058 public boolean isListening = false; 2059 2060 UidImportanceListener() { 2061 if (SdkLevel.isAtLeastU()) { 2062 // On U+, we inform the SDK when the app has transitioned to and from foreground 2063 // importance. 2064 mImportanceCutpoint = IMPORTANCE_FOREGROUND; 2065 } else { 2066 // On T, we unbind the sandbox when the app stops being visible to the user in some 2067 // way. 2068 mImportanceCutpoint = IMPORTANCE_VISIBLE; 2069 } 2070 } 2071 2072 public void startListening() { 2073 synchronized (mLock) { 2074 if (isListening) { 2075 return; 2076 } 2077 mActivityManager.addOnUidImportanceListener(this, mImportanceCutpoint); 2078 isListening = true; 2079 } 2080 } 2081 2082 public void stopListening() { 2083 synchronized (mLock) { 2084 if (!isListening) { 2085 return; 2086 } 2087 mActivityManager.removeOnUidImportanceListener(this); 2088 isListening = false; 2089 } 2090 } 2091 2092 @Override 2093 public void onUidImportance(int uid, int importance) { 2094 synchronized (mLock) { 2095 for (int i = 0; i < mCallingInfosWithDeathRecipients.size(); i++) { 2096 final CallingInfo callingInfo = mCallingInfosWithDeathRecipients.keyAt(i); 2097 if (callingInfo.getUid() == uid) { 2098 if (SdkLevel.isAtLeastU()) { 2099 informSdksAboutAppTransition(importance, callingInfo); 2100 } else { 2101 unbindSandbox(importance, callingInfo); 2102 } 2103 } 2104 } 2105 } 2106 } 2107 2108 private void unbindSandbox(int importance, CallingInfo callingInfo) { 2109 if (importance <= mImportanceCutpoint) { 2110 // The lower the importance value, the more "important" the process is. We 2111 // are only interested when the process is no longer visible. 2112 return; 2113 } 2114 LogUtil.d( 2115 TAG, 2116 "App with uid " 2117 + callingInfo.getUid() 2118 + " is no longer visible, unbinding sandbox"); 2119 // Unbind the sandbox when the app is no longer visible to lower its priority. 2120 mServiceProvider.unbindService(callingInfo); 2121 } 2122 2123 private void informSdksAboutAppTransition(int importance, CallingInfo callingInfo) { 2124 ISdkSandboxService sandbox = mServiceProvider.getSdkSandboxServiceForApp(callingInfo); 2125 if (sandbox == null) { 2126 return; 2127 } 2128 2129 try { 2130 // Inform the sandbox when the client app uid has changed from foreground to 2131 // background importance or vice versa. 2132 sandbox.notifySdkSandboxClientImportanceChange(importance <= mImportanceCutpoint); 2133 } catch (RemoteException e) { 2134 Log.e( 2135 TAG, 2136 "Could not inform sandbox about state change of " 2137 + callingInfo 2138 + " : " 2139 + e.getMessage()); 2140 } 2141 } 2142 } 2143 2144 // For testing as SANDBOXED_ACTIVITY_HANDLER_KEY is hidden from 2145 // SdkSandboxManagerServiceUnitTests 2146 @NonNull 2147 public String getSandboxedActivityHandlerKey() { 2148 return EXTRA_SANDBOXED_ACTIVITY_HANDLER; 2149 } 2150 2151 private ArraySet<String> getContentProviderAllowlist() { 2152 String curWebViewPackageName = WebViewUpdateService.getCurrentWebViewPackageName(); 2153 ArraySet<String> contentProviderAuthoritiesAllowlist = new ArraySet<>(); 2154 // TODO(b/279557220): Make curWebViewPackageName a static variable once fixed. 2155 for (String webViewAuthority : 2156 new String[] { 2157 WEBVIEW_DEVELOPER_MODE_CONTENT_PROVIDER, WEBVIEW_SAFE_MODE_CONTENT_PROVIDER 2158 }) { 2159 contentProviderAuthoritiesAllowlist.add(curWebViewPackageName + '.' + webViewAuthority); 2160 } 2161 2162 synchronized (mLock) { 2163 if (mSdkSandboxSettingsListener.applySdkSandboxRestrictionsNext() 2164 && mSdkSandboxSettingsListener.getNextContentProviderAllowlist() != null) { 2165 contentProviderAuthoritiesAllowlist.addAll( 2166 mSdkSandboxSettingsListener.getNextContentProviderAllowlist()); 2167 return contentProviderAuthoritiesAllowlist; 2168 } 2169 2170 // TODO(b/271547387): Filter out the allowlist based on targetSdkVersion. 2171 ArraySet<String> contentProviderAllowlistForTargetSdkVersion = 2172 mSdkSandboxSettingsListener 2173 .getContentProviderAllowlistPerTargetSdkVersion() 2174 .get(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 2175 if (contentProviderAllowlistForTargetSdkVersion != null) { 2176 contentProviderAuthoritiesAllowlist.addAll( 2177 contentProviderAllowlistForTargetSdkVersion); 2178 } else { 2179 contentProviderAuthoritiesAllowlist.addAll( 2180 DEFAULT_CONTENTPROVIDER_ALLOWED_AUTHORITIES); 2181 } 2182 } 2183 return contentProviderAuthoritiesAllowlist; 2184 } 2185 2186 // Returns null if an allowlist was not set at all. 2187 @Nullable 2188 private ArraySet<String> getBroadcastReceiverAllowlist() { 2189 synchronized (mLock) { 2190 if (mSdkSandboxSettingsListener.applySdkSandboxRestrictionsNext()) { 2191 return mSdkSandboxSettingsListener.getNextBroadcastReceiverAllowlist(); 2192 } 2193 2194 ArrayMap<Integer, ArraySet<String>> broadcastReceiverAllowlist = 2195 mSdkSandboxSettingsListener.getBroadcastReceiverAllowlistPerTargetSdkVersion(); 2196 2197 if (broadcastReceiverAllowlist == null) { 2198 return null; 2199 } 2200 // TODO(b/271547387): Filter out the allowlist based on targetSdkVersion. 2201 return broadcastReceiverAllowlist.get(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 2202 } 2203 } 2204 2205 @NonNull 2206 private ArraySet<String> getActivityAllowlist() { 2207 synchronized (mLock) { 2208 if (mSdkSandboxSettingsListener.applySdkSandboxRestrictionsNext() 2209 && mSdkSandboxSettingsListener.getNextActivityAllowlist() != null) { 2210 return mSdkSandboxSettingsListener.getNextActivityAllowlist(); 2211 } 2212 return getActivityAllowlistForTargetSdk(); 2213 } 2214 } 2215 2216 @NonNull 2217 private ArraySet<String> getActivityAllowlistForTargetSdk() { 2218 synchronized (mLock) { 2219 if (mSdkSandboxSettingsListener.getActivityAllowlistPerTargetSdkVersion() == null) { 2220 return DEFAULT_ACTIVITY_ALLOWED_ACTIONS; 2221 } 2222 // TODO(b/271547387): Filter out the allowlist based on targetSdkVersion. 2223 ArraySet<String> activityAllowlistPerTargetSdkVersion = 2224 mSdkSandboxSettingsListener 2225 .getActivityAllowlistPerTargetSdkVersion() 2226 .get(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 2227 if (activityAllowlistPerTargetSdkVersion == null) { 2228 return DEFAULT_ACTIVITY_ALLOWED_ACTIONS; 2229 } 2230 return activityAllowlistPerTargetSdkVersion; 2231 } 2232 } 2233 2234 private boolean requestAllowedPerAllowlist( 2235 String action, 2236 String packageName, 2237 String componentClassName, 2238 String componentPackageName) { 2239 // TODO(b/288873117): Use effective targetSdkVersion of the sandbox for the client app. 2240 AllowedServices allowedServices = 2241 mSdkSandboxSettingsListener.applySdkSandboxRestrictionsNext() 2242 ? mSdkSandboxSettingsListener.getNextServiceAllowlist() 2243 : mSdkSandboxSettingsListener.getServiceAllowlistForTargetSdkVersion( 2244 /*targetSdkVersion=*/ 34); 2245 2246 if (Objects.isNull(allowedServices)) { 2247 return false; 2248 } 2249 2250 for (int i = 0; i < allowedServices.getAllowedServicesCount(); i++) { 2251 AllowedService allowedService = allowedServices.getAllowedServices(i); 2252 if (StringHelper.doesInputMatchWildcardPattern( 2253 allowedService.getAction(), action, /*matchOnNullInput=*/ true) 2254 && StringHelper.doesInputMatchWildcardPattern( 2255 allowedService.getPackageName(), 2256 packageName, 2257 /*matchOnNullInput=*/ true) 2258 && StringHelper.doesInputMatchWildcardPattern( 2259 allowedService.getComponentClassName(), 2260 componentClassName, 2261 /*matchOnNullInput=*/ true) 2262 && StringHelper.doesInputMatchWildcardPattern( 2263 allowedService.getComponentPackageName(), 2264 componentPackageName, 2265 /*matchOnNullInput=*/ true)) { 2266 return true; 2267 } 2268 } 2269 return false; 2270 } 2271 2272 private int getEffectiveTargetSdkVersion(int sdkSandboxUid) 2273 throws PackageManager.NameNotFoundException { 2274 return mSdkSandboxRestrictionManager.getEffectiveTargetSdkVersion( 2275 Process.getAppUidForSdkSandboxUid(sdkSandboxUid)); 2276 } 2277 2278 class LocalImpl implements SdkSandboxManagerLocal { 2279 // The following test allowlists are used to temporarily allow test components 2280 // (ContentProviders, BroadcastReceivers etc.) to be accessed during testing. This is not 2281 // combined with the existing allowlist and is checked independently. 2282 private ArraySet<String> mTestCpAllowlist = new ArraySet<>(); 2283 private ArraySet<String> mTestSendBroadcastAllowlist = new ArraySet<>(); 2284 2285 @Override 2286 public void registerAdServicesManagerService(IBinder iBinder, boolean published) { 2287 SdkSandboxManagerService.this.registerAdServicesManagerService(iBinder, published); 2288 } 2289 2290 @NonNull 2291 @Override 2292 public String getSdkSandboxProcessNameForInstrumentation( 2293 @NonNull ApplicationInfo clientAppInfo) { 2294 CallingInfo callingInfo = new CallingInfo(clientAppInfo.uid, clientAppInfo.packageName); 2295 try { 2296 return mServiceProvider.toSandboxProcessNameForInstrumentation(callingInfo); 2297 } catch (PackageManager.NameNotFoundException e) { 2298 Log.e( 2299 TAG, 2300 "getSdkSandboxProcessNameForInstrumentation failed for: " 2301 + callingInfo.toString(), 2302 e); 2303 throw new SecurityException(e.toString()); 2304 } 2305 } 2306 2307 @NonNull 2308 @Override 2309 public ApplicationInfo getSdkSandboxApplicationInfoForInstrumentation( 2310 @NonNull ApplicationInfo clientAppInfo, boolean isSdkInSandbox) 2311 throws PackageManager.NameNotFoundException { 2312 return SdkSandboxManagerService.this.getSdkSandboxApplicationInfoForInstrumentation( 2313 clientAppInfo, isSdkInSandbox); 2314 } 2315 2316 @Override 2317 public void notifyInstrumentationStarted( 2318 @NonNull String clientAppPackageName, int clientAppUid) { 2319 SdkSandboxManagerService.this.notifyInstrumentationStarted( 2320 new CallingInfo(clientAppUid, clientAppPackageName)); 2321 } 2322 2323 @Override 2324 public void notifyInstrumentationFinished( 2325 @NonNull String clientAppPackageName, int clientAppUid) { 2326 SdkSandboxManagerService.this.notifyInstrumentationFinished( 2327 new CallingInfo(clientAppUid, clientAppPackageName)); 2328 } 2329 2330 @Override 2331 public boolean isInstrumentationRunning( 2332 @NonNull String clientAppPackageName, int clientAppUid) { 2333 return SdkSandboxManagerService.this.isInstrumentationRunning( 2334 new CallingInfo(clientAppUid, clientAppPackageName)); 2335 } 2336 2337 @Override 2338 public void enforceAllowedToSendBroadcast(@NonNull Intent intent) { 2339 if (!canSendBroadcast(intent)) { 2340 throw new SecurityException( 2341 "Intent " 2342 + intent.getAction() 2343 + " may not be broadcast from an SDK sandbox uid"); 2344 } 2345 } 2346 2347 @Override 2348 public boolean canSendBroadcast(@NonNull Intent intent) { 2349 return StringHelper.doesInputMatchAnyWildcardPattern( 2350 mTestSendBroadcastAllowlist, intent.getAction()); 2351 } 2352 2353 @Override 2354 public void enforceAllowedToStartActivity(@NonNull Intent intent) { 2355 if (!Process.isSdkSandboxUid(Binder.getCallingUid()) 2356 || !mSdkSandboxSettingsListener.areRestrictionsEnforced()) { 2357 return; 2358 } 2359 2360 if (intent.getAction() == null) { 2361 return; 2362 } 2363 2364 if (StringHelper.doesInputMatchAnyWildcardPattern( 2365 getActivityAllowlist(), intent.getAction())) { 2366 return; 2367 } 2368 // During CTS-in-sandbox testing, we store the package name of the instrumented test in 2369 // the intent identifier to match it against the running instrumentations. 2370 final String instrumentationPackageName = intent.getIdentifier(); 2371 final int callingUid = Binder.getCallingUid(); 2372 final int appUid = Process.getAppUidForSdkSandboxUid(callingUid); 2373 synchronized (mLock) { 2374 if (instrumentationPackageName != null 2375 && Process.isSdkSandboxUid(callingUid) 2376 && mRunningInstrumentations.contains( 2377 new CallingInfo(appUid, instrumentationPackageName)) 2378 && isSdkSandboxAllowedToStartActivities( 2379 Binder.getCallingPid(), callingUid)) { 2380 // allow launching activities for sdk-in-sandbox instrumented tests. 2381 return; 2382 } 2383 } 2384 throw new SecurityException( 2385 "Intent " 2386 + intent.getAction() 2387 + " may not be started from an SDK sandbox uid."); 2388 } 2389 2390 @Override 2391 public void enforceAllowedToStartOrBindService(@NonNull Intent intent) { 2392 SdkSandboxManagerService.this.enforceAllowedToStartOrBindService(intent); 2393 } 2394 2395 @Override 2396 public boolean canAccessContentProviderFromSdkSandbox(@NonNull ProviderInfo providerInfo) { 2397 if (!Process.isSdkSandboxUid(Binder.getCallingUid())) { 2398 return true; 2399 } 2400 2401 /** 2402 * By clearing the calling identity, system server identity is set which allows us to 2403 * call {@DeviceConfig.getBoolean} 2404 */ 2405 long token = Binder.clearCallingIdentity(); 2406 2407 try { 2408 return !mSdkSandboxSettingsListener.areRestrictionsEnforced() 2409 || StringHelper.doesInputMatchAnyWildcardPattern( 2410 getContentProviderAllowlist(), providerInfo.authority) 2411 || StringHelper.doesInputMatchAnyWildcardPattern( 2412 mTestCpAllowlist, providerInfo.authority); 2413 } finally { 2414 Binder.restoreCallingIdentity(token); 2415 } 2416 } 2417 2418 @Override 2419 public void enforceAllowedToHostSandboxedActivity( 2420 @NonNull Intent intent, int clientAppUid, @NonNull String clientAppPackageName) { 2421 long timeEventStarted = mInjector.elapsedRealtime(); 2422 try { 2423 if (Process.isSdkSandboxUid(clientAppUid)) { 2424 throw new SecurityException( 2425 "Sandbox process is not allowed to start sandbox activities."); 2426 } 2427 if (intent == null) { 2428 throw new SecurityException("Intent to start sandbox activity is null."); 2429 } 2430 if (intent.getAction() == null 2431 || !intent.getAction().equals(ACTION_START_SANDBOXED_ACTIVITY)) { 2432 throw new SecurityException( 2433 "Sandbox activity intent must have an action (" 2434 + ACTION_START_SANDBOXED_ACTIVITY 2435 + ")."); 2436 } 2437 String sandboxPackageName = mContext.getPackageManager().getSdkSandboxPackageName(); 2438 if (intent.getPackage() == null 2439 || !intent.getPackage().equals(sandboxPackageName)) { 2440 throw new SecurityException( 2441 "Sandbox activity intent's package must be set to the sandbox package"); 2442 } 2443 if (intent.getComponent() != null) { 2444 final String componentPackageName = intent.getComponent().getPackageName(); 2445 if (!componentPackageName.equals(sandboxPackageName)) { 2446 throw new SecurityException( 2447 "Sandbox activity intent's component must refer to the sandbox" 2448 + " package"); 2449 } 2450 } 2451 } catch (SecurityException e) { 2452 logEnforceAllowedToHostSandboxedActivityLatency( 2453 SANDBOX_ACTIVITY_EVENT_OCCURRED__CALL_RESULT__FAILURE_SECURITY_EXCEPTION, 2454 timeEventStarted); 2455 throw e; 2456 } 2457 2458 final CallingInfo callingInfo = new CallingInfo(clientAppUid, clientAppPackageName); 2459 if (mServiceProvider.getSdkSandboxServiceForApp(callingInfo) == null) { 2460 logEnforceAllowedToHostSandboxedActivityLatency( 2461 SdkSandboxStatsLog 2462 .SANDBOX_ACTIVITY_EVENT_OCCURRED__CALL_RESULT__FAILURE_SECURITY_EXCEPTION_NO_SANDBOX_PROCESS, 2463 timeEventStarted); 2464 throw new SecurityException( 2465 "There is no sandbox process running for the caller uid" 2466 + ": " 2467 + clientAppUid 2468 + "."); 2469 } 2470 2471 Bundle extras = intent.getExtras(); 2472 if (extras == null || extras.getBinder(getSandboxedActivityHandlerKey()) == null) { 2473 logEnforceAllowedToHostSandboxedActivityLatency( 2474 SdkSandboxStatsLog 2475 .SANDBOX_ACTIVITY_EVENT_OCCURRED__CALL_RESULT__FAILURE_ILLEGAL_ARGUMENT_EXCEPTION, 2476 timeEventStarted); 2477 throw new IllegalArgumentException( 2478 "Intent should contain an extra params with key = " 2479 + getSandboxedActivityHandlerKey() 2480 + " and value is an IBinder that identifies a registered " 2481 + "SandboxedActivityHandler."); 2482 } 2483 2484 logEnforceAllowedToHostSandboxedActivityLatency( 2485 SdkSandboxStatsLog.SANDBOX_ACTIVITY_EVENT_OCCURRED__CALL_RESULT__SUCCESS, 2486 timeEventStarted); 2487 } 2488 2489 private void logEnforceAllowedToHostSandboxedActivityLatency( 2490 int callResult, long timeEventStarted) { 2491 SdkSandboxManagerService.this.logSandboxActivityApiLatency( 2492 SdkSandboxStatsLog 2493 .SANDBOX_ACTIVITY_EVENT_OCCURRED__METHOD__ENFORCE_ALLOWED_TO_HOST_SANDBOXED_ACTIVITY, 2494 callResult, 2495 (int) (mInjector.elapsedRealtime() - timeEventStarted)); 2496 } 2497 2498 @Override 2499 public boolean canRegisterBroadcastReceiver( 2500 @NonNull IntentFilter intentFilter, int flags, boolean onlyProtectedBroadcasts) { 2501 if (!Process.isSdkSandboxUid(Binder.getCallingUid())) { 2502 return true; 2503 } 2504 2505 int actionsCount = intentFilter.countActions(); 2506 if (actionsCount == 0) { 2507 return false; 2508 } 2509 2510 /** 2511 * By clearing the calling identity, system server identity is set which allows us to 2512 * call {@DeviceConfig.getBoolean} 2513 */ 2514 long token = Binder.clearCallingIdentity(); 2515 2516 try { 2517 if (!mSdkSandboxSettingsListener.areRestrictionsEnforced()) { 2518 return true; 2519 } 2520 2521 ArraySet<String> broadcastReceiverAllowlist = getBroadcastReceiverAllowlist(); 2522 // If an allowlist was not set at all, only allow protected broadcasts. Note that 2523 // this is different from an empty allowlist (which blocks all BroadcastReceivers). 2524 if (broadcastReceiverAllowlist == null) { 2525 return onlyProtectedBroadcasts; 2526 } 2527 2528 ArraySet<String> actions = new ArraySet<>(); 2529 for (int i = 0; i < actionsCount; ++i) { 2530 actions.add(intentFilter.getAction(i)); 2531 } 2532 2533 return broadcastReceiverAllowlist.containsAll(actions); 2534 } finally { 2535 Binder.restoreCallingIdentity(token); 2536 } 2537 } 2538 2539 @Override 2540 public int getEffectiveTargetSdkVersion(int sdkSandboxUid) 2541 throws PackageManager.NameNotFoundException { 2542 return SdkSandboxManagerService.this.getEffectiveTargetSdkVersion(sdkSandboxUid); 2543 } 2544 2545 void appendTestContentProviderAllowlist(@NonNull String[] testCpAllowlist) { 2546 mTestCpAllowlist.addAll(Arrays.asList(testCpAllowlist)); 2547 } 2548 2549 void appendTestSendBroadcastAllowlist(@NonNull String[] testSendBroadcastAllowlist) { 2550 mTestSendBroadcastAllowlist.addAll(Arrays.asList(testSendBroadcastAllowlist)); 2551 } 2552 2553 void clearTestAllowlists() { 2554 mTestCpAllowlist = new ArraySet<>(); 2555 mTestSendBroadcastAllowlist = new ArraySet<>(); 2556 } 2557 2558 ArraySet<String> getTestContentProviderAllowlist() { 2559 return mTestCpAllowlist; 2560 } 2561 2562 ArraySet<String> getTestSendBroadcastAllowlist() { 2563 return mTestSendBroadcastAllowlist; 2564 } 2565 } 2566 } 2567