Merge "AR/FR: Keyboard challenge takes precedence."

This commit is contained in:
TreeHugger Robot
2018-01-31 19:42:03 +00:00
committed by Android (Google) Code Review
2 changed files with 155 additions and 36 deletions

View File

@@ -123,24 +123,34 @@ public class MasterClear extends InstrumentedPreferenceFragment {
return !((requestCode != KEYGUARD_REQUEST) && (requestCode != CREDENTIAL_CONFIRM_REQUEST)); return !((requestCode != KEYGUARD_REQUEST) && (requestCode != CREDENTIAL_CONFIRM_REQUEST));
} }
@VisibleForTesting
boolean isShowFinalConfirmation(int requestCode, int resultCode) {
return (resultCode == Activity.RESULT_OK) || (requestCode == CREDENTIAL_CONFIRM_REQUEST);
}
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
onActivityResultInternal(requestCode, resultCode, data);
}
/*
* Internal method that allows easy testing without dealing with super references.
*/
@VisibleForTesting
void onActivityResultInternal(int requestCode, int resultCode, Intent data) {
if (!isValidRequestCode(requestCode)) { if (!isValidRequestCode(requestCode)) {
return; return;
} }
// If the user entered a valid keyguard trace, present the final if (resultCode != Activity.RESULT_OK) {
// confirmation prompt; otherwise, go back to the initial state.
if (isShowFinalConfirmation(requestCode, resultCode)) {
showFinalConfirmation();
} else {
establishInitialState(); establishInitialState();
return;
}
Intent intent = null;
// If returning from a Keyguard request, try to show an account confirmation request if
// applciable.
if (CREDENTIAL_CONFIRM_REQUEST != requestCode
&& (intent = getAccountConfirmationIntent()) != null) {
showAccountCredentialConfirmation(intent);
} else {
showFinalConfirmation();
} }
} }
@@ -155,7 +165,12 @@ public class MasterClear extends InstrumentedPreferenceFragment {
} }
@VisibleForTesting @VisibleForTesting
boolean tryShowAccountConfirmation() { void showAccountCredentialConfirmation(Intent intent) {
startActivityForResult(intent, CREDENTIAL_CONFIRM_REQUEST);
}
@VisibleForTesting
Intent getAccountConfirmationIntent() {
final Context context = getActivity(); final Context context = getActivity();
final String accountType = context.getString(R.string.account_type); final String accountType = context.getString(R.string.account_type);
final String packageName = context.getString(R.string.account_confirmation_package); final String packageName = context.getString(R.string.account_confirmation_package);
@@ -163,7 +178,8 @@ public class MasterClear extends InstrumentedPreferenceFragment {
if (TextUtils.isEmpty(accountType) if (TextUtils.isEmpty(accountType)
|| TextUtils.isEmpty(packageName) || TextUtils.isEmpty(packageName)
|| TextUtils.isEmpty(className)) { || TextUtils.isEmpty(className)) {
return false; Log.i(TAG, "Resources not set for account confirmation.");
return null;
} }
final AccountManager am = AccountManager.get(context); final AccountManager am = AccountManager.get(context);
Account[] accounts = am.getAccountsByType(accountType); Account[] accounts = am.getAccountsByType(accountType);
@@ -179,12 +195,14 @@ public class MasterClear extends InstrumentedPreferenceFragment {
&& packageName.equals(resolution.activityInfo.packageName)) { && packageName.equals(resolution.activityInfo.packageName)) {
// Note that we need to check the packagename to make sure that an Activity resolver // Note that we need to check the packagename to make sure that an Activity resolver
// wasn't returned. // wasn't returned.
startActivityForResult( return requestAccountConfirmation;
requestAccountConfirmation, CREDENTIAL_CONFIRM_REQUEST); } else {
return true; Log.i(TAG, "Unable to resolve Activity: " + packageName + "/" + className);
} }
} else {
Log.d(TAG, "No " + accountType + " accounts installed!");
} }
return false; return null;
} }
/** /**
@@ -210,7 +228,14 @@ public class MasterClear extends InstrumentedPreferenceFragment {
return; return;
} }
if (!tryShowAccountConfirmation() && !runKeyguardConfirmation(KEYGUARD_REQUEST)) { if (runKeyguardConfirmation(KEYGUARD_REQUEST)) {
return;
}
Intent intent = getAccountConfirmationIntent();
if (intent != null) {
showAccountCredentialConfirmation(intent);
} else {
showFinalConfirmation(); showFinalConfirmation();
} }
} }
@@ -228,7 +253,8 @@ public class MasterClear extends InstrumentedPreferenceFragment {
* time, then simply reuse the inflated views directly whenever we need * time, then simply reuse the inflated views directly whenever we need
* to change contents. * to change contents.
*/ */
private void establishInitialState() { @VisibleForTesting
void establishInitialState() {
mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_master_clear); mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_master_clear);
mInitiateButton.setOnClickListener(mInitiateListener); mInitiateButton.setOnClickListener(mInitiateListener);
mExternalStorageContainer = mContentView.findViewById(R.id.erase_external_container); mExternalStorageContainer = mContentView.findViewById(R.id.erase_external_container);

View File

@@ -18,11 +18,14 @@ package com.android.settings;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq; import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf; import static org.robolectric.Shadows.shadowOf;
@@ -86,6 +89,9 @@ public class MasterClearTest {
@Mock @Mock
private Activity mMockActivity; private Activity mMockActivity;
@Mock
private Intent mMockIntent;
private ShadowActivity mShadowActivity; private ShadowActivity mShadowActivity;
private ShadowAccountManager mShadowAccountManager; private ShadowAccountManager mShadowAccountManager;
private Activity mActivity; private Activity mActivity;
@@ -110,7 +116,7 @@ public class MasterClearTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mMasterClear = spy(new MasterClear()); mMasterClear = spy(new MasterClear());
mActivity = Robolectric.setupActivity(Activity.class); mActivity = Robolectric.setupActivity(Activity.class);
mShadowActivity = shadowOf(mActivity); mShadowActivity = shadowOf(mActivity);https://stackoverflow.com/questions/14889951/how-to-verify-a-method-is-called-two-times-with-mockito-verify
// mShadowAccountManager = shadowOf(AccountManager.get(mActivity)); // mShadowAccountManager = shadowOf(AccountManager.get(mActivity));
mContentView = LayoutInflater.from(mActivity).inflate(R.layout.master_clear, null); mContentView = LayoutInflater.from(mActivity).inflate(R.layout.master_clear, null);
@@ -213,38 +219,115 @@ public class MasterClearTest {
} }
@Test @Test
public void testTryShowAccountConfirmation_unsupported() { public void testOnActivityResultInternal_invalideRequest() {
when(mMasterClear.getActivity()).thenReturn(mActivity); int invalidRequestCode = -1;
/* Using the default resources, account confirmation shouldn't trigger */ doReturn(false).when(mMasterClear).isValidRequestCode(eq(invalidRequestCode));
assertThat(mMasterClear.tryShowAccountConfirmation()).isFalse();
mMasterClear.onActivityResultInternal(invalidRequestCode, Activity.RESULT_OK, null);
verify(mMasterClear, times(1)).isValidRequestCode(eq(invalidRequestCode));
verify(mMasterClear, times(0)).establishInitialState();
verify(mMasterClear, times(0)).getAccountConfirmationIntent();
verify(mMasterClear, times(0)).showFinalConfirmation();
} }
@Test @Test
public void testTryShowAccountConfirmation_no_relevant_accounts() { public void testOnActivityResultInternal_resultCanceled() {
doReturn(true).when(mMasterClear).isValidRequestCode(eq(MasterClear.KEYGUARD_REQUEST));
doNothing().when(mMasterClear).establishInitialState();
mMasterClear.onActivityResultInternal(
MasterClear.KEYGUARD_REQUEST, Activity.RESULT_CANCELED, null);
verify(mMasterClear, times(1)).isValidRequestCode(eq(MasterClear.KEYGUARD_REQUEST));
verify(mMasterClear, times(1)).establishInitialState();
verify(mMasterClear, times(0)).getAccountConfirmationIntent();
verify(mMasterClear, times(0)).showFinalConfirmation();
}
@Test
public void testOnActivityResultInternal_keyguardRequestTriggeringConfirmAccount() {
doReturn(true).when(mMasterClear).isValidRequestCode(eq(MasterClear.KEYGUARD_REQUEST));
doReturn(mMockIntent).when(mMasterClear).getAccountConfirmationIntent();
doNothing().when(mMasterClear).showAccountCredentialConfirmation(eq(mMockIntent));
mMasterClear.onActivityResultInternal(
MasterClear.KEYGUARD_REQUEST, Activity.RESULT_OK, null);
verify(mMasterClear, times(1)).isValidRequestCode(eq(MasterClear.KEYGUARD_REQUEST));
verify(mMasterClear, times(0)).establishInitialState();
verify(mMasterClear, times(1)).getAccountConfirmationIntent();
verify(mMasterClear, times(1)).showAccountCredentialConfirmation(eq(mMockIntent));
}
@Test
public void testOnActivityResultInternal_keyguardRequestTriggeringShowFinal() {
doReturn(true).when(mMasterClear).isValidRequestCode(eq(MasterClear.KEYGUARD_REQUEST));
doReturn(null).when(mMasterClear).getAccountConfirmationIntent();
doNothing().when(mMasterClear).showFinalConfirmation();
mMasterClear.onActivityResultInternal(
MasterClear.KEYGUARD_REQUEST, Activity.RESULT_OK, null);
verify(mMasterClear, times(1)).isValidRequestCode(eq(MasterClear.KEYGUARD_REQUEST));
verify(mMasterClear, times(0)).establishInitialState();
verify(mMasterClear, times(1)).getAccountConfirmationIntent();
verify(mMasterClear, times(1)).showFinalConfirmation();
}
@Test
public void testOnActivityResultInternal_confirmRequestTriggeringShowFinal() {
doReturn(true).when(mMasterClear)
.isValidRequestCode(eq(MasterClear.CREDENTIAL_CONFIRM_REQUEST));
doNothing().when(mMasterClear).showFinalConfirmation();
mMasterClear.onActivityResultInternal(
MasterClear.CREDENTIAL_CONFIRM_REQUEST, Activity.RESULT_OK, null);
verify(mMasterClear, times(1))
.isValidRequestCode(eq(MasterClear.CREDENTIAL_CONFIRM_REQUEST));
verify(mMasterClear, times(0)).establishInitialState();
verify(mMasterClear, times(0)).getAccountConfirmationIntent();
verify(mMasterClear, times(1)).showFinalConfirmation();
}
@Test
public void testGetAccountConfirmationIntent_unsupported() {
when(mMasterClear.getActivity()).thenReturn(mActivity);
/* Using the default resources, account confirmation shouldn't trigger */
assertThat(mMasterClear.getAccountConfirmationIntent()).isNull();
}
@Test
public void testGetAccountConfirmationIntent_no_relevant_accounts() {
when(mMasterClear.getActivity()).thenReturn(mMockActivity); when(mMasterClear.getActivity()).thenReturn(mMockActivity);
when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE); when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
when(mMockActivity.getString(R.string.account_confirmation_package)).thenReturn(TEST_CONFIRMATION_PACKAGE); when(mMockActivity.getString(R.string.account_confirmation_package))
when(mMockActivity.getString(R.string.account_confirmation_class)).thenReturn(TEST_CONFIRMATION_CLASS); .thenReturn(TEST_CONFIRMATION_PACKAGE);
when(mMockActivity.getString(R.string.account_confirmation_class))
.thenReturn(TEST_CONFIRMATION_CLASS);
Account[] accounts = new Account[0]; Account[] accounts = new Account[0];
when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager); when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts); when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts);
assertThat(mMasterClear.tryShowAccountConfirmation()).isFalse(); assertThat(mMasterClear.getAccountConfirmationIntent()).isNull();
} }
@Test @Test
public void testTryShowAccountConfirmation_unresolved() { public void testGetAccountConfirmationIntent_unresolved() {
when(mMasterClear.getActivity()).thenReturn(mMockActivity); when(mMasterClear.getActivity()).thenReturn(mMockActivity);
when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE); when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
when(mMockActivity.getString(R.string.account_confirmation_package)).thenReturn(TEST_CONFIRMATION_PACKAGE); when(mMockActivity.getString(R.string.account_confirmation_package))
when(mMockActivity.getString(R.string.account_confirmation_class)).thenReturn(TEST_CONFIRMATION_CLASS); .thenReturn(TEST_CONFIRMATION_PACKAGE);
when(mMockActivity.getString(R.string.account_confirmation_class))
.thenReturn(TEST_CONFIRMATION_CLASS);
Account[] accounts = new Account[] { new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE) }; Account[] accounts = new Account[] { new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE) };
when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager); when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts); when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts);
// The package manager should not resolve the confirmation intent targeting the non-existent // The package manager should not resolve the confirmation intent targeting the non-existent
// confirmation package. // confirmation package.
when(mMockActivity.getPackageManager()).thenReturn(mPackageManager); when(mMockActivity.getPackageManager()).thenReturn(mPackageManager);
assertThat(mMasterClear.tryShowAccountConfirmation()).isFalse(); assertThat(mMasterClear.getAccountConfirmationIntent()).isNull();
} }
@Test @Test
@@ -252,8 +335,10 @@ public class MasterClearTest {
when(mMasterClear.getActivity()).thenReturn(mMockActivity); when(mMasterClear.getActivity()).thenReturn(mMockActivity);
// Only try to show account confirmation if the appropriate resource overlays are available. // Only try to show account confirmation if the appropriate resource overlays are available.
when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE); when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
when(mMockActivity.getString(R.string.account_confirmation_package)).thenReturn(TEST_CONFIRMATION_PACKAGE); when(mMockActivity.getString(R.string.account_confirmation_package))
when(mMockActivity.getString(R.string.account_confirmation_class)).thenReturn(TEST_CONFIRMATION_CLASS); .thenReturn(TEST_CONFIRMATION_PACKAGE);
when(mMockActivity.getString(R.string.account_confirmation_class))
.thenReturn(TEST_CONFIRMATION_CLASS);
// Add accounts to trigger the search for a resolving intent. // Add accounts to trigger the search for a resolving intent.
Account[] accounts = new Account[] { new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE) }; Account[] accounts = new Account[] { new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE) };
when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager); when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
@@ -268,10 +353,18 @@ public class MasterClearTest {
resolveInfo.activityInfo = activityInfo; resolveInfo.activityInfo = activityInfo;
when(mPackageManager.resolveActivity(any(), eq(0))).thenReturn(resolveInfo); when(mPackageManager.resolveActivity(any(), eq(0))).thenReturn(resolveInfo);
// Finally mock out the startActivityForResultCall Intent actualIntent = mMasterClear.getAccountConfirmationIntent();
doNothing().when(mMasterClear).startActivityForResult(any(), eq(MasterClear.CREDENTIAL_CONFIRM_REQUEST)); assertEquals(TEST_CONFIRMATION_PACKAGE, actualIntent.getComponent().getPackageName());
assertEquals(TEST_CONFIRMATION_CLASS, actualIntent.getComponent().getClassName());
}
assertThat(mMasterClear.tryShowAccountConfirmation()).isTrue(); public void testShowAccountCredentialConfirmation() {
// Finally mock out the startActivityForResultCall
doNothing().when(mMasterClear)
.startActivityForResult(eq(mMockIntent), eq(MasterClear.CREDENTIAL_CONFIRM_REQUEST));
mMasterClear.showAccountCredentialConfirmation(mMockIntent);
verify(mMasterClear, times(1))
.startActivityForResult(eq(mMockIntent), eq(MasterClear.CREDENTIAL_CONFIRM_REQUEST));
} }
@Test @Test