Actually launch onboarding flow if needed
Launch OnboardingActivity for exported activities
(DialtactsActivity, CallDetailsActivity) to ensure that
a) We prompt the user to make us the default dialer at least once
b) The user has granted us both the Phone and Contacts permissions
Bug: 24270592
Change-Id: I232314e42f5331a72c1a84be917d9d74c5813976
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());
}