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.
+}