1 /* 2 * Copyright (C) 2019 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 android.appenumeration.cts; 18 19 import static android.appenumeration.cts.Constants.ACTION_CHECK_SIGNATURES; 20 import static android.appenumeration.cts.Constants.ACTION_GET_INSTALLED_PACKAGES; 21 import static android.appenumeration.cts.Constants.ACTION_GET_NAMES_FOR_UIDS; 22 import static android.appenumeration.cts.Constants.ACTION_GET_NAME_FOR_UID; 23 import static android.appenumeration.cts.Constants.ACTION_GET_PACKAGES_FOR_UID; 24 import static android.appenumeration.cts.Constants.ACTION_GET_PACKAGE_INFO; 25 import static android.appenumeration.cts.Constants.ACTION_HAS_SIGNING_CERTIFICATE; 26 import static android.appenumeration.cts.Constants.ACTION_JUST_FINISH; 27 import static android.appenumeration.cts.Constants.ACTION_QUERY_ACTIVITIES; 28 import static android.appenumeration.cts.Constants.ACTION_QUERY_PROVIDERS; 29 import static android.appenumeration.cts.Constants.ACTION_QUERY_SERVICES; 30 import static android.appenumeration.cts.Constants.ACTION_SEND_RESULT; 31 import static android.appenumeration.cts.Constants.ACTION_START_DIRECTLY; 32 import static android.appenumeration.cts.Constants.ACTION_START_FOR_RESULT; 33 import static android.appenumeration.cts.Constants.ACTION_START_SENDER_FOR_RESULT; 34 import static android.appenumeration.cts.Constants.CALLBACK_EVENT_INVALID; 35 import static android.appenumeration.cts.Constants.CALLBACK_EVENT_PACKAGES_AVAILABLE; 36 import static android.appenumeration.cts.Constants.CALLBACK_EVENT_PACKAGES_SUSPENDED; 37 import static android.appenumeration.cts.Constants.CALLBACK_EVENT_PACKAGES_UNAVAILABLE; 38 import static android.appenumeration.cts.Constants.CALLBACK_EVENT_PACKAGES_UNSUSPENDED; 39 import static android.appenumeration.cts.Constants.CALLBACK_EVENT_PACKAGE_ADDED; 40 import static android.appenumeration.cts.Constants.CALLBACK_EVENT_PACKAGE_CHANGED; 41 import static android.appenumeration.cts.Constants.CALLBACK_EVENT_PACKAGE_REMOVED; 42 import static android.appenumeration.cts.Constants.EXTRA_ACCOUNT; 43 import static android.appenumeration.cts.Constants.EXTRA_AUTHORITY; 44 import static android.appenumeration.cts.Constants.EXTRA_CERT; 45 import static android.appenumeration.cts.Constants.EXTRA_DATA; 46 import static android.appenumeration.cts.Constants.EXTRA_ERROR; 47 import static android.appenumeration.cts.Constants.EXTRA_FLAGS; 48 import static android.appenumeration.cts.Constants.EXTRA_ID; 49 import static android.appenumeration.cts.Constants.EXTRA_PENDING_INTENT; 50 import static android.appenumeration.cts.Constants.EXTRA_REMOTE_CALLBACK; 51 import static android.appenumeration.cts.Constants.EXTRA_REMOTE_READY_CALLBACK; 52 import static android.content.Intent.EXTRA_COMPONENT_NAME; 53 import static android.content.Intent.EXTRA_PACKAGES; 54 import static android.content.Intent.EXTRA_RETURN_RESULT; 55 import static android.content.Intent.EXTRA_UID; 56 import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509; 57 import static android.os.Process.INVALID_UID; 58 import static android.os.Process.ROOT_UID; 59 60 import android.accounts.Account; 61 import android.app.Activity; 62 import android.app.AppOpsManager; 63 import android.app.PendingIntent; 64 import android.appwidget.AppWidgetManager; 65 import android.appwidget.AppWidgetProviderInfo; 66 import android.content.ActivityNotFoundException; 67 import android.content.BroadcastReceiver; 68 import android.content.ComponentName; 69 import android.content.ContentResolver; 70 import android.content.Context; 71 import android.content.Intent; 72 import android.content.IntentFilter; 73 import android.content.IntentSender; 74 import android.content.ServiceConnection; 75 import android.content.SyncAdapterType; 76 import android.content.SyncStatusObserver; 77 import android.content.pm.LauncherApps; 78 import android.content.pm.PackageInfo; 79 import android.content.pm.PackageInstaller.SessionCallback; 80 import android.content.pm.PackageInstaller.SessionInfo; 81 import android.content.pm.PackageManager; 82 import android.content.pm.SharedLibraryInfo; 83 import android.database.Cursor; 84 import android.net.Uri; 85 import android.os.Bundle; 86 import android.os.Handler; 87 import android.os.HandlerThread; 88 import android.os.IBinder; 89 import android.os.Parcelable; 90 import android.os.PatternMatcher; 91 import android.os.Process; 92 import android.os.RemoteCallback; 93 import android.os.UserHandle; 94 import android.util.SparseArray; 95 import android.view.accessibility.AccessibilityManager; 96 97 import java.util.ArrayList; 98 import java.util.Arrays; 99 import java.util.List; 100 import java.util.stream.Collectors; 101 102 /** 103 * A test activity running in the query and target applications. 104 */ 105 public class TestActivity extends Activity { 106 107 private final static long TIMEOUT_MS = 3000; 108 109 /** 110 * Extending the timeout time of non broadcast receivers, avoid not 111 * receiving callbacks in time on some common low-end platforms and 112 * do not affect the situation that callback can be received in advance. 113 */ 114 private final static long EXTENDED_TIMEOUT_MS = 5000; 115 116 SparseArray<RemoteCallback> callbacks = new SparseArray<>(); 117 118 private Handler mainHandler; 119 private Handler backgroundHandler; 120 private HandlerThread backgroundThread; 121 private Object syncStatusHandle; 122 123 @Override onCreate(Bundle savedInstanceState)124 protected void onCreate(Bundle savedInstanceState) { 125 mainHandler = new Handler(getMainLooper()); 126 backgroundThread = new HandlerThread("testBackground"); 127 backgroundThread.start(); 128 backgroundHandler = new Handler(backgroundThread.getLooper()); 129 super.onCreate(savedInstanceState); 130 handleIntent(getIntent()); 131 onCommandReady(getIntent()); 132 } 133 134 @Override onDestroy()135 protected void onDestroy() { 136 if (syncStatusHandle != null) { 137 ContentResolver.removeStatusChangeListener(syncStatusHandle); 138 } 139 backgroundThread.quitSafely(); 140 super.onDestroy(); 141 } 142 handleIntent(Intent intent)143 private void handleIntent(Intent intent) { 144 RemoteCallback remoteCallback = intent.getParcelableExtra(EXTRA_REMOTE_CALLBACK); 145 try { 146 final String action = intent.getAction(); 147 final Intent queryIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT); 148 if (ACTION_GET_PACKAGE_INFO.equals(action)) { 149 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 150 sendPackageInfo(remoteCallback, packageName); 151 } else if (ACTION_GET_PACKAGES_FOR_UID.equals(action)) { 152 final int uid = intent.getIntExtra(EXTRA_UID, INVALID_UID); 153 sendPackagesForUid(remoteCallback, uid); 154 } else if (ACTION_GET_NAME_FOR_UID.equals(action)) { 155 final int uid = intent.getIntExtra(EXTRA_UID, INVALID_UID); 156 sendNameForUid(remoteCallback, uid); 157 } else if (ACTION_GET_NAMES_FOR_UIDS.equals(action)) { 158 final int uid = intent.getIntExtra(EXTRA_UID, INVALID_UID); 159 sendNamesForUids(remoteCallback, uid); 160 } else if (ACTION_CHECK_SIGNATURES.equals(action)) { 161 final int uid1 = getPackageManager().getApplicationInfo( 162 getPackageName(), /* flags */ 0).uid; 163 final int uid2 = intent.getIntExtra(EXTRA_UID, INVALID_UID); 164 sendCheckSignatures(remoteCallback, uid1, uid2); 165 } else if (ACTION_HAS_SIGNING_CERTIFICATE.equals(action)) { 166 final int uid = intent.getIntExtra(EXTRA_UID, INVALID_UID); 167 final byte[] cert = intent.getBundleExtra(EXTRA_DATA).getByteArray(EXTRA_CERT); 168 sendHasSigningCertificate(remoteCallback, uid, cert, CERT_INPUT_RAW_X509); 169 } else if (ACTION_START_FOR_RESULT.equals(action)) { 170 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 171 int requestCode = RESULT_FIRST_USER + callbacks.size(); 172 callbacks.put(requestCode, remoteCallback); 173 startActivityForResult( 174 new Intent(ACTION_SEND_RESULT).setComponent( 175 new ComponentName(packageName, getClass().getCanonicalName())), 176 requestCode); 177 // don't send anything... await result callback 178 } else if (ACTION_SEND_RESULT.equals(action)) { 179 try { 180 setResult(RESULT_OK, 181 getIntent().putExtra( 182 Intent.EXTRA_RETURN_RESULT, 183 getPackageManager().getPackageInfo(getCallingPackage(), 0))); 184 } catch (PackageManager.NameNotFoundException e) { 185 setResult(RESULT_FIRST_USER, new Intent().putExtra("error", e)); 186 } 187 finish(); 188 } else if (ACTION_QUERY_ACTIVITIES.equals(action)) { 189 sendQueryIntentActivities(remoteCallback, queryIntent); 190 } else if (ACTION_QUERY_SERVICES.equals(action)) { 191 sendQueryIntentServices(remoteCallback, queryIntent); 192 } else if (ACTION_QUERY_PROVIDERS.equals(action)) { 193 sendQueryIntentProviders(remoteCallback, queryIntent); 194 } else if (ACTION_START_DIRECTLY.equals(action)) { 195 try { 196 startActivity(queryIntent); 197 remoteCallback.sendResult(new Bundle()); 198 } catch (ActivityNotFoundException e) { 199 sendError(remoteCallback, e); 200 } 201 finish(); 202 } else if (ACTION_JUST_FINISH.equals(action)) { 203 finish(); 204 } else if (ACTION_GET_INSTALLED_PACKAGES.equals(action)) { 205 sendGetInstalledPackages(remoteCallback, queryIntent.getIntExtra(EXTRA_FLAGS, 0)); 206 } else if (ACTION_START_SENDER_FOR_RESULT.equals(action)) { 207 PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_PENDING_INTENT); 208 int requestCode = RESULT_FIRST_USER + callbacks.size(); 209 callbacks.put(requestCode, remoteCallback); 210 try { 211 startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null, 212 0, 0, 0); 213 } catch (IntentSender.SendIntentException e) { 214 sendError(remoteCallback, e); 215 } 216 } else if (Constants.ACTION_AWAIT_PACKAGE_REMOVED.equals(action)) { 217 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 218 awaitPackageBroadcast( 219 remoteCallback, packageName, Intent.ACTION_PACKAGE_REMOVED, TIMEOUT_MS); 220 } else if (Constants.ACTION_AWAIT_PACKAGE_ADDED.equals(action)) { 221 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 222 awaitPackageBroadcast( 223 remoteCallback, packageName, Intent.ACTION_PACKAGE_ADDED, TIMEOUT_MS); 224 } else if (Constants.ACTION_AWAIT_PACKAGE_FULLY_REMOVED.equals(action)) { 225 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 226 awaitPackageBroadcast(remoteCallback, packageName, 227 Intent.ACTION_PACKAGE_FULLY_REMOVED, TIMEOUT_MS); 228 } else if (Constants.ACTION_AWAIT_PACKAGE_DATA_CLEARED.equals(action)) { 229 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 230 awaitPackageBroadcast(remoteCallback, packageName, 231 Intent.ACTION_PACKAGE_DATA_CLEARED, TIMEOUT_MS); 232 } else if (Constants.ACTION_QUERY_RESOLVER.equals(action)) { 233 final String authority = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 234 queryResolverForVisiblePackages(remoteCallback, authority); 235 } else if (Constants.ACTION_BIND_SERVICE.equals(action)) { 236 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 237 bindService(remoteCallback, packageName); 238 } else if (Constants.ACTION_GET_SYNCADAPTER_TYPES.equals(action)) { 239 sendSyncAdapterTypes(remoteCallback); 240 } else if (Constants.ACTION_GET_INSTALLED_APPWIDGET_PROVIDERS.equals(action)) { 241 sendInstalledAppWidgetProviders(remoteCallback); 242 } else if (Constants.ACTION_AWAIT_PACKAGES_SUSPENDED.equals(action)) { 243 final String[] awaitPackages = intent.getBundleExtra(EXTRA_DATA) 244 .getStringArray(EXTRA_PACKAGES); 245 awaitSuspendedPackagesBroadcast(remoteCallback, Arrays.asList(awaitPackages), 246 Intent.ACTION_PACKAGES_SUSPENDED, TIMEOUT_MS); 247 } else if (Constants.ACTION_LAUNCHER_APPS_IS_ACTIVITY_ENABLED.equals(action)) { 248 final String componentName = intent.getBundleExtra(EXTRA_DATA) 249 .getString(EXTRA_COMPONENT_NAME); 250 sendIsActivityEnabled(remoteCallback, ComponentName.unflattenFromString( 251 componentName)); 252 } else if (Constants.ACTION_LAUNCHER_APPS_GET_SUSPENDED_PACKAGE_LAUNCHER_EXTRAS.equals( 253 action)) { 254 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 255 sendGetSuspendedPackageLauncherExtras(remoteCallback, packageName); 256 } else if (Constants.ACTION_GET_SYNCADAPTER_PACKAGES_FOR_AUTHORITY.equals(action)) { 257 final String authority = intent.getBundleExtra(EXTRA_DATA) 258 .getString(EXTRA_AUTHORITY); 259 final int userId = intent.getBundleExtra(EXTRA_DATA) 260 .getInt(Intent.EXTRA_USER); 261 sendSyncAdapterPackagesForAuthorityAsUser(remoteCallback, authority, userId); 262 } else if (Constants.ACTION_REQUEST_SYNC_AND_AWAIT_STATUS.equals(action)) { 263 final String authority = intent.getBundleExtra(EXTRA_DATA) 264 .getString(EXTRA_AUTHORITY); 265 final Account account = intent.getBundleExtra(EXTRA_DATA) 266 .getParcelable(EXTRA_ACCOUNT); 267 awaitRequestSyncStatus(remoteCallback, action, account, authority, 268 EXTENDED_TIMEOUT_MS); 269 } else if (Constants.ACTION_AWAIT_LAUNCHER_APPS_CALLBACK.equals(action)) { 270 final int expectedEventCode = intent.getBundleExtra(EXTRA_DATA) 271 .getInt(EXTRA_FLAGS, CALLBACK_EVENT_INVALID); 272 awaitLauncherAppsCallback(remoteCallback, expectedEventCode, EXTENDED_TIMEOUT_MS); 273 } else if (Constants.ACTION_GET_SHAREDLIBRARY_DEPENDENT_PACKAGES.equals(action)) { 274 final String sharedLibName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 275 sendGetSharedLibraryDependentPackages(remoteCallback, sharedLibName); 276 } else if (Constants.ACTION_GET_PREFERRED_ACTIVITIES.equals(action)) { 277 sendGetPreferredActivities(remoteCallback); 278 } else if (Constants.ACTION_SET_INSTALLER_PACKAGE_NAME.equals(action)) { 279 final String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 280 final String installerPackageName = intent.getBundleExtra(EXTRA_DATA) 281 .getString(Intent.EXTRA_INSTALLER_PACKAGE_NAME); 282 sendSetInstallerPackageName(remoteCallback, targetPackageName, 283 installerPackageName); 284 } else if (Constants.ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES.equals( 285 action)) { 286 sendGetInstalledAccessibilityServicePackages(remoteCallback); 287 } else if (Constants.ACTION_LAUNCHER_APPS_SHOULD_HIDE_FROM_SUGGESTIONS.equals(action)) { 288 final String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 289 final int userId = intent.getBundleExtra(EXTRA_DATA).getInt(Intent.EXTRA_USER); 290 sendLauncherAppsShouldHideFromSuggestions(remoteCallback, targetPackageName, 291 userId); 292 } else if (Constants.ACTION_CHECK_URI_PERMISSION.equals(action)) { 293 final String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 294 final int targetUid = intent.getIntExtra(EXTRA_UID, INVALID_UID); 295 final String sourceAuthority = intent.getBundleExtra(EXTRA_DATA) 296 .getString(EXTRA_AUTHORITY); 297 sendCheckUriPermission(remoteCallback, sourceAuthority, targetPackageName, 298 targetUid); 299 } else if (Constants.ACTION_TAKE_PERSISTABLE_URI_PERMISSION.equals(action)) { 300 final Uri uri = intent.getData(); 301 final int modeFlags = intent.getFlags(); 302 if (uri != null) { 303 getContentResolver().takePersistableUriPermission(uri, modeFlags); 304 } 305 finish(); 306 } else if (Constants.ACTION_CAN_PACKAGE_QUERY.equals(action)) { 307 final String sourcePackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 308 final String targetPackageName = intent.getBundleExtra(EXTRA_DATA) 309 .getString(Intent.EXTRA_PACKAGE_NAME); 310 sendCanPackageQuery(remoteCallback, sourcePackageName, targetPackageName); 311 } else if (Constants.ACTION_GET_ALL_PACKAGE_INSTALLER_SESSIONS.equals(action)) { 312 final List<SessionInfo> infos = getSystemService(LauncherApps.class) 313 .getAllPackageInstallerSessions(); 314 sendSessionInfosListResult(remoteCallback, infos); 315 } else if (Constants.ACTION_AWAIT_LAUNCHER_APPS_SESSION_CALLBACK.equals(action)) { 316 final int expectedEventCode = intent.getBundleExtra(EXTRA_DATA) 317 .getInt(EXTRA_ID, SessionInfo.INVALID_ID); 318 awaitLauncherAppsSessionCallback(remoteCallback, expectedEventCode, 319 EXTENDED_TIMEOUT_MS); 320 } else if (Constants.ACTION_GET_SESSION_INFO.equals(action)) { 321 final int sessionId = intent.getBundleExtra(EXTRA_DATA) 322 .getInt(EXTRA_ID, SessionInfo.INVALID_ID); 323 final List<SessionInfo> infos = Arrays.asList(getPackageManager() 324 .getPackageInstaller() 325 .getSessionInfo(sessionId)); 326 sendSessionInfosListResult(remoteCallback, infos); 327 } else if (Constants.ACTION_GET_STAGED_SESSIONS.equals(action)) { 328 final List<SessionInfo> infos = getPackageManager().getPackageInstaller() 329 .getStagedSessions(); 330 sendSessionInfosListResult(remoteCallback, infos); 331 } else if (Constants.ACTION_GET_ALL_SESSIONS.equals(action)) { 332 final List<SessionInfo> infos = getPackageManager().getPackageInstaller() 333 .getAllSessions(); 334 sendSessionInfosListResult(remoteCallback, infos); 335 } else if (Constants.ACTION_PENDING_INTENT_GET_ACTIVITY.equals(action)) { 336 sendPendingIntentGetActivity(remoteCallback); 337 } else if (Constants.ACTION_PENDING_INTENT_GET_CREATOR_PACKAGE.equals(action)) { 338 sendPendingIntentGetCreatorPackage(remoteCallback, 339 intent.getParcelableExtra(EXTRA_PENDING_INTENT)); 340 } else if (Constants.ACTION_CHECK_PACKAGE.equals(action)) { 341 // Using ROOT_UID as default value here to pass the check in #verifyAndGetBypass, 342 // this is intended by design. 343 final int uid = intent.getIntExtra(EXTRA_UID, ROOT_UID); 344 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 345 sendCheckPackageResult(remoteCallback, packageName, uid); 346 } else if (Constants.ACTION_GRANT_URI_PERMISSION.equals(action)) { 347 final String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 348 final String sourceAuthority = intent.getBundleExtra(EXTRA_DATA) 349 .getString(EXTRA_AUTHORITY); 350 sendGrantUriPermission(remoteCallback, sourceAuthority, targetPackageName); 351 } else if (Constants.ACTION_REVOKE_URI_PERMISSION.equals(action)) { 352 final String sourceAuthority = intent.getBundleExtra(EXTRA_DATA) 353 .getString(EXTRA_AUTHORITY); 354 sendRevokeUriPermission(remoteCallback, sourceAuthority); 355 } else { 356 sendError(remoteCallback, new Exception("unknown action " + action)); 357 } 358 } catch (Exception e) { 359 sendError(remoteCallback, e); 360 } 361 } 362 sendGetInstalledAccessibilityServicePackages(RemoteCallback remoteCallback)363 private void sendGetInstalledAccessibilityServicePackages(RemoteCallback remoteCallback) { 364 final String[] packages = getSystemService( 365 AccessibilityManager.class).getInstalledAccessibilityServiceList().stream().map( 366 p -> p.getComponentName().getPackageName()).distinct().toArray(String[]::new); 367 final Bundle result = new Bundle(); 368 result.putStringArray(EXTRA_RETURN_RESULT, packages); 369 remoteCallback.sendResult(result); 370 finish(); 371 } 372 onCommandReady(Intent intent)373 private void onCommandReady(Intent intent) { 374 final RemoteCallback callback = intent.getParcelableExtra(EXTRA_REMOTE_READY_CALLBACK); 375 if (callback != null) { 376 callback.sendResult(null); 377 } 378 } 379 awaitPackageBroadcast(RemoteCallback remoteCallback, String packageName, String action, long timeoutMs)380 private void awaitPackageBroadcast(RemoteCallback remoteCallback, String packageName, 381 String action, long timeoutMs) { 382 final IntentFilter filter = new IntentFilter(action); 383 filter.addDataScheme("package"); 384 filter.addDataSchemeSpecificPart(packageName, PatternMatcher.PATTERN_LITERAL); 385 final Object token = new Object(); 386 registerReceiver(new BroadcastReceiver() { 387 @Override 388 public void onReceive(Context context, Intent intent) { 389 final Bundle result = new Bundle(); 390 result.putString(EXTRA_DATA, intent.getDataString()); 391 remoteCallback.sendResult(result); 392 mainHandler.removeCallbacksAndMessages(token); 393 finish(); 394 } 395 }, filter, Context.RECEIVER_EXPORTED_UNAUDITED); 396 mainHandler.postDelayed( 397 () -> sendError(remoteCallback, 398 new MissingBroadcastException(action, timeoutMs)), 399 token, timeoutMs); 400 } 401 awaitSuspendedPackagesBroadcast(RemoteCallback remoteCallback, List<String> awaitList, String action, long timeoutMs)402 private void awaitSuspendedPackagesBroadcast(RemoteCallback remoteCallback, 403 List<String> awaitList, String action, long timeoutMs) { 404 final IntentFilter filter = new IntentFilter(action); 405 final ArrayList<String> suspendedList = new ArrayList<>(); 406 final Object token = new Object(); 407 final Runnable sendResult = () -> { 408 final Bundle result = new Bundle(); 409 result.putStringArray(EXTRA_PACKAGES, suspendedList.toArray(new String[] {})); 410 remoteCallback.sendResult(result); 411 finish(); 412 }; 413 registerReceiver(new BroadcastReceiver() { 414 @Override 415 public void onReceive(Context context, Intent intent) { 416 final Bundle extras = intent.getExtras(); 417 final String[] changedList = extras.getStringArray( 418 Intent.EXTRA_CHANGED_PACKAGE_LIST); 419 suspendedList.addAll(Arrays.stream(changedList).filter( 420 p -> awaitList.contains(p)).collect(Collectors.toList())); 421 if (suspendedList.size() == awaitList.size()) { 422 mainHandler.removeCallbacksAndMessages(token); 423 sendResult.run(); 424 } 425 } 426 }, filter, Context.RECEIVER_EXPORTED_UNAUDITED); 427 mainHandler.postDelayed(() -> sendResult.run(), token, timeoutMs); 428 } 429 awaitLauncherAppsCallback(RemoteCallback remoteCallback, int expectedEventCode, long timeoutMs)430 private void awaitLauncherAppsCallback(RemoteCallback remoteCallback, int expectedEventCode, 431 long timeoutMs) { 432 final Object token = new Object(); 433 final Bundle result = new Bundle(); 434 final LauncherApps launcherApps = getSystemService(LauncherApps.class); 435 final LauncherApps.Callback launcherAppsCallback = new LauncherApps.Callback() { 436 437 private void onPackageStateUpdated(String[] packageNames, int resultCode) { 438 if (resultCode != expectedEventCode) { 439 return; 440 } 441 442 mainHandler.removeCallbacksAndMessages(token); 443 result.putStringArray(EXTRA_PACKAGES, packageNames); 444 result.putInt(EXTRA_FLAGS, resultCode); 445 remoteCallback.sendResult(result); 446 447 launcherApps.unregisterCallback(this); 448 finish(); 449 } 450 451 @Override 452 public void onPackageRemoved(String packageName, UserHandle user) { 453 onPackageStateUpdated(new String[]{packageName}, CALLBACK_EVENT_PACKAGE_REMOVED); 454 } 455 456 @Override 457 public void onPackageAdded(String packageName, UserHandle user) { 458 onPackageStateUpdated(new String[]{packageName}, CALLBACK_EVENT_PACKAGE_ADDED); 459 } 460 461 @Override 462 public void onPackageChanged(String packageName, UserHandle user) { 463 onPackageStateUpdated(new String[]{packageName}, CALLBACK_EVENT_PACKAGE_CHANGED); 464 } 465 466 @Override 467 public void onPackagesAvailable(String[] packageNames, UserHandle user, 468 boolean replacing) { 469 onPackageStateUpdated(packageNames, CALLBACK_EVENT_PACKAGES_AVAILABLE); 470 } 471 472 @Override 473 public void onPackagesUnavailable(String[] packageNames, UserHandle user, 474 boolean replacing) { 475 onPackageStateUpdated(packageNames, CALLBACK_EVENT_PACKAGES_UNAVAILABLE); 476 } 477 478 @Override 479 public void onPackagesSuspended(String[] packageNames, UserHandle user) { 480 onPackageStateUpdated(packageNames, CALLBACK_EVENT_PACKAGES_SUSPENDED); 481 super.onPackagesSuspended(packageNames, user); 482 } 483 484 @Override 485 public void onPackagesUnsuspended(String[] packageNames, UserHandle user) { 486 onPackageStateUpdated(packageNames, CALLBACK_EVENT_PACKAGES_UNSUSPENDED); 487 super.onPackagesUnsuspended(packageNames, user); 488 } 489 }; 490 491 launcherApps.registerCallback(launcherAppsCallback); 492 493 mainHandler.postDelayed(() -> { 494 result.putStringArray(EXTRA_PACKAGES, new String[]{}); 495 result.putInt(EXTRA_FLAGS, CALLBACK_EVENT_INVALID); 496 remoteCallback.sendResult(result); 497 498 launcherApps.unregisterCallback(launcherAppsCallback); 499 finish(); 500 }, token, timeoutMs); 501 } 502 sendGetInstalledPackages(RemoteCallback remoteCallback, int flags)503 private void sendGetInstalledPackages(RemoteCallback remoteCallback, int flags) { 504 String[] packages = 505 getPackageManager().getInstalledPackages(flags) 506 .stream().map(p -> p.packageName).distinct().toArray(String[]::new); 507 Bundle result = new Bundle(); 508 result.putStringArray(EXTRA_RETURN_RESULT, packages); 509 remoteCallback.sendResult(result); 510 finish(); 511 } 512 sendQueryIntentActivities(RemoteCallback remoteCallback, Intent queryIntent)513 private void sendQueryIntentActivities(RemoteCallback remoteCallback, Intent queryIntent) { 514 final String[] resolveInfos = getPackageManager().queryIntentActivities( 515 queryIntent, 0 /* flags */).stream() 516 .map(ri -> ri.activityInfo.applicationInfo.packageName) 517 .distinct() 518 .toArray(String[]::new); 519 Bundle result = new Bundle(); 520 result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos); 521 remoteCallback.sendResult(result); 522 finish(); 523 } 524 sendQueryIntentServices(RemoteCallback remoteCallback, Intent queryIntent)525 private void sendQueryIntentServices(RemoteCallback remoteCallback, Intent queryIntent) { 526 final String[] resolveInfos = getPackageManager().queryIntentServices( 527 queryIntent, 0 /* flags */).stream() 528 .map(ri -> ri.serviceInfo.applicationInfo.packageName) 529 .distinct() 530 .toArray(String[]::new); 531 Bundle result = new Bundle(); 532 result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos); 533 remoteCallback.sendResult(result); 534 finish(); 535 } 536 sendQueryIntentProviders(RemoteCallback remoteCallback, Intent queryIntent)537 private void sendQueryIntentProviders(RemoteCallback remoteCallback, Intent queryIntent) { 538 final String[] resolveInfos = getPackageManager().queryIntentContentProviders( 539 queryIntent, 0 /* flags */).stream() 540 .map(ri -> ri.providerInfo.applicationInfo.packageName) 541 .distinct() 542 .toArray(String[]::new); 543 Bundle result = new Bundle(); 544 result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos); 545 remoteCallback.sendResult(result); 546 finish(); 547 } 548 queryResolverForVisiblePackages(RemoteCallback remoteCallback, String authority)549 private void queryResolverForVisiblePackages(RemoteCallback remoteCallback, String authority) { 550 backgroundHandler.post(() -> { 551 Uri queryUri = Uri.parse("content://" + authority + "/test"); 552 Cursor query = getContentResolver().query(queryUri, null, null, null, null); 553 if (query == null || !query.moveToFirst()) { 554 sendError(remoteCallback, 555 new IllegalStateException( 556 "Query of " + queryUri + " could not be completed")); 557 return; 558 } 559 ArrayList<String> visiblePackages = new ArrayList<>(); 560 while (!query.isAfterLast()) { 561 visiblePackages.add(query.getString(0)); 562 query.moveToNext(); 563 } 564 query.close(); 565 566 mainHandler.post(() -> { 567 Bundle result = new Bundle(); 568 result.putStringArray(EXTRA_RETURN_RESULT, visiblePackages.toArray(new String[]{})); 569 remoteCallback.sendResult(result); 570 finish(); 571 }); 572 573 }); 574 } 575 sendError(RemoteCallback remoteCallback, Exception failure)576 private void sendError(RemoteCallback remoteCallback, Exception failure) { 577 Bundle result = new Bundle(); 578 result.putSerializable(EXTRA_ERROR, failure); 579 remoteCallback.sendResult(result); 580 finish(); 581 } 582 sendPackageInfo(RemoteCallback remoteCallback, String packageName)583 private void sendPackageInfo(RemoteCallback remoteCallback, String packageName) { 584 final PackageInfo pi; 585 try { 586 pi = getPackageManager().getPackageInfo(packageName, 0); 587 } catch (PackageManager.NameNotFoundException e) { 588 sendError(remoteCallback, e); 589 return; 590 } 591 Bundle result = new Bundle(); 592 result.putParcelable(EXTRA_RETURN_RESULT, pi); 593 remoteCallback.sendResult(result); 594 finish(); 595 } 596 sendPackagesForUid(RemoteCallback remoteCallback, int uid)597 private void sendPackagesForUid(RemoteCallback remoteCallback, int uid) { 598 final String[] packages = getPackageManager().getPackagesForUid(uid); 599 final Bundle result = new Bundle(); 600 result.putStringArray(EXTRA_RETURN_RESULT, packages); 601 remoteCallback.sendResult(result); 602 finish(); 603 } 604 sendNameForUid(RemoteCallback remoteCallback, int uid)605 private void sendNameForUid(RemoteCallback remoteCallback, int uid) { 606 final String name = getPackageManager().getNameForUid(uid); 607 final Bundle result = new Bundle(); 608 result.putString(EXTRA_RETURN_RESULT, name); 609 remoteCallback.sendResult(result); 610 finish(); 611 } 612 sendNamesForUids(RemoteCallback remoteCallback, int uid)613 private void sendNamesForUids(RemoteCallback remoteCallback, int uid) { 614 final String[] names = getPackageManager().getNamesForUids(new int[]{uid}); 615 final Bundle result = new Bundle(); 616 result.putStringArray(EXTRA_RETURN_RESULT, names); 617 remoteCallback.sendResult(result); 618 finish(); 619 } 620 sendCheckSignatures(RemoteCallback remoteCallback, int uid1, int uid2)621 private void sendCheckSignatures(RemoteCallback remoteCallback, int uid1, int uid2) { 622 final int signatureResult = getPackageManager().checkSignatures(uid1, uid2); 623 final Bundle result = new Bundle(); 624 result.putInt(EXTRA_RETURN_RESULT, signatureResult); 625 remoteCallback.sendResult(result); 626 finish(); 627 } 628 sendHasSigningCertificate(RemoteCallback remoteCallback, int uid, byte[] cert, int type)629 private void sendHasSigningCertificate(RemoteCallback remoteCallback, int uid, byte[] cert, 630 int type) { 631 final boolean signatureResult = getPackageManager().hasSigningCertificate(uid, cert, type); 632 final Bundle result = new Bundle(); 633 result.putBoolean(EXTRA_RETURN_RESULT, signatureResult); 634 remoteCallback.sendResult(result); 635 finish(); 636 } 637 638 /** 639 * Instead of sending a list of package names, this function sends a List of 640 * {@link SyncAdapterType}, since the {@link SyncAdapterType#getPackageName()} is a test api 641 * which can only be invoked in the instrumentation. 642 */ sendSyncAdapterTypes(RemoteCallback remoteCallback)643 private void sendSyncAdapterTypes(RemoteCallback remoteCallback) { 644 final SyncAdapterType[] types = ContentResolver.getSyncAdapterTypes(); 645 final ArrayList<Parcelable> parcelables = new ArrayList<>(); 646 for (SyncAdapterType type : types) { 647 parcelables.add(type); 648 } 649 final Bundle result = new Bundle(); 650 result.putParcelableArrayList(EXTRA_RETURN_RESULT, parcelables); 651 remoteCallback.sendResult(result); 652 finish(); 653 } 654 sendIsActivityEnabled(RemoteCallback remoteCallback, ComponentName componentName)655 private void sendIsActivityEnabled(RemoteCallback remoteCallback, ComponentName componentName) { 656 final LauncherApps launcherApps = getSystemService(LauncherApps.class); 657 final Bundle result = new Bundle(); 658 try { 659 result.putBoolean(EXTRA_RETURN_RESULT, launcherApps.isActivityEnabled(componentName, 660 Process.myUserHandle())); 661 } catch (IllegalArgumentException e) { 662 } 663 remoteCallback.sendResult(result); 664 finish(); 665 } 666 sendGetSuspendedPackageLauncherExtras(RemoteCallback remoteCallback, String packageName)667 private void sendGetSuspendedPackageLauncherExtras(RemoteCallback remoteCallback, 668 String packageName) { 669 final LauncherApps launcherApps = getSystemService(LauncherApps.class); 670 final Bundle result = new Bundle(); 671 try { 672 result.putBundle(EXTRA_RETURN_RESULT, 673 launcherApps.getSuspendedPackageLauncherExtras(packageName, 674 Process.myUserHandle())); 675 } catch (IllegalArgumentException e) { 676 } 677 remoteCallback.sendResult(result); 678 finish(); 679 } 680 sendInstalledAppWidgetProviders(RemoteCallback remoteCallback)681 private void sendInstalledAppWidgetProviders(RemoteCallback remoteCallback) { 682 final AppWidgetManager appWidgetManager = getSystemService(AppWidgetManager.class); 683 final List<AppWidgetProviderInfo> providers = appWidgetManager.getInstalledProviders(); 684 final ArrayList<Parcelable> parcelables = new ArrayList<>(); 685 for (AppWidgetProviderInfo info : providers) { 686 parcelables.add(info); 687 } 688 final Bundle result = new Bundle(); 689 result.putParcelableArrayList(EXTRA_RETURN_RESULT, parcelables); 690 remoteCallback.sendResult(result); 691 finish(); 692 } 693 sendSyncAdapterPackagesForAuthorityAsUser(RemoteCallback remoteCallback, String authority, int userId)694 private void sendSyncAdapterPackagesForAuthorityAsUser(RemoteCallback remoteCallback, 695 String authority, int userId) { 696 final String[] syncAdapterPackages = ContentResolver 697 .getSyncAdapterPackagesForAuthorityAsUser(authority, userId); 698 final Bundle result = new Bundle(); 699 result.putStringArray(Intent.EXTRA_PACKAGES, syncAdapterPackages); 700 remoteCallback.sendResult(result); 701 finish(); 702 } 703 awaitRequestSyncStatus(RemoteCallback remoteCallback, String action, Account account, String authority, long timeoutMs)704 private void awaitRequestSyncStatus(RemoteCallback remoteCallback, String action, 705 Account account, String authority, long timeoutMs) { 706 ContentResolver.cancelSync(account, authority); 707 final Object token = new Object(); 708 final SyncStatusObserver observer = which -> { 709 final Bundle result = new Bundle(); 710 result.putBoolean(EXTRA_RETURN_RESULT, true); 711 remoteCallback.sendResult(result); 712 mainHandler.removeCallbacksAndMessages(token); 713 finish(); 714 }; 715 syncStatusHandle = ContentResolver.addStatusChangeListener( 716 ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE 717 | ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS 718 | ContentResolver.SYNC_OBSERVER_TYPE_PENDING, observer); 719 720 ContentResolver.requestSync(account, authority, new Bundle()); 721 mainHandler.postDelayed( 722 () -> sendError(remoteCallback, new MissingCallbackException(action, timeoutMs)), 723 token, timeoutMs); 724 } 725 sendGetSharedLibraryDependentPackages(RemoteCallback remoteCallback, String sharedLibName)726 private void sendGetSharedLibraryDependentPackages(RemoteCallback remoteCallback, 727 String sharedLibName) { 728 final List<SharedLibraryInfo> sharedLibraryInfos = getPackageManager() 729 .getSharedLibraries(0 /* flags */); 730 SharedLibraryInfo sharedLibraryInfo = sharedLibraryInfos.stream().filter( 731 info -> sharedLibName.equals(info.getName())).findAny().orElse(null); 732 final String[] dependentPackages = sharedLibraryInfo == null ? null 733 : sharedLibraryInfo.getDependentPackages().stream() 734 .map(versionedPackage -> versionedPackage.getPackageName()) 735 .distinct().collect(Collectors.toList()).toArray(new String[]{}); 736 final Bundle result = new Bundle(); 737 result.putStringArray(Intent.EXTRA_PACKAGES, dependentPackages); 738 remoteCallback.sendResult(result); 739 finish(); 740 } 741 sendGetPreferredActivities(RemoteCallback remoteCallback)742 private void sendGetPreferredActivities(RemoteCallback remoteCallback) { 743 final List<IntentFilter> filters = new ArrayList<>(); 744 final List<ComponentName> activities = new ArrayList<>(); 745 getPackageManager().getPreferredActivities(filters, activities, null /* packageName*/); 746 final String[] packages = activities.stream() 747 .map(componentName -> componentName.getPackageName()).distinct() 748 .collect(Collectors.toList()).toArray(new String[]{}); 749 final Bundle result = new Bundle(); 750 result.putStringArray(Intent.EXTRA_PACKAGES, packages); 751 remoteCallback.sendResult(result); 752 finish(); 753 } 754 sendSetInstallerPackageName(RemoteCallback remoteCallback, String targetPackageName, String installerPackageName)755 private void sendSetInstallerPackageName(RemoteCallback remoteCallback, 756 String targetPackageName, String installerPackageName) { 757 try { 758 getPackageManager().setInstallerPackageName(targetPackageName, installerPackageName); 759 remoteCallback.sendResult(null); 760 finish(); 761 } catch (Exception e) { 762 sendError(remoteCallback, e); 763 } 764 } 765 sendLauncherAppsShouldHideFromSuggestions(RemoteCallback remoteCallback, String targetPackageName, int userId)766 private void sendLauncherAppsShouldHideFromSuggestions(RemoteCallback remoteCallback, 767 String targetPackageName, int userId) { 768 final LauncherApps launcherApps = getSystemService(LauncherApps.class); 769 final boolean hideFromSuggestions = launcherApps.shouldHideFromSuggestions( 770 targetPackageName, UserHandle.of(userId)); 771 final Bundle result = new Bundle(); 772 result.putBoolean(EXTRA_RETURN_RESULT, hideFromSuggestions); 773 remoteCallback.sendResult(result); 774 finish(); 775 } 776 sendCheckUriPermission(RemoteCallback remoteCallback, String sourceAuthority, String targetPackageName, int targetUid)777 private void sendCheckUriPermission(RemoteCallback remoteCallback, String sourceAuthority, 778 String targetPackageName, int targetUid) { 779 final Uri uri = Uri.parse("content://" + sourceAuthority); 780 grantUriPermission(targetPackageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 781 final int permissionResult = checkUriPermission(uri, 0 /* pid */, targetUid, 782 Intent.FLAG_GRANT_READ_URI_PERMISSION); 783 revokeUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 784 final Bundle result = new Bundle(); 785 result.putInt(EXTRA_RETURN_RESULT, permissionResult); 786 remoteCallback.sendResult(result); 787 finish(); 788 } 789 sendGrantUriPermission(RemoteCallback remoteCallback, String sourceAuthority, String targetPackageName)790 private void sendGrantUriPermission(RemoteCallback remoteCallback, String sourceAuthority, 791 String targetPackageName) { 792 final Uri uri = Uri.parse("content://" + sourceAuthority); 793 grantUriPermission(targetPackageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 794 remoteCallback.sendResult(null); 795 finish(); 796 } 797 sendRevokeUriPermission(RemoteCallback remoteCallback, String sourceAuthority)798 private void sendRevokeUriPermission(RemoteCallback remoteCallback, String sourceAuthority) { 799 final Uri uri = Uri.parse("content://" + sourceAuthority); 800 revokeUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); 801 remoteCallback.sendResult(null); 802 finish(); 803 } 804 sendCanPackageQuery(RemoteCallback remoteCallback, String sourcePackageName, String targetPackageName)805 private void sendCanPackageQuery(RemoteCallback remoteCallback, String sourcePackageName, 806 String targetPackageName) { 807 try { 808 final boolean visibility = getPackageManager().canPackageQuery(sourcePackageName, 809 targetPackageName); 810 final Bundle result = new Bundle(); 811 result.putBoolean(EXTRA_RETURN_RESULT, visibility); 812 remoteCallback.sendResult(result); 813 finish(); 814 } catch (PackageManager.NameNotFoundException e) { 815 sendError(remoteCallback, e); 816 } 817 } 818 sendSessionInfosListResult(RemoteCallback remoteCallback, List<SessionInfo> infos)819 private void sendSessionInfosListResult(RemoteCallback remoteCallback, 820 List<SessionInfo> infos) { 821 final ArrayList<Parcelable> parcelables = new ArrayList<>(infos); 822 for (SessionInfo info : infos) { 823 parcelables.add(info); 824 } 825 final Bundle result = new Bundle(); 826 result.putParcelableArrayList(EXTRA_RETURN_RESULT, parcelables); 827 remoteCallback.sendResult(result); 828 finish(); 829 } 830 awaitLauncherAppsSessionCallback(RemoteCallback remoteCallback, int expectedSessionId, long timeoutMs)831 private void awaitLauncherAppsSessionCallback(RemoteCallback remoteCallback, 832 int expectedSessionId, long timeoutMs) { 833 final Object token = new Object(); 834 final Bundle result = new Bundle(); 835 final LauncherApps launcherApps = getSystemService(LauncherApps.class); 836 final SessionCallback sessionCallback = new SessionCallback() { 837 838 @Override 839 public void onCreated(int sessionId) { 840 // No-op 841 } 842 843 @Override 844 public void onBadgingChanged(int sessionId) { 845 // No-op 846 } 847 848 @Override 849 public void onActiveChanged(int sessionId, boolean active) { 850 // No-op 851 } 852 853 @Override 854 public void onProgressChanged(int sessionId, float progress) { 855 // No-op 856 } 857 858 @Override 859 public void onFinished(int sessionId, boolean success) { 860 if (sessionId != expectedSessionId) { 861 return; 862 } 863 864 mainHandler.removeCallbacksAndMessages(token); 865 result.putInt(EXTRA_ID, sessionId); 866 remoteCallback.sendResult(result); 867 868 launcherApps.unregisterPackageInstallerSessionCallback(this); 869 finish(); 870 } 871 }; 872 873 launcherApps.registerPackageInstallerSessionCallback(this.getMainExecutor(), 874 sessionCallback); 875 876 mainHandler.postDelayed(() -> { 877 result.putInt(EXTRA_ID, SessionInfo.INVALID_ID); 878 remoteCallback.sendResult(result); 879 880 launcherApps.unregisterPackageInstallerSessionCallback(sessionCallback); 881 finish(); 882 }, token, timeoutMs); 883 } 884 sendPendingIntentGetActivity(RemoteCallback remoteCallback)885 private void sendPendingIntentGetActivity(RemoteCallback remoteCallback) { 886 final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* requestCode */, 887 new Intent(this, TestActivity.class), PendingIntent.FLAG_IMMUTABLE); 888 final Bundle result = new Bundle(); 889 result.putParcelable(EXTRA_PENDING_INTENT, pendingIntent); 890 remoteCallback.sendResult(result); 891 finish(); 892 } 893 sendPendingIntentGetCreatorPackage(RemoteCallback remoteCallback, PendingIntent pendingIntent)894 private void sendPendingIntentGetCreatorPackage(RemoteCallback remoteCallback, 895 PendingIntent pendingIntent) { 896 final Bundle result = new Bundle(); 897 result.putString(Intent.EXTRA_PACKAGE_NAME, pendingIntent.getCreatorPackage()); 898 remoteCallback.sendResult(result); 899 finish(); 900 } 901 sendCheckPackageResult(RemoteCallback remoteCallback, String packageName, int uid)902 private void sendCheckPackageResult(RemoteCallback remoteCallback, String packageName, 903 int uid) { 904 try { 905 getSystemService(AppOpsManager.class).checkPackage(uid, packageName); 906 final Bundle result = new Bundle(); 907 result.putBoolean(EXTRA_RETURN_RESULT, true); 908 remoteCallback.sendResult(result); 909 finish(); 910 } catch (SecurityException e) { 911 sendError(remoteCallback, e); 912 } 913 } 914 915 @Override onActivityResult(int requestCode, int resultCode, Intent data)916 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 917 super.onActivityResult(requestCode, resultCode, data); 918 final RemoteCallback remoteCallback = callbacks.get(requestCode); 919 if (resultCode != RESULT_OK) { 920 Exception e = (Exception) data.getSerializableExtra(EXTRA_ERROR); 921 sendError(remoteCallback, e == null ? new Exception("Result was " + resultCode) : e); 922 return; 923 } 924 final Bundle result = new Bundle(); 925 result.putParcelable(EXTRA_RETURN_RESULT, data.getParcelableExtra(EXTRA_RETURN_RESULT)); 926 remoteCallback.sendResult(result); 927 finish(); 928 } 929 bindService(RemoteCallback remoteCallback, String packageName)930 private void bindService(RemoteCallback remoteCallback, String packageName) { 931 final String SERVICE_NAME = "android.appenumeration.testapp.DummyService"; 932 final Intent intent = new Intent(); 933 intent.setClassName(packageName, SERVICE_NAME); 934 final ServiceConnection serviceConnection = new ServiceConnection() { 935 @Override 936 public void onServiceConnected(ComponentName className, IBinder service) { 937 // No-op 938 } 939 940 @Override 941 public void onServiceDisconnected(ComponentName className) { 942 // No-op 943 } 944 945 @Override 946 public void onBindingDied(ComponentName name) { 947 // Remote service die 948 finish(); 949 } 950 951 @Override 952 public void onNullBinding(ComponentName name) { 953 // Since the DummyService doesn't implement onBind, it returns null and 954 // onNullBinding would be called. Use postDelayed to keep this service 955 // connection alive for 3 seconds. 956 mainHandler.postDelayed(() -> { 957 unbindService(this); 958 finish(); 959 }, TIMEOUT_MS); 960 } 961 }; 962 963 final boolean bound = bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 964 final Bundle result = new Bundle(); 965 result.putBoolean(EXTRA_RETURN_RESULT, bound); 966 remoteCallback.sendResult(result); 967 // Don't invoke finish() right here if service is bound successfully to keep the service 968 // connection alive since the ServiceRecord would be remove from the ServiceMap once no 969 // client is binding the service. 970 if (!bound) finish(); 971 } 972 } 973