aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tradefed/device/ITestDevice.java
blob: 746b2c6df9b86f01f0da5c36ec1205d5c2bf2d68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.tradefed.device;

import com.android.ddmlib.IDevice;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.util.KeyguardControllerState;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Provides an reliable and slightly higher level API to a ddmlib {@link IDevice}.
 * <p/>
 * Retries device commands for a configurable amount, and provides a device recovery
 * interface for devices which are unresponsive.
 */
public interface ITestDevice extends INativeDevice {

    public enum RecoveryMode {
        /** don't attempt to recover device. */
        NONE,
        /** recover device to online state only */
        ONLINE,
        /**
         * Recover device into fully testable state - framework is up, and external storage is
         * mounted.
         */
        AVAILABLE
    }

    /**
     * A simple struct class to store information about a single mountpoint
     */
    public static class MountPointInfo {
        public String filesystem;
        public String mountpoint;
        public String type;
        public List<String> options;

        /** Simple constructor */
        public MountPointInfo() {}

        /**
         * Convenience constructor to set all members
         */
        public MountPointInfo(String filesystem, String mountpoint, String type,
                List<String> options) {
            this.filesystem = filesystem;
            this.mountpoint = mountpoint;
            this.type = type;
            this.options = options;
        }

        public MountPointInfo(String filesystem, String mountpoint, String type, String optString) {
            this(filesystem, mountpoint, type, splitMountOptions(optString));
        }

        public static List<String> splitMountOptions(String options) {
            List<String> list = Arrays.asList(options.split(","));
            return list;
        }

        @Override
        public String toString() {
            return String.format("%s %s %s %s", this.filesystem, this.mountpoint, this.type,
                    this.options);
        }
    }

    /**
     * Install an Android package on device.
     *
     * @param packageFile the apk file to install
     * @param reinstall <code>true</code> if a reinstall should be performed
     * @param extraArgs optional extra arguments to pass. See 'adb shell pm install --help' for
     *            available options.
     * @return a {@link String} with an error code, or <code>null</code> if success.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public String installPackage(File packageFile, boolean reinstall, String... extraArgs)
            throws DeviceNotAvailableException;

    /**
     * Install an Android package on device.
     * <p>Note: Only use cases that requires explicit control of granting runtime permission at
     * install time should call this function.
     * @param packageFile the apk file to install
     * @param reinstall <code>true</code> if a reinstall should be performed
     * @param grantPermissions if all runtime permissions should be granted at install time
     * @param extraArgs optional extra arguments to pass. See 'adb shell pm install --help' for
     *            available options.
     * @return a {@link String} with an error code, or <code>null</code> if success.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     * @throws UnsupportedOperationException if runtime permission is not supported by the platform
     *         on device.
     */
    public String installPackage(File packageFile, boolean reinstall, boolean grantPermissions,
            String... extraArgs) throws DeviceNotAvailableException;

    /**
     * Install an Android package on device for a given user.
     *
     * @param packageFile the apk file to install
     * @param reinstall <code>true</code> if a reinstall should be performed
     * @param userId the integer user id to install for.
     * @param extraArgs optional extra arguments to pass. See 'adb shell pm install --help' for
     *            available options.
     * @return a {@link String} with an error code, or <code>null</code> if success.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public String installPackageForUser(File packageFile, boolean reinstall, int userId,
            String... extraArgs) throws DeviceNotAvailableException;

    /**
     * Install an Android package on device for a given user.
     * <p>Note: Only use cases that requires explicit control of granting runtime permission at
     * install time should call this function.
     * @param packageFile the apk file to install
     * @param reinstall <code>true</code> if a reinstall should be performed
     * @param grantPermissions if all runtime permissions should be granted at install time
     * @param userId the integer user id to install for.
     * @param extraArgs optional extra arguments to pass. See 'adb shell pm install --help' for
     *            available options.
     * @return a {@link String} with an error code, or <code>null</code> if success.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     * @throws UnsupportedOperationException if runtime permission is not supported by the platform
     *         on device.
     */
    public String installPackageForUser(File packageFile, boolean reinstall,
            boolean grantPermissions, int userId, String... extraArgs)
                    throws DeviceNotAvailableException;

    /**
     * Uninstall an Android package from device.
     *
     * @param packageName the Android package to uninstall
     * @return a {@link String} with an error code, or <code>null</code> if success.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public String uninstallPackage(String packageName) throws DeviceNotAvailableException;

    /**
     * Grabs a screenshot from the device.
     *
     * @return a {@link InputStreamSource} of the screenshot in png format, or <code>null</code> if
     *         the screenshot was not successful.
     * @throws DeviceNotAvailableException
     */
    public InputStreamSource getScreenshot() throws DeviceNotAvailableException;

    /**
     * Grabs a screenshot from the device.
     * Recommended to use getScreenshot(format) instead with JPEG encoding for smaller size
     * @param format supported PNG, JPEG
     * @return a {@link InputStreamSource} of the screenshot in format, or <code>null</code> if
     *         the screenshot was not successful.
     * @throws DeviceNotAvailableException
     */
    public InputStreamSource getScreenshot(String format) throws DeviceNotAvailableException;

    /**
     * Grabs a screenshot from the device. Recommended to use {@link #getScreenshot(String)} instead
     * with JPEG encoding for smaller size.
     *
     * @param format supported PNG, JPEG
     * @param rescale if screenshot should be rescaled to reduce the size of resulting image
     * @return a {@link InputStreamSource} of the screenshot in format, or <code>null</code> if the
     *     screenshot was not successful.
     * @throws DeviceNotAvailableException
     */
    public InputStreamSource getScreenshot(String format, boolean rescale)
            throws DeviceNotAvailableException;

    /**
     * Clears the last connected wifi network. This should be called when starting a new invocation
     * to avoid connecting to the wifi network used in the previous test after device reboots.
     */
    public void clearLastConnectedWifiNetwork();

    /**
     * Connects to a wifi network.
     * <p/>
     * Turns on wifi and blocks until a successful connection is made to the specified wifi network.
     * Once a connection is made, the instance will try to restore the connection after every reboot
     * until {@link ITestDevice#disconnectFromWifi()} or
     * {@link ITestDevice#clearLastConnectedWifiNetwork()} is called.
     *
     * @param wifiSsid the wifi ssid to connect to
     * @param wifiPsk PSK passphrase or null if unencrypted
     * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
     *         otherwise
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public boolean connectToWifiNetwork(String wifiSsid, String wifiPsk)
            throws DeviceNotAvailableException;

    /**
     * Connects to a wifi network.
     * <p/>
     * Turns on wifi and blocks until a successful connection is made to the specified wifi network.
     * Once a connection is made, the instance will try to restore the connection after every reboot
     * until {@link ITestDevice#disconnectFromWifi()} or
     * {@link ITestDevice#clearLastConnectedWifiNetwork()} is called.
     *
     * @param wifiSsid the wifi ssid to connect to
     * @param wifiPsk PSK passphrase or null if unencrypted
     * @param scanSsid whether to scan for hidden SSID for this network.
     * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
     *         otherwise
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public boolean connectToWifiNetwork(String wifiSsid, String wifiPsk, boolean scanSsid)
            throws DeviceNotAvailableException;

    /**
     * A variant of {@link #connectToWifiNetwork(String, String)} that only connects if device
     * currently does not have network connectivity.
     *
     * @param wifiSsid
     * @param wifiPsk
     * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
     *         otherwise
     * @throws DeviceNotAvailableException
     */
    public boolean connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk)
            throws DeviceNotAvailableException;

    /**
     * A variant of {@link #connectToWifiNetwork(String, String)} that only connects if device
     * currently does not have network connectivity.
     *
     * @param wifiSsid
     * @param wifiPsk
     * @param scanSsid whether to scan for hidden SSID for this network
     * @return <code>true</code> if connected to wifi network successfully. <code>false</code>
     *         otherwise
     * @throws DeviceNotAvailableException
     */
    public boolean connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk, boolean scanSsid)
            throws DeviceNotAvailableException;

    /**
     * Disconnects from a wifi network.
     * <p/>
     * Removes all networks from known networks list and disables wifi.
     *
     * @return <code>true</code> if disconnected from wifi network successfully. <code>false</code>
     *         if disconnect failed.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public boolean disconnectFromWifi() throws DeviceNotAvailableException;

    /**
     * Test if wifi is enabled.
     * <p/>
     * Checks if wifi is enabled on device. Useful for asserting wifi status before tests that
     * shouldn't run with wifi, e.g. mobile data tests.
     *
     * @return <code>true</code> if wifi is enabled. <code>false</code> if disabled
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public boolean isWifiEnabled() throws DeviceNotAvailableException;

    /**
     * Gets the device's IP address.
     *
     * @return the device's IP address, or <code>null</code> if device has no IP address
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public String getIpAddress() throws DeviceNotAvailableException;

    /**
     * Enables network monitoring on device.
     *
     * @return <code>true</code> if monitoring is enabled successfully. <code>false</code>
     *         if it failed.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public boolean enableNetworkMonitor() throws DeviceNotAvailableException;

    /**
     * Disables network monitoring on device.
     *
     * @return <code>true</code> if monitoring is disabled successfully. <code>false</code>
     *         if it failed.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public boolean disableNetworkMonitor() throws DeviceNotAvailableException;

    /**
     * Check that device has network connectivity.
     *
     * @return <code>true</code> if device has a working network connection,
     *          <code>false</code> overwise.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *          recovered.
     */
    public boolean checkConnectivity() throws DeviceNotAvailableException;

    /**
     * Attempt to dismiss any error dialogs currently displayed on device UI.
     *
     * @return <code>true</code> if no dialogs were present or dialogs were successfully cleared.
     *         <code>false</code> otherwise.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *             recovered.
     */
    public boolean clearErrorDialogs() throws DeviceNotAvailableException;

    /**
     * Return an object to get the current state of the keyguard or null if not supported.
     *
     * @return a {@link KeyguardControllerState} containing a snapshot of the state of the keyguard
     *     and returns Null if the Keyguard query is not supported.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *     recovered.
     */
    public KeyguardControllerState getKeyguardState() throws DeviceNotAvailableException;

    /**
     * Fetch the test options for the device.
     *
     * @return {@link TestDeviceOptions} related to the device under test.
     */
    public TestDeviceOptions getOptions();

    /**
     * Fetch the application package names present on the device.
     *
     * @return {@link Set} of {@link String} package names currently installed on the device.
     * @throws DeviceNotAvailableException
     */
    public Set<String> getInstalledPackageNames() throws DeviceNotAvailableException;

    /**
     * Fetch the application package names that can be uninstalled. This is presently defined as
     * non-system packages, and updated system packages.
     *
     * @return {@link Set} of uninstallable {@link String} package names currently installed on the
     *         device.
     * @throws DeviceNotAvailableException
     */
    public Set<String> getUninstallablePackageNames() throws DeviceNotAvailableException;

    /**
     * Fetch information about a package installed on device.
     *
     * @return the {@link PackageInfo} or <code>null</code> if information could not be retrieved
     * @throws DeviceNotAvailableException
     */
    public PackageInfo getAppPackageInfo(String packageName) throws DeviceNotAvailableException;

    /**
     * Determines if multi user is supported.
     *
     * @return true if multi user is supported, false otherwise
     * @throws DeviceNotAvailableException
     */
    public boolean isMultiUserSupported() throws DeviceNotAvailableException;

    /**
     * Create a user with a given name and default flags 0.
     *
     * @param name of the user to create on the device
     * @return the integer for the user id created
     * @throws DeviceNotAvailableException
     */
    public int createUser(String name) throws DeviceNotAvailableException, IllegalStateException;

    /**
     * Create a user with a given name and the provided flags
     *
     * @param name of the user to create on the device
     * @param guest enable the user flag --guest during creation
     * @param ephemeral enable the user flag --ephemeral during creation
     * @return id of the created user
     * @throws DeviceNotAvailableException
     */
    public int createUser(String name, boolean guest, boolean ephemeral)
            throws DeviceNotAvailableException, IllegalStateException;

    /**
     * Remove a given user from the device.
     *
     * @param userId of the user to remove
     * @return true if we were succesful in removing the user, false otherwise.
     * @throws DeviceNotAvailableException
     */
    public boolean removeUser(int userId) throws DeviceNotAvailableException;

    /**
     * Gets the list of users on the device. Defaults to null.
     *
     * @return the list of user ids or null if there was an error.
     * @throws DeviceNotAvailableException
     */
    ArrayList<Integer> listUsers() throws DeviceNotAvailableException;

    /**
     * Get the maximum number of supported users. Defaults to 0.
     *
     * @return an integer indicating the number of supported users
     * @throws DeviceNotAvailableException
     */
    public int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException;

    /**
     * Starts a given user in the background if it is currently stopped. If the user is already
     * running in the background, this method is a NOOP.
     * @param userId of the user to start in the background
     * @return true if the user was successfully started in the background.
     * @throws DeviceNotAvailableException
     */
    public boolean startUser(int userId) throws DeviceNotAvailableException;

    /**
     * Stops a given user. If the user is already stopped, this method is a NOOP.
     * Cannot stop current and system user.
     *
     * @param userId of the user to stop.
     * @return true if the user was successfully stopped.
     * @throws DeviceNotAvailableException
     */
    public boolean stopUser(int userId) throws DeviceNotAvailableException;

    /**
     * Stop a given user. Possible to provide extra flags to wait for the operation to have effect,
     * and force terminate the user. Cannot stop current and system user.
     *
     * @param userId of the user to stop.
     * @param waitFlag will make the command wait until user is stopped.
     * @param forceFlag will force stop the user.
     * @return true if the user was successfully stopped.
     * @throws DeviceNotAvailableException
     */
    public boolean stopUser(int userId, boolean waitFlag, boolean forceFlag)
            throws DeviceNotAvailableException;

    /**
     * Returns the primary user id.
     * @return the userId of the primary user if there is one, and null if there is no primary user.
     * @throws DeviceNotAvailableException
     */
    public Integer getPrimaryUserId() throws DeviceNotAvailableException;

    /**
     * Return the id of the current running user.
     *
     * @throws DeviceNotAvailableException
     */
    public int getCurrentUser() throws DeviceNotAvailableException;

    /**
     * Find and return the flags of a given user.
     * Flags are defined in "android.content.pm.UserInfo" class in Android Open Source Project.
     *
     * @return the flags associated with the userId provided if found, -10000 in any other cases.
     * @throws DeviceNotAvailableException
     */
    public int getUserFlags(int userId) throws DeviceNotAvailableException;

    /**
     * Return the serial number associated to the userId if found, -10000 in any other cases.
     *
     * @throws DeviceNotAvailableException
     */
    public int getUserSerialNumber(int userId) throws DeviceNotAvailableException;

    /**
     * Switch to another userId with a default timeout. {@link #switchUser(int, long)}.
     *
     * @return True if the new userId matches the userId provider. False otherwise.
     * @throws DeviceNotAvailableException
     */
    public boolean switchUser(int userId) throws DeviceNotAvailableException;

    /**
     * Switch to another userId with the provided timeout as deadline.
     * Attempt to disable keyguard after user change is successful.
     *
     * @param timeout to wait before returning false for switch-user failed.
     * @return True if the new userId matches the userId provider. False otherwise.
     * @throws DeviceNotAvailableException
     */
    public boolean switchUser(int userId, long timeout) throws DeviceNotAvailableException;

    /**
     * Check if a given user is running.
     *
     * @return True if the user is running, false in every other cases.
     * @throws DeviceNotAvailableException
     */
    public boolean isUserRunning(int userId) throws DeviceNotAvailableException;

    /**
     * Check if a feature is available on a device.
     *
     * @param feature which format should be "feature:<name>".
     * @return True if feature is found, false otherwise.
     * @throws DeviceNotAvailableException
     */
    public boolean hasFeature(String feature) throws DeviceNotAvailableException;

    /**
     * See {@link #getSetting(int, String, String)} and performed on system user.
     *
     * @throws DeviceNotAvailableException
     */
    public String getSetting(String namespace, String key) throws DeviceNotAvailableException;

    /**
     * Return the value of the requested setting.
     * namespace must be one of: {"system", "secure", "global"}
     *
     * @return the value associated with the namespace:key of a user. Null if not found.
     * @throws DeviceNotAvailableException
     */
    public String getSetting(int userId, String namespace, String key)
            throws DeviceNotAvailableException;

    /**
     * See {@link #setSetting(int, String, String, String)} and performed on system user.
     *
     * @throws DeviceNotAvailableException
     */
    public void setSetting(String namespace, String key, String value)
            throws DeviceNotAvailableException;

    /**
     * Add a setting value to the namespace of a given user. Some settings will only be available
     * after a reboot.
     * namespace must be one of: {"system", "secure", "global"}
     *
     * @throws DeviceNotAvailableException
     */
    public void setSetting(int userId, String namespace, String key, String value)
            throws DeviceNotAvailableException;

    /**
     * Find and return the android-id associated to a userId, null if not found.
     *
     * @throws DeviceNotAvailableException
     */
    public String getAndroidId(int userId) throws DeviceNotAvailableException;

    /**
     * Create a Map of android ids found matching user ids. There is no insurance that each user
     * id will found an android id associated in this function so some user ids may match null.
     *
     * @return Map of android ids found matching user ids.
     * @throws DeviceNotAvailableException
     */
    public Map<Integer, String> getAndroidIds() throws DeviceNotAvailableException;

    /**
     * Set a device admin component as device owner in given user.
     *
     * @param componentName of device admin to be device owner.
     * @param userId of the user that the device owner lives in.
     * @return True if it is successful, false otherwise.
     * @throws DeviceNotAvailableException
     */
    public boolean setDeviceOwner(String componentName, int userId)
            throws DeviceNotAvailableException;

    /**
     * Remove given device admin in given user and return {@code true} if it is successful, {@code
     * false} otherwise.
     *
     * @param componentName of device admin to be removed.
     * @param userId of user that the device admin lives in.
     * @return True if it is successful, false otherwise.
     * @throws DeviceNotAvailableException
     */
    public boolean removeAdmin(String componentName, int userId) throws DeviceNotAvailableException;

    /**
     * Remove all existing device profile owners with the best effort.
     *
     * @throws DeviceNotAvailableException
     */
    public void removeOwners() throws DeviceNotAvailableException;

    /**
     * Attempts to disable the keyguard.
     * <p>
     * First wait for the input dispatch to become ready, this happens around the same time when the
     * device reports BOOT_COMPLETE, apparently asynchronously, because current framework
     * implementation has occasional race condition. Then command is sent to dismiss keyguard (works
     * on non-secure ones only)
     */
    public void disableKeyguard() throws DeviceNotAvailableException;

    /**
     * Attempt to dump the heap from the system_server. It is the caller responsibility to clean up
     * the dumped file.
     *
     * @param process the name of the device process to dumpheap on.
     * @param devicePath the path on the device where to put the dump. This must be a location where
     *     permissions allow it.
     * @return the {@link File} containing the report. Null if something failed.
     * @throws DeviceNotAvailableException
     */
    public File dumpHeap(String process, String devicePath) throws DeviceNotAvailableException;
}