Check permissions before creating dynamic shortcuts.
Dynamic shortcuts is initialized before permissions may have been granted so
it needs to check permissions before running queries.
Test
Ran the following:
$ adb shell pm revoke com.android.contacts android.permission.READ_CONTACTS
$ adb shell pm revoke com.android.contacts android.permission.WRITE_CONTACTS
$ adb shell pm revoke com.android.contacts android.permission.GET_ACCOUNTS
$ adb shell pm revoke com.android.contacts android.permission.READ_PHONE_STATE
$ adb shell pm revoke com.android.contacts android.permission.READ_CALL_LOG
$ adb shell pm revoke com.android.contacts android.permission.CALL_PHONE
$ adb shell am instrument -w \
com.google.android.contacts.tests/android.support.test.runner.AndroidJUnitRunner \
-e class com.android.contacts.NoPermissionsLaunchSmokeTest
Bug 30189449
Change-Id: I3e7f865559d142c12f3b026a9d6aa2d7e1a1e5f9
diff --git a/tests/Android.mk b/tests/Android.mk
index 6b31593..46ab201 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -21,7 +21,9 @@
LOCAL_STATIC_JAVA_LIBRARIES += \
hamcrest-library \
- mockito-target-minus-junit4
+ mockito-target-minus-junit4 \
+ ub-uiautomator
+
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 65be28a..0c2cda7 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -93,7 +93,7 @@
<service android:name=".PhoneNumberTestService" />
</application>
- <instrumentation android:name="android.test.InstrumentationTestRunner"
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.contacts"
android:label="Contacts app tests">
</instrumentation>
diff --git a/tests/src/com/android/contacts/NoPermissionsLaunchSmokeTest.java b/tests/src/com/android/contacts/NoPermissionsLaunchSmokeTest.java
new file mode 100644
index 0000000..a196ffa
--- /dev/null
+++ b/tests/src/com/android/contacts/NoPermissionsLaunchSmokeTest.java
@@ -0,0 +1,88 @@
+package com.android.contacts;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.android.contacts.common.util.PermissionsUtil.hasPermission;
+import static org.junit.Assume.assumeTrue;
+
+/**
+ * Make sure the app doesn't crash when it is started without permissions. Note: this won't
+ * run in most environments because permissions will already have been granted.
+ *
+ * To exercise this run:
+ *
+ * $ adb shell pm revoke com.android.contacts android.permission.READ_CONTACTS
+ * $ adb shell pm revoke com.android.contacts android.permission.WRITE_CONTACTS
+ * $ adb shell pm revoke com.android.contacts android.permission.GET_ACCOUNTS
+ * $ adb shell pm revoke com.android.contacts android.permission.READ_PHONE_STATE
+ * $ adb shell pm revoke com.android.contacts android.permission.READ_CALL_LOG
+ * $ adb shell pm revoke com.android.contacts android.permission.CALL_PHONE
+ * $ adb shell am instrument -w \
+ * com.google.android.contacts.tests/android.support.test.runner.AndroidJUnitRunner \
+ * -e class com.android.contacts.NoPermissionsLaunchSmokeTest
+ */
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class NoPermissionsLaunchSmokeTest {
+ private static final long TIMEOUT = 5000;
+
+ private Context mTargetContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mTargetContext = InstrumentationRegistry.getTargetContext();
+ assumeTrue(!hasPermission(mTargetContext, Manifest.permission.READ_CONTACTS));
+ assumeTrue(!hasPermission(mTargetContext, Manifest.permission.WRITE_CONTACTS));
+ assumeTrue(!hasPermission(mTargetContext, Manifest.permission.GET_ACCOUNTS));
+ assumeTrue(!hasPermission(mTargetContext, Manifest.permission.READ_PHONE_STATE));
+ assumeTrue(!hasPermission(mTargetContext, Manifest.permission.READ_CALL_LOG));
+ assumeTrue(!hasPermission(mTargetContext, Manifest.permission.CALL_PHONE));
+
+ // remove state that might exist outside of the app
+ // (e.g. launcher shortcuts and scheduled jobs)
+ DynamicShortcuts.reset(mTargetContext);
+ }
+
+ @Test
+ public void launchingMainActivityDoesntCrash() throws Exception {
+ final UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ // Launch the main activity
+ InstrumentationRegistry.getContext().startActivity(
+ new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_DEFAULT)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ .setPackage(InstrumentationRegistry.getTargetContext().getPackageName()));
+
+ device.waitForIdle();
+
+ device.wait(Until.hasObject(By.textStartsWith("Allow Contacts")), TIMEOUT);
+ final UiObject2 grantContactsPermissionButton = device.findObject(By.text("ALLOW"));
+
+ grantContactsPermissionButton.click();
+
+ device.wait(Until.hasObject(By.textEndsWith("make and manage phone calls?")), TIMEOUT);
+
+ final UiObject2 grantPhonePermissionButton = device.findObject(By.text("ALLOW"));
+
+ grantPhonePermissionButton.clickAndWait(Until.newWindow(), TIMEOUT);
+
+ // Not sure if this actually waits for the load to complete or not.
+ device.waitForIdle();
+ }
+
+ // TODO: it would be good to have similar tests for other entry points that might be reached
+ // without required permissions.
+}