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.log.ITestLogger;
21 import com.android.tradefed.result.InputStreamSource;
22 import com.android.tradefed.util.Bugreport;
23 import com.android.tradefed.util.KeyguardControllerState;
24 
25 import java.io.File;
26 import java.io.InputStream;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 
33 /**
34  * Provides an reliable and slightly higher level API to a ddmlib {@link IDevice}.
35  * <p/>
36  * Retries device commands for a configurable amount, and provides a device recovery
37  * interface for devices which are unresponsive.
38  */
39 public interface ITestDevice extends INativeDevice {
40 
41     public enum RecoveryMode {
42         /** don't attempt to recover device. */
43         NONE,
44         /** recover device to online state only */
45         ONLINE,
46         /**
47          * Recover device into fully testable state - framework is up, and external storage is
48          * mounted.
49          */
50         AVAILABLE
51     }
52 
53     /**
54      * A simple struct class to store information about a single mountpoint
55      */
56     public static class MountPointInfo {
57         public String filesystem;
58         public String mountpoint;
59         public String type;
60         public List<String> options;
61 
62         /** Simple constructor */
MountPointInfo()63         public MountPointInfo() {}
64 
65         /**
66          * Convenience constructor to set all members
67          */
MountPointInfo(String filesystem, String mountpoint, String type, List<String> options)68         public MountPointInfo(String filesystem, String mountpoint, String type,
69                 List<String> options) {
70             this.filesystem = filesystem;
71             this.mountpoint = mountpoint;
72             this.type = type;
73             this.options = options;
74         }
75 
MountPointInfo(String filesystem, String mountpoint, String type, String optString)76         public MountPointInfo(String filesystem, String mountpoint, String type, String optString) {
77             this(filesystem, mountpoint, type, splitMountOptions(optString));
78         }
79 
splitMountOptions(String options)80         public static List<String> splitMountOptions(String options) {
81             List<String> list = Arrays.asList(options.split(","));
82             return list;
83         }
84 
85         @Override
toString()86         public String toString() {
87             return String.format("%s %s %s %s", this.filesystem, this.mountpoint, this.type,
88                     this.options);
89         }
90     }
91 
92     /** A simple struct class to store information about a single APEX */
93     public static class ApexInfo {
94         public final String name;
95         public final long versionCode;
96         public final String sourceDir;
97 
ApexInfo(String name, long versionCode, String sourceDir)98         public ApexInfo(String name, long versionCode, String sourceDir) {
99             this.name = name;
100             this.versionCode = versionCode;
101             this.sourceDir = sourceDir;
102         }
103 
ApexInfo(String name, long versionCode)104         public ApexInfo(String name, long versionCode) {
105             this(name, versionCode, "");
106         }
107 
108         @Override
equals(Object other)109         public boolean equals(Object other) {
110             if (other != null && other instanceof ApexInfo) {
111                 ApexInfo ai = (ApexInfo) other;
112                 return name.equals(ai.name) && versionCode == ai.versionCode;
113             }
114             return false;
115         }
116 
117         @Override
hashCode()118         public int hashCode() {
119             // no need to consider versionCode here.
120             return name.hashCode();
121         }
122 
123         @Override
toString()124         public String toString() {
125             return "packageName: "
126                     + name
127                     + ", versionCode: "
128                     + versionCode
129                     + ", sourceDir: "
130                     + sourceDir;
131         }
132     }
133 
134     /**
135      * Install an Android package on device.
136      *
137      * @param packageFile the apk file to install
138      * @param reinstall <code>true</code> if a reinstall should be performed
139      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
140      *     options.
141      * @return a {@link String} with an error code, or <code>null</code> if success.
142      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
143      *     recovered.
144      */
installPackage(File packageFile, boolean reinstall, String... extraArgs)145     public String installPackage(File packageFile, boolean reinstall, String... extraArgs)
146             throws DeviceNotAvailableException;
147 
148     /**
149      * Install an Android package on device.
150      *
151      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
152      * install time should call this function.
153      *
154      * @param packageFile the apk file to install
155      * @param reinstall <code>true</code> if a reinstall should be performed
156      * @param grantPermissions if all runtime permissions should be granted at install time
157      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
158      *     options.
159      * @return a {@link String} with an error code, or <code>null</code> if success.
160      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
161      *     recovered.
162      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
163      *     on device.
164      */
installPackage( File packageFile, boolean reinstall, boolean grantPermissions, String... extraArgs)165     public String installPackage(
166             File packageFile, boolean reinstall, boolean grantPermissions, String... extraArgs)
167             throws DeviceNotAvailableException;
168 
169     /**
170      * Install an Android package on device for a given user.
171      *
172      * @param packageFile the apk file to install
173      * @param reinstall <code>true</code> if a reinstall should be performed
174      * @param userId the integer user id to install for.
175      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
176      *     options.
177      * @return a {@link String} with an error code, or <code>null</code> if success.
178      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
179      *     recovered.
180      */
installPackageForUser( File packageFile, boolean reinstall, int userId, String... extraArgs)181     public String installPackageForUser(
182             File packageFile, boolean reinstall, int userId, String... extraArgs)
183             throws DeviceNotAvailableException;
184 
185     /**
186      * Install an Android package on device for a given user.
187      *
188      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
189      * install time should call this function.
190      *
191      * @param packageFile the apk file to install
192      * @param reinstall <code>true</code> if a reinstall should be performed
193      * @param grantPermissions if all runtime permissions should be granted at install time
194      * @param userId the integer user id to install for.
195      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
196      *     options.
197      * @return a {@link String} with an error code, or <code>null</code> if success.
198      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
199      *     recovered.
200      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
201      *     on device.
202      */
installPackageForUser( File packageFile, boolean reinstall, boolean grantPermissions, int userId, String... extraArgs)203     public String installPackageForUser(
204             File packageFile,
205             boolean reinstall,
206             boolean grantPermissions,
207             int userId,
208             String... extraArgs)
209             throws DeviceNotAvailableException;
210 
211     /**
212      * Uninstall an Android package from device.
213      *
214      * @param packageName the Android package to uninstall
215      * @return a {@link String} with an error code, or <code>null</code> if success.
216      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
217      *     recovered.
218      */
uninstallPackage(String packageName)219     public String uninstallPackage(String packageName) throws DeviceNotAvailableException;
220 
221     /**
222      * Uninstall an Android package from device for a given user.
223      *
224      * @param packageName the Android package to uninstall
225      * @param userId the integer user id to uninstall for.
226      * @return a {@link String} with an error code, or <code>null</code> if success.
227      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
228      *     recovered.
229      */
uninstallPackageForUser(String packageName, int userId)230     public String uninstallPackageForUser(String packageName, int userId)
231             throws DeviceNotAvailableException;
232 
233     /**
234      * Install an Android application made of several APK files (one main and extra split packages).
235      * See "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
236      * several files.
237      *
238      * @param packageFiles the local apk files
239      * @param reinstall <code>true</code> if a reinstall should be performed
240      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
241      *     options.
242      * @return a {@link String} with an error code, or <code>null</code> if success.
243      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
244      *     recovered.
245      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
246      *     on device.
247      */
installPackages( List<File> packageFiles, boolean reinstall, String... extraArgs)248     public default String installPackages(
249             List<File> packageFiles, boolean reinstall, String... extraArgs)
250             throws DeviceNotAvailableException {
251         throw new UnsupportedOperationException("No support for Package Manager's features");
252     }
253 
254     /**
255      * Install an Android application made of several APK files (one main and extra split packages)
256      * that are sitting on the android device. See
257      * "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
258      * several files.
259      *
260      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
261      * install time should call this function.
262      *
263      * @param packageFiles the remote apk file paths to install
264      * @param reinstall <code>true</code> if a reinstall should be performed
265      * @param grantPermissions if all runtime permissions should be granted at install time
266      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
267      *     options.
268      * @return a {@link String} with an error code, or <code>null</code> if success.
269      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
270      *     recovered.
271      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
272      *     on device.
273      */
installPackages( List<File> packageFiles, boolean reinstall, boolean grantPermissions, String... extraArgs)274     public default String installPackages(
275             List<File> packageFiles,
276             boolean reinstall,
277             boolean grantPermissions,
278             String... extraArgs)
279             throws DeviceNotAvailableException {
280         throw new UnsupportedOperationException("No support for Package Manager's features");
281     }
282 
283     /**
284      * Install an Android application made of several APK files (one main and extra split packages)
285      * for a given user. See "https://developer.android.com/studio/build/configure-apk-splits" on
286      * how to split apk to several files.
287      *
288      * @param packageFiles the local apk files
289      * @param reinstall <code>true</code> if a reinstall should be performed
290      * @param userId the integer user id to install for.
291      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
292      *     options.
293      * @return a {@link String} with an error code, or <code>null</code> if success.
294      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
295      *     recovered.
296      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
297      *     on device.
298      */
installPackagesForUser( List<File> packageFiles, boolean reinstall, int userId, String... extraArgs)299     public default String installPackagesForUser(
300             List<File> packageFiles, boolean reinstall, int userId, String... extraArgs)
301             throws DeviceNotAvailableException {
302         throw new UnsupportedOperationException("No support for Package Manager's features");
303     }
304 
305     /**
306      * Install an Android application made of several APK files (one main and extra split packages)
307      * for a given user. See "https://developer.android.com/studio/build/configure-apk-splits" on
308      * how to split apk to several files.
309      *
310      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
311      * install time should call this function.
312      *
313      * @param packageFiles the local apk files
314      * @param reinstall <code>true</code> if a reinstall should be performed
315      * @param grantPermissions if all runtime permissions should be granted at install time
316      * @param userId the integer user id to install for.
317      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
318      *     options.
319      * @return a {@link String} with an error code, or <code>null</code> if success.
320      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
321      *     recovered.
322      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
323      *     on device.
324      */
installPackagesForUser( List<File> packageFiles, boolean reinstall, boolean grantPermissions, int userId, String... extraArgs)325     public default String installPackagesForUser(
326             List<File> packageFiles,
327             boolean reinstall,
328             boolean grantPermissions,
329             int userId,
330             String... extraArgs)
331             throws DeviceNotAvailableException {
332         throw new UnsupportedOperationException("No support for Package Manager's features");
333     }
334 
335     /**
336      * Install an Android application made of several APK files (one main and extra split packages)
337      * that are sitting on the android device. See
338      * "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
339      * several files.
340      *
341      * <p>Note: Only use cases that requires explicit control of granting runtime permission at
342      * install time should call this function.
343      *
344      * @param remoteApkPaths the remote apk file paths
345      * @param reinstall <code>true</code> if a reinstall should be performed
346      * @param grantPermissions if all runtime permissions should be granted at install time
347      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
348      *     options.
349      * @return a {@link String} with an error code, or <code>null</code> if success.
350      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
351      *     recovered.
352      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
353      *     on device.
354      */
installRemotePackages( List<String> remoteApkPaths, boolean reinstall, boolean grantPermissions, String... extraArgs)355     public default String installRemotePackages(
356             List<String> remoteApkPaths,
357             boolean reinstall,
358             boolean grantPermissions,
359             String... extraArgs)
360             throws DeviceNotAvailableException {
361         throw new UnsupportedOperationException("No support for Package Manager's features");
362     }
363 
364     /**
365      * Install an Android application made of several APK files (one main and extra split packages)
366      * that are sitting on the android device. See
367      * "https://developer.android.com/studio/build/configure-apk-splits" on how to split apk to
368      * several files.
369      *
370      * @param remoteApkPaths the remote apk file paths
371      * @param reinstall <code>true</code> if a reinstall should be performed
372      * @param extraArgs optional extra arguments to pass. See 'adb shell pm -h' for available
373      *     options.
374      * @return a {@link String} with an error code, or <code>null</code> if success.
375      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
376      *     recovered.
377      * @throws UnsupportedOperationException if runtime permission is not supported by the platform
378      *     on device.
379      */
installRemotePackages( List<String> remoteApkPaths, boolean reinstall, String... extraArgs)380     public default String installRemotePackages(
381             List<String> remoteApkPaths, boolean reinstall, String... extraArgs)
382             throws DeviceNotAvailableException {
383         throw new UnsupportedOperationException("No support for Package Manager's features");
384     }
385 
386 
387     /**
388      * Grabs a screenshot from the device.
389      *
390      * @return a {@link InputStreamSource} of the screenshot in png format, or <code>null</code> if
391      *         the screenshot was not successful.
392      * @throws DeviceNotAvailableException
393      */
getScreenshot()394     public InputStreamSource getScreenshot() throws DeviceNotAvailableException;
395 
396     /**
397      * Grabs a screenshot from the device.
398      * Recommended to use getScreenshot(format) instead with JPEG encoding for smaller size
399      * @param format supported PNG, JPEG
400      * @return a {@link InputStreamSource} of the screenshot in format, or <code>null</code> if
401      *         the screenshot was not successful.
402      * @throws DeviceNotAvailableException
403      */
getScreenshot(String format)404     public InputStreamSource getScreenshot(String format) throws DeviceNotAvailableException;
405 
406     /**
407      * Grabs a screenshot from the device. Recommended to use {@link #getScreenshot(String)} instead
408      * with JPEG encoding for smaller size.
409      *
410      * @param format supported PNG, JPEG
411      * @param rescale if screenshot should be rescaled to reduce the size of resulting image
412      * @return a {@link InputStreamSource} of the screenshot in format, or <code>null</code> if the
413      *     screenshot was not successful.
414      * @throws DeviceNotAvailableException
415      */
getScreenshot(String format, boolean rescale)416     public InputStreamSource getScreenshot(String format, boolean rescale)
417             throws DeviceNotAvailableException;
418 
419     /**
420      * Grabs a screenshot from the device given display id. Format is PNG.
421      *
422      * <p>TODO: extend the implementations above to support 'format' and 'rescale'
423      *
424      * @param displayId the display id of the screen to get screenshot from.
425      * @return a {@link InputStreamSource} of the screenshot in format, or <code>null</code> if the
426      *     screenshot was not successful.
427      * @throws DeviceNotAvailableException
428      */
getScreenshot(long displayId)429     public InputStreamSource getScreenshot(long displayId) throws DeviceNotAvailableException;
430 
431     /**
432      * Clears the last connected wifi network. This should be called when starting a new invocation
433      * to avoid connecting to the wifi network used in the previous test after device reboots.
434      */
clearLastConnectedWifiNetwork()435     public void clearLastConnectedWifiNetwork();
436 
437     /**
438      * Connects to a wifi network.
439      * <p/>
440      * Turns on wifi and blocks until a successful connection is made to the specified wifi network.
441      * Once a connection is made, the instance will try to restore the connection after every reboot
442      * until {@link ITestDevice#disconnectFromWifi()} or
443      * {@link ITestDevice#clearLastConnectedWifiNetwork()} is called.
444      *
445      * @param wifiSsid the wifi ssid to connect to
446      * @param wifiPsk PSK passphrase or null if unencrypted
447      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
448      *         otherwise
449      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
450      *             recovered.
451      */
connectToWifiNetwork(String wifiSsid, String wifiPsk)452     public boolean connectToWifiNetwork(String wifiSsid, String wifiPsk)
453             throws DeviceNotAvailableException;
454 
455     /**
456      * Connects to a wifi network.
457      * <p/>
458      * Turns on wifi and blocks until a successful connection is made to the specified wifi network.
459      * Once a connection is made, the instance will try to restore the connection after every reboot
460      * until {@link ITestDevice#disconnectFromWifi()} or
461      * {@link ITestDevice#clearLastConnectedWifiNetwork()} is called.
462      *
463      * @param wifiSsid the wifi ssid to connect to
464      * @param wifiPsk PSK passphrase or null if unencrypted
465      * @param scanSsid whether to scan for hidden SSID for this network.
466      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
467      *         otherwise
468      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
469      *             recovered.
470      */
connectToWifiNetwork(String wifiSsid, String wifiPsk, boolean scanSsid)471     public boolean connectToWifiNetwork(String wifiSsid, String wifiPsk, boolean scanSsid)
472             throws DeviceNotAvailableException;
473 
474     /**
475      * Connects to a wifi network.
476      *
477      * <p>Turns on wifi and blocks until a successful connection is made with one of the wifi
478      * networks given in the wifiSsidToPsk map. Once a connection is made, the instance will try to
479      * restore the connection after every reboot until {@link ITestDevice#disconnectFromWifi()} or
480      * {@link ITestDevice#clearLastConnectedWifiNetwork()} is called.
481      *
482      * @param wifiSsidToPsk A map of wifi SSIDs to passwords.
483      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
484      *     otherwise
485      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
486      *     recovered.
487      */
connectToWifiNetwork(Map<String, String> wifiSsidToPsk)488     public boolean connectToWifiNetwork(Map<String, String> wifiSsidToPsk)
489             throws DeviceNotAvailableException;
490 
491     /**
492      * Connects to a wifi network.
493      *
494      * <p>Turns on wifi and blocks until a successful connection is made with one of the wifi
495      * networks given in the wifiSsidToPsk map. Once a connection is made, the instance will try to
496      * restore the connection after every reboot until {@link ITestDevice#disconnectFromWifi()} or
497      * {@link ITestDevice#clearLastConnectedWifiNetwork()} is called.
498      *
499      * @param wifiSsidToPsk A map of wifi SSIDs to passwords.
500      * @param scanSsid whether to scan for hidden SSIDs for this network.
501      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
502      *     otherwise
503      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
504      *     recovered.
505      */
connectToWifiNetwork(Map<String, String> wifiSsidToPsk, boolean scanSsid)506     public boolean connectToWifiNetwork(Map<String, String> wifiSsidToPsk, boolean scanSsid)
507             throws DeviceNotAvailableException;
508 
509     /**
510      * A variant of {@link #connectToWifiNetwork(String, String)} that only connects if device
511      * currently does not have network connectivity.
512      *
513      * @param wifiSsid
514      * @param wifiPsk
515      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
516      *         otherwise
517      * @throws DeviceNotAvailableException
518      */
connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk)519     public boolean connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk)
520             throws DeviceNotAvailableException;
521 
522     /**
523      * A variant of {@link #connectToWifiNetwork(String, String)} that only connects if device
524      * currently does not have network connectivity.
525      *
526      * @param wifiSsid
527      * @param wifiPsk
528      * @param scanSsid whether to scan for hidden SSID for this network
529      * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
530      *         otherwise
531      * @throws DeviceNotAvailableException
532      */
connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk, boolean scanSsid)533     public boolean connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk, boolean scanSsid)
534             throws DeviceNotAvailableException;
535 
536     /**
537      * Disconnects from a wifi network.
538      * <p/>
539      * Removes all networks from known networks list and disables wifi.
540      *
541      * @return <code>true</code> if disconnected from wifi network successfully. <code>false</code>
542      *         if disconnect failed.
543      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
544      *             recovered.
545      */
disconnectFromWifi()546     public boolean disconnectFromWifi() throws DeviceNotAvailableException;
547 
548     /**
549      * Test if wifi is enabled.
550      * <p/>
551      * Checks if wifi is enabled on device. Useful for asserting wifi status before tests that
552      * shouldn't run with wifi, e.g. mobile data tests.
553      *
554      * @return <code>true</code> if wifi is enabled. <code>false</code> if disabled
555      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
556      *             recovered.
557      */
isWifiEnabled()558     public boolean isWifiEnabled() throws DeviceNotAvailableException;
559 
560     /**
561      * Gets the device's IP address.
562      *
563      * @return the device's IP address, or <code>null</code> if device has no IP address
564      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
565      *             recovered.
566      */
getIpAddress()567     public String getIpAddress() throws DeviceNotAvailableException;
568 
569     /**
570      * Enables network monitoring on device.
571      *
572      * @return <code>true</code> if monitoring is enabled successfully. <code>false</code>
573      *         if it failed.
574      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
575      *             recovered.
576      */
enableNetworkMonitor()577     public boolean enableNetworkMonitor() throws DeviceNotAvailableException;
578 
579     /**
580      * Disables network monitoring on device.
581      *
582      * @return <code>true</code> if monitoring is disabled successfully. <code>false</code>
583      *         if it failed.
584      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
585      *             recovered.
586      */
disableNetworkMonitor()587     public boolean disableNetworkMonitor() throws DeviceNotAvailableException;
588 
589     /**
590      * Check that device has network connectivity.
591      *
592      * @return <code>true</code> if device has a working network connection,
593      *          <code>false</code> overwise.
594      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
595      *          recovered.
596      */
checkConnectivity()597     public boolean checkConnectivity() throws DeviceNotAvailableException;
598 
599     /**
600      * Attempt to dismiss any error dialogs currently displayed on device UI.
601      *
602      * @return <code>true</code> if no dialogs were present or dialogs were successfully cleared.
603      *         <code>false</code> otherwise.
604      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
605      *             recovered.
606      */
clearErrorDialogs()607     public boolean clearErrorDialogs() throws DeviceNotAvailableException;
608 
609     /**
610      * Return an object to get the current state of the keyguard or null if not supported.
611      *
612      * @return a {@link KeyguardControllerState} containing a snapshot of the state of the keyguard
613      *     and returns Null if the Keyguard query is not supported.
614      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
615      *     recovered.
616      */
getKeyguardState()617     public KeyguardControllerState getKeyguardState() throws DeviceNotAvailableException;
618 
619     /**
620      * Fetch the test options for the device.
621      *
622      * @return {@link TestDeviceOptions} related to the device under test.
623      */
getOptions()624     public TestDeviceOptions getOptions();
625 
626     /**
627      * Fetch the application package names present on the device.
628      *
629      * @return {@link Set} of {@link String} package names currently installed on the device.
630      * @throws DeviceNotAvailableException
631      */
getInstalledPackageNames()632     public Set<String> getInstalledPackageNames() throws DeviceNotAvailableException;
633 
634     /**
635      * Query the device for a given package name to check if it's currently installed or not.
636      *
637      * @return True if the package is reported as installed. False otherwise.
638      * @throws DeviceNotAvailableException
639      */
isPackageInstalled(String packageName)640     public boolean isPackageInstalled(String packageName) throws DeviceNotAvailableException;
641 
642     /**
643      * Query the device for a given package name and given user id to check if it's currently
644      * installed or not for that user.
645      *
646      * @param packageName the package we are checking if it's installed.
647      * @param userId The user id we are checking the package is installed for. If null, primary user
648      *     zero will be used.
649      * @return True if the package is reported as installed. False otherwise.
650      * @throws DeviceNotAvailableException
651      */
isPackageInstalled(String packageName, String userId)652     public boolean isPackageInstalled(String packageName, String userId)
653             throws DeviceNotAvailableException;
654 
655     /**
656      * Fetch the information about APEXes activated on the device.
657      *
658      * @return {@link Set} of {@link ApexInfo} currently activated on the device
659      * @throws DeviceNotAvailableException
660      */
getActiveApexes()661     public Set<ApexInfo> getActiveApexes() throws DeviceNotAvailableException;
662 
663     /**
664      * Get the information about the mainline modules installed on the device.
665      *
666      * @return {@link Set} of {@link String} mainline modules currently installed on the device.
667      * @throws DeviceNotAvailableException
668      */
getMainlineModuleInfo()669     public Set<String> getMainlineModuleInfo() throws DeviceNotAvailableException;
670 
671     /**
672      * Fetch the application package names that can be uninstalled. This is presently defined as
673      * non-system packages, and updated system packages.
674      *
675      * @return {@link Set} of uninstallable {@link String} package names currently installed on the
676      *         device.
677      * @throws DeviceNotAvailableException
678      */
getUninstallablePackageNames()679     public Set<String> getUninstallablePackageNames() throws DeviceNotAvailableException;
680 
681     /**
682      * Fetch information about a package installed on device.
683      *
684      * @return the {@link PackageInfo} or <code>null</code> if information could not be retrieved
685      * @throws DeviceNotAvailableException
686      */
getAppPackageInfo(String packageName)687     public PackageInfo getAppPackageInfo(String packageName) throws DeviceNotAvailableException;
688 
689     /**
690      * Fetch information of packages installed on the device.
691      *
692      * @return {@link List} of {@link PackageInfo}s installed on the device.
693      * @throws DeviceNotAvailableException
694      */
getAppPackageInfos()695     public List<PackageInfo> getAppPackageInfos() throws DeviceNotAvailableException;
696 
697     /**
698      * Determines if multi user is supported.
699      *
700      * @return true if multi user is supported, false otherwise
701      * @throws DeviceNotAvailableException
702      */
isMultiUserSupported()703     public boolean isMultiUserSupported() throws DeviceNotAvailableException;
704 
705     /** Returns whether the device uses headless system user mode. */
isHeadlessSystemUserMode()706     public boolean isHeadlessSystemUserMode() throws DeviceNotAvailableException;
707 
708     /** Returns whether it's allowed to switch to the headless SYSTEM user. */
canSwitchToHeadlessSystemUser()709     public boolean canSwitchToHeadlessSystemUser() throws DeviceNotAvailableException;
710 
711     /**
712      * Returns whether the main user is a permanent admin and can't be deleted or downgraded to
713      * non-admin status.
714      */
isMainUserPermanentAdmin()715     public boolean isMainUserPermanentAdmin() throws DeviceNotAvailableException;
716 
717     /**
718      * Create a user with a given name and default flags 0.
719      *
720      * @param name of the user to create on the device
721      * @return the integer for the user id created
722      * @throws DeviceNotAvailableException
723      */
createUser(String name)724     public int createUser(String name) throws DeviceNotAvailableException, IllegalStateException;
725 
726     /**
727      * Create a user with a given name and the provided flags
728      *
729      * @param name of the user to create on the device
730      * @param guest enable the user flag --guest during creation
731      * @param ephemeral enable the user flag --ephemeral during creation
732      * @return id of the created user
733      * @throws DeviceNotAvailableException
734      */
createUser(String name, boolean guest, boolean ephemeral)735     public int createUser(String name, boolean guest, boolean ephemeral)
736             throws DeviceNotAvailableException, IllegalStateException;
737 
738     /**
739      * Create a user with a given name and the provided flags
740      *
741      * @param name of the user to create on the device
742      * @param guest enable the user flag --guest during creation
743      * @param ephemeral enable the user flag --ephemeral during creation
744      * @param forTesting enable the test flag --for-testing during creation
745      * @return id of the created user
746      * @throws DeviceNotAvailableException
747      */
createUser(String name, boolean guest, boolean ephemeral, boolean forTesting)748     public int createUser(String name, boolean guest, boolean ephemeral, boolean forTesting)
749             throws DeviceNotAvailableException, IllegalStateException;
750 
751     /**
752      * Create a user with a given name and default flags 0.
753      *
754      * @param name of the user to create on the device
755      * @return the integer for the user id created or -1 for error.
756      * @throws DeviceNotAvailableException
757      */
createUserNoThrow(String name)758     public int createUserNoThrow(String name) throws DeviceNotAvailableException;
759 
760     /**
761      * Remove a given user from the device.
762      *
763      * @param userId of the user to remove
764      * @return true if we were successful in removing the user, false otherwise.
765      * @throws DeviceNotAvailableException
766      */
removeUser(int userId)767     public boolean removeUser(int userId) throws DeviceNotAvailableException;
768 
769     /**
770      * Gets the list of users on the device. Will throw {@link DeviceRuntimeException} if output
771      * from device is not as expected.
772      *
773      * @return the list of user ids.
774      * @throws DeviceNotAvailableException
775      * @throws DeviceRuntimeException
776      */
listUsers()777     ArrayList<Integer> listUsers() throws DeviceNotAvailableException;
778 
779     /**
780      * Gets the Map of useId to {@link UserInfo} on the device. Will throw {@link
781      * DeviceRuntimeException} if output from device is not as expected.
782      *
783      * @return the list of UserInfo objects.
784      * @throws DeviceNotAvailableException
785      * @throws DeviceRuntimeException
786      */
getUserInfos()787     public Map<Integer, UserInfo> getUserInfos() throws DeviceNotAvailableException;
788 
789     /**
790      * Get the maximum number of supported users. Defaults to 0.
791      *
792      * @return an integer indicating the number of supported users
793      * @throws DeviceNotAvailableException
794      */
getMaxNumberOfUsersSupported()795     public int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException;
796 
797     /**
798      * Get the maximum number of supported simultaneously running users. Defaults to 0.
799      *
800      * @return an integer indicating the number of simultaneously running users
801      * @throws DeviceNotAvailableException
802      */
getMaxNumberOfRunningUsersSupported()803     public int getMaxNumberOfRunningUsersSupported() throws DeviceNotAvailableException;
804 
805     /**
806      * Starts a given user in the background if it is currently stopped. If the user is already
807      * running in the background, this method is a NOOP.
808      * @param userId of the user to start in the background
809      * @return true if the user was successfully started in the background.
810      * @throws DeviceNotAvailableException
811      */
startUser(int userId)812     public boolean startUser(int userId) throws DeviceNotAvailableException;
813 
814     /**
815      * Starts a given user in the background if it is currently stopped. If the user is already
816      * running in the background, this method is a NOOP. Possible to provide extra flag to wait for
817      * the operation to have effect.
818      *
819      * @param userId of the user to start in the background
820      * @param waitFlag will make the command wait until user is started and unlocked.
821      * @return true if the user was successfully started in the background.
822      * @throws DeviceNotAvailableException
823      */
startUser(int userId, boolean waitFlag)824     public boolean startUser(int userId, boolean waitFlag) throws DeviceNotAvailableException;
825 
826     /**
827      * Starts a given user in the background, visible in the given display (i.e., allowing the user
828      * to launch activities in that display).
829      *
830      * <p><b>NOTE: </b>this command doesn't check if the user exists, display is available, {@link
831      * #isVisibleBackgroundUsersSupported() device supports such feature}, etc.
832      *
833      * @param userId of the user to start in the background
834      * @param displayId display to start user visible on
835      * @param waitFlag will make the command wait until user is started and unlocked.
836      * @return {@code true} if the user was successfully started visible in the background.
837      */
startVisibleBackgroundUser(int userId, int displayId, boolean waitFlag)838     public boolean startVisibleBackgroundUser(int userId, int displayId, boolean waitFlag)
839             throws DeviceNotAvailableException;
840 
841     /**
842      * Stops a given user. If the user is already stopped, this method is a NOOP.
843      * Cannot stop current and system user.
844      *
845      * @param userId of the user to stop.
846      * @return true if the user was successfully stopped.
847      * @throws DeviceNotAvailableException
848      */
stopUser(int userId)849     public boolean stopUser(int userId) throws DeviceNotAvailableException;
850 
851     /**
852      * Stop a given user. Possible to provide extra flags to wait for the operation to have effect,
853      * and force terminate the user. Cannot stop current and system user.
854      *
855      * @param userId of the user to stop.
856      * @param waitFlag will make the command wait until user is stopped.
857      * @param forceFlag will force stop the user.
858      * @return true if the user was successfully stopped.
859      * @throws DeviceNotAvailableException
860      */
stopUser(int userId, boolean waitFlag, boolean forceFlag)861     public boolean stopUser(int userId, boolean waitFlag, boolean forceFlag)
862             throws DeviceNotAvailableException;
863 
864     /**
865      * Returns whether the device allow users to be started visible in the background.
866      *
867      * <p>If it does, you could call {@link #startVisibleBackgroundUser(int, int, boolean)}, passing
868      * a display returned by {@link #listDisplayIdsForStartingVisibleBackgroundUsers()}.
869      */
isVisibleBackgroundUsersSupported()870     public boolean isVisibleBackgroundUsersSupported() throws DeviceNotAvailableException;
871 
872     /**
873      * Returns whether the device allow users to be started visible in the background in the {@link
874      * java.android.view.Display#DEFAULT_DISPLAY}.
875      *
876      * <p>If it does, you could call {@link #startVisibleBackgroundUser(int, int, boolean)}, passing
877      * a display returned by {@link #listDisplayIdsForStartingVisibleBackgroundUsers()} (which
878      * should include {@link java.android.view.Display#DEFAULT_DISPLAY}).
879      */
isVisibleBackgroundUsersOnDefaultDisplaySupported()880     public boolean isVisibleBackgroundUsersOnDefaultDisplaySupported()
881             throws DeviceNotAvailableException;
882 
883     /**
884      * Returns the primary user id.
885      *
886      * @return the userId of the primary user if there is one, and null if there is no primary user.
887      * @throws DeviceNotAvailableException
888      * @throws DeviceRuntimeException if the output from the device is not as expected.
889      */
getPrimaryUserId()890     public Integer getPrimaryUserId() throws DeviceNotAvailableException;
891 
892     /**
893      * Returns the main user id.
894      *
895      * @return the userId of the main user if there is one, and null if there is no main user.
896      * @throws DeviceNotAvailableException
897      * @throws DeviceRuntimeException if the output from the device is not as expected.
898      */
getMainUserId()899     public Integer getMainUserId() throws DeviceNotAvailableException;
900 
901     /**
902      * Return the id of the current running user. In case of error, return -10000.
903      *
904      * @throws DeviceNotAvailableException
905      */
getCurrentUser()906     public int getCurrentUser() throws DeviceNotAvailableException;
907 
908     /**
909      * Checks if the given user is visible.
910      *
911      * <p>A "visible" user is a user that is interacting with the "human" user and hence is able to
912      * launch launch activities (typically in the default display).
913      */
isUserVisible(int userId)914     public boolean isUserVisible(int userId) throws DeviceNotAvailableException;
915 
916     /**
917      * Checks if the given user is visible in the given display.
918      *
919      * <p>A "visible" user is a user that is interacting with the "human" user and hence is able to
920      * launch launch activities in that display.
921      */
isUserVisibleOnDisplay(int userId, int displayId)922     public boolean isUserVisibleOnDisplay(int userId, int displayId)
923             throws DeviceNotAvailableException;
924 
925     /**
926      * Find and return the flags of a given user.
927      * Flags are defined in "android.content.pm.UserInfo" class in Android Open Source Project.
928      *
929      * @return the flags associated with the userId provided if found, -10000 in any other cases.
930      * @throws DeviceNotAvailableException
931      */
getUserFlags(int userId)932     public int getUserFlags(int userId) throws DeviceNotAvailableException;
933 
934     /**
935      * Return whether the specified user is a secondary user according to it's flags.
936      *
937      * @return true if the user is secondary, false otherwise.
938      * @throws DeviceNotAvailableException
939      */
isUserSecondary(int userId)940     public boolean isUserSecondary(int userId) throws DeviceNotAvailableException;
941 
942     /**
943      * Return the serial number associated to the userId if found, -10000 in any other cases.
944      *
945      * @throws DeviceNotAvailableException
946      */
getUserSerialNumber(int userId)947     public int getUserSerialNumber(int userId) throws DeviceNotAvailableException;
948 
949     /**
950      * Switch to another userId with a default timeout. {@link #switchUser(int, long)}.
951      *
952      * @return True if the new userId matches the userId provider. False otherwise.
953      * @throws DeviceNotAvailableException
954      */
switchUser(int userId)955     public boolean switchUser(int userId) throws DeviceNotAvailableException;
956 
957     /**
958      * Switch to another userId with the provided timeout as deadline.
959      * Attempt to disable keyguard after user change is successful.
960      *
961      * @param timeout to wait before returning false for switch-user failed.
962      * @return True if the new userId matches the userId provider. False otherwise.
963      * @throws DeviceNotAvailableException
964      */
switchUser(int userId, long timeout)965     public boolean switchUser(int userId, long timeout) throws DeviceNotAvailableException;
966 
967     /**
968      * Check if a given user is running.
969      *
970      * @return True if the user is running, false in every other cases.
971      * @throws DeviceNotAvailableException
972      */
isUserRunning(int userId)973     public boolean isUserRunning(int userId) throws DeviceNotAvailableException;
974 
975     /**
976      * Check if a feature is available on a device.
977      *
978      * @param feature which format should be "feature:<name>" or "<name>" directly.
979      * @return True if feature is found, false otherwise.
980      * @throws DeviceNotAvailableException
981      */
hasFeature(String feature)982     public boolean hasFeature(String feature) throws DeviceNotAvailableException;
983 
984     /**
985      * See {@link #getSetting(int, String, String)} and performed on system user.
986      *
987      * @throws DeviceNotAvailableException
988      */
getSetting(String namespace, String key)989     public String getSetting(String namespace, String key) throws DeviceNotAvailableException;
990 
991     /**
992      * Return the value of the requested setting.
993      * namespace must be one of: {"system", "secure", "global"}
994      *
995      * @return the value associated with the namespace:key of a user. Null if not found.
996      * @throws DeviceNotAvailableException
997      */
getSetting(int userId, String namespace, String key)998     public String getSetting(int userId, String namespace, String key)
999             throws DeviceNotAvailableException;
1000 
1001     /**
1002      * Return key value pairs of requested namespace.
1003      *
1004      * @param namespace must be one of {"system", "secure", "global"}
1005      * @return the map of key value pairs. Null if namespace is not supported.
1006      * @throws DeviceNotAvailableException
1007      */
getAllSettings(String namespace)1008     public Map<String, String> getAllSettings(String namespace) throws DeviceNotAvailableException;
1009 
1010     /**
1011      * See {@link #setSetting(int, String, String, String)} and performed on system user.
1012      *
1013      * @throws DeviceNotAvailableException
1014      */
setSetting(String namespace, String key, String value)1015     public void setSetting(String namespace, String key, String value)
1016             throws DeviceNotAvailableException;
1017 
1018     /**
1019      * Add a setting value to the namespace of a given user. Some settings will only be available
1020      * after a reboot.
1021      * namespace must be one of: {"system", "secure", "global"}
1022      *
1023      * @throws DeviceNotAvailableException
1024      */
setSetting(int userId, String namespace, String key, String value)1025     public void setSetting(int userId, String namespace, String key, String value)
1026             throws DeviceNotAvailableException;
1027 
1028     /**
1029      * Find and return the android-id associated to a userId, null if not found.
1030      *
1031      * @throws DeviceNotAvailableException
1032      */
getAndroidId(int userId)1033     public String getAndroidId(int userId) throws DeviceNotAvailableException;
1034 
1035     /**
1036      * Create a Map of android ids found matching user ids. There is no insurance that each user
1037      * id will found an android id associated in this function so some user ids may match null.
1038      *
1039      * @return Map of android ids found matching user ids.
1040      * @throws DeviceNotAvailableException
1041      */
getAndroidIds()1042     public Map<Integer, String> getAndroidIds() throws DeviceNotAvailableException;
1043 
1044     /**
1045      * Set a device admin component as device owner in given user.
1046      *
1047      * @param componentName of device admin to be device owner.
1048      * @param userId of the user that the device owner lives in.
1049      * @return True if it is successful, false otherwise.
1050      * @throws DeviceNotAvailableException
1051      */
setDeviceOwner(String componentName, int userId)1052     public boolean setDeviceOwner(String componentName, int userId)
1053             throws DeviceNotAvailableException;
1054 
1055     /**
1056      * Remove given device admin in given user and return {@code true} if it is successful, {@code
1057      * false} otherwise.
1058      *
1059      * @param componentName of device admin to be removed.
1060      * @param userId of user that the device admin lives in.
1061      * @return True if it is successful, false otherwise.
1062      * @throws DeviceNotAvailableException
1063      */
removeAdmin(String componentName, int userId)1064     public boolean removeAdmin(String componentName, int userId) throws DeviceNotAvailableException;
1065 
1066     /**
1067      * Remove all existing device profile owners with the best effort.
1068      *
1069      * @throws DeviceNotAvailableException
1070      */
removeOwners()1071     public void removeOwners() throws DeviceNotAvailableException;
1072 
1073     /**
1074      * Attempts to disable the keyguard.
1075      * <p>
1076      * First wait for the input dispatch to become ready, this happens around the same time when the
1077      * device reports BOOT_COMPLETE, apparently asynchronously, because current framework
1078      * implementation has occasional race condition. Then command is sent to dismiss keyguard (works
1079      * on non-secure ones only)
1080      */
disableKeyguard()1081     public void disableKeyguard() throws DeviceNotAvailableException;
1082 
1083     /**
1084      * Attempt to dump the heap from the system_server. It is the caller responsibility to clean up
1085      * the dumped file.
1086      *
1087      * @param process the name of the device process to dumpheap on.
1088      * @param devicePath the path on the device where to put the dump. This must be a location where
1089      *     permissions allow it.
1090      * @return the {@link File} containing the report. Null if something failed.
1091      * @throws DeviceNotAvailableException
1092      */
dumpHeap(String process, String devicePath)1093     public File dumpHeap(String process, String devicePath) throws DeviceNotAvailableException;
1094 
1095     /**
1096      * Collect the list of available displays id on the device as reported by "dumpsys
1097      * SurfaceFlinger".
1098      *
1099      * @return The list of displays. Default always returns the default display 0.
1100      * @throws DeviceNotAvailableException
1101      */
listDisplayIds()1102     public Set<Long> listDisplayIds() throws DeviceNotAvailableException;
1103 
1104     /**
1105      * Gets the list of displays that can be used to {@link #startVisibleBackgroundUser(int, int,
1106      * boolean) start a user visible in the background}.
1107      */
listDisplayIdsForStartingVisibleBackgroundUsers()1108     public Set<Integer> listDisplayIdsForStartingVisibleBackgroundUsers()
1109             throws DeviceNotAvailableException;
1110 
1111     /**
1112      * Returns the list of foldable states on the device. Can be obtained with "cmd device_state
1113      * print-states".
1114      *
1115      * @throws DeviceNotAvailableException
1116      */
getFoldableStates()1117     public Set<DeviceFoldableState> getFoldableStates() throws DeviceNotAvailableException;
1118 
1119     /**
1120      * Returns the current foldable state of the device or null if some issues occurred.
1121      *
1122      * @throws DeviceNotAvailableException
1123      */
getCurrentFoldableState()1124     public DeviceFoldableState getCurrentFoldableState() throws DeviceNotAvailableException;
1125 
1126     /**
1127      * Helper method to determine if file on device exists for a given user.
1128      *
1129      * @param deviceFilePath the absolute path of file on device to check
1130      * @param userId The user id against which to check file existence
1131      * @return <code>true</code> if file exists, <code>false</code> otherwise.
1132      * @throws DeviceNotAvailableException if connection with device is lost and cannot be
1133      *     recovered.
1134      */
doesFileExist(String deviceFilePath, int userId)1135     public boolean doesFileExist(String deviceFilePath, int userId)
1136             throws DeviceNotAvailableException;
1137 
1138     /**
1139      * Registers a {@link IDeviceActionReceiver} for this device.
1140      *
1141      * <p>All registered {@link IDeviceActionReceiver}s will be notified before a device action
1142      * starts and after the device action ends.
1143      *
1144      * @param deviceActionReceiver A {@link IDeviceActionReceiver} which will be registered.
1145      */
registerDeviceActionReceiver(IDeviceActionReceiver deviceActionReceiver)1146     public void registerDeviceActionReceiver(IDeviceActionReceiver deviceActionReceiver);
1147 
1148     /**
1149      * Removes the registered {@link IDeviceActionReceiver}.
1150      *
1151      * @param deviceActionReceiver A {@link IDeviceActionReceiver} which will be removed.
1152      */
deregisterDeviceActionReceiver(IDeviceActionReceiver deviceActionReceiver)1153     public void deregisterDeviceActionReceiver(IDeviceActionReceiver deviceActionReceiver);
1154 
1155     /**
1156      * Retrieves a bugreport from the device.
1157      *
1158      * <p>The implementation of this is guaranteed to continue to work on a device without an sdcard
1159      * (or where the sdcard is not yet mounted).
1160      *
1161      * @return An {@link InputStreamSource} which will produce the bugreport contents on demand. In
1162      *     case of failure, the {@code InputStreamSource} will produce an empty {@link InputStream}.
1163      */
getBugreport()1164     public InputStreamSource getBugreport();
1165 
1166     /**
1167      * Retrieves a bugreportz from the device. Zip format bugreport contains the main bugreport and
1168      * other log files that are useful for debugging.
1169      *
1170      * <p>Only supported for 'adb version' > 1.0.36
1171      *
1172      * @return a {@link InputStreamSource} of the zip file containing the bugreportz, return null in
1173      *     case of failure.
1174      */
getBugreportz()1175     public InputStreamSource getBugreportz();
1176 
1177     /**
1178      * Helper method to take a bugreport and log it to the reporters.
1179      *
1180      * @param dataName name under which the bugreport will be reported.
1181      * @param listener an {@link ITestLogger} to log the bugreport.
1182      * @return True if the logging was successful, false otherwise.
1183      */
logBugreport(String dataName, ITestLogger listener)1184     public boolean logBugreport(String dataName, ITestLogger listener);
1185 
1186     /**
1187      * Take a bugreport and returns it inside a {@link Bugreport} object to handle it. Return null
1188      * in case of issue. File referenced in the Bugreport object need to be cleaned via {@link
1189      * Bugreport#close()}.
1190      */
takeBugreport()1191     public Bugreport takeBugreport();
1192 
1193     /** Notify the device to wait for snapuserd completion. */
notifySnapuserd(SnapuserdWaitPhase waitPhase)1194     public default void notifySnapuserd(SnapuserdWaitPhase waitPhase) {
1195         // Empty on purpose
1196     }
1197 
1198     /** If expected, wait for snapuserd to complete. */
waitForSnapuserd(SnapuserdWaitPhase currentPhase)1199     public default void waitForSnapuserd(SnapuserdWaitPhase currentPhase)
1200             throws DeviceNotAvailableException {
1201         // Empty on purpose
1202     }
1203 }
1204