• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.content.pm;
18 
19 import com.android.ddmlib.AndroidDebugBridge;
20 import com.android.ddmlib.IDevice;
21 import com.android.ddmlib.IShellOutputReceiver;
22 import com.android.ddmlib.Log;
23 import com.android.ddmlib.MultiLineReceiver;
24 import com.android.ddmlib.SyncService;
25 import com.android.ddmlib.SyncService.ISyncProgressMonitor;
26 import com.android.ddmlib.SyncService.SyncResult;
27 import com.android.ddmlib.testrunner.ITestRunListener;
28 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
29 import com.android.ddmlib.testrunner.TestIdentifier;
30 import com.android.hosttest.DeviceTestCase;
31 import com.android.hosttest.DeviceTestSuite;
32 
33 import java.io.BufferedReader;
34 import java.io.File;
35 import java.io.InputStreamReader;
36 import java.io.IOException;
37 import java.io.StringReader;
38 import java.lang.Runtime;
39 import java.lang.Process;
40 import java.util.Hashtable;
41 import java.util.Map;
42 import java.util.Map.Entry;
43 import java.util.regex.Matcher;
44 import java.util.regex.Pattern;
45 
46 import junit.framework.Assert;
47 import com.android.hosttest.DeviceTestCase;
48 
49 /**
50  * Set of tests that verify host side install cases
51  */
52 public class PackageManagerHostTestUtils extends Assert {
53 
54     private static final String LOG_TAG = "PackageManagerHostTests";
55     private IDevice mDevice = null;
56 
57     // TODO: get this value from Android Environment instead of hardcoding
58     private static final String APP_PRIVATE_PATH = "/data/app-private/";
59     private static final String DEVICE_APP_PATH = "/data/app/";
60     private static final String SDCARD_APP_PATH = "/mnt/secure/asec/";
61 
62     private static final int MAX_WAIT_FOR_DEVICE_TIME = 120 * 1000;
63     private static final int WAIT_FOR_DEVICE_POLL_TIME = 10 * 1000;
64     private static final int MAX_WAIT_FOR_APP_LAUNCH_TIME = 60 * 1000;
65     private static final int WAIT_FOR_APP_LAUNCH_POLL_TIME = 5 * 1000;
66 
67     // Install preference on the device-side
68     public static enum InstallLocPreference {
69         AUTO,
70         INTERNAL,
71         EXTERNAL
72     }
73 
74     // Actual install location
75     public static enum InstallLocation {
76         DEVICE,
77         SDCARD
78     }
79 
80     /**
81      * Constructor takes the device to use
82      * @param the device to use when performing operations
83      */
PackageManagerHostTestUtils(IDevice device)84     public PackageManagerHostTestUtils(IDevice device)
85     {
86           mDevice = device;
87     }
88 
89     /**
90      * Disable default constructor
91      */
PackageManagerHostTestUtils()92     private PackageManagerHostTestUtils() {}
93 
94     /**
95      * Returns the path on the device of forward-locked apps.
96      *
97      * @return path of forward-locked apps on the device
98      */
getAppPrivatePath()99     public static String getAppPrivatePath() {
100         return APP_PRIVATE_PATH;
101     }
102 
103     /**
104      * Returns the path on the device of normal apps.
105      *
106      * @return path of forward-locked apps on the device
107      */
getDeviceAppPath()108     public static String getDeviceAppPath() {
109         return DEVICE_APP_PATH;
110     }
111 
112     /**
113      * Returns the path of apps installed on the SD card.
114      *
115      * @return path of forward-locked apps on the device
116      */
getSDCardAppPath()117     public static String getSDCardAppPath() {
118         return SDCARD_APP_PATH;
119     }
120 
121     /**
122      * Helper method to run tests and return the listener that collected the results.
123      *
124      * For the optional params, pass null to use the default values.
125 
126      * @param pkgName Android application package for tests
127      * @param className (optional) The class containing the method to test
128      * @param methodName (optional) The method in the class of which to test
129      * @param runnerName (optional) The name of the TestRunner of the test on the device to be run
130      * @param params (optional) Any additional parameters to pass into the Test Runner
131      * @return the {@link CollectingTestRunListener}
132      */
doRunTests(String pkgName, String className, String methodName, String runnerName, Map<String, String> params)133     private CollectingTestRunListener doRunTests(String pkgName, String className, String
134             methodName, String runnerName, Map<String, String> params) throws IOException {
135 
136         RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName, runnerName,
137                 mDevice);
138 
139         if (className != null && methodName != null) {
140             testRunner.setMethodName(className, methodName);
141         }
142 
143         // Add in any additional args to pass into the test
144         if (params != null) {
145             for (Entry<String, String> argPair : params.entrySet()) {
146                 testRunner.addInstrumentationArg(argPair.getKey(), argPair.getValue());
147             }
148         }
149 
150         CollectingTestRunListener listener = new CollectingTestRunListener();
151         testRunner.run(listener);
152         return listener;
153     }
154 
155     /**
156      * Runs the specified packages tests, and returns whether all tests passed or not.
157      *
158      * @param pkgName Android application package for tests
159      * @param className The class containing the method to test
160      * @param methodName The method in the class of which to test
161      * @param runnerName The name of the TestRunner of the test on the device to be run
162      * @param params Any additional parameters to pass into the Test Runner
163      * @return true if test passed, false otherwise.
164      */
runDeviceTestsDidAllTestsPass(String pkgName, String className, String methodName, String runnerName, Map<String, String> params)165     public boolean runDeviceTestsDidAllTestsPass(String pkgName, String className,
166             String methodName, String runnerName, Map<String, String> params) throws IOException {
167         CollectingTestRunListener listener = doRunTests(pkgName, className, methodName,
168                 runnerName, params);
169         return listener.didAllTestsPass();
170     }
171 
172     /**
173      * Runs the specified packages tests, and returns whether all tests passed or not.
174      *
175      * @param pkgName Android application package for tests
176      * @return true if every test passed, false otherwise.
177      */
runDeviceTestsDidAllTestsPass(String pkgName)178     public boolean runDeviceTestsDidAllTestsPass(String pkgName) throws IOException {
179         CollectingTestRunListener listener = doRunTests(pkgName, null, null, null, null);
180         return listener.didAllTestsPass();
181     }
182 
183     /**
184      * Helper method to push a file to device
185      * @param apkAppPrivatePath
186      * @throws IOException
187      */
pushFile(final String localFilePath, final String destFilePath)188     public void pushFile(final String localFilePath, final String destFilePath)
189             throws IOException {
190         SyncResult result = mDevice.getSyncService().pushFile(
191                 localFilePath, destFilePath, new NullSyncProgressMonitor());
192         assertEquals(SyncService.RESULT_OK, result.getCode());
193     }
194 
195     /**
196      * Helper method to install a file
197      * @param localFilePath the absolute file system path to file on local host to install
198      * @param reinstall set to <code>true</code> if re-install of app should be performed
199      * @throws IOException
200      */
installFile(final String localFilePath, final boolean replace)201     public void installFile(final String localFilePath, final boolean replace) throws IOException {
202         String result = mDevice.installPackage(localFilePath, replace);
203         assertEquals(null, result);
204     }
205 
206     /**
207      * Helper method to install a file that should not be install-able
208      * @param localFilePath the absolute file system path to file on local host to install
209      * @param reinstall set to <code>true</code> if re-install of app should be performed
210      * @return the string output of the failed install attempt
211      * @throws IOException
212      */
installFileFail(final String localFilePath, final boolean replace)213     public String installFileFail(final String localFilePath, final boolean replace)
214             throws IOException {
215         String result = mDevice.installPackage(localFilePath, replace);
216         assertNotNull(result);
217         return result;
218     }
219 
220     /**
221      * Helper method to install a file to device as forward locked
222      * @param localFilePath the absolute file system path to file on local host to install
223      * @param reinstall set to <code>true</code> if re-install of app should be performed
224      * @throws IOException
225      */
installFileForwardLocked(final String localFilePath, final boolean replace)226     public String installFileForwardLocked(final String localFilePath, final boolean replace)
227             throws IOException {
228         String remoteFilePath = mDevice.syncPackageToDevice(localFilePath);
229         InstallReceiver receiver = new InstallReceiver();
230         String cmd = String.format(replace ? "pm install -r -l \"%1$s\"" :
231                 "pm install -l \"%1$s\"", remoteFilePath);
232         mDevice.executeShellCommand(cmd, receiver);
233         mDevice.removeRemotePackage(remoteFilePath);
234         return receiver.getErrorMessage();
235     }
236 
237     /**
238      * Helper method to determine if file on device exists.
239      *
240      * @param destPath the absolute path of file on device to check
241      * @return <code>true</code> if file exists, <code>false</code> otherwise.
242      * @throws IOException if adb shell command failed
243      */
doesRemoteFileExist(String destPath)244     public boolean doesRemoteFileExist(String destPath) throws IOException {
245         String lsGrep = executeShellCommand(String.format("ls %s", destPath));
246         return !lsGrep.contains("No such file or directory");
247     }
248 
249     /**
250      * Helper method to determine if file exists on the device containing a given string.
251      *
252      * @param destPath the absolute path of the file
253      * @return <code>true</code> if file exists containing given string,
254      *         <code>false</code> otherwise.
255      * @throws IOException if adb shell command failed
256      */
doesRemoteFileExistContainingString(String destPath, String searchString)257     public boolean doesRemoteFileExistContainingString(String destPath, String searchString)
258             throws IOException {
259         String lsResult = executeShellCommand(String.format("ls %s", destPath));
260         return lsResult.contains(searchString);
261     }
262 
263     /**
264      * Helper method to determine if package on device exists.
265      *
266      * @param packageName the Android manifest package to check.
267      * @return <code>true</code> if package exists, <code>false</code> otherwise
268      * @throws IOException if adb shell command failed
269      */
doesPackageExist(String packageName)270     public boolean doesPackageExist(String packageName) throws IOException {
271         String pkgGrep = executeShellCommand(String.format("pm path %s", packageName));
272         return pkgGrep.contains("package:");
273     }
274 
275     /**
276      * Determines if app was installed on device.
277      *
278      * @param packageName package name to check for
279      * @return <code>true</code> if file exists, <code>false</code> otherwise.
280      * @throws IOException if adb shell command failed
281      */
doesAppExistOnDevice(String packageName)282     public boolean doesAppExistOnDevice(String packageName) throws IOException {
283         return doesRemoteFileExistContainingString(DEVICE_APP_PATH, packageName);
284     }
285 
286     /**
287      * Determines if app was installed on SD card.
288      *
289      * @param packageName package name to check for
290      * @return <code>true</code> if file exists, <code>false</code> otherwise.
291      * @throws IOException if adb shell command failed
292      */
doesAppExistOnSDCard(String packageName)293     public boolean doesAppExistOnSDCard(String packageName) throws IOException {
294         return doesRemoteFileExistContainingString(SDCARD_APP_PATH, packageName);
295     }
296 
297     /**
298      * Helper method to determine if app was installed on SD card.
299      *
300      * @param packageName package name to check for
301      * @return <code>true</code> if file exists, <code>false</code> otherwise.
302      * @throws IOException if adb shell command failed
303      */
doesAppExistAsForwardLocked(String packageName)304     public boolean doesAppExistAsForwardLocked(String packageName) throws IOException {
305         return doesRemoteFileExistContainingString(APP_PRIVATE_PATH, packageName);
306     }
307 
308     /**
309      * Waits for device's package manager to respond.
310      *
311      * @throws InterruptedException
312      * @throws IOException
313      */
waitForPackageManager()314     public void waitForPackageManager() throws InterruptedException, IOException {
315         Log.i(LOG_TAG, "waiting for device");
316         int currentWaitTime = 0;
317         // poll the package manager until it returns something for android
318         while (!doesPackageExist("android")) {
319             Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
320             currentWaitTime += WAIT_FOR_DEVICE_POLL_TIME;
321             if (currentWaitTime > MAX_WAIT_FOR_DEVICE_TIME) {
322                 Log.e(LOG_TAG, "time out waiting for device");
323                 throw new InterruptedException();
324             }
325         }
326     }
327 
328     /**
329      * Helper to determine if the device is currently online and visible via ADB.
330      *
331      * @return true iff the device is currently available to ADB and online, false otherwise.
332      */
deviceIsOnline()333     private boolean deviceIsOnline() {
334         AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
335         IDevice[] devices = bridge.getDevices();
336 
337         for (IDevice device : devices) {
338             // only online if the device appears in the devices list, and its state is online
339             if ((mDevice != null) &&
340                     mDevice.getSerialNumber().equals(device.getSerialNumber()) &&
341                     device.isOnline()) {
342                 return true;
343             }
344         }
345         return false;
346     }
347 
348     /**
349      * Waits for device to be online (visible to ADB) before returning, or times out if we've
350      * waited too long. Note that this only means the device is visible via ADB, not that
351      * PackageManager is fully up and running yet.
352      *
353      * @throws InterruptedException
354      * @throws IOException
355      */
waitForDeviceToComeOnline()356     public void waitForDeviceToComeOnline() throws InterruptedException, IOException {
357         Log.i(LOG_TAG, "waiting for device to be online");
358         int currentWaitTime = 0;
359 
360         // poll ADB until we see the device is online
361         while (!deviceIsOnline()) {
362             Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
363             currentWaitTime += WAIT_FOR_DEVICE_POLL_TIME;
364             if (currentWaitTime > MAX_WAIT_FOR_DEVICE_TIME) {
365                 Log.e(LOG_TAG, "time out waiting for device");
366                 throw new InterruptedException();
367             }
368         }
369         // Note: if we try to access the device too quickly after it is "officially" online,
370         // there are sometimes strange issues where it's actually not quite ready yet,
371         // so we pause for a bit once more before actually returning.
372         Thread.sleep(WAIT_FOR_DEVICE_POLL_TIME);
373     }
374 
375     /**
376      * Queries package manager and waits until a package is launched (or times out)
377      *
378      * @param packageName The name of the package to wait to load
379      * @throws InterruptedException
380      * @throws IOException
381      */
waitForApp(String packageName)382     public void waitForApp(String packageName) throws InterruptedException, IOException {
383         Log.i(LOG_TAG, "waiting for app to launch");
384         int currentWaitTime = 0;
385         // poll the package manager until it returns something for the package we're looking for
386         while (!doesPackageExist(packageName)) {
387             Thread.sleep(WAIT_FOR_APP_LAUNCH_POLL_TIME);
388             currentWaitTime += WAIT_FOR_APP_LAUNCH_POLL_TIME;
389             if (currentWaitTime > MAX_WAIT_FOR_APP_LAUNCH_TIME) {
390                 Log.e(LOG_TAG, "time out waiting for app to launch: " + packageName);
391                 throw new InterruptedException();
392             }
393         }
394     }
395 
396     /**
397      * Helper method which executes a adb shell command and returns output as a {@link String}
398      * @return the output of the command
399      * @throws IOException
400      */
executeShellCommand(String command)401     public String executeShellCommand(String command) throws IOException {
402         Log.i(LOG_TAG, String.format("adb shell %s", command));
403         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
404         mDevice.executeShellCommand(command, receiver);
405         String output = receiver.getOutput();
406         Log.i(LOG_TAG, String.format("Result: %s", output));
407         return output;
408     }
409 
410     /**
411      * Helper method ensures we are in root mode on the host side. It returns only after
412      * PackageManager is actually up and running.
413      * @throws IOException
414      */
runAdbRoot()415     public void runAdbRoot() throws IOException, InterruptedException {
416         Log.i(LOG_TAG, "adb root");
417         Runtime runtime = Runtime.getRuntime();
418         Process process = runtime.exec("adb root"); // adb should be in the path
419         BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
420 
421         String nextLine = null;
422         while (null != (nextLine = output.readLine())) {
423             Log.i(LOG_TAG, nextLine);
424         }
425         process.waitFor();
426         waitForDeviceToComeOnline();
427         waitForPackageManager(); // now wait for package manager to actually load
428     }
429 
430     /**
431      * Helper method which reboots the device and returns once the device is online again
432      * and package manager is up and running (note this function is synchronous to callers).
433      * @throws IOException
434      * @throws InterruptedException
435      */
rebootDevice()436     public void rebootDevice() throws IOException, InterruptedException {
437         String command = "reboot"; // no need for -s since mDevice is already tied to a device
438         Log.i(LOG_TAG, command);
439         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
440         mDevice.executeShellCommand(command, receiver);
441         String output = receiver.getOutput();
442         Log.i(LOG_TAG, String.format("Result: %s", output));
443         waitForDeviceToComeOnline(); // wait for device to come online
444         runAdbRoot();
445     }
446 
447     /**
448      * A {@link IShellOutputReceiver} which collects the whole shell output into one {@link String}
449      */
450     private class CollectingOutputReceiver extends MultiLineReceiver {
451 
452         private StringBuffer mOutputBuffer = new StringBuffer();
453 
getOutput()454         public String getOutput() {
455             return mOutputBuffer.toString();
456         }
457 
458         @Override
processNewLines(String[] lines)459         public void processNewLines(String[] lines) {
460             for (String line: lines) {
461                 mOutputBuffer.append(line);
462                 mOutputBuffer.append("\n");
463             }
464         }
465 
isCancelled()466         public boolean isCancelled() {
467             return false;
468         }
469     }
470 
471     private class NullSyncProgressMonitor implements ISyncProgressMonitor {
advance(int work)472         public void advance(int work) {
473             // ignore
474         }
475 
isCanceled()476         public boolean isCanceled() {
477             // ignore
478             return false;
479         }
480 
start(int totalWork)481         public void start(int totalWork) {
482             // ignore
483 
484         }
485 
startSubTask(String name)486         public void startSubTask(String name) {
487             // ignore
488         }
489 
stop()490         public void stop() {
491             // ignore
492         }
493     }
494 
495     // For collecting results from running device tests
496     public static class CollectingTestRunListener implements ITestRunListener {
497 
498         private boolean mAllTestsPassed = true;
499         private String mTestRunErrorMessage = null;
500 
testEnded(TestIdentifier test)501         public void testEnded(TestIdentifier test) {
502             // ignore
503         }
504 
testFailed(TestFailure status, TestIdentifier test, String trace)505         public void testFailed(TestFailure status, TestIdentifier test,
506                 String trace) {
507             Log.w(LOG_TAG, String.format("%s#%s failed: %s", test.getClassName(),
508                     test.getTestName(), trace));
509             mAllTestsPassed = false;
510         }
511 
testRunEnded(long elapsedTime)512         public void testRunEnded(long elapsedTime) {
513             // ignore
514         }
515 
testRunFailed(String errorMessage)516         public void testRunFailed(String errorMessage) {
517             Log.w(LOG_TAG, String.format("test run failed: %s", errorMessage));
518             mAllTestsPassed = false;
519             mTestRunErrorMessage = errorMessage;
520         }
521 
testRunStarted(int testCount)522         public void testRunStarted(int testCount) {
523             // ignore
524         }
525 
testRunStopped(long elapsedTime)526         public void testRunStopped(long elapsedTime) {
527             // ignore
528         }
529 
testStarted(TestIdentifier test)530         public void testStarted(TestIdentifier test) {
531             // ignore
532         }
533 
didAllTestsPass()534         boolean didAllTestsPass() {
535             return mAllTestsPassed;
536         }
537 
538         /**
539          * Get the test run failure error message.
540          * @return the test run failure error message or <code>null</code> if test run completed.
541          */
getTestRunErrorMessage()542         String getTestRunErrorMessage() {
543             return mTestRunErrorMessage;
544         }
545     }
546 
547     /**
548      * Output receiver for "pm install package.apk" command line.
549      *
550      */
551     private static final class InstallReceiver extends MultiLineReceiver {
552 
553         private static final String SUCCESS_OUTPUT = "Success"; //$NON-NLS-1$
554         private static final Pattern FAILURE_PATTERN = Pattern.compile("Failure\\s+\\[(.*)\\]"); //$NON-NLS-1$
555 
556         private String mErrorMessage = null;
557 
InstallReceiver()558         public InstallReceiver() {
559         }
560 
561         @Override
processNewLines(String[] lines)562         public void processNewLines(String[] lines) {
563             for (String line : lines) {
564                 if (line.length() > 0) {
565                     if (line.startsWith(SUCCESS_OUTPUT)) {
566                         mErrorMessage = null;
567                     } else {
568                         Matcher m = FAILURE_PATTERN.matcher(line);
569                         if (m.matches()) {
570                             mErrorMessage = m.group(1);
571                         }
572                     }
573                 }
574             }
575         }
576 
isCancelled()577         public boolean isCancelled() {
578             return false;
579         }
580 
getErrorMessage()581         public String getErrorMessage() {
582             return mErrorMessage;
583         }
584     }
585 
586     /**
587      * Helper method for installing an app to wherever is specified in its manifest, and
588      * then verifying the app was installed onto SD Card.
589      *
590      * @param the path of the apk to install
591      * @param the name of the package
592      * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
593      * @throws IOException if adb shell command failed
594      * @throws InterruptedException if the thread was interrupted
595      * <p/>
596      * Assumes adb is running as root in device under test.
597      */
installAppAndVerifyExistsOnSDCard(String apkPath, String pkgName, boolean overwrite)598     public void installAppAndVerifyExistsOnSDCard(String apkPath, String pkgName, boolean overwrite)
599             throws IOException, InterruptedException {
600         // Start with a clean slate if we're not overwriting
601         if (!overwrite) {
602             // cleanup test app just in case it already exists
603             mDevice.uninstallPackage(pkgName);
604             // grep for package to make sure its not installed
605             assertFalse(doesPackageExist(pkgName));
606         }
607 
608         installFile(apkPath, overwrite);
609         assertTrue(doesAppExistOnSDCard(pkgName));
610         assertFalse(doesAppExistOnDevice(pkgName));
611         waitForPackageManager();
612 
613         // grep for package to make sure it is installed
614         assertTrue(doesPackageExist(pkgName));
615     }
616 
617     /**
618      * Helper method for installing an app to wherever is specified in its manifest, and
619      * then verifying the app was installed onto device.
620      *
621      * @param the path of the apk to install
622      * @param the name of the package
623      * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
624      * @throws IOException if adb shell command failed
625      * @throws InterruptedException if the thread was interrupted
626      * <p/>
627      * Assumes adb is running as root in device under test.
628      */
installAppAndVerifyExistsOnDevice(String apkPath, String pkgName, boolean overwrite)629     public void installAppAndVerifyExistsOnDevice(String apkPath, String pkgName, boolean overwrite)
630             throws IOException, InterruptedException {
631         // Start with a clean slate if we're not overwriting
632         if (!overwrite) {
633             // cleanup test app just in case it already exists
634             mDevice.uninstallPackage(pkgName);
635             // grep for package to make sure its not installed
636             assertFalse(doesPackageExist(pkgName));
637         }
638 
639         installFile(apkPath, overwrite);
640         assertFalse(doesAppExistOnSDCard(pkgName));
641         assertTrue(doesAppExistOnDevice(pkgName));
642         waitForPackageManager();
643 
644         // grep for package to make sure it is installed
645         assertTrue(doesPackageExist(pkgName));
646     }
647 
648     /**
649      * Helper method for installing an app as forward-locked, and
650      * then verifying the app was installed in the proper forward-locked location.
651      *
652      * @param the path of the apk to install
653      * @param the name of the package
654      * @param <code>true</code> if the app should be overwritten, <code>false</code> otherwise
655      * @throws IOException if adb shell command failed
656      * @throws InterruptedException if the thread was interrupted
657      * <p/>
658      * Assumes adb is running as root in device under test.
659      */
installFwdLockedAppAndVerifyExists(String apkPath, String pkgName, boolean overwrite)660     public void installFwdLockedAppAndVerifyExists(String apkPath,
661             String pkgName, boolean overwrite) throws IOException, InterruptedException {
662         // Start with a clean slate if we're not overwriting
663         if (!overwrite) {
664             // cleanup test app just in case it already exists
665             mDevice.uninstallPackage(pkgName);
666             // grep for package to make sure its not installed
667             assertFalse(doesPackageExist(pkgName));
668         }
669 
670         String result = installFileForwardLocked(apkPath, overwrite);
671         assertEquals(null, result);
672         assertTrue(doesAppExistAsForwardLocked(pkgName));
673         assertFalse(doesAppExistOnSDCard(pkgName));
674         waitForPackageManager();
675 
676         // grep for package to make sure it is installed
677         assertTrue(doesPackageExist(pkgName));
678     }
679 
680     /**
681      * Helper method for uninstalling an app.
682      *
683      * @param pkgName package name to uninstall
684      * @throws IOException if adb shell command failed
685      * @throws InterruptedException if the thread was interrupted
686      * <p/>
687      * Assumes adb is running as root in device under test.
688      */
uninstallApp(String pkgName)689     public void uninstallApp(String pkgName) throws IOException, InterruptedException {
690         mDevice.uninstallPackage(pkgName);
691         // make sure its not installed anymore
692         assertFalse(doesPackageExist(pkgName));
693     }
694 
695     /**
696      * Helper method for clearing any installed non-system apps.
697      * Useful ensuring no non-system apps are installed, and for cleaning up stale files that
698      * may be lingering on the system for whatever reason.
699      *
700      * @throws IOException if adb shell command failed
701      * <p/>
702      * Assumes adb is running as root in device under test.
703      */
wipeNonSystemApps()704     public void wipeNonSystemApps() throws IOException {
705       String allInstalledPackages = executeShellCommand("pm list packages -f");
706       BufferedReader outputReader = new BufferedReader(new StringReader(allInstalledPackages));
707 
708       // First use Package Manager to uninstall all non-system apps
709       String currentLine = null;
710       while ((currentLine = outputReader.readLine()) != null) {
711           // Skip over any system apps...
712           if (currentLine.contains("/system/")) {
713               continue;
714           }
715           String packageName = currentLine.substring(currentLine.indexOf('=') + 1);
716           mDevice.uninstallPackage(packageName);
717       }
718       // Make sure there are no stale app files under these directories
719       executeShellCommand(String.format("rm %s*", SDCARD_APP_PATH, "*"));
720       executeShellCommand(String.format("rm %s*", DEVICE_APP_PATH, "*"));
721       executeShellCommand(String.format("rm %s*", APP_PRIVATE_PATH, "*"));
722     }
723 
724     /**
725      * Sets the device's install location preference.
726      *
727      * <p/>
728      * Assumes adb is running as root in device under test.
729      */
setDevicePreferredInstallLocation(InstallLocPreference pref)730     public void setDevicePreferredInstallLocation(InstallLocPreference pref) throws IOException {
731         String command = "pm setInstallLocation %d";
732         int locValue = 0;
733         switch (pref) {
734             case INTERNAL:
735                 locValue = 1;
736                 break;
737             case EXTERNAL:
738                 locValue = 2;
739                 break;
740             default: // AUTO
741                 locValue = 0;
742                 break;
743         }
744         executeShellCommand(String.format(command, locValue));
745     }
746 
747     /**
748      * Gets the device's install location preference.
749      *
750      * <p/>
751      * Assumes adb is running as root in device under test.
752      */
getDevicePreferredInstallLocation()753     public InstallLocPreference getDevicePreferredInstallLocation() throws IOException {
754         String result = executeShellCommand("pm getInstallLocation");
755         if (result.indexOf('0') != -1) {
756             return InstallLocPreference.AUTO;
757         }
758         else if (result.indexOf('1') != -1) {
759             return InstallLocPreference.INTERNAL;
760         }
761         else {
762             return InstallLocPreference.EXTERNAL;
763         }
764     }
765 }
766