Merge "Show blocked icon in call log." into ub-contactsdialer-a-dev
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index c8a5356..ee1f5ad 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -47,6 +47,7 @@
 import com.android.contacts.common.util.UriUtils;
 import com.android.dialer.calllog.CallDetailHistoryAdapter;
 import com.android.dialer.calllog.CallLogAsyncTaskUtil.CallLogAsyncTaskListener;
+import com.android.dialer.onboard.OnboardingActivity;
 import com.android.dialer.calllog.CallLogAsyncTaskUtil;
 import com.android.dialer.calllog.CallTypeHelper;
 import com.android.dialer.calllog.ContactInfoHelper;
@@ -220,6 +221,11 @@
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
+        if (OnboardingActivity.shouldStartOnboardingActivity(this)) {
+            OnboardingActivity.startOnboardingActivity(this);
+            finish();
+        }
+
         mContext = this;
 
         setContentView(R.layout.call_detail);
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 9978bbe..455b097 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -80,6 +80,7 @@
 import com.android.dialer.list.SearchFragment;
 import com.android.dialer.list.SmartDialSearchFragment;
 import com.android.dialer.list.SpeedDialFragment;
+import com.android.dialer.onboard.OnboardingActivity;
 import com.android.dialer.settings.DialerSettingsActivity;
 import com.android.dialer.util.IntentUtil;
 import com.android.dialer.util.TelecomUtil;
@@ -374,6 +375,11 @@
         Trace.beginSection(TAG + " onCreate");
         super.onCreate(savedInstanceState);
 
+        if (OnboardingActivity.shouldStartOnboardingActivity(this)) {
+            OnboardingActivity.startOnboardingActivity(this);
+            finish();
+        }
+
         mFirstLaunch = true;
 
         final Resources resources = getResources();
diff --git a/src/com/android/dialer/onboard/OnboardingActivity.java b/src/com/android/dialer/onboard/OnboardingActivity.java
index 75378e9..144e6d4 100644
--- a/src/com/android/dialer/onboard/OnboardingActivity.java
+++ b/src/com/android/dialer/onboard/OnboardingActivity.java
@@ -19,9 +19,11 @@
 import static android.Manifest.permission.CALL_PHONE;
 import static android.Manifest.permission.READ_CONTACTS;
 
+import android.Manifest;
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
@@ -45,6 +47,8 @@
         PermissionsChecker, OnboardingFragment.HostInterface {
     public static final String KEY_ALREADY_REQUESTED_DEFAULT_DIALER =
             "key_already_requested_default_dialer";
+    public static final String KEY_CALLING_ACTIVITY_INTENT =
+            "key_calling_activity_intent";
 
     public static final int SCREEN_DEFAULT_DIALER = 0;
     public static final int SCREEN_PERMISSIONS = 1;
@@ -95,6 +99,16 @@
     public void completeOnboardingFlow() {
         final Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
         editor.putBoolean(KEY_ALREADY_REQUESTED_DEFAULT_DIALER, true).apply();
+
+        // Once we have completed the onboarding flow, relaunch the activity that called us, so
+        // that we return the user to the intended activity.
+        if (getIntent() != null && getIntent().getExtras() != null) {
+            final Intent previousActivityIntent =
+                    getIntent().getExtras().getParcelable(KEY_CALLING_ACTIVITY_INTENT);
+            if (previousActivityIntent != null) {
+                startActivity(previousActivityIntent);
+            }
+        }
         finish();
     }
 
@@ -114,12 +128,61 @@
     }
 
     @Override
-    public boolean previouslyRequestedDefaultDialer() {
-        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+    public boolean hasAlreadyRequestedDefaultDialer() {
+        return getAlreadyRequestedDefaultDialerFromPreferences(this);
+    }
+
+    private static boolean getAlreadyRequestedDefaultDialerFromPreferences(Context context) {
+        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
         return preferences.getBoolean(KEY_ALREADY_REQUESTED_DEFAULT_DIALER, false);
     }
 
     /**
+     * Checks the current permissions/application state to determine if the
+     * {@link OnboardingActivity} should be displayed. The onboarding flow should be launched if
+     * the current application is NOT the system dialer AND any of these criteria are true.
+     *
+     * 1) The phone application is not currently the default dialer AND we have not
+     * previously displayed a prompt to ask the user to set our app as the default dialer.
+     * 2) The phone application does not have the Phone permission.
+     * 3) The phone application does not have the Contacts permission.
+     *
+     * The exception if the current application is the system dialer applies because:
+     *
+     * 1) The system dialer must always provide immediate access to the dialpad to allow
+     * emergency calls to be made.
+     * 2) In order for the system dialer to require the onboarding flow, the user must have
+     * intentionally removed certain permissions/selected a different dialer. This assumes the
+     * that the user understands the implications of the actions previously taken. For example,
+     * removing the Phone permission from the system dialer displays a dialog that warns the
+     * user that this might break certain core phone functionality. Furthermore, various elements in
+     * the Dialer will prompt the user to grant permissions as needed.
+     *
+     * @param context A valid context object.
+     * @return {@code true} if the onboarding flow should be launched to request for the
+     *         necessary permissions or prompt the user to make us the default dialer, {@code false}
+     *         otherwise.
+     */
+    public static boolean shouldStartOnboardingActivity(Context context) {
+        // Since there is no official TelecomManager API to check for the system dialer,
+        // check to see if we have the system-only MODIFY_PHONE_STATE permission.
+        if (PermissionsUtil.hasPermission(context, Manifest.permission.MODIFY_PHONE_STATE)) {
+            return false;
+        }
+
+        return (!getAlreadyRequestedDefaultDialerFromPreferences(context)
+                && !TelecomUtil.isDefaultDialer(context))
+                        || !PermissionsUtil.hasPhonePermissions(context)
+                        || !PermissionsUtil.hasContactsPermissions(context);
+    }
+
+    public static void startOnboardingActivity(Activity callingActivity) {
+        final Intent intent = new Intent(callingActivity, OnboardingActivity.class);
+        intent.putExtra(KEY_CALLING_ACTIVITY_INTENT, callingActivity.getIntent());
+        callingActivity.startActivity(intent);
+    }
+
+    /**
      * Triggers the screen-specific logic that should occur when the next button is clicked.
      */
     @Override
@@ -180,7 +243,7 @@
 
         @Override
         public boolean shouldShowScreen() {
-            return !mPermissionsChecker.previouslyRequestedDefaultDialer()
+            return !mPermissionsChecker.hasAlreadyRequestedDefaultDialer()
                     && !mPermissionsChecker.isDefaultOrSystemDialer();
         }
 
diff --git a/src/com/android/dialer/onboard/PermissionsChecker.java b/src/com/android/dialer/onboard/PermissionsChecker.java
index 78d175e..c6b0bbf 100644
--- a/src/com/android/dialer/onboard/PermissionsChecker.java
+++ b/src/com/android/dialer/onboard/PermissionsChecker.java
@@ -23,5 +23,5 @@
     public boolean hasPhonePermissions();
     public boolean hasContactsPermissions();
     public boolean isDefaultOrSystemDialer();
-    public boolean previouslyRequestedDefaultDialer();
+    public boolean hasAlreadyRequestedDefaultDialer();
 }
diff --git a/tests/src/com/android/dialer/onboard/DefaultDialerOnboardScreenTest.java b/tests/src/com/android/dialer/onboard/DefaultDialerOnboardScreenTest.java
index f9724c1..26e513f 100644
--- a/tests/src/com/android/dialer/onboard/DefaultDialerOnboardScreenTest.java
+++ b/tests/src/com/android/dialer/onboard/DefaultDialerOnboardScreenTest.java
@@ -36,17 +36,17 @@
     }
 
     public void testNeverRequestedForDefaultDialer_shouldShowScreen() {
-        when(mPermissionsChecker.previouslyRequestedDefaultDialer()).thenReturn(false);
+        when(mPermissionsChecker.hasAlreadyRequestedDefaultDialer()).thenReturn(false);
         assertTrue(mScreen.shouldShowScreen());
     }
 
     public void testAlreadyAskedForDefaultDialer_shouldNotShowScreen() {
-        when(mPermissionsChecker.previouslyRequestedDefaultDialer()).thenReturn(true);
+        when(mPermissionsChecker.hasAlreadyRequestedDefaultDialer()).thenReturn(true);
         assertFalse(mScreen.shouldShowScreen());
     }
 
     public void testAlreadySetAsDefaultDialer_shouldNotShowScreen() {
-        when(mPermissionsChecker.previouslyRequestedDefaultDialer()).thenReturn(false);
+        when(mPermissionsChecker.hasAlreadyRequestedDefaultDialer()).thenReturn(false);
         when(mPermissionsChecker.isDefaultOrSystemDialer()).thenReturn(true);
         assertFalse(mScreen.shouldShowScreen());
     }