1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tradefed.device;
18 
19 import com.android.ddmlib.IDevice;
20 import com.android.tradefed.result.InputStreamSource;
21 import com.android.tradefed.util.KeyguardControllerState;
22 
23 import java.io.File;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 
30 /**
31  * Provides an reliable and slightly higher level API to a ddmlib {@link IDevice}.
32  * <p/>
33  * Retries device commands for a configurable amount, and provides a device recovery
34  * interface for devices which are unresponsive.
35  */
36 public interface ITestDevice extends INativeDevice {
37 
38     public enum RecoveryMode {
39         /** don't attempt to recover device. */
40         NONE,
41         /** recover device to online state only */
42         ONLINE,
43         /**
44          * Recover device into fully testable state - framework is up, and external storage is
45          * mounted.
46          */
47         AVAILABLE
48     }
49 
50     /**
51      * A simple struct class to store information about a single mountpoint
52      */
53     public static class MountPointInfo {
54         public String filesystem;
55         public String mountpoint;
56         public String type;
57         public List<String> options;
58 
59         /** Simple constructor */
MountPointInfo()60         public MountPointInfo() {}
61 
62         /**
63          * Convenience constructor to set all members
64          */
MountPointInfo(String filesystem, String mountpoint, String type, List<String> options)65         public MountPointInfo(String filesystem, String mountpoint, String type,
66                 List<String> options) {
67             this.filesystem = filesystem;
68             this.mountpoint = mountpoint;
69             this.type = type;
70             this.options = options;
71         }
72 
MountPointInfo(String filesystem, String mountpoint, String type, String optString)73         public MountPointInfo(String filesystem, String mountpoint, String type, String optString) {
74             this(filesystem, mountpoint, type, splitMountOptions(optString));
75         }
76 
splitMountOptions(String options)77         public static List<String> splitMountOptions(String options) {
78             List<String> list = Arrays.asList(options.split(","));
79             return list;
80         }
81 
82         @Override
toString()83         public String toString() {
84             return String.format("%s %s %s %s", this.filesystem, this.mountpoint, this.type,
85                     this.options);
86         }
87     }
88 
89     /** A simple struct class to store information about a single APEX */
90     public static class ApexInfo {
91         public final String name;
92         public final long versionCode;
93         public final String sourceDir;
94 
ApexInfo(String name, long versionCode, String sourceDir)95         public ApexInfo(String name, long versionCode, String sourceDir) {
96             this.name = name;
97             this.versionCode = versionCode;
98             this.sourceDir = sourceDir;
99         }
100 
ApexInfo(String name, long versionCode)101         public ApexInfo(String name, long versionCode) {
102             this(name, versionCode, "");
103         }
104 
105         @Override
equals(Object other)106         public boolean equals(Object other) {
107             if (other != null && other instanceof ApexInfo) {
108                 ApexInfo ai = (ApexInfo) other;
109                 return name.equals(ai.name) && versionCode == ai.versionCode;
110             }
111             return false;
112         }
113 
114         @Override
hashCode()115         public int hashCode() {
116             // no need to consider versionCode here.
117             return name.hashCode();
118         }
119 
120         @Override
toString()121         public String toString() {
122             return "packageName: "
123                     + name
124                     + ", versionCode: "
125                     + versionCode
126                     + ", sourceDir: "
127                     + sourceDir;
128         }
129     }
130 
131     /**
132      * Install an Android package on device.
133      *
134      * @param packageFile the apk file to install
135      * @param reinstall <code>true</code> if a reinstall should be performed
136      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
137      *     options.
138      * @return a {@link String} with an error code, or <code>null</code> if success.
139      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
140      *     recovered.
141      */
installPackage(File packageFile, boolean reinstall, String... extraArgs)142     public String installPackage(File packageFile, boolean reinstall, String... extraArgs)
143             throws DeviceNotAvailableException;
144 
145     /**
146      * Install an Android package on device.
147      *
148      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
149      * install time should call this function.
150      *
151      * @param packageFile the apk file to install
152      * @param reinstall <code>true</code> if a reinstall should be performed
153      * @param grantPermissions if all runtime permissions should be granted at install time
154      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
155      *     options.
156      * @return a {@link String} with an error code, or <code>null</code> if success.
157      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
158      *     recovered.
159      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
160      *     on device.
161      */
installPackage( File packageFile, boolean reinstall, boolean grantPermissions, String... extraArgs)162     public String installPackage(
163             File packageFile, boolean reinstall, boolean grantPermissions, String... extraArgs)
164             throws DeviceNotAvailableException;
165 
166     /**
167      * Install an Android package on device for a given user.
168      *
169      * @param packageFile the apk file to install
170      * @param reinstall <code>true</code> if a reinstall should be performed
171      * @param userId the integer user id to install for.
172      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
173      *     options.
174      * @return a {@link String} with an error code, or <code>null</code> if success.
175      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
176      *     recovered.
177      */
installPackageForUser( File packageFile, boolean reinstall, int userId, String... extraArgs)178     public String installPackageForUser(
179             File packageFile, boolean reinstall, int userId, String... extraArgs)
180             throws DeviceNotAvailableException;
181 
182     /**
183      * Install an Android package on device for a given user.
184      *
185      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
186      * install time should call this function.
187      *
188      * @param packageFile the apk file to install
189      * @param reinstall <code>true</code> if a reinstall should be performed
190      * @param grantPermissions if all runtime permissions should be granted at install time
191      * @param userId the integer user id to install for.
192      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
193      *     options.
194      * @return a {@link String} with an error code, or <code>null</code> if success.
195      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
196      *     recovered.
197      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
198      *     on device.
199      */
installPackageForUser( File packageFile, boolean reinstall, boolean grantPermissions, int userId, String... extraArgs)200     public String installPackageForUser(
201             File packageFile,
202             boolean reinstall,
203             boolean grantPermissions,
204             int userId,
205             String... extraArgs)
206             throws DeviceNotAvailableException;
207 
208     /**
209      * Uninstall an Android package from device.
210      *
211      * @param packageName the Android package to uninstall
212      * @return a {@link String} with an error code, or <code>null</code> if success.
213      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
214      *     recovered.
215      */
uninstallPackage(String packageName)216     public String uninstallPackage(String packageName) throws DeviceNotAvailableException;
217 
218     /**
219      * Install an Android application made of several APK files (one main and extra split packages).
220      * See "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
221      * several files.
222      *
223      * @param packageFiles the local apk files
224      * @param reinstall <code>true</code> if a reinstall should be performed
225      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
226      *     options.
227      * @return a {@link String} with an error code, or <code>null</code> if success.
228      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
229      *     recovered.
230      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
231      *     on device.
232      */
installPackages( List<File> packageFiles, boolean reinstall, String... extraArgs)233     public default String installPackages(
234             List<File> packageFiles, boolean reinstall, String... extraArgs)
235             throws DeviceNotAvailableException {
236         throw new UnsupportedOperationException("No support for Package Manager's features");
237     }
238 
239     /**
240      * Install an Android application made of several APK files (one main and extra split packages)
241      * that are sitting on the android device. See
242      * "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
243      * several files.
244      *
245      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
246      * install time should call this function.
247      *
248      * @param packageFiles the remote apk file paths to install
249      * @param reinstall <code>true</code> if a reinstall should be performed
250      * @param grantPermissions if all runtime permissions should be granted at install time
251      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
252      *     options.
253      * @return a {@link String} with an error code, or <code>null</code> if success.
254      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
255      *     recovered.
256      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
257      *     on device.
258      */
installPackages( List<File> packageFiles, boolean reinstall, boolean grantPermissions, String... extraArgs)259     public default String installPackages(
260             List<File> packageFiles,
261             boolean reinstall,
262             boolean grantPermissions,
263             String... extraArgs)
264             throws DeviceNotAvailableException {
265         throw new UnsupportedOperationException("No support for Package Manager's features");
266     }
267 
268     /**
269      * Install an Android application made of several APK files (one main and extra split packages)
270      * for a given user. See "https://developer.android.com/studio/build/configure-apk-splits" on
271      * how to split apk to several files.
272      *
273      * @param packageFiles the local apk files
274      * @param reinstall <code>true</code> if a reinstall should be performed
275      * @param userId the integer user id to install for.
276      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
277      *     options.
278      * @return a {@link String} with an error code, or <code>null</code> if success.
279      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
280      *     recovered.
281      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
282      *     on device.
283      */
installPackagesForUser( List<File> packageFiles, boolean reinstall, int userId, String... extraArgs)284     public default String installPackagesForUser(
285             List<File> packageFiles, boolean reinstall, int userId, String... extraArgs)
286             throws DeviceNotAvailableException {
287         throw new UnsupportedOperationException("No support for Package Manager's features");
288     }
289 
290     /**
291      * Install an Android application made of several APK files (one main and extra split packages)
292      * for a given user. See "https://developer.android.com/studio/build/configure-apk-splits" on
293      * how to split apk to several files.
294      *
295      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
296      * install time should call this function.
297      *
298      * @param packageFiles the local apk files
299      * @param reinstall <code>true</code> if a reinstall should be performed
300      * @param grantPermissions if all runtime permissions should be granted at install time
301      * @param userId the integer user id to install for.
302      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
303      *     options.
304      * @return a {@link String} with an error code, or <code>null</code> if success.
305      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
306      *     recovered.
307      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
308      *     on device.
309      */
installPackagesForUser( List<File> packageFiles, boolean reinstall, boolean grantPermissions, int userId, String... extraArgs)310     public default String installPackagesForUser(
311             List<File> packageFiles,
312             boolean reinstall,
313             boolean grantPermissions,
314             int userId,
315             String... extraArgs)
316             throws DeviceNotAvailableException {
317         throw new UnsupportedOperationException("No support for Package Manager's features");
318     }
319 
320     /**
321      * Install an Android application made of several APK files (one main and extra split packages)
322      * that are sitting on the android device. See
323      * "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
324      * several files.
325      *
326      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
327      * install time should call this function.
328      *
329      * @param remoteApkPaths the remote apk file paths
330      * @param reinstall <code>true</code> if a reinstall should be performed
331      * @param grantPermissions if all runtime permissions should be granted at install time
332      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
333      *     options.
334      * @return a {@link String} with an error code, or <code>null</code> if success.
335      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
336      *     recovered.
337      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
338      *     on device.
339      */
installRemotePackages( List<String> remoteApkPaths, boolean reinstall, boolean grantPermissions, String... extraArgs)340     public default String installRemotePackages(
341             List<String> remoteApkPaths,
342             boolean reinstall,
343             boolean grantPermissions,
344             String... extraArgs)
345             throws DeviceNotAvailableException {
346         throw new UnsupportedOperationException("No support for Package Manager's features");
347     }
348 
349     /**
350      * Install an Android application made of several APK files (one main and extra split packages)
351      * that are sitting on the android device. See
352      * "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
353      * several files.
354      *
355      * @param remoteApkPaths the remote apk file paths
356      * @param reinstall <code>true</code> if a reinstall should be performed
357      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
358      *     options.
359      * @return a {@link String} with an error code, or <code>null</code> if success.
360      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
361      *     recovered.
362      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
363      *     on device.
364      */
installRemotePackages( List<String> remoteApkPaths, boolean reinstall, String... extraArgs)365     public default String installRemotePackages(
366             List<String> remoteApkPaths, boolean reinstall, String... extraArgs)
367             throws DeviceNotAvailableException {
368         throw new UnsupportedOperationException("No support for Package Manager's features");
369     }
370 
371 
372     /**
373      * Grabs a screenshot from the device.
374      *
375      * @return a {@link InputStreamSource} of the screenshot in png format, or <code>null</code> if
376      *         the screenshot was not successful.
377      * @throws DeviceNotAvailableException
378      */
getScreenshot()379     public InputStreamSource getScreenshot() throws DeviceNotAvailableException;
380 
381     /**
382      * Grabs a screenshot from the device.
383      * Recommended to use getScreenshot(format) instead with JPEG encoding for smaller size
384      * @param format supported PNG, JPEG
385      * @return a {@link InputStreamSource} of the screenshot in format, or <code>null</code> if
386      *         the screenshot was not successful.
387      * @throws DeviceNotAvailableException
388      */
getScreenshot(String format)389     public InputStreamSource getScreenshot(String format) throws DeviceNotAvailableException;
390 
391     /**
392      * Grabs a screenshot from the device. Recommended to use {@link #getScreenshot(String)} instead
393      * with JPEG encoding for smaller size.
394      *
395      * @param format supported PNG, JPEG
396      * @param rescale if screenshot should be rescaled to reduce the size of resulting image
397      * @return a {@link InputStreamSource} of the screenshot in format, or <code>null</code> if the
398      *     screenshot was not successful.
399      * @throws DeviceNotAvailableException
400      */
getScreenshot(String format, boolean rescale)401     public InputStreamSource getScreenshot(String format, boolean rescale)
402             throws DeviceNotAvailableException;
403 
404     /**
405      * Grabs a screenshot from the device given display id. Format is PNG.
406      *
407      * <p>TODO: extend the implementations above to support 'format' and 'rescale'
408      *
409      * @param displayId the display id of the screen to get screenshot from.
410      * @return a {@link InputStreamSource} of the screenshot in format, or <code>null</code> if the
411      *     screenshot was not successful.
412      * @throws DeviceNotAvailableException
413      */
getScreenshot(long displayId)414     public InputStreamSource getScreenshot(long displayId) throws DeviceNotAvailableException;
415 
416     /**
417      * Clears the last connected wifi network. This should be called when starting a new invocation
418      * to avoid connecting to the wifi network used in the previous test after device reboots.
419      */
clearLastConnectedWifiNetwork()420     public void clearLastConnectedWifiNetwork();
421 
422     /**
423      * Connects to a wifi network.
424      * <p/>
425      * Turns on wifi and blocks until a successful connection is made to the specified wifi network.
426      * Once a connection is made, the instance will try to restore the connection after every reboot
427      * until {@link ITestDevice#disconnectFromWifi()} or
428      * {@link ITestDevice#clearLastConnectedWifiNetwork()} is called.
429      *
430      * @param wifiSsid the wifi ssid to connect to
431      * @param wifiPsk PSK passphrase or null if unencrypted
432      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
433      *         otherwise
434      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
435      *             recovered.
436      */
connectToWifiNetwork(String wifiSsid, String wifiPsk)437     public boolean connectToWifiNetwork(String wifiSsid, String wifiPsk)
438             throws DeviceNotAvailableException;
439 
440     /**
441      * Connects to a wifi network.
442      * <p/>
443      * Turns on wifi and blocks until a successful connection is made to the specified wifi network.
444      * Once a connection is made, the instance will try to restore the connection after every reboot
445      * until {@link ITestDevice#disconnectFromWifi()} or
446      * {@link ITestDevice#clearLastConnectedWifiNetwork()} is called.
447      *
448      * @param wifiSsid the wifi ssid to connect to
449      * @param wifiPsk PSK passphrase or null if unencrypted
450      * @param scanSsid whether to scan for hidden SSID for this network.
451      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
452      *         otherwise
453      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
454      *             recovered.
455      */
connectToWifiNetwork(String wifiSsid, String wifiPsk, boolean scanSsid)456     public boolean connectToWifiNetwork(String wifiSsid, String wifiPsk, boolean scanSsid)
457             throws DeviceNotAvailableException;
458 
459     /**
460      * A variant of {@link #connectToWifiNetwork(String, String)} that only connects if device
461      * currently does not have network connectivity.
462      *
463      * @param wifiSsid
464      * @param wifiPsk
465      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
466      *         otherwise
467      * @throws DeviceNotAvailableException
468      */
connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk)469     public boolean connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk)
470             throws DeviceNotAvailableException;
471 
472     /**
473      * A variant of {@link #connectToWifiNetwork(String, String)} that only connects if device
474      * currently does not have network connectivity.
475      *
476      * @param wifiSsid
477      * @param wifiPsk
478      * @param scanSsid whether to scan for hidden SSID for this network
479      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
480      *         otherwise
481      * @throws DeviceNotAvailableException
482      */
connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk, boolean scanSsid)483     public boolean connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk, boolean scanSsid)
484             throws DeviceNotAvailableException;
485 
486     /**
487      * Disconnects from a wifi network.
488      * <p/>
489      * Removes all networks from known networks list and disables wifi.
490      *
491      * @return <code>true</code> if disconnected from wifi network successfully. <code>false</code>
492      *         if disconnect failed.
493      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
494      *             recovered.
495      */
disconnectFromWifi()496     public boolean disconnectFromWifi() throws DeviceNotAvailableException;
497 
498     /**
499      * Test if wifi is enabled.
500      * <p/>
501      * Checks if wifi is enabled on device. Useful for asserting wifi status before tests that
502      * shouldn't run with wifi, e.g. mobile data tests.
503      *
504      * @return <code>true</code> if wifi is enabled. <code>false</code> if disabled
505      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
506      *             recovered.
507      */
isWifiEnabled()508     public boolean isWifiEnabled() throws DeviceNotAvailableException;
509 
510     /**
511      * Gets the device's IP address.
512      *
513      * @return the device's IP address, or <code>null</code> if device has no IP address
514      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
515      *             recovered.
516      */
getIpAddress()517     public String getIpAddress() throws DeviceNotAvailableException;
518 
519     /**
520      * Enables network monitoring on device.
521      *
522      * @return <code>true</code> if monitoring is enabled successfully. <code>false</code>
523      *         if it failed.
524      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
525      *             recovered.
526      */
enableNetworkMonitor()527     public boolean enableNetworkMonitor() throws DeviceNotAvailableException;
528 
529     /**
530      * Disables network monitoring on device.
531      *
532      * @return <code>true</code> if monitoring is disabled successfully. <code>false</code>
533      *         if it failed.
534      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
535      *             recovered.
536      */
disableNetworkMonitor()537     public boolean disableNetworkMonitor() throws DeviceNotAvailableException;
538 
539     /**
540      * Check that device has network connectivity.
541      *
542      * @return <code>true</code> if device has a working network connection,
543      *          <code>false</code> overwise.
544      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
545      *          recovered.
546      */
checkConnectivity()547     public boolean checkConnectivity() throws DeviceNotAvailableException;
548 
549     /**
550      * Attempt to dismiss any error dialogs currently displayed on device UI.
551      *
552      * @return <code>true</code> if no dialogs were present or dialogs were successfully cleared.
553      *         <code>false</code> otherwise.
554      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
555      *             recovered.
556      */
clearErrorDialogs()557     public boolean clearErrorDialogs() throws DeviceNotAvailableException;
558 
559     /**
560      * Return an object to get the current state of the keyguard or null if not supported.
561      *
562      * @return a {@link KeyguardControllerState} containing a snapshot of the state of the keyguard
563      *     and returns Null if the Keyguard query is not supported.
564      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
565      *     recovered.
566      */
getKeyguardState()567     public KeyguardControllerState getKeyguardState() throws DeviceNotAvailableException;
568 
569     /**
570      * Fetch the test options for the device.
571      *
572      * @return {@link TestDeviceOptions} related to the device under test.
573      */
getOptions()574     public TestDeviceOptions getOptions();
575 
576     /**
577      * Fetch the application package names present on the device.
578      *
579      * @return {@link Set} of {@link String} package names currently installed on the device.
580      * @throws DeviceNotAvailableException
581      */
getInstalledPackageNames()582     public Set<String> getInstalledPackageNames() throws DeviceNotAvailableException;
583 
584     /**
585      * Query the device for a given package name to check if it's currently installed or not.
586      *
587      * @return True if the package is reported as installed. False otherwise.
588      * @throws DeviceNotAvailableException
589      */
isPackageInstalled(String packageName)590     public boolean isPackageInstalled(String packageName) throws DeviceNotAvailableException;
591 
592     /**
593      * Query the device for a given package name and given user id to check if it's currently
594      * installed or not for that user.
595      *
596      * @param packageName the package we are checking if it's installed.
597      * @param userId The user id we are checking the package is installed for. If null, primary user
598      *     zero will be used.
599      * @return True if the package is reported as installed. False otherwise.
600      * @throws DeviceNotAvailableException
601      */
isPackageInstalled(String packageName, String userId)602     public boolean isPackageInstalled(String packageName, String userId)
603             throws DeviceNotAvailableException;
604 
605     /**
606      * Fetch the information about APEXes activated on the device.
607      *
608      * @return {@link Set} of {@link ApexInfo} currently activated on the device
609      * @throws DeviceNotAvailableException
610      */
getActiveApexes()611     public Set<ApexInfo> getActiveApexes() throws DeviceNotAvailableException;
612 
613     /**
614      * Fetch the application package names that can be uninstalled. This is presently defined as
615      * non-system packages, and updated system packages.
616      *
617      * @return {@link Set} of uninstallable {@link String} package names currently installed on the
618      *         device.
619      * @throws DeviceNotAvailableException
620      */
getUninstallablePackageNames()621     public Set<String> getUninstallablePackageNames() throws DeviceNotAvailableException;
622 
623     /**
624      * Fetch information about a package installed on device.
625      *
626      * @return the {@link PackageInfo} or <code>null</code> if information could not be retrieved
627      * @throws DeviceNotAvailableException
628      */
getAppPackageInfo(String packageName)629     public PackageInfo getAppPackageInfo(String packageName) throws DeviceNotAvailableException;
630 
631     /**
632      * Fetch information of packages installed on the device.
633      *
634      * @return {@link List} of {@link PackageInfo}s installed on the device.
635      * @throws DeviceNotAvailableException
636      */
getAppPackageInfos()637     public List<PackageInfo> getAppPackageInfos() throws DeviceNotAvailableException;
638 
639     /**
640      * Determines if multi user is supported.
641      *
642      * @return true if multi user is supported, false otherwise
643      * @throws DeviceNotAvailableException
644      */
isMultiUserSupported()645     public boolean isMultiUserSupported() throws DeviceNotAvailableException;
646 
647     /**
648      * Create a user with a given name and default flags 0.
649      *
650      * @param name of the user to create on the device
651      * @return the integer for the user id created
652      * @throws DeviceNotAvailableException
653      */
createUser(String name)654     public int createUser(String name) throws DeviceNotAvailableException, IllegalStateException;
655 
656     /**
657      * Create a user with a given name and default flags 0.
658      *
659      * @param name of the user to create on the device
660      * @return the integer for the user id created or -1 for error.
661      * @throws DeviceNotAvailableException
662      */
createUserNoThrow(String name)663     public int createUserNoThrow(String name) throws DeviceNotAvailableException;
664 
665     /**
666      * Create a user with a given name and the provided flags
667      *
668      * @param name of the user to create on the device
669      * @param guest enable the user flag --guest during creation
670      * @param ephemeral enable the user flag --ephemeral during creation
671      * @return id of the created user
672      * @throws DeviceNotAvailableException
673      */
createUser(String name, boolean guest, boolean ephemeral)674     public int createUser(String name, boolean guest, boolean ephemeral)
675             throws DeviceNotAvailableException, IllegalStateException;
676 
677     /**
678      * Remove a given user from the device.
679      *
680      * @param userId of the user to remove
681      * @return true if we were successful in removing the user, false otherwise.
682      * @throws DeviceNotAvailableException
683      */
removeUser(int userId)684     public boolean removeUser(int userId) throws DeviceNotAvailableException;
685 
686     /**
687      * Gets the list of users on the device. Will throw {@link DeviceRuntimeException} if output
688      * from device is not as expected.
689      *
690      * @return the list of user ids.
691      * @throws DeviceNotAvailableException
692      * @throws DeviceRuntimeException
693      */
listUsers()694     ArrayList<Integer> listUsers() throws DeviceNotAvailableException;
695 
696     /**
697      * Gets the Map of useId to {@link UserInfo} on the device. Will throw {@link
698      * DeviceRuntimeException} if output from device is not as expected.
699      *
700      * @return the list of UserInfo objects.
701      * @throws DeviceNotAvailableException
702      * @throws DeviceRuntimeException
703      */
getUserInfos()704     public Map<Integer, UserInfo> getUserInfos() throws DeviceNotAvailableException;
705 
706     /**
707      * Get the maximum number of supported users. Defaults to 0.
708      *
709      * @return an integer indicating the number of supported users
710      * @throws DeviceNotAvailableException
711      */
getMaxNumberOfUsersSupported()712     public int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException;
713 
714     /**
715      * Get the maximum number of supported simultaneously running users. Defaults to 0.
716      *
717      * @return an integer indicating the number of simultaneously running users
718      * @throws DeviceNotAvailableException
719      */
getMaxNumberOfRunningUsersSupported()720     public int getMaxNumberOfRunningUsersSupported() throws DeviceNotAvailableException;
721 
722     /**
723      * Starts a given user in the background if it is currently stopped. If the user is already
724      * running in the background, this method is a NOOP.
725      * @param userId of the user to start in the background
726      * @return true if the user was successfully started in the background.
727      * @throws DeviceNotAvailableException
728      */
startUser(int userId)729     public boolean startUser(int userId) throws DeviceNotAvailableException;
730 
731     /**
732      * Starts a given user in the background if it is currently stopped. If the user is already
733      * running in the background, this method is a NOOP. Possible to provide extra flag to wait for
734      * the operation to have effect.
735      *
736      * @param userId of the user to start in the background
737      * @param waitFlag will make the command wait until user is started and unlocked.
738      * @return true if the user was successfully started in the background.
739      * @throws DeviceNotAvailableException
740      */
startUser(int userId, boolean waitFlag)741     public boolean startUser(int userId, boolean waitFlag) throws DeviceNotAvailableException;
742 
743     /**
744      * Stops a given user. If the user is already stopped, this method is a NOOP.
745      * Cannot stop current and system user.
746      *
747      * @param userId of the user to stop.
748      * @return true if the user was successfully stopped.
749      * @throws DeviceNotAvailableException
750      */
stopUser(int userId)751     public boolean stopUser(int userId) throws DeviceNotAvailableException;
752 
753     /**
754      * Stop a given user. Possible to provide extra flags to wait for the operation to have effect,
755      * and force terminate the user. Cannot stop current and system user.
756      *
757      * @param userId of the user to stop.
758      * @param waitFlag will make the command wait until user is stopped.
759      * @param forceFlag will force stop the user.
760      * @return true if the user was successfully stopped.
761      * @throws DeviceNotAvailableException
762      */
stopUser(int userId, boolean waitFlag, boolean forceFlag)763     public boolean stopUser(int userId, boolean waitFlag, boolean forceFlag)
764             throws DeviceNotAvailableException;
765 
766     /**
767      * Returns the primary user id.
768      *
769      * @return the userId of the primary user if there is one, and null if there is no primary user.
770      * @throws DeviceNotAvailableException
771      * @throws DeviceRuntimeException if the output from the device is not as expected.
772      */
getPrimaryUserId()773     public Integer getPrimaryUserId() throws DeviceNotAvailableException;
774 
775     /**
776      * Return the id of the current running user. In case of error, return -10000.
777      *
778      * @throws DeviceNotAvailableException
779      */
getCurrentUser()780     public int getCurrentUser() throws DeviceNotAvailableException;
781 
782     /**
783      * Find and return the flags of a given user.
784      * Flags are defined in "android.content.pm.UserInfo" class in Android Open Source Project.
785      *
786      * @return the flags associated with the userId provided if found, -10000 in any other cases.
787      * @throws DeviceNotAvailableException
788      */
getUserFlags(int userId)789     public int getUserFlags(int userId) throws DeviceNotAvailableException;
790 
791     /**
792      * Return whether the specified user is a secondary user according to it's flags.
793      *
794      * @return true if the user is secondary, false otherwise.
795      * @throws DeviceNotAvailableException
796      */
isUserSecondary(int userId)797     public boolean isUserSecondary(int userId) throws DeviceNotAvailableException;
798 
799     /**
800      * Return the serial number associated to the userId if found, -10000 in any other cases.
801      *
802      * @throws DeviceNotAvailableException
803      */
getUserSerialNumber(int userId)804     public int getUserSerialNumber(int userId) throws DeviceNotAvailableException;
805 
806     /**
807      * Switch to another userId with a default timeout. {@link #switchUser(int, long)}.
808      *
809      * @return True if the new userId matches the userId provider. False otherwise.
810      * @throws DeviceNotAvailableException
811      */
switchUser(int userId)812     public boolean switchUser(int userId) throws DeviceNotAvailableException;
813 
814     /**
815      * Switch to another userId with the provided timeout as deadline.
816      * Attempt to disable keyguard after user change is successful.
817      *
818      * @param timeout to wait before returning false for switch-user failed.
819      * @return True if the new userId matches the userId provider. False otherwise.
820      * @throws DeviceNotAvailableException
821      */
switchUser(int userId, long timeout)822     public boolean switchUser(int userId, long timeout) throws DeviceNotAvailableException;
823 
824     /**
825      * Check if a given user is running.
826      *
827      * @return True if the user is running, false in every other cases.
828      * @throws DeviceNotAvailableException
829      */
isUserRunning(int userId)830     public boolean isUserRunning(int userId) throws DeviceNotAvailableException;
831 
832     /**
833      * Check if a feature is available on a device.
834      *
835      * @param feature which format should be "feature:<name>" or "<name>" directly.
836      * @return True if feature is found, false otherwise.
837      * @throws DeviceNotAvailableException
838      */
hasFeature(String feature)839     public boolean hasFeature(String feature) throws DeviceNotAvailableException;
840 
841     /**
842      * See {@link #getSetting(int, String, String)} and performed on system user.
843      *
844      * @throws DeviceNotAvailableException
845      */
getSetting(String namespace, String key)846     public String getSetting(String namespace, String key) throws DeviceNotAvailableException;
847 
848     /**
849      * Return the value of the requested setting.
850      * namespace must be one of: {"system", "secure", "global"}
851      *
852      * @return the value associated with the namespace:key of a user. Null if not found.
853      * @throws DeviceNotAvailableException
854      */
getSetting(int userId, String namespace, String key)855     public String getSetting(int userId, String namespace, String key)
856             throws DeviceNotAvailableException;
857 
858     /**
859      * Return key value pairs of requested namespace.
860      *
861      * @param namespace must be one of {"system", "secure", "global"}
862      * @return the map of key value pairs. Null if namespace is not supported.
863      * @throws DeviceNotAvailableException
864      */
getAllSettings(String namespace)865     public Map<String, String> getAllSettings(String namespace) throws DeviceNotAvailableException;
866 
867     /**
868      * See {@link #setSetting(int, String, String, String)} and performed on system user.
869      *
870      * @throws DeviceNotAvailableException
871      */
setSetting(String namespace, String key, String value)872     public void setSetting(String namespace, String key, String value)
873             throws DeviceNotAvailableException;
874 
875     /**
876      * Add a setting value to the namespace of a given user. Some settings will only be available
877      * after a reboot.
878      * namespace must be one of: {"system", "secure", "global"}
879      *
880      * @throws DeviceNotAvailableException
881      */
setSetting(int userId, String namespace, String key, String value)882     public void setSetting(int userId, String namespace, String key, String value)
883             throws DeviceNotAvailableException;
884 
885     /**
886      * Find and return the android-id associated to a userId, null if not found.
887      *
888      * @throws DeviceNotAvailableException
889      */
getAndroidId(int userId)890     public String getAndroidId(int userId) throws DeviceNotAvailableException;
891 
892     /**
893      * Create a Map of android ids found matching user ids. There is no insurance that each user
894      * id will found an android id associated in this function so some user ids may match null.
895      *
896      * @return Map of android ids found matching user ids.
897      * @throws DeviceNotAvailableException
898      */
getAndroidIds()899     public Map<Integer, String> getAndroidIds() throws DeviceNotAvailableException;
900 
901     /**
902      * Set a device admin component as device owner in given user.
903      *
904      * @param componentName of device admin to be device owner.
905      * @param userId of the user that the device owner lives in.
906      * @return True if it is successful, false otherwise.
907      * @throws DeviceNotAvailableException
908      */
setDeviceOwner(String componentName, int userId)909     public boolean setDeviceOwner(String componentName, int userId)
910             throws DeviceNotAvailableException;
911 
912     /**
913      * Remove given device admin in given user and return {@code true} if it is successful, {@code
914      * false} otherwise.
915      *
916      * @param componentName of device admin to be removed.
917      * @param userId of user that the device admin lives in.
918      * @return True if it is successful, false otherwise.
919      * @throws DeviceNotAvailableException
920      */
removeAdmin(String componentName, int userId)921     public boolean removeAdmin(String componentName, int userId) throws DeviceNotAvailableException;
922 
923     /**
924      * Remove all existing device profile owners with the best effort.
925      *
926      * @throws DeviceNotAvailableException
927      */
removeOwners()928     public void removeOwners() throws DeviceNotAvailableException;
929 
930     /**
931      * Attempts to disable the keyguard.
932      * <p>
933      * First wait for the input dispatch to become ready, this happens around the same time when the
934      * device reports BOOT_COMPLETE, apparently asynchronously, because current framework
935      * implementation has occasional race condition. Then command is sent to dismiss keyguard (works
936      * on non-secure ones only)
937      */
disableKeyguard()938     public void disableKeyguard() throws DeviceNotAvailableException;
939 
940     /**
941      * Attempt to dump the heap from the system_server. It is the caller responsibility to clean up
942      * the dumped file.
943      *
944      * @param process the name of the device process to dumpheap on.
945      * @param devicePath the path on the device where to put the dump. This must be a location where
946      *     permissions allow it.
947      * @return the {@link File} containing the report. Null if something failed.
948      * @throws DeviceNotAvailableException
949      */
dumpHeap(String process, String devicePath)950     public File dumpHeap(String process, String devicePath) throws DeviceNotAvailableException;
951 
952     /**
953      * Collect the list of available displays id on the device as reported by "dumpsys
954      * SurfaceFlinger".
955      *
956      * @return The list of displays. Default always returns the default display 0.
957      * @throws DeviceNotAvailableException
958      */
listDisplayIds()959     public Set<Long> listDisplayIds() throws DeviceNotAvailableException;
960 }
961