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