1 package com.android.contacts;
2 
3 import static com.android.contacts.util.PermissionsUtil.hasPermission;
4 
5 import static org.junit.Assume.assumeTrue;
6 
7 import android.Manifest;
8 import android.content.Context;
9 import android.content.Intent;
10 import android.content.pm.PackageManager;
11 
12 import androidx.test.InstrumentationRegistry;
13 import androidx.test.filters.MediumTest;
14 import androidx.test.filters.Suppress;
15 import androidx.test.runner.AndroidJUnit4;
16 import androidx.test.uiautomator.By;
17 import androidx.test.uiautomator.UiDevice;
18 import androidx.test.uiautomator.UiObject2;
19 import androidx.test.uiautomator.Until;
20 
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 
25 /**
26  * Make sure the app doesn't crash when it is started without permissions. Note: this won't
27  * run in most environments because permissions will already have been granted.
28  *
29  * To exercise this run:
30  *
31  * $ adb shell pm revoke com.android.contacts android.permission.READ_CONTACTS
32  * $ adb shell pm revoke com.android.contacts android.permission.WRITE_CONTACTS
33  * $ adb shell pm revoke com.android.contacts android.permission.GET_ACCOUNTS
34  * $ adb shell pm revoke com.android.contacts android.permission.READ_PHONE_STATE
35  * $ adb shell pm revoke com.android.contacts android.permission.CALL_PHONE
36  * $ adb shell am instrument -w \
37  *     com.google.android.contacts.tests/androidx.test.runner.AndroidJUnitRunner \
38  *     -e class com.android.contacts.NoPermissionsLaunchSmokeTest
39  */
40 @MediumTest
41 // suppressed because failed assumptions are reported as test failures by the build server
42 @Suppress
43 @RunWith(AndroidJUnit4.class)
44 public class NoPermissionsLaunchSmokeTest {
45     private static final long TIMEOUT = 5000;
46 
47     private Context mTargetContext;
48 
49     @Before
setUp()50     public void setUp() throws Exception {
51         mTargetContext = InstrumentationRegistry.getTargetContext();
52         assumeTrue(!hasPermission(mTargetContext, Manifest.permission.READ_CONTACTS));
53         assumeTrue(!hasPermission(mTargetContext, Manifest.permission.WRITE_CONTACTS));
54         assumeTrue(!hasPermission(mTargetContext, Manifest.permission.GET_ACCOUNTS));
55         assumeTrue(!hasPermission(mTargetContext, Manifest.permission.READ_PHONE_STATE));
56         assumeTrue(!hasPermission(mTargetContext, Manifest.permission.CALL_PHONE));
57         assumeTrue(!hasPermission(mTargetContext, Manifest.permission.READ_CALL_LOG));
58 
59         // remove state that might exist outside of the app
60         // (e.g. launcher shortcuts and scheduled jobs)
61         DynamicShortcuts.reset(mTargetContext);
62     }
63 
64     @Test
launchingMainActivityDoesntCrash()65     public void launchingMainActivityDoesntCrash() throws Exception {
66         final UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
67 
68         // Launch the main activity
69         InstrumentationRegistry.getContext().startActivity(
70                 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_DEFAULT)
71                         .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
72                         .setPackage(InstrumentationRegistry.getTargetContext().getPackageName()));
73 
74         device.waitForIdle();
75 
76         final PackageManager packageManager = mTargetContext.getPackageManager();
77         if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
78             device.wait(Until.hasObject(By.textEndsWith("your phone call logs?")), TIMEOUT);
79             final UiObject2 grantCallLogPermissionButton = device.findObject(By.text("ALLOW"));
80             grantCallLogPermissionButton.click();
81         }
82 
83         device.wait(Until.hasObject(By.textEndsWith("access your contacts?")), TIMEOUT);
84         final UiObject2 grantContactsPermissionButton = device.findObject(By.text("ALLOW"));
85 
86         grantContactsPermissionButton.click();
87 
88         device.wait(Until.hasObject(By.textEndsWith("make and manage phone calls?")), TIMEOUT);
89 
90         if (!packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
91             device.waitForIdle();
92             return;
93         }
94 
95         final UiObject2 grantPhonePermissionButton = device.findObject(By.text("ALLOW"));
96 
97         grantPhonePermissionButton.clickAndWait(Until.newWindow(), TIMEOUT);
98 
99         // Not sure if this actually waits for the load to complete or not.
100         device.waitForIdle();
101     }
102 
103     // TODO: it would be good to have similar tests for other entry points that might be reached
104     // without required permissions.
105 }
106