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
17package android.content.pm;
18
19import com.android.ddmlib.AdbCommandRejectedException;
20import com.android.ddmlib.InstallException;
21import com.android.ddmlib.Log;
22import com.android.ddmlib.ShellCommandUnresponsiveException;
23import com.android.ddmlib.SyncException;
24import com.android.ddmlib.TimeoutException;
25import com.android.hosttest.DeviceTestCase;
26import com.android.hosttest.DeviceTestSuite;
27
28import java.io.File;
29import java.io.IOException;
30
31import junit.framework.Test;
32
33/**
34 * Set of tests that verify host side install cases
35 */
36public class PackageManagerHostTests extends DeviceTestCase {
37
38    private static final String LOG_TAG = "PackageManagerHostTests";
39    private PackageManagerHostTestUtils mPMHostUtils = null;
40
41    private String appPrivatePath = null;
42    private String deviceAppPath = null;
43    private String sdcardAppPath = null;
44
45    // Various test files and their corresponding package names...
46
47    // testPushAppPrivate constants
48    // these constants must match values defined in test-apps/SimpleTestApp
49    private static final String SIMPLE_APK = "SimpleTestApp.apk";
50    private static final String SIMPLE_PKG = "com.android.framework.simpletestapp";
51
52    // Apk with install location set to auto
53    private static final String AUTO_LOC_APK = "AutoLocTestApp.apk";
54    private static final String AUTO_LOC_PKG = "com.android.framework.autoloctestapp";
55    // Apk with install location set to internalOnly
56    private static final String INTERNAL_LOC_APK = "InternalLocTestApp.apk";
57    private static final String INTERNAL_LOC_PKG = "com.android.framework.internalloctestapp";
58    // Apk with install location set to preferExternal
59    private static final String EXTERNAL_LOC_APK = "ExternalLocTestApp.apk";
60    private static final String EXTERNAL_LOC_PKG = "com.android.framework.externalloctestapp";
61    // Apk with install location set to auto (2 versions, for update testing)
62    private static final String AUTO_LOC_VERSION_V1_APK = "AutoLocVersionedTestApp_v1.apk";
63    private static final String AUTO_LOC_VERSION_V2_APK = "AutoLocVersionedTestApp_v2.apk";
64    private static final String AUTO_LOC_VERSION_PKG =
65            "com.android.framework.autolocversionedtestapp";
66    // Apk with install location set to preferExternal (2 versions, for update testing)
67    private static final String EXTERNAL_LOC_VERSION_V1_APK = "ExternalLocVersionedTestApp_v1.apk";
68    private static final String EXTERNAL_LOC_VERSION_V2_APK = "ExternalLocVersionedTestApp_v2.apk";
69    private static final String EXTERNAL_LOC_VERSION_PKG =
70            "com.android.framework.externallocversionedtestapp";
71    // Apk with install location set to auto (2 versions, for update testing)
72    private static final String NO_LOC_VERSION_V1_APK = "NoLocVersionedTestApp_v1.apk";
73    private static final String NO_LOC_VERSION_V2_APK = "NoLocVersionedTestApp_v2.apk";
74    private static final String NO_LOC_VERSION_PKG =
75            "com.android.framework.nolocversionedtestapp";
76    // Apk with no install location set
77    private static final String NO_LOC_APK = "NoLocTestApp.apk";
78    private static final String NO_LOC_PKG = "com.android.framework.noloctestapp";
79    // Apk with 2 different versions - v1 is set to external, v2 has no location setting
80    private static final String UPDATE_EXTERNAL_LOC_V1_EXT_APK
81            = "UpdateExternalLocTestApp_v1_ext.apk";
82    private static final String UPDATE_EXTERNAL_LOC_V2_NONE_APK
83            = "UpdateExternalLocTestApp_v2_none.apk";
84    private static final String UPDATE_EXTERNAL_LOC_PKG
85            = "com.android.framework.updateexternalloctestapp";
86    // Apk with 2 different versions - v1 is set to external, v2 is set to internalOnly
87    private static final String UPDATE_EXT_TO_INT_LOC_V1_EXT_APK
88            = "UpdateExtToIntLocTestApp_v1_ext.apk";
89    private static final String UPDATE_EXT_TO_INT_LOC_V2_INT_APK
90            = "UpdateExtToIntLocTestApp_v2_int.apk";
91    private static final String UPDATE_EXT_TO_INT_LOC_PKG
92            = "com.android.framework.updateexttointloctestapp";
93    // Apk set to preferExternal, with Access Fine Location permissions set in its manifest
94    private static final String FL_PERMS_APK = "ExternalLocPermsFLTestApp.apk";
95    private static final String FL_PERMS_PKG = "com.android.framework.externallocpermsfltestapp";
96    // Apk set to preferExternal, with all permissions set in manifest
97    private static final String ALL_PERMS_APK = "ExternalLocAllPermsTestApp.apk";
98    private static final String ALL_PERMS_PKG = "com.android.framework.externallocallpermstestapp";
99    // Apks with the same package name, but install location set to
100    // one of: Internal, External, Auto, or None
101    private static final String VERSATILE_LOC_PKG = "com.android.framework.versatiletestapp";
102    private static final String VERSATILE_LOC_INTERNAL_APK = "VersatileTestApp_Internal.apk";
103    private static final String VERSATILE_LOC_EXTERNAL_APK = "VersatileTestApp_External.apk";
104    private static final String VERSATILE_LOC_AUTO_APK = "VersatileTestApp_Auto.apk";
105    private static final String VERSATILE_LOC_NONE_APK = "VersatileTestApp_None.apk";
106    // Apks with shared UserID
107    private static final String SHARED_PERMS_APK = "ExternalSharedPermsTestApp.apk";
108    private static final String SHARED_PERMS_PKG
109            = "com.android.framework.externalsharedpermstestapp";
110    private static final String SHARED_PERMS_FL_APK = "ExternalSharedPermsFLTestApp.apk";
111    private static final String SHARED_PERMS_FL_PKG
112            = "com.android.framework.externalsharedpermsfltestapp";
113    private static final String SHARED_PERMS_BT_APK = "ExternalSharedPermsBTTestApp.apk";
114    private static final String SHARED_PERMS_BT_PKG
115            = "com.android.framework.externalsharedpermsbttestapp";
116    // Apk with shared UserID, but signed with a different cert (the media cert)
117    private static final String SHARED_PERMS_DIFF_KEY_APK = "ExternalSharedPermsDiffKeyTestApp.apk";
118    private static final String SHARED_PERMS_DIFF_KEY_PKG
119            = "com.android.framework.externalsharedpermsdiffkeytestapp";
120
121    @Override
122    protected void setUp() throws Exception {
123        super.setUp();
124        // ensure apk path has been set before test is run
125        assertNotNull(getTestAppPath());
126
127        // setup the PackageManager host tests utilities class, and get various paths we'll need...
128        mPMHostUtils = new PackageManagerHostTestUtils(getDevice());
129        appPrivatePath = mPMHostUtils.getAppPrivatePath();
130        deviceAppPath = mPMHostUtils.getDeviceAppPath();
131        sdcardAppPath = mPMHostUtils.getSDCardAppPath();
132
133        // Ensure the default is set to let the system decide where to install apps
134        // (It's ok for individual tests to override and change this during their test, but should
135        // reset it back when they're done)
136        mPMHostUtils.setDevicePreferredInstallLocation(
137                PackageManagerHostTestUtils.InstallLocPreference.AUTO);
138    }
139
140    /**
141     * Get the absolute file system location of test app with given filename
142     * @param fileName the file name of the test app apk
143     * @return {@link String} of absolute file path
144     */
145    public String getTestAppFilePath(String fileName) {
146        return String.format("%s%s%s", getTestAppPath(), File.separator, fileName);
147    }
148
149    public static Test suite() {
150        return new DeviceTestSuite(PackageManagerHostTests.class);
151    }
152
153    /**
154     * Regression test to verify that pushing an apk to the private app directory doesn't install
155     * the app, and otherwise cause the system to blow up.
156     * <p/>
157     * Assumes adb is running as root in device under test.
158     * @throws InterruptedException if the thread was interrupted
159     * @throws TimeoutException in case of a timeout on the connection.
160     * @throws AdbCommandRejectedException if adb rejects the command
161     * @throws ShellCommandUnresponsiveException if the device did not output anything for
162     * a period longer than the max time to output.
163     * @throws IOException if connection to device was lost.
164     * @throws SyncException if the sync failed for another reason.
165     * @throws InstallException if the install failed.
166     */
167    public void testPushAppPrivate() throws IOException, InterruptedException, InstallException,
168            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
169            SyncException {
170        Log.i(LOG_TAG, "testing pushing an apk to /data/app-private");
171        final String apkAppPrivatePath =  appPrivatePath + SIMPLE_APK;
172
173        // cleanup test app just in case it was accidently installed
174        getDevice().uninstallPackage(SIMPLE_PKG);
175        mPMHostUtils.executeShellCommand("stop");
176        mPMHostUtils.pushFile(getTestAppFilePath(SIMPLE_APK), apkAppPrivatePath);
177
178        // sanity check to make sure file is there
179        assertTrue(mPMHostUtils.doesRemoteFileExist(apkAppPrivatePath));
180        mPMHostUtils.executeShellCommand("start");
181
182        mPMHostUtils.waitForPackageManager();
183
184        // grep for package to make sure its not installed
185        assertFalse(mPMHostUtils.doesPackageExist(SIMPLE_PKG));
186        // ensure it has been deleted from app-private
187        assertFalse(mPMHostUtils.doesRemoteFileExist(apkAppPrivatePath));
188    }
189
190    /**
191     * Helper to do a standard install of an apk and verify it installed to the correct location.
192     * <p/>
193     * Assumes adb is running as root in device under test.
194     * @param apkName the file name of the test app apk
195     * @param pkgName the package name of the test app apk
196     * @param expectedLocation the file name of the test app apk
197     * @throws InterruptedException if the thread was interrupted
198     * @throws TimeoutException in case of a timeout on the connection.
199     * @throws AdbCommandRejectedException if adb rejects the command
200     * @throws ShellCommandUnresponsiveException if the device did not output anything for
201     * a period longer than the max time to output.
202     * @throws IOException if connection to device was lost.
203     * @throws InstallException if the install failed.
204     */
205    private void doStandardInstall(String apkName, String pkgName,
206            PackageManagerHostTestUtils.InstallLocation expectedLocation)
207            throws IOException, InterruptedException, InstallException, TimeoutException,
208            AdbCommandRejectedException, ShellCommandUnresponsiveException {
209
210        if (expectedLocation == PackageManagerHostTestUtils.InstallLocation.DEVICE) {
211            mPMHostUtils.installAppAndVerifyExistsOnDevice(
212                    getTestAppFilePath(apkName), pkgName, false);
213        }
214        else {
215            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
216                    getTestAppFilePath(apkName), pkgName, false);
217        }
218    }
219
220    /**
221     * Installs the Auto app using the preferred device install location specified,
222     * and verifies it was installed on the device.
223     * <p/>
224     * Assumes adb is running as root in device under test.
225     * @param preference the device's preferred location of where to install apps
226     * @param expectedLocation the expected location of where the apk was installed
227     * @throws InterruptedException if the thread was interrupted
228     * @throws TimeoutException in case of a timeout on the connection.
229     * @throws AdbCommandRejectedException if adb rejects the command
230     * @throws ShellCommandUnresponsiveException if the device did not output anything for
231     * a period longer than the max time to output.
232     * @throws IOException if connection to device was lost.
233     * @throws InstallException if the install failed.
234     */
235    public void installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
236            PackageManagerHostTestUtils.InstallLocation expectedLocation)
237            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
238            ShellCommandUnresponsiveException, InstallException {
239
240        PackageManagerHostTestUtils.InstallLocPreference savedPref =
241                PackageManagerHostTestUtils.InstallLocPreference.AUTO;
242
243        try {
244            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
245            mPMHostUtils.setDevicePreferredInstallLocation(preference);
246
247            doStandardInstall(AUTO_LOC_APK, AUTO_LOC_PKG, expectedLocation);
248        }
249        // cleanup test app
250        finally {
251            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
252            mPMHostUtils.uninstallApp(AUTO_LOC_PKG);
253        }
254    }
255
256    /**
257     * Regression test to verify that an app with its manifest set to installLocation=auto
258     * will install the app to the device when device's preference is auto.
259     * <p/>
260     * Assumes adb is running as root in device under test.
261     * @throws InterruptedException if the thread was interrupted
262     * @throws TimeoutException in case of a timeout on the connection.
263     * @throws AdbCommandRejectedException if adb rejects the command
264     * @throws ShellCommandUnresponsiveException if the device did not output anything for
265     * a period longer than the max time to output.
266     * @throws IOException if connection to device was lost.
267     * @throws InstallException if the install failed.
268     */
269    public void testInstallAppAutoLocPrefIsAuto() throws IOException, InterruptedException,
270            InstallException, TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
271        Log.i(LOG_TAG, "Test installLocation=auto, prefer=auto gets installed on device");
272        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
273                PackageManagerHostTestUtils.InstallLocation.DEVICE);
274    }
275
276    /**
277     * Regression test to verify that an app with its manifest set to installLocation=auto
278     * will install the app to the device when device's preference is internal.
279     * <p/>
280     * Assumes adb is running as root in device under test.
281     * @throws InterruptedException if the thread was interrupted
282     * @throws TimeoutException in case of a timeout on the connection.
283     * @throws AdbCommandRejectedException if adb rejects the command
284     * @throws ShellCommandUnresponsiveException if the device did not output anything for
285     * a period longer than the max time to output.
286     * @throws IOException if connection to device was lost.
287     * @throws InstallException if the install failed.
288     */
289    public void testInstallAppAutoLocPrefIsInternal() throws IOException, InterruptedException,
290            InstallException, TimeoutException, AdbCommandRejectedException,
291            ShellCommandUnresponsiveException {
292        Log.i(LOG_TAG, "Test installLocation=auto, prefer=internal gets installed on device");
293        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
294                PackageManagerHostTestUtils.InstallLocation.DEVICE);
295    }
296
297    /**
298     * Regression test to verify that an app with its manifest set to installLocation=auto
299     * will install the app to the SD card when device's preference is external.
300     * <p/>
301     * Assumes adb is running as root in device under test.
302     * @throws InterruptedException if the thread was interrupted
303     * @throws TimeoutException in case of a timeout on the connection.
304     * @throws AdbCommandRejectedException if adb rejects the command
305     * @throws ShellCommandUnresponsiveException if the device did not output anything for
306     * a period longer than the max time to output.
307     * @throws IOException if connection to device was lost.
308     * @throws InstallException if the install failed.
309     */
310    public void testInstallAppAutoLocPrefIsExternal() throws IOException, InterruptedException,
311            InstallException, TimeoutException, AdbCommandRejectedException,
312            ShellCommandUnresponsiveException {
313        Log.i(LOG_TAG, "Test installLocation=auto, prefer=external gets installed on device");
314        installAppAutoLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
315                PackageManagerHostTestUtils.InstallLocation.DEVICE);
316    }
317
318    /**
319     * Installs the Internal app using the preferred device install location specified,
320     * and verifies it was installed to the location expected.
321     * <p/>
322     * Assumes adb is running as root in device under test.
323     * @param preference the device's preferred location of where to install apps
324     * @param expectedLocation the expected location of where the apk was installed
325     * @throws InterruptedException if the thread was interrupted
326     * @throws TimeoutException in case of a timeout on the connection.
327     * @throws AdbCommandRejectedException if adb rejects the command
328     * @throws ShellCommandUnresponsiveException if the device did not output anything for
329     * a period longer than the max time to output.
330     * @throws IOException if connection to device was lost.
331     * @throws InstallException if the (un)install failed.
332     */
333    public void installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
334            PackageManagerHostTestUtils.InstallLocation expectedLocation)
335            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
336            ShellCommandUnresponsiveException, InstallException {
337
338        PackageManagerHostTestUtils.InstallLocPreference savedPref =
339            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
340
341        try {
342            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
343            mPMHostUtils.setDevicePreferredInstallLocation(preference);
344
345            doStandardInstall(INTERNAL_LOC_APK, INTERNAL_LOC_PKG, expectedLocation);
346        }
347        // cleanup test app
348        finally {
349            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
350            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
351        }
352    }
353
354    /**
355     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
356     * will install the app to the device when device's preference is auto.
357     * <p/>
358     * Assumes adb is running as root in device under test.
359     * @throws InterruptedException if the thread was interrupted
360     * @throws TimeoutException in case of a timeout on the connection.
361     * @throws AdbCommandRejectedException if adb rejects the command
362     * @throws ShellCommandUnresponsiveException if the device did not output anything for
363     * a period longer than the max time to output.
364     * @throws IOException if connection to device was lost.
365     * @throws InstallException if the install failed.
366     */
367    public void testInstallAppInternalLocPrefIsAuto() throws IOException, InterruptedException,
368            InstallException, TimeoutException, AdbCommandRejectedException,
369            ShellCommandUnresponsiveException {
370        Log.i(LOG_TAG, "Test installLocation=internal, prefer=auto gets installed on device");
371        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
372                PackageManagerHostTestUtils.InstallLocation.DEVICE);
373    }
374
375    /**
376     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
377     * will install the app to the device when device's preference is internal.
378     * <p/>
379     * Assumes adb is running as root in device under test.
380     * @throws InterruptedException if the thread was interrupted
381     * @throws TimeoutException in case of a timeout on the connection.
382     * @throws AdbCommandRejectedException if adb rejects the command
383     * @throws ShellCommandUnresponsiveException if the device did not output anything for
384     * a period longer than the max time to output.
385     * @throws IOException if connection to device was lost.
386     * @throws InstallException if the install failed.
387     */
388    public void testInstallAppInternalLocPrefIsInternal() throws IOException, InterruptedException,
389            InstallException, TimeoutException, AdbCommandRejectedException,
390            ShellCommandUnresponsiveException {
391        Log.i(LOG_TAG, "Test installLocation=internal, prefer=internal is installed on device");
392        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
393                PackageManagerHostTestUtils.InstallLocation.DEVICE);
394    }
395
396    /**
397     * Regression test to verify that an app with its manifest set to installLocation=internalOnly
398     * will install the app to the device when device's preference is external.
399     * <p/>
400     * Assumes adb is running as root in device under test.
401     * @throws InterruptedException if the thread was interrupted
402     * @throws TimeoutException in case of a timeout on the connection.
403     * @throws AdbCommandRejectedException if adb rejects the command
404     * @throws ShellCommandUnresponsiveException if the device did not output anything for
405     * a period longer than the max time to output.
406     * @throws IOException if connection to device was lost.
407     * @throws InstallException if the install failed.
408     */
409    public void testInstallAppInternalLocPrefIsExternal() throws IOException, InterruptedException,
410            InstallException, TimeoutException, AdbCommandRejectedException,
411            ShellCommandUnresponsiveException {
412        Log.i(LOG_TAG, "Test installLocation=internal, prefer=external is installed on device");
413        installAppInternalLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
414                PackageManagerHostTestUtils.InstallLocation.DEVICE);
415    }
416
417    /**
418     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
419     * will install the app to the SD card.
420     * <p/>
421     * Assumes adb is running as root in device under test.
422     * @param preference the device's preferred location of where to install apps
423     * @param expectedLocation the expected location of where the apk was installed
424     * @throws InterruptedException if the thread was interrupted
425     * @throws TimeoutException in case of a timeout on the connection.
426     * @throws AdbCommandRejectedException if adb rejects the command
427     * @throws ShellCommandUnresponsiveException if the device did not output anything for
428     * a period longer than the max time to output.
429     * @throws IOException if connection to device was lost.
430     * @throws InstallException if the install failed.
431     */
432    public void installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference preference,
433            PackageManagerHostTestUtils.InstallLocation expectedLocation)
434            throws IOException, InterruptedException, TimeoutException, AdbCommandRejectedException,
435            ShellCommandUnresponsiveException, InstallException {
436
437        PackageManagerHostTestUtils.InstallLocPreference savedPref =
438            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
439
440        try {
441            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
442            mPMHostUtils.setDevicePreferredInstallLocation(preference);
443
444            doStandardInstall(EXTERNAL_LOC_APK, EXTERNAL_LOC_PKG, expectedLocation);
445
446        }
447        // cleanup test app
448        finally {
449            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
450            mPMHostUtils.uninstallApp(EXTERNAL_LOC_PKG);
451        }
452    }
453
454    /**
455     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
456     * will install the app to the device when device's preference is auto.
457     * <p/>
458     * Assumes adb is running as root in device under test.
459     * @throws InterruptedException if the thread was interrupted
460     * @throws TimeoutException in case of a timeout on the connection.
461     * @throws AdbCommandRejectedException if adb rejects the command
462     * @throws ShellCommandUnresponsiveException if the device did not output anything for
463     * a period longer than the max time to output.
464     * @throws IOException if connection to device was lost.
465     * @throws InstallException if the install failed.
466     */
467    public void testInstallAppExternalLocPrefIsAuto() throws IOException, InterruptedException,
468            InstallException, TimeoutException, AdbCommandRejectedException,
469            ShellCommandUnresponsiveException {
470        Log.i(LOG_TAG, "Test installLocation=external, pref=auto gets installed on SD Card");
471        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.AUTO,
472                PackageManagerHostTestUtils.InstallLocation.SDCARD);
473    }
474
475    /**
476     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
477     * will install the app to the device when device's preference is internal.
478     * <p/>
479     * Assumes adb is running as root in device under test.
480     * @throws InterruptedException if the thread was interrupted
481     * @throws TimeoutException in case of a timeout on the connection.
482     * @throws AdbCommandRejectedException if adb rejects the command
483     * @throws ShellCommandUnresponsiveException if the device did not output anything for
484     * a period longer than the max time to output.
485     * @throws IOException if connection to device was lost.
486     * @throws InstallException if the install failed.
487     */
488    public void testInstallAppExternalLocPrefIsInternal() throws IOException, InterruptedException,
489            InstallException, TimeoutException, AdbCommandRejectedException,
490            ShellCommandUnresponsiveException {
491        Log.i(LOG_TAG, "Test installLocation=external, pref=internal gets installed on SD Card");
492        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.INTERNAL,
493                PackageManagerHostTestUtils.InstallLocation.SDCARD);
494    }
495
496    /**
497     * Regression test to verify that an app with its manifest set to installLocation=preferExternal
498     * will install the app to the device when device's preference is external.
499     * <p/>
500     * Assumes adb is running as root in device under test.
501     * @throws InterruptedException if the thread was interrupted
502     * @throws TimeoutException in case of a timeout on the connection.
503     * @throws AdbCommandRejectedException if adb rejects the command
504     * @throws ShellCommandUnresponsiveException if the device did not output anything for
505     * a period longer than the max time to output.
506     * @throws IOException if connection to device was lost.
507     * @throws InstallException if the install failed.
508     */
509    public void testInstallAppExternalLocPrefIsExternal() throws IOException, InterruptedException,
510            InstallException, TimeoutException, AdbCommandRejectedException,
511            ShellCommandUnresponsiveException {
512        Log.i(LOG_TAG, "Test installLocation=external, pref=external gets installed on SD Card");
513        installAppExternalLoc(PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL,
514                PackageManagerHostTestUtils.InstallLocation.SDCARD);
515    }
516
517    /**
518     * Regression test to verify that an app without installLocation in its manifest
519     * will install the app to the device by default when the system default pref is to let the
520     * system decide.
521     * <p/>
522     * Assumes adb is running as root in device under test.
523     * @throws InterruptedException if the thread was interrupted
524     * @throws TimeoutException in case of a timeout on the connection.
525     * @throws AdbCommandRejectedException if adb rejects the command
526     * @throws ShellCommandUnresponsiveException if the device did not output anything for
527     * a period longer than the max time to output.
528     * @throws IOException if connection to device was lost.
529     * @throws InstallException if the install failed.
530     */
531    public void testInstallAppNoLocPrefIsAuto() throws IOException, InterruptedException,
532            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
533            InstallException {
534        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on device");
535
536        PackageManagerHostTestUtils.InstallLocPreference savedPref =
537            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
538
539        try {
540            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
541            mPMHostUtils.setDevicePreferredInstallLocation(
542                    PackageManagerHostTestUtils.InstallLocPreference.AUTO);
543            mPMHostUtils.installAppAndVerifyExistsOnDevice(
544                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
545        }
546        // cleanup test app
547        finally {
548            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
549            mPMHostUtils.uninstallApp(NO_LOC_PKG);
550        }
551    }
552
553    /**
554     * Regression test to verify that an app without installLocation in its manifest
555     * will install the app to the device by default when the system default pref is to install
556     * external.
557     * <p/>
558     * Assumes adb is running as root in device under test.
559     * @throws InterruptedException if the thread was interrupted
560     * @throws TimeoutException in case of a timeout on the connection.
561     * @throws AdbCommandRejectedException if adb rejects the command
562     * @throws ShellCommandUnresponsiveException if the device did not output anything for
563     * a period longer than the max time to output.
564     * @throws IOException if connection to device was lost.
565     * @throws InstallException if the install failed.
566     */
567    public void testInstallAppNoLocPrefIsExternal() throws IOException, InterruptedException,
568            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
569            InstallException {
570        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on SD card");
571
572        PackageManagerHostTestUtils.InstallLocPreference savedPref =
573            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
574
575        try {
576            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
577            mPMHostUtils.setDevicePreferredInstallLocation(
578                    PackageManagerHostTestUtils.InstallLocPreference.EXTERNAL);
579            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
580                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
581        }
582        // cleanup test app
583        finally {
584            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
585            mPMHostUtils.uninstallApp(NO_LOC_PKG);
586        }
587    }
588
589    /**
590     * Regression test to verify that an app without installLocation in its manifest
591     * will install the app to the device by default when the system default pref is to install
592     * internal.
593     * <p/>
594     * Assumes adb is running as root in device under test.
595     * @throws InterruptedException if the thread was interrupted
596     * @throws TimeoutException in case of a timeout on the connection.
597     * @throws AdbCommandRejectedException if adb rejects the command
598     * @throws ShellCommandUnresponsiveException if the device did not output anything for
599     * a period longer than the max time to output.
600     * @throws IOException if connection to device was lost.
601     * @throws InstallException if the install failed.
602     */
603    public void testInstallAppNoLocPrefIsInternal() throws IOException, InterruptedException,
604            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
605            InstallException {
606        Log.i(LOG_TAG, "Test an app with no installLocation gets installed on device");
607
608        PackageManagerHostTestUtils.InstallLocPreference savedPref =
609            PackageManagerHostTestUtils.InstallLocPreference.AUTO;
610
611        try {
612            savedPref = mPMHostUtils.getDevicePreferredInstallLocation();
613            mPMHostUtils.setDevicePreferredInstallLocation(
614                    PackageManagerHostTestUtils.InstallLocPreference.INTERNAL);
615            mPMHostUtils.installAppAndVerifyExistsOnDevice(
616                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
617        }
618        // cleanup test app
619        finally {
620            mPMHostUtils.setDevicePreferredInstallLocation(savedPref);
621            mPMHostUtils.uninstallApp(NO_LOC_PKG);
622        }
623    }
624
625    /**
626     * Regression test to verify that an app with its installLocation set to internal that is
627     * forward-locked will get installed to the correct location.
628     * <p/>
629     * Assumes adb is running as root in device under test.
630     * @throws InterruptedException if the thread was interrupted
631     * @throws TimeoutException in case of a timeout on the connection.
632     * @throws AdbCommandRejectedException if adb rejects the command
633     * @throws ShellCommandUnresponsiveException if the device did not output anything for
634     * a period longer than the max time to output.
635     * @throws IOException if connection to device was lost.
636     * @throws SyncException if the sync failed for another reason.
637     * @throws InstallException if the install failed.
638     */
639    public void testInstallFwdLockedAppInternal() throws IOException, InterruptedException,
640            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
641            ShellCommandUnresponsiveException {
642        Log.i(LOG_TAG, "Test an app with installLoc set to Internal gets installed to app-private");
643
644        try {
645            mPMHostUtils.installFwdLockedAppAndVerifyExists(
646                    getTestAppFilePath(INTERNAL_LOC_APK), INTERNAL_LOC_PKG, false);
647        }
648        // cleanup test app
649        finally {
650            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
651        }
652    }
653
654    /**
655     * Regression test to verify that an app with its installLocation set to external that is
656     * forward-locked will get installed to the correct location.
657     * <p/>
658     * Assumes adb is running as root in device under test.
659     * @throws InterruptedException if the thread was interrupted
660     * @throws TimeoutException in case of a timeout on the connection.
661     * @throws AdbCommandRejectedException if adb rejects the command
662     * @throws ShellCommandUnresponsiveException if the device did not output anything for
663     * a period longer than the max time to output.
664     * @throws IOException if connection to device was lost.
665     * @throws SyncException if the sync failed for another reason.
666     * @throws InstallException if the install failed.
667     */
668    public void testInstallFwdLockedAppExternal() throws IOException, InterruptedException,
669            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
670            ShellCommandUnresponsiveException {
671        Log.i(LOG_TAG, "Test an app with installLoc set to Internal gets installed to app-private");
672
673        try {
674            mPMHostUtils.installFwdLockedAppAndVerifyExists(
675                    getTestAppFilePath(INTERNAL_LOC_APK), INTERNAL_LOC_PKG, false);
676        }
677        // cleanup test app
678        finally {
679            mPMHostUtils.uninstallApp(INTERNAL_LOC_PKG);
680        }
681    }
682
683    /**
684     * Regression test to verify that an app with its installLocation set to external that is
685     * forward-locked will get installed to the correct location.
686     * <p/>
687     * Assumes adb is running as root in device under test.
688     * @throws InterruptedException if the thread was interrupted
689     * @throws TimeoutException in case of a timeout on the connection.
690     * @throws AdbCommandRejectedException if adb rejects the command
691     * @throws ShellCommandUnresponsiveException if the device did not output anything for
692     * a period longer than the max time to output.
693     * @throws IOException if connection to device was lost.
694     * @throws SyncException if the sync failed for another reason.
695     * @throws InstallException if the install failed.
696     */
697    public void testInstallFwdLockedAppAuto() throws IOException, InterruptedException,
698            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
699            ShellCommandUnresponsiveException {
700        Log.i(LOG_TAG, "Test an app with installLoc set to Auto gets installed to app-private");
701
702        try {
703            mPMHostUtils.installFwdLockedAppAndVerifyExists(
704                    getTestAppFilePath(AUTO_LOC_APK), AUTO_LOC_PKG, false);
705        }
706        // cleanup test app
707        finally {
708            mPMHostUtils.uninstallApp(AUTO_LOC_PKG);
709        }
710    }
711
712    /**
713     * Regression test to verify that an app with no installLocation set and is
714     * forward-locked installed will get installed to the correct location.
715     * <p/>
716     * Assumes adb is running as root in device under test.
717     * @throws InterruptedException if the thread was interrupted
718     * @throws TimeoutException in case of a timeout on the connection.
719     * @throws AdbCommandRejectedException if adb rejects the command
720     * @throws ShellCommandUnresponsiveException if the device did not output anything for
721     * a period longer than the max time to output.
722     * @throws IOException if connection to device was lost.
723     * @throws SyncException if the sync failed for another reason.
724     * @throws InstallException if the install failed.
725     */
726    public void testInstallFwdLockedAppNone() throws IOException, InterruptedException,
727            InstallException, SyncException, TimeoutException, AdbCommandRejectedException,
728            ShellCommandUnresponsiveException {
729        Log.i(LOG_TAG, "Test an app with no installLoc set gets installed to app-private");
730
731        try {
732            mPMHostUtils.installFwdLockedAppAndVerifyExists(
733                    getTestAppFilePath(NO_LOC_APK), NO_LOC_PKG, false);
734        }
735        // cleanup test app
736        finally {
737            mPMHostUtils.uninstallApp(NO_LOC_PKG);
738        }
739    }
740
741    /**
742     * Regression test to verify that we can install an app onto the device,
743     * uninstall it, and reinstall it onto the SD card.
744     * <p/>
745     * Assumes adb is running as root in device under test.
746     * @throws InterruptedException if the thread was interrupted
747     * @throws TimeoutException in case of a timeout on the connection.
748     * @throws AdbCommandRejectedException if adb rejects the command
749     * @throws ShellCommandUnresponsiveException if the device did not output anything for
750     * a period longer than the max time to output.
751     * @throws IOException if connection to device was lost.
752     * @throws InstallException if the install failed.
753     */
754    // TODO: This currently relies on the app's manifest to switch from device to
755    // SD card install locations. We might want to make Device's installPackage()
756    // accept a installLocation flag so we can install a package to the
757    // destination of our choosing.
758    public void testReinstallInternalToExternal() throws IOException, InterruptedException,
759            InstallException, TimeoutException, AdbCommandRejectedException,
760            ShellCommandUnresponsiveException {
761        Log.i(LOG_TAG, "Test installing an app first to the device, then to the SD Card");
762
763        try {
764            mPMHostUtils.installAppAndVerifyExistsOnDevice(
765                    getTestAppFilePath(VERSATILE_LOC_INTERNAL_APK), VERSATILE_LOC_PKG, false);
766            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
767            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
768                    getTestAppFilePath(VERSATILE_LOC_EXTERNAL_APK), VERSATILE_LOC_PKG, false);
769        }
770        // cleanup test app
771        finally {
772            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
773        }
774    }
775
776    /**
777     * Regression test to verify that we can install an app onto the SD Card,
778     * uninstall it, and reinstall it onto the device.
779     * <p/>
780     * Assumes adb is running as root in device under test.
781     * @throws InterruptedException if the thread was interrupted
782     * @throws TimeoutException in case of a timeout on the connection.
783     * @throws AdbCommandRejectedException if adb rejects the command
784     * @throws ShellCommandUnresponsiveException if the device did not output anything for
785     * a period longer than the max time to output.
786     * @throws IOException if connection to device was lost.
787     * @throws InstallException if the install failed.
788     */
789    // TODO: This currently relies on the app's manifest to switch from device to
790    // SD card install locations. We might want to make Device's installPackage()
791    // accept a installLocation flag so we can install a package to the
792    // destination of our choosing.
793    public void testReinstallExternalToInternal() throws IOException, InterruptedException,
794            InstallException, TimeoutException, AdbCommandRejectedException,
795            ShellCommandUnresponsiveException {
796        Log.i(LOG_TAG, "Test installing an app first to the SD Care, then to the device");
797
798        try {
799            // install the app externally
800            mPMHostUtils.installAppAndVerifyExistsOnSDCard(
801                    getTestAppFilePath(VERSATILE_LOC_EXTERNAL_APK), VERSATILE_LOC_PKG, false);
802            mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
803            // then replace the app with one marked for internalOnly
804            mPMHostUtils.installAppAndVerifyExistsOnDevice(
805                    getTestAppFilePath(VERSATILE_LOC_INTERNAL_APK), VERSATILE_LOC_PKG, false);
806        }
807        // cleanup test app
808        finally {
809          mPMHostUtils.uninstallApp(VERSATILE_LOC_PKG);
810        }
811    }
812
813    /**
814     * Regression test to verify that updating an app on the SD card will install
815     * the update onto the SD card as well when location is set to external for both versions
816     * <p/>
817     * Assumes adb is running as root in device under test.
818     * @throws InterruptedException if the thread was interrupted
819     * @throws TimeoutException in case of a timeout on the connection.
820     * @throws AdbCommandRejectedException if adb rejects the command
821     * @throws ShellCommandUnresponsiveException if the device did not output anything for
822     * a period longer than the max time to output.
823     * @throws IOException if connection to device was lost.
824     * @throws InstallException if the install failed.
825     */
826    public void testUpdateBothExternal() throws IOException, InterruptedException, InstallException,
827            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
828        Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
829
830        try {
831            // install the app externally
832            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
833                    EXTERNAL_LOC_VERSION_V1_APK), EXTERNAL_LOC_VERSION_PKG, false);
834            // now replace the app with one where the location is still set to preferExternal
835            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
836                    EXTERNAL_LOC_VERSION_V2_APK), EXTERNAL_LOC_VERSION_PKG, true);
837        }
838        // cleanup test app
839        finally {
840          mPMHostUtils.uninstallApp(EXTERNAL_LOC_VERSION_PKG);
841        }
842    }
843
844    /**
845     * Regression test to verify that updating an app on the SD card will install
846     * the update onto the SD card as well when location is not explicitly set in the
847     * updated apps' manifest file.
848     * <p/>
849     * Assumes adb is running as root in device under test.
850     * @throws InterruptedException if the thread was interrupted
851     * @throws TimeoutException in case of a timeout on the connection.
852     * @throws AdbCommandRejectedException if adb rejects the command
853     * @throws ShellCommandUnresponsiveException if the device did not output anything for
854     * a period longer than the max time to output.
855     * @throws IOException if connection to device was lost.
856     * @throws InstallException if the install failed.
857     */
858    public void testUpdateToSDCard() throws IOException, InterruptedException, InstallException,
859            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
860        Log.i(LOG_TAG, "Test updating an app on the SD card stays on the SD card");
861
862        try {
863            // install the app externally
864            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
865                    UPDATE_EXTERNAL_LOC_V1_EXT_APK), UPDATE_EXTERNAL_LOC_PKG, false);
866            // now replace the app with one where the location is blank (app should stay external)
867            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
868                    UPDATE_EXTERNAL_LOC_V2_NONE_APK), UPDATE_EXTERNAL_LOC_PKG, true);
869        }
870        // cleanup test app
871        finally {
872          mPMHostUtils.uninstallApp(UPDATE_EXTERNAL_LOC_PKG);
873        }
874    }
875
876    /**
877     * Regression test to verify that updating an app on the SD card will install
878     * the update onto the device if the manifest has changed to installLocation=internalOnly
879     * <p/>
880     * Assumes adb is running as root in device under test.
881     * @throws InterruptedException if the thread was interrupted
882     * @throws TimeoutException in case of a timeout on the connection.
883     * @throws AdbCommandRejectedException if adb rejects the command
884     * @throws ShellCommandUnresponsiveException if the device did not output anything for
885     * a period longer than the max time to output.
886     * @throws IOException if connection to device was lost.
887     * @throws InstallException if the install failed.
888     */
889    public void testUpdateSDCardToDevice() throws IOException, InterruptedException,
890            InstallException, TimeoutException, AdbCommandRejectedException,
891            ShellCommandUnresponsiveException {
892        Log.i(LOG_TAG, "Test updating an app on the SD card to the Device through manifest change");
893
894        try {
895            // install the app externally
896            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
897                    UPDATE_EXT_TO_INT_LOC_V1_EXT_APK), UPDATE_EXT_TO_INT_LOC_PKG, false);
898            // now replace the app with an update marked for internalOnly...(should move internal)
899            mPMHostUtils.installAppAndVerifyExistsOnDevice(getTestAppFilePath(
900                    UPDATE_EXT_TO_INT_LOC_V2_INT_APK), UPDATE_EXT_TO_INT_LOC_PKG, true);
901        }
902        // cleanup test app
903        finally {
904            mPMHostUtils.uninstallApp(UPDATE_EXT_TO_INT_LOC_PKG);
905        }
906    }
907
908    /**
909     * Regression test to verify that installing and updating a forward-locked app will install
910     * the update onto the device's forward-locked location
911     * <p/>
912     * Assumes adb is running as root in device under test.
913     * @throws InterruptedException if the thread was interrupted
914     * @throws TimeoutException in case of a timeout on the connection.
915     * @throws AdbCommandRejectedException if adb rejects the command
916     * @throws ShellCommandUnresponsiveException if the device did not output anything for
917     * a period longer than the max time to output.
918     * @throws IOException if connection to device was lost.
919     * @throws SyncException if the sync failed for another reason.
920     * @throws InstallException if the install failed.
921     */
922    public void testInstallAndUpdateExternalLocForwardLockedApp()
923            throws IOException, InterruptedException, InstallException, SyncException,
924            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
925        Log.i(LOG_TAG, "Test updating a forward-locked app marked preferExternal");
926
927        try {
928            // first try to install the forward-locked app externally
929            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
930                    EXTERNAL_LOC_VERSION_V1_APK), EXTERNAL_LOC_VERSION_PKG, false);
931            // now replace the app with an update marked for internalOnly and as forward locked
932            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
933                    EXTERNAL_LOC_VERSION_V2_APK), EXTERNAL_LOC_VERSION_PKG, true);
934        }
935        // cleanup test app
936        finally {
937            mPMHostUtils.uninstallApp(EXTERNAL_LOC_VERSION_PKG);
938        }
939    }
940
941    /**
942     * Regression test to verify that updating a forward-locked app will install
943     * the update onto the device's forward-locked location
944     * <p/>
945     * Assumes adb is running as root in device under test.
946     * @throws InterruptedException if the thread was interrupted
947     * @throws TimeoutException in case of a timeout on the connection.
948     * @throws AdbCommandRejectedException if adb rejects the command
949     * @throws ShellCommandUnresponsiveException if the device did not output anything for
950     * a period longer than the max time to output.
951     * @throws IOException if connection to device was lost.
952     * @throws SyncException if the sync failed for another reason.
953     * @throws InstallException if the install failed.
954     */
955    public void testInstallAndUpdateNoLocForwardLockedApp()
956            throws IOException, InterruptedException, InstallException, SyncException,
957            TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException {
958        Log.i(LOG_TAG, "Test updating a forward-locked app with no installLocation pref set");
959
960        try {
961            // install the app
962            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
963                    NO_LOC_VERSION_V1_APK), NO_LOC_VERSION_PKG, false);
964            // now replace the app with an update marked for internalOnly...
965            mPMHostUtils.installFwdLockedAppAndVerifyExists(getTestAppFilePath(
966                    NO_LOC_VERSION_V2_APK), NO_LOC_VERSION_PKG, true);
967        }
968        // cleanup test app
969        finally {
970            mPMHostUtils.uninstallApp(NO_LOC_VERSION_PKG);
971        }
972    }
973
974    /**
975     * Regression test to verify that an app with all permissions set can be installed on SD card
976     * and then launched without crashing.
977     * <p/>
978     * Assumes adb is running as root in device under test.
979     * @throws InterruptedException if the thread was interrupted
980     * @throws TimeoutException in case of a timeout on the connection.
981     * @throws AdbCommandRejectedException if adb rejects the command
982     * @throws ShellCommandUnresponsiveException if the device did not output anything for
983     * a period longer than the max time to output.
984     * @throws IOException if connection to device was lost.
985     * @throws SyncException if the sync failed for another reason.
986     * @throws InstallException if the install failed.
987     */
988    public void testInstallAndLaunchAllPermsAppOnSD()
989            throws IOException, InterruptedException, InstallException, TimeoutException,
990            AdbCommandRejectedException, ShellCommandUnresponsiveException {
991        Log.i(LOG_TAG, "Test launching an app with all perms set, installed on SD card");
992
993        try {
994            // install the app
995            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
996                    ALL_PERMS_APK), ALL_PERMS_PKG, false);
997            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(ALL_PERMS_PKG);
998            assert(testsPassed);
999        }
1000        // cleanup test app
1001        finally {
1002            mPMHostUtils.uninstallApp(ALL_PERMS_PKG);
1003        }
1004    }
1005
1006    /**
1007     * Regression test to verify that an app with ACCESS_FINE_LOCATION (GPS) permissions can
1008     * run without permissions errors.
1009     * <p/>
1010     * Assumes adb is running as root in device under test.
1011     * @throws InterruptedException if the thread was interrupted
1012     * @throws TimeoutException in case of a timeout on the connection.
1013     * @throws AdbCommandRejectedException if adb rejects the command
1014     * @throws ShellCommandUnresponsiveException if the device did not output anything for
1015     * a period longer than the max time to output.
1016     * @throws IOException if connection to device was lost.
1017     * @throws InstallException if the install failed.
1018     */
1019    public void testInstallAndLaunchFLPermsAppOnSD()
1020            throws IOException, InterruptedException, InstallException, TimeoutException,
1021            AdbCommandRejectedException, ShellCommandUnresponsiveException {
1022        Log.i(LOG_TAG, "Test launching an app with location perms set, installed on SD card");
1023
1024        try {
1025            // install the app and verify we can launch it without permissions errors
1026            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1027                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
1028            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
1029            assert(testsPassed);
1030        }
1031        // cleanup test app
1032        finally {
1033            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
1034        }
1035    }
1036
1037    /**
1038     * Regression test to verify that an app with BLUE_TOOTH permissions can
1039     * run without permissions errors.
1040     * <p/>
1041     * Assumes adb is running as root in device under test.
1042     * @throws InterruptedException if the thread was interrupted
1043     * @throws TimeoutException in case of a timeout on the connection.
1044     * @throws AdbCommandRejectedException if adb rejects the command
1045     * @throws ShellCommandUnresponsiveException if the device did not output anything for
1046     * a period longer than the max time to output.
1047     * @throws IOException if connection to device was lost.
1048     * @throws InstallException if the install failed.
1049     */
1050    public void testInstallAndLaunchBTPermsAppOnSD()
1051            throws IOException, InterruptedException, InstallException, TimeoutException,
1052            AdbCommandRejectedException, ShellCommandUnresponsiveException {
1053        Log.i(LOG_TAG, "Test launching an app with bluetooth perms set, installed on SD card");
1054
1055        try {
1056            // install the app and verify we can launch it without permissions errors
1057            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1058                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
1059            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_BT_PKG);
1060            assert(testsPassed);
1061        }
1062        // cleanup test app
1063        finally {
1064            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
1065        }
1066    }
1067
1068    /**
1069     * Regression test to verify that a shared app with no explicit permissions throws a
1070     * SecurityException when launched if its other shared apps are not installed.
1071     * <p/>
1072     * Assumes adb is running as root in device under test.
1073     * @throws InterruptedException if the thread was interrupted
1074     * @throws TimeoutException in case of a timeout on the connection.
1075     * @throws AdbCommandRejectedException if adb rejects the command
1076     * @throws ShellCommandUnresponsiveException if the device did not output anything for
1077     * a period longer than the max time to output.
1078     * @throws IOException if connection to device was lost.
1079     * @throws InstallException if the install failed.
1080     */
1081    public void testInstallAndLaunchSharedPermsAppOnSD_NoPerms()
1082            throws IOException, InterruptedException, InstallException, TimeoutException,
1083            AdbCommandRejectedException, ShellCommandUnresponsiveException {
1084        Log.i(LOG_TAG, "Test launching an app with no explicit perms set, installed on SD card");
1085
1086        try {
1087            // Make sure the 2 shared apps with needed permissions are not installed...
1088            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
1089            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
1090
1091            // now install the app and see if when we launch it we get a permissions error
1092            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1093                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
1094
1095            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
1096            assertEquals("Shared perms app should fail to run", false, testsPassed);
1097        }
1098        // cleanup test app
1099        finally {
1100            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
1101        }
1102    }
1103
1104    /**
1105     * Regression test to verify that a shared app with no explicit permissions can run if its other
1106     * shared apps are installed.
1107     * <p/>
1108     * Assumes adb is running as root in device under test.
1109     * @throws InterruptedException if the thread was interrupted
1110     * @throws TimeoutException in case of a timeout on the connection.
1111     * @throws AdbCommandRejectedException if adb rejects the command
1112     * @throws ShellCommandUnresponsiveException if the device did not output anything for
1113     * a period longer than the max time to output.
1114     * @throws IOException if connection to device was lost.
1115     * @throws InstallException if the install failed.
1116     */
1117    public void testInstallAndLaunchSharedPermsAppOnSD_GrantedPerms()
1118            throws IOException, InterruptedException, InstallException, TimeoutException,
1119            AdbCommandRejectedException, ShellCommandUnresponsiveException {
1120        Log.i(LOG_TAG, "Test launching an app with no explicit perms set, installed on SD card");
1121
1122        try {
1123            // install the 2 shared apps with needed permissions first
1124            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1125                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
1126            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1127                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
1128
1129            // now install the test app and see if we can launch it without errors
1130            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1131                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
1132            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
1133            assert(testsPassed);
1134        }
1135        // cleanup test app
1136        finally {
1137            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
1138            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
1139            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
1140        }
1141    }
1142
1143    /**
1144     * Regression test to verify that an app with ACCESS_FINE_LOCATION (GPS) permissions can
1145     * run without permissions errors even after a reboot
1146     * <p/>
1147     * Assumes adb is running as root in device under test.
1148     * @throws InterruptedException if the thread was interrupted
1149     * @throws TimeoutException in case of a timeout on the connection.
1150     * @throws AdbCommandRejectedException if adb rejects the command
1151     * @throws ShellCommandUnresponsiveException if the device did not output anything for
1152     * a period longer than the max time to output.
1153     * @throws IOException if connection to device was lost.
1154     * @throws InstallException if the install failed.
1155     */
1156    public void testInstallAndLaunchFLPermsAppOnSD_Reboot()
1157            throws IOException, InterruptedException, InstallException, TimeoutException,
1158            AdbCommandRejectedException, ShellCommandUnresponsiveException {
1159        Log.i(LOG_TAG, "Test launching an app with location perms set, installed on SD card");
1160
1161        try {
1162            // install the app and verify we can launch it without permissions errors
1163            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1164                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
1165            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
1166            assert(testsPassed);
1167
1168            mPMHostUtils.rebootDevice();
1169
1170            testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_FL_PKG);
1171            assert(testsPassed);
1172        }
1173        // cleanup test app
1174        finally {
1175            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
1176        }
1177    }
1178
1179    /**
1180     * Regression test to verify that a shared app with no explicit permissions can run if its other
1181     * shared apps are installed, even after a reboot.
1182     * <p/>
1183     * Assumes adb is running as root in device under test.
1184     * @throws InterruptedException if the thread was interrupted
1185     * @throws TimeoutException in case of a timeout on the connection.
1186     * @throws AdbCommandRejectedException if adb rejects the command
1187     * @throws ShellCommandUnresponsiveException if the device did not output anything for
1188     * a period longer than the max time to output.
1189     * @throws IOException if connection to device was lost.
1190     * @throws InstallException if the install failed.
1191     */
1192    public void testInstallAndLaunchSharedPermsAppOnSD_Reboot()
1193            throws IOException, InterruptedException, InstallException, TimeoutException,
1194            AdbCommandRejectedException, ShellCommandUnresponsiveException {
1195        Log.i(LOG_TAG, "Test launching an app on SD, with no explicit perms set after reboot");
1196
1197        try {
1198            // install the 2 shared apps with needed permissions first
1199            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1200                    SHARED_PERMS_FL_APK), SHARED_PERMS_FL_PKG, false);
1201            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1202                    SHARED_PERMS_BT_APK), SHARED_PERMS_BT_PKG, false);
1203
1204            // now install the test app and see if we can launch it without errors
1205            mPMHostUtils.installAppAndVerifyExistsOnSDCard(getTestAppFilePath(
1206                    SHARED_PERMS_APK), SHARED_PERMS_PKG, false);
1207            boolean testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
1208            assert(testsPassed);
1209
1210            // reboot
1211            mPMHostUtils.rebootDevice();
1212
1213            // Verify we can still launch the app
1214            testsPassed = mPMHostUtils.runDeviceTestsDidAllTestsPass(SHARED_PERMS_PKG);
1215            assert(testsPassed);
1216        }
1217        // cleanup test app
1218        finally {
1219            mPMHostUtils.uninstallApp(SHARED_PERMS_PKG);
1220            mPMHostUtils.uninstallApp(SHARED_PERMS_BT_PKG);
1221            mPMHostUtils.uninstallApp(SHARED_PERMS_FL_PKG);
1222        }
1223    }
1224}
1225