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.query; 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_AUTHORITY; 43 import static android.appenumeration.cts.Constants.EXTRA_CERT; 44 import static android.appenumeration.cts.Constants.EXTRA_DATA; 45 import static android.appenumeration.cts.Constants.EXTRA_ERROR; 46 import static android.appenumeration.cts.Constants.EXTRA_FLAGS; 47 import static android.appenumeration.cts.Constants.EXTRA_REMOTE_CALLBACK; 48 import static android.appenumeration.cts.Constants.EXTRA_REMOTE_READY_CALLBACK; 49 import static android.content.Intent.EXTRA_COMPONENT_NAME; 50 import static android.content.Intent.EXTRA_PACKAGES; 51 import static android.content.Intent.EXTRA_RETURN_RESULT; 52 import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509; 53 import static android.os.Process.INVALID_UID; 54 55 import android.app.Activity; 56 import android.app.PendingIntent; 57 import android.appenumeration.cts.Constants; 58 import android.appenumeration.cts.MissingBroadcastException; 59 import android.appwidget.AppWidgetManager; 60 import android.appwidget.AppWidgetProviderInfo; 61 import android.content.ActivityNotFoundException; 62 import android.content.BroadcastReceiver; 63 import android.content.ComponentName; 64 import android.content.ContentResolver; 65 import android.content.Context; 66 import android.content.Intent; 67 import android.content.IntentFilter; 68 import android.content.IntentSender; 69 import android.content.ServiceConnection; 70 import android.content.SyncAdapterType; 71 import android.content.pm.LauncherApps; 72 import android.content.pm.PackageInfo; 73 import android.content.pm.PackageManager; 74 import android.content.pm.SharedLibraryInfo; 75 import android.database.Cursor; 76 import android.net.Uri; 77 import android.os.Bundle; 78 import android.os.Handler; 79 import android.os.HandlerThread; 80 import android.os.IBinder; 81 import android.os.Parcelable; 82 import android.os.PatternMatcher; 83 import android.os.Process; 84 import android.os.RemoteCallback; 85 import android.os.UserHandle; 86 import android.util.SparseArray; 87 import android.view.accessibility.AccessibilityManager; 88 89 import java.util.ArrayList; 90 import java.util.Arrays; 91 import java.util.List; 92 import java.util.stream.Collectors; 93 94 public class TestActivity extends Activity { 95 96 private final static long TIMEOUT_MS = 3000; 97 98 /** 99 * Extending the timeout time of non broadcast receivers, avoid not 100 * receiving callbacks in time on some common low-end platforms and 101 * do not affect the situation that callback can be received in advance. 102 */ 103 private final static long EXTENDED_TIMEOUT_MS = 5000; 104 105 SparseArray<RemoteCallback> callbacks = new SparseArray<>(); 106 107 private Handler mainHandler; 108 private Handler backgroundHandler; 109 private HandlerThread backgroundThread; 110 111 @Override onCreate(Bundle savedInstanceState)112 protected void onCreate(Bundle savedInstanceState) { 113 mainHandler = new Handler(getMainLooper()); 114 backgroundThread = new HandlerThread("testBackground"); 115 backgroundThread.start(); 116 backgroundHandler = new Handler(backgroundThread.getLooper()); 117 super.onCreate(savedInstanceState); 118 handleIntent(getIntent()); 119 onCommandReady(getIntent()); 120 } 121 122 @Override onDestroy()123 protected void onDestroy() { 124 backgroundThread.quitSafely(); 125 super.onDestroy(); 126 } 127 handleIntent(Intent intent)128 private void handleIntent(Intent intent) { 129 RemoteCallback remoteCallback = intent.getParcelableExtra(EXTRA_REMOTE_CALLBACK); 130 try { 131 final String action = intent.getAction(); 132 final Intent queryIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT); 133 if (ACTION_GET_PACKAGE_INFO.equals(action)) { 134 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 135 sendPackageInfo(remoteCallback, packageName); 136 } else if (ACTION_GET_PACKAGES_FOR_UID.equals(action)) { 137 final int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID); 138 sendPackagesForUid(remoteCallback, uid); 139 } else if (ACTION_GET_NAME_FOR_UID.equals(action)) { 140 final int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID); 141 sendNameForUid(remoteCallback, uid); 142 } else if (ACTION_GET_NAMES_FOR_UIDS.equals(action)) { 143 final int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID); 144 sendNamesForUids(remoteCallback, uid); 145 } else if (ACTION_CHECK_SIGNATURES.equals(action)) { 146 final int uid1 = getPackageManager().getApplicationInfo( 147 getPackageName(), /* flags */ 0).uid; 148 final int uid2 = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID); 149 sendCheckSignatures(remoteCallback, uid1, uid2); 150 } else if (ACTION_HAS_SIGNING_CERTIFICATE.equals(action)) { 151 final int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID); 152 final byte[] cert = intent.getBundleExtra(EXTRA_DATA).getByteArray(EXTRA_CERT); 153 sendHasSigningCertificate(remoteCallback, uid, cert, CERT_INPUT_RAW_X509); 154 } else if (ACTION_START_FOR_RESULT.equals(action)) { 155 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 156 int requestCode = RESULT_FIRST_USER + callbacks.size(); 157 callbacks.put(requestCode, remoteCallback); 158 startActivityForResult( 159 new Intent(ACTION_SEND_RESULT).setComponent( 160 new ComponentName(packageName, getClass().getCanonicalName())), 161 requestCode); 162 // don't send anything... await result callback 163 } else if (ACTION_SEND_RESULT.equals(action)) { 164 try { 165 setResult(RESULT_OK, 166 getIntent().putExtra( 167 Intent.EXTRA_RETURN_RESULT, 168 getPackageManager().getPackageInfo(getCallingPackage(), 0))); 169 } catch (PackageManager.NameNotFoundException e) { 170 setResult(RESULT_FIRST_USER, new Intent().putExtra("error", e)); 171 } 172 finish(); 173 } else if (ACTION_QUERY_ACTIVITIES.equals(action)) { 174 sendQueryIntentActivities(remoteCallback, queryIntent); 175 } else if (ACTION_QUERY_SERVICES.equals(action)) { 176 sendQueryIntentServices(remoteCallback, queryIntent); 177 } else if (ACTION_QUERY_PROVIDERS.equals(action)) { 178 sendQueryIntentProviders(remoteCallback, queryIntent); 179 } else if (ACTION_START_DIRECTLY.equals(action)) { 180 try { 181 startActivity(queryIntent); 182 remoteCallback.sendResult(new Bundle()); 183 } catch (ActivityNotFoundException e) { 184 sendError(remoteCallback, e); 185 } 186 finish(); 187 } else if (ACTION_JUST_FINISH.equals(action)) { 188 finish(); 189 } else if (ACTION_GET_INSTALLED_PACKAGES.equals(action)) { 190 sendGetInstalledPackages(remoteCallback, queryIntent.getIntExtra(EXTRA_FLAGS, 0)); 191 } else if (ACTION_START_SENDER_FOR_RESULT.equals(action)) { 192 PendingIntent pendingIntent = intent.getParcelableExtra("pendingIntent"); 193 int requestCode = RESULT_FIRST_USER + callbacks.size(); 194 callbacks.put(requestCode, remoteCallback); 195 try { 196 startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null, 197 0, 0, 0); 198 } catch (IntentSender.SendIntentException e) { 199 sendError(remoteCallback, e); 200 } 201 } else if (Constants.ACTION_AWAIT_PACKAGE_REMOVED.equals(action)) { 202 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 203 awaitPackageBroadcast( 204 remoteCallback, packageName, Intent.ACTION_PACKAGE_REMOVED, TIMEOUT_MS); 205 } else if (Constants.ACTION_AWAIT_PACKAGE_ADDED.equals(action)) { 206 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 207 awaitPackageBroadcast( 208 remoteCallback, packageName, Intent.ACTION_PACKAGE_ADDED, TIMEOUT_MS); 209 } else if (Constants.ACTION_QUERY_RESOLVER.equals(action)) { 210 final String authority = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 211 queryResolverForVisiblePackages(remoteCallback, authority); 212 } else if (Constants.ACTION_BIND_SERVICE.equals(action)) { 213 final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 214 bindService(remoteCallback, packageName); 215 } else if (Constants.ACTION_GET_SYNCADAPTER_TYPES.equals(action)) { 216 sendSyncAdapterTypes(remoteCallback); 217 } else if (Constants.ACTION_GET_INSTALLED_APPWIDGET_PROVIDERS.equals(action)) { 218 sendInstalledAppWidgetProviders(remoteCallback); 219 } else if (Constants.ACTION_AWAIT_PACKAGES_SUSPENDED.equals(action)) { 220 final String[] awaitPackages = intent.getBundleExtra(EXTRA_DATA) 221 .getStringArray(EXTRA_PACKAGES); 222 awaitSuspendedPackagesBroadcast(remoteCallback, Arrays.asList(awaitPackages), 223 Intent.ACTION_PACKAGES_SUSPENDED, TIMEOUT_MS); 224 } else if (Constants.ACTION_LAUNCHER_APPS_IS_ACTIVITY_ENABLED.equals(action)) { 225 final String componentName = intent.getBundleExtra(EXTRA_DATA) 226 .getString(EXTRA_COMPONENT_NAME); 227 sendIsActivityEnabled(remoteCallback, ComponentName.unflattenFromString( 228 componentName)); 229 } else if (Constants.ACTION_GET_SYNCADAPTER_PACKAGES_FOR_AUTHORITY.equals(action)) { 230 final String authority = intent.getBundleExtra(EXTRA_DATA) 231 .getString(EXTRA_AUTHORITY); 232 final int userId = intent.getBundleExtra(EXTRA_DATA) 233 .getInt(Intent.EXTRA_USER); 234 sendSyncAdapterPackagesForAuthorityAsUser(remoteCallback, authority, userId); 235 } else if (Constants.ACTION_AWAIT_LAUNCHER_APPS_CALLBACK.equals(action)) { 236 final int expectedEventCode = intent.getBundleExtra(EXTRA_DATA) 237 .getInt(EXTRA_FLAGS, CALLBACK_EVENT_INVALID); 238 awaitLauncherAppsCallback(remoteCallback, expectedEventCode, EXTENDED_TIMEOUT_MS); 239 } else if (Constants.ACTION_GET_SHAREDLIBRARY_DEPENDENT_PACKAGES.equals(action)) { 240 final String sharedLibName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 241 sendGetSharedLibraryDependentPackages(remoteCallback, sharedLibName); 242 } else if (Constants.ACTION_GET_PREFERRED_ACTIVITIES.equals(action)) { 243 sendGetPreferredActivities(remoteCallback); 244 } else if (Constants.ACTION_SET_INSTALLER_PACKAGE_NAME.equals(action)) { 245 final String targetPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 246 final String installerPackageName = intent.getBundleExtra(EXTRA_DATA) 247 .getString(Intent.EXTRA_INSTALLER_PACKAGE_NAME); 248 sendSetInstallerPackageName(remoteCallback, targetPackageName, 249 installerPackageName); 250 } else if (Constants.ACTION_GET_INSTALLED_ACCESSIBILITYSERVICES_PACKAGES.equals( 251 action)) { 252 sendGetInstalledAccessibilityServicePackages(remoteCallback); 253 } else { 254 sendError(remoteCallback, new Exception("unknown action " + action)); 255 } 256 } catch (Exception e) { 257 sendError(remoteCallback, e); 258 } 259 } 260 sendGetInstalledAccessibilityServicePackages(RemoteCallback remoteCallback)261 private void sendGetInstalledAccessibilityServicePackages(RemoteCallback remoteCallback) { 262 final String[] packages = getSystemService( 263 AccessibilityManager.class).getInstalledAccessibilityServiceList().stream().map( 264 p -> p.getComponentName().getPackageName()).distinct().toArray(String[]::new); 265 final Bundle result = new Bundle(); 266 result.putStringArray(EXTRA_RETURN_RESULT, packages); 267 remoteCallback.sendResult(result); 268 finish(); 269 } 270 onCommandReady(Intent intent)271 private void onCommandReady(Intent intent) { 272 final RemoteCallback callback = intent.getParcelableExtra(EXTRA_REMOTE_READY_CALLBACK); 273 if (callback != null) { 274 callback.sendResult(null); 275 } 276 } 277 awaitPackageBroadcast(RemoteCallback remoteCallback, String packageName, String action, long timeoutMs)278 private void awaitPackageBroadcast(RemoteCallback remoteCallback, String packageName, 279 String action, long timeoutMs) { 280 final IntentFilter filter = new IntentFilter(action); 281 filter.addDataScheme("package"); 282 filter.addDataSchemeSpecificPart(packageName, PatternMatcher.PATTERN_LITERAL); 283 final Object token = new Object(); 284 registerReceiver(new BroadcastReceiver() { 285 @Override 286 public void onReceive(Context context, Intent intent) { 287 final Bundle result = new Bundle(); 288 result.putString(EXTRA_DATA, intent.getDataString()); 289 remoteCallback.sendResult(result); 290 mainHandler.removeCallbacksAndMessages(token); 291 finish(); 292 } 293 }, filter); 294 mainHandler.postDelayed( 295 () -> sendError(remoteCallback, 296 new MissingBroadcastException(action, timeoutMs)), 297 token, timeoutMs); 298 } 299 awaitSuspendedPackagesBroadcast(RemoteCallback remoteCallback, List<String> awaitList, String action, long timeoutMs)300 private void awaitSuspendedPackagesBroadcast(RemoteCallback remoteCallback, 301 List<String> awaitList, String action, long timeoutMs) { 302 final IntentFilter filter = new IntentFilter(action); 303 final ArrayList<String> suspendedList = new ArrayList<>(); 304 final Object token = new Object(); 305 final Runnable sendResult = () -> { 306 final Bundle result = new Bundle(); 307 result.putStringArray(EXTRA_PACKAGES, suspendedList.toArray(new String[] {})); 308 remoteCallback.sendResult(result); 309 finish(); 310 }; 311 registerReceiver(new BroadcastReceiver() { 312 @Override 313 public void onReceive(Context context, Intent intent) { 314 final Bundle extras = intent.getExtras(); 315 final String[] changedList = extras.getStringArray( 316 Intent.EXTRA_CHANGED_PACKAGE_LIST); 317 suspendedList.addAll(Arrays.stream(changedList).filter( 318 p -> awaitList.contains(p)).collect(Collectors.toList())); 319 if (suspendedList.size() == awaitList.size()) { 320 mainHandler.removeCallbacksAndMessages(token); 321 sendResult.run(); 322 } 323 } 324 }, filter); 325 mainHandler.postDelayed(() -> sendResult.run(), token, timeoutMs); 326 } 327 awaitLauncherAppsCallback(RemoteCallback remoteCallback, int expectedEventCode, long timeoutMs)328 private void awaitLauncherAppsCallback(RemoteCallback remoteCallback, int expectedEventCode, 329 long timeoutMs) { 330 final Object token = new Object(); 331 final Bundle result = new Bundle(); 332 final LauncherApps launcherApps = getSystemService(LauncherApps.class); 333 final LauncherApps.Callback launcherAppsCallback = new LauncherApps.Callback() { 334 335 private void onPackageStateUpdated(String[] packageNames, int resultCode) { 336 if (resultCode != expectedEventCode) { 337 return; 338 } 339 340 mainHandler.removeCallbacksAndMessages(token); 341 result.putStringArray(EXTRA_PACKAGES, packageNames); 342 result.putInt(EXTRA_FLAGS, resultCode); 343 remoteCallback.sendResult(result); 344 345 launcherApps.unregisterCallback(this); 346 finish(); 347 } 348 349 @Override 350 public void onPackageRemoved(String packageName, UserHandle user) { 351 onPackageStateUpdated(new String[]{packageName}, CALLBACK_EVENT_PACKAGE_REMOVED); 352 } 353 354 @Override 355 public void onPackageAdded(String packageName, UserHandle user) { 356 onPackageStateUpdated(new String[]{packageName}, CALLBACK_EVENT_PACKAGE_ADDED); 357 } 358 359 @Override 360 public void onPackageChanged(String packageName, UserHandle user) { 361 onPackageStateUpdated(new String[]{packageName}, CALLBACK_EVENT_PACKAGE_CHANGED); 362 } 363 364 @Override 365 public void onPackagesAvailable(String[] packageNames, UserHandle user, 366 boolean replacing) { 367 onPackageStateUpdated(packageNames, CALLBACK_EVENT_PACKAGES_AVAILABLE); 368 } 369 370 @Override 371 public void onPackagesUnavailable(String[] packageNames, UserHandle user, 372 boolean replacing) { 373 onPackageStateUpdated(packageNames, CALLBACK_EVENT_PACKAGES_UNAVAILABLE); 374 } 375 376 @Override 377 public void onPackagesSuspended(String[] packageNames, UserHandle user) { 378 onPackageStateUpdated(packageNames, CALLBACK_EVENT_PACKAGES_SUSPENDED); 379 super.onPackagesSuspended(packageNames, user); 380 } 381 382 @Override 383 public void onPackagesUnsuspended(String[] packageNames, UserHandle user) { 384 onPackageStateUpdated(packageNames, CALLBACK_EVENT_PACKAGES_UNSUSPENDED); 385 super.onPackagesUnsuspended(packageNames, user); 386 } 387 }; 388 389 launcherApps.registerCallback(launcherAppsCallback); 390 391 mainHandler.postDelayed(() -> { 392 result.putStringArray(EXTRA_PACKAGES, new String[]{}); 393 result.putInt(EXTRA_FLAGS, CALLBACK_EVENT_INVALID); 394 remoteCallback.sendResult(result); 395 396 launcherApps.unregisterCallback(launcherAppsCallback); 397 finish(); 398 }, token, timeoutMs); 399 } 400 sendGetInstalledPackages(RemoteCallback remoteCallback, int flags)401 private void sendGetInstalledPackages(RemoteCallback remoteCallback, int flags) { 402 String[] packages = 403 getPackageManager().getInstalledPackages(flags) 404 .stream().map(p -> p.packageName).distinct().toArray(String[]::new); 405 Bundle result = new Bundle(); 406 result.putStringArray(EXTRA_RETURN_RESULT, packages); 407 remoteCallback.sendResult(result); 408 finish(); 409 } 410 sendQueryIntentActivities(RemoteCallback remoteCallback, Intent queryIntent)411 private void sendQueryIntentActivities(RemoteCallback remoteCallback, Intent queryIntent) { 412 final String[] resolveInfos = getPackageManager().queryIntentActivities( 413 queryIntent, 0 /* flags */).stream() 414 .map(ri -> ri.activityInfo.applicationInfo.packageName) 415 .distinct() 416 .toArray(String[]::new); 417 Bundle result = new Bundle(); 418 result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos); 419 remoteCallback.sendResult(result); 420 finish(); 421 } 422 sendQueryIntentServices(RemoteCallback remoteCallback, Intent queryIntent)423 private void sendQueryIntentServices(RemoteCallback remoteCallback, Intent queryIntent) { 424 final String[] resolveInfos = getPackageManager().queryIntentServices( 425 queryIntent, 0 /* flags */).stream() 426 .map(ri -> ri.serviceInfo.applicationInfo.packageName) 427 .distinct() 428 .toArray(String[]::new); 429 Bundle result = new Bundle(); 430 result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos); 431 remoteCallback.sendResult(result); 432 finish(); 433 } 434 sendQueryIntentProviders(RemoteCallback remoteCallback, Intent queryIntent)435 private void sendQueryIntentProviders(RemoteCallback remoteCallback, Intent queryIntent) { 436 final String[] resolveInfos = getPackageManager().queryIntentContentProviders( 437 queryIntent, 0 /* flags */).stream() 438 .map(ri -> ri.providerInfo.applicationInfo.packageName) 439 .distinct() 440 .toArray(String[]::new); 441 Bundle result = new Bundle(); 442 result.putStringArray(EXTRA_RETURN_RESULT, resolveInfos); 443 remoteCallback.sendResult(result); 444 finish(); 445 } 446 queryResolverForVisiblePackages(RemoteCallback remoteCallback, String authority)447 private void queryResolverForVisiblePackages(RemoteCallback remoteCallback, String authority) { 448 backgroundHandler.post(() -> { 449 Uri queryUri = Uri.parse("content://" + authority + "/test"); 450 Cursor query = getContentResolver().query(queryUri, null, null, null, null); 451 if (query == null || !query.moveToFirst()) { 452 sendError(remoteCallback, 453 new IllegalStateException( 454 "Query of " + queryUri + " could not be completed")); 455 return; 456 } 457 ArrayList<String> visiblePackages = new ArrayList<>(); 458 while (!query.isAfterLast()) { 459 visiblePackages.add(query.getString(0)); 460 query.moveToNext(); 461 } 462 query.close(); 463 464 mainHandler.post(() -> { 465 Bundle result = new Bundle(); 466 result.putStringArray(EXTRA_RETURN_RESULT, visiblePackages.toArray(new String[]{})); 467 remoteCallback.sendResult(result); 468 finish(); 469 }); 470 471 }); 472 } 473 sendError(RemoteCallback remoteCallback, Exception failure)474 private void sendError(RemoteCallback remoteCallback, Exception failure) { 475 Bundle result = new Bundle(); 476 result.putSerializable(EXTRA_ERROR, failure); 477 remoteCallback.sendResult(result); 478 finish(); 479 } 480 sendPackageInfo(RemoteCallback remoteCallback, String packageName)481 private void sendPackageInfo(RemoteCallback remoteCallback, String packageName) { 482 final PackageInfo pi; 483 try { 484 pi = getPackageManager().getPackageInfo(packageName, 0); 485 } catch (PackageManager.NameNotFoundException e) { 486 sendError(remoteCallback, e); 487 return; 488 } 489 Bundle result = new Bundle(); 490 result.putParcelable(EXTRA_RETURN_RESULT, pi); 491 remoteCallback.sendResult(result); 492 finish(); 493 } 494 sendPackagesForUid(RemoteCallback remoteCallback, int uid)495 private void sendPackagesForUid(RemoteCallback remoteCallback, int uid) { 496 final String[] packages = getPackageManager().getPackagesForUid(uid); 497 final Bundle result = new Bundle(); 498 result.putStringArray(EXTRA_RETURN_RESULT, packages); 499 remoteCallback.sendResult(result); 500 finish(); 501 } 502 sendNameForUid(RemoteCallback remoteCallback, int uid)503 private void sendNameForUid(RemoteCallback remoteCallback, int uid) { 504 final String name = getPackageManager().getNameForUid(uid); 505 final Bundle result = new Bundle(); 506 result.putString(EXTRA_RETURN_RESULT, name); 507 remoteCallback.sendResult(result); 508 finish(); 509 } 510 sendNamesForUids(RemoteCallback remoteCallback, int uid)511 private void sendNamesForUids(RemoteCallback remoteCallback, int uid) { 512 final String[] names = getPackageManager().getNamesForUids(new int[]{uid}); 513 final Bundle result = new Bundle(); 514 result.putStringArray(EXTRA_RETURN_RESULT, names); 515 remoteCallback.sendResult(result); 516 finish(); 517 } 518 sendCheckSignatures(RemoteCallback remoteCallback, int uid1, int uid2)519 private void sendCheckSignatures(RemoteCallback remoteCallback, int uid1, int uid2) { 520 final int signatureResult = getPackageManager().checkSignatures(uid1, uid2); 521 final Bundle result = new Bundle(); 522 result.putInt(EXTRA_RETURN_RESULT, signatureResult); 523 remoteCallback.sendResult(result); 524 finish(); 525 } 526 sendHasSigningCertificate(RemoteCallback remoteCallback, int uid, byte[] cert, int type)527 private void sendHasSigningCertificate(RemoteCallback remoteCallback, int uid, byte[] cert, 528 int type) { 529 final boolean signatureResult = getPackageManager().hasSigningCertificate(uid, cert, type); 530 final Bundle result = new Bundle(); 531 result.putBoolean(EXTRA_RETURN_RESULT, signatureResult); 532 remoteCallback.sendResult(result); 533 finish(); 534 } 535 536 /** 537 * Instead of sending a list of package names, this function sends a List of 538 * {@link SyncAdapterType}, since the {@link SyncAdapterType#getPackageName()} is a test api 539 * which can only be invoked in the instrumentation. 540 */ sendSyncAdapterTypes(RemoteCallback remoteCallback)541 private void sendSyncAdapterTypes(RemoteCallback remoteCallback) { 542 final SyncAdapterType[] types = ContentResolver.getSyncAdapterTypes(); 543 final ArrayList<Parcelable> parcelables = new ArrayList<>(); 544 for (SyncAdapterType type : types) { 545 parcelables.add(type); 546 } 547 final Bundle result = new Bundle(); 548 result.putParcelableArrayList(EXTRA_RETURN_RESULT, parcelables); 549 remoteCallback.sendResult(result); 550 finish(); 551 } 552 sendIsActivityEnabled(RemoteCallback remoteCallback, ComponentName componentName)553 private void sendIsActivityEnabled(RemoteCallback remoteCallback, ComponentName componentName) { 554 final LauncherApps launcherApps = getSystemService(LauncherApps.class); 555 final Bundle result = new Bundle(); 556 try { 557 result.putBoolean(EXTRA_RETURN_RESULT, launcherApps.isActivityEnabled(componentName, 558 Process.myUserHandle())); 559 } catch (IllegalArgumentException e) { 560 } 561 remoteCallback.sendResult(result); 562 finish(); 563 } 564 sendInstalledAppWidgetProviders(RemoteCallback remoteCallback)565 private void sendInstalledAppWidgetProviders(RemoteCallback remoteCallback) { 566 final AppWidgetManager appWidgetManager = getSystemService(AppWidgetManager.class); 567 final List<AppWidgetProviderInfo> providers = appWidgetManager.getInstalledProviders(); 568 final ArrayList<Parcelable> parcelables = new ArrayList<>(); 569 for (AppWidgetProviderInfo info : providers) { 570 parcelables.add(info); 571 } 572 final Bundle result = new Bundle(); 573 result.putParcelableArrayList(EXTRA_RETURN_RESULT, parcelables); 574 remoteCallback.sendResult(result); 575 finish(); 576 } 577 sendSyncAdapterPackagesForAuthorityAsUser(RemoteCallback remoteCallback, String authority, int userId)578 private void sendSyncAdapterPackagesForAuthorityAsUser(RemoteCallback remoteCallback, 579 String authority, int userId) { 580 final String[] syncAdapterPackages = ContentResolver 581 .getSyncAdapterPackagesForAuthorityAsUser(authority, userId); 582 final Bundle result = new Bundle(); 583 result.putStringArray(Intent.EXTRA_PACKAGES, syncAdapterPackages); 584 remoteCallback.sendResult(result); 585 finish(); 586 } 587 sendGetSharedLibraryDependentPackages(RemoteCallback remoteCallback, String sharedLibName)588 private void sendGetSharedLibraryDependentPackages(RemoteCallback remoteCallback, 589 String sharedLibName) { 590 final List<SharedLibraryInfo> sharedLibraryInfos = getPackageManager() 591 .getSharedLibraries(0 /* flags */); 592 SharedLibraryInfo sharedLibraryInfo = sharedLibraryInfos.stream().filter( 593 info -> sharedLibName.equals(info.getName())).findAny().orElse(null); 594 final String[] dependentPackages = sharedLibraryInfo == null ? null 595 : sharedLibraryInfo.getDependentPackages().stream() 596 .map(versionedPackage -> versionedPackage.getPackageName()) 597 .distinct().collect(Collectors.toList()).toArray(new String[]{}); 598 final Bundle result = new Bundle(); 599 result.putStringArray(Intent.EXTRA_PACKAGES, dependentPackages); 600 remoteCallback.sendResult(result); 601 finish(); 602 } 603 sendGetPreferredActivities(RemoteCallback remoteCallback)604 private void sendGetPreferredActivities(RemoteCallback remoteCallback) { 605 final List<IntentFilter> filters = new ArrayList<>(); 606 final List<ComponentName> activities = new ArrayList<>(); 607 getPackageManager().getPreferredActivities(filters, activities, null /* packageName*/); 608 final String[] packages = activities.stream() 609 .map(componentName -> componentName.getPackageName()).distinct() 610 .collect(Collectors.toList()).toArray(new String[]{}); 611 final Bundle result = new Bundle(); 612 result.putStringArray(Intent.EXTRA_PACKAGES, packages); 613 remoteCallback.sendResult(result); 614 finish(); 615 } 616 sendSetInstallerPackageName(RemoteCallback remoteCallback, String targetPackageName, String installerPackageName)617 private void sendSetInstallerPackageName(RemoteCallback remoteCallback, 618 String targetPackageName, String installerPackageName) { 619 try { 620 getPackageManager().setInstallerPackageName(targetPackageName, installerPackageName); 621 remoteCallback.sendResult(null); 622 finish(); 623 } catch (Exception e) { 624 sendError(remoteCallback, e); 625 } 626 } 627 628 @Override onActivityResult(int requestCode, int resultCode, Intent data)629 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 630 super.onActivityResult(requestCode, resultCode, data); 631 final RemoteCallback remoteCallback = callbacks.get(requestCode); 632 if (resultCode != RESULT_OK) { 633 Exception e = (Exception) data.getSerializableExtra(EXTRA_ERROR); 634 sendError(remoteCallback, e == null ? new Exception("Result was " + resultCode) : e); 635 return; 636 } 637 final Bundle result = new Bundle(); 638 result.putParcelable(EXTRA_RETURN_RESULT, data.getParcelableExtra(EXTRA_RETURN_RESULT)); 639 remoteCallback.sendResult(result); 640 finish(); 641 } 642 bindService(RemoteCallback remoteCallback, String packageName)643 private void bindService(RemoteCallback remoteCallback, String packageName) { 644 final String SERVICE_NAME = "android.appenumeration.testapp.DummyService"; 645 final Intent intent = new Intent(); 646 intent.setClassName(packageName, SERVICE_NAME); 647 final ServiceConnection serviceConnection = new ServiceConnection() { 648 @Override 649 public void onServiceConnected(ComponentName className, IBinder service) { 650 // No-op 651 } 652 653 @Override 654 public void onServiceDisconnected(ComponentName className) { 655 // No-op 656 } 657 658 @Override 659 public void onBindingDied(ComponentName name) { 660 // Remote service die 661 finish(); 662 } 663 664 @Override 665 public void onNullBinding(ComponentName name) { 666 // Since the DummyService doesn't implement onBind, it returns null and 667 // onNullBinding would be called. Use postDelayed to keep this service 668 // connection alive for 3 seconds. 669 mainHandler.postDelayed(() -> { 670 unbindService(this); 671 finish(); 672 }, TIMEOUT_MS); 673 } 674 }; 675 676 final boolean bound = bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 677 final Bundle result = new Bundle(); 678 result.putBoolean(EXTRA_RETURN_RESULT, bound); 679 remoteCallback.sendResult(result); 680 // Don't invoke finish() right here if service is bound successfully to keep the service 681 // connection alive since the ServiceRecord would be remove from the ServiceMap once no 682 // client is binding the service. 683 if (!bound) finish(); 684 } 685 } 686