diff --git a/src/com/android/settings/password/PasswordUtils.java b/src/com/android/settings/password/PasswordUtils.java index 2300b980a6a..1ead492788c 100644 --- a/src/com/android/settings/password/PasswordUtils.java +++ b/src/com/android/settings/password/PasswordUtils.java @@ -68,7 +68,7 @@ public final class PasswordUtils extends com.android.settingslib.Utils { * Returns the package name which the activity with {@code activityToken} is launched from. */ @Nullable - private static String getCallingAppPackageName(IBinder activityToken) { + public static String getCallingAppPackageName(IBinder activityToken) { String pkg = null; try { pkg = ActivityManager.getService().getLaunchedFromPackage(activityToken); diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java index 8ea85144ea7..8e8e7bc35f8 100644 --- a/src/com/android/settings/password/SetNewPasswordActivity.java +++ b/src/com/android/settings/password/SetNewPasswordActivity.java @@ -29,12 +29,15 @@ import android.app.Activity; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager.PasswordComplexity; import android.app.admin.PasswordMetrics; +import android.app.settings.SettingsEnums; import android.content.Intent; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import com.android.settings.Utils; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; /** * Trampolines {@link DevicePolicyManager#ACTION_SET_NEW_PASSWORD} and @@ -73,19 +76,23 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo return; } - IBinder activityToken = getActivityToken(); + logSetNewPasswordIntent(); + + final IBinder activityToken = getActivityToken(); mCallerAppName = (String) PasswordUtils.getCallingAppLabel(this, activityToken); if (ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction) && getIntent().hasExtra(EXTRA_PASSWORD_COMPLEXITY)) { - boolean hasPermission = PasswordUtils.isCallingAppPermitted( + final boolean hasPermission = PasswordUtils.isCallingAppPermitted( this, activityToken, GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY); if (hasPermission) { - mRequestedMinComplexity = PasswordMetrics.sanitizeComplexityLevel(getIntent() - .getIntExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)); + mRequestedMinComplexity = + PasswordMetrics.sanitizeComplexityLevel(getIntent() + .getIntExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE)); } else { PasswordUtils.crashCallingApplication(activityToken, - "Must have permission " + GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY - + " to use extra " + EXTRA_PASSWORD_COMPLEXITY); + "Must have permission " + + GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY + " to use extra " + + EXTRA_PASSWORD_COMPLEXITY); finish(); return; } @@ -112,4 +119,29 @@ public class SetNewPasswordActivity extends Activity implements SetNewPasswordCo startActivity(intent); finish(); } + + private void logSetNewPasswordIntent() { + final String callingAppPackageName = + PasswordUtils.getCallingAppPackageName(getActivityToken()); + + // use int min value to denote absence of EXTRA_PASSWORD_COMPLEXITY + final int extraPasswordComplexity = getIntent().hasExtra(EXTRA_PASSWORD_COMPLEXITY) + ? getIntent().getIntExtra(EXTRA_PASSWORD_COMPLEXITY, PASSWORD_COMPLEXITY_NONE) + : Integer.MIN_VALUE; + + // this activity is launched by either ACTION_SET_NEW_PASSWORD or + // ACTION_SET_NEW_PARENT_PROFILE_PASSWORD + final int action = ACTION_SET_NEW_PASSWORD.equals(mNewPasswordAction) + ? SettingsEnums.ACTION_SET_NEW_PASSWORD + : SettingsEnums.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD; + + final MetricsFeatureProvider metricsProvider = + FeatureFactory.getFactory(this).getMetricsFeatureProvider(); + metricsProvider.action( + metricsProvider.getAttribution(this), + action, + SettingsEnums.SET_NEW_PASSWORD_ACTIVITY, + callingAppPackageName, + extraPasswordComplexity); + } } diff --git a/tests/robotests/src/com/android/settings/password/PasswordUtilsTest.java b/tests/robotests/src/com/android/settings/password/PasswordUtilsTest.java index 845d346da8f..dc473b28abe 100644 --- a/tests/robotests/src/com/android/settings/password/PasswordUtilsTest.java +++ b/tests/robotests/src/com/android/settings/password/PasswordUtilsTest.java @@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static com.android.settings.password.PasswordUtils.getCallingAppLabel; +import static com.android.settings.password.PasswordUtils.getCallingAppPackageName; import static com.android.settings.password.PasswordUtils.isCallingAppPermitted; import static com.google.common.truth.Truth.assertThat; @@ -77,7 +78,7 @@ public class PasswordUtilsTest { } @Test - public void getCallingAppLabel_activityServiceThrowsRemoteException_returnsNull() + public void getCallingAppLabel_getCallingAppPackageNameReturnsNull_returnsNull() throws Exception { when(mActivityService.getLaunchedFromPackage(mActivityToken)) .thenThrow(new RemoteException()); @@ -86,7 +87,7 @@ public class PasswordUtilsTest { } @Test - public void getCallingAppLabel_activityServiceReturnsSettingsApp_returnsNull() + public void getCallingAppLabel_getCallingAppPackageNameReturnsSettingsApp_returnsNull() throws Exception { when(mActivityService.getLaunchedFromPackage(mActivityToken)) .thenReturn("com.android.settings"); @@ -115,6 +116,23 @@ public class PasswordUtilsTest { assertThat(getCallingAppLabel(mContext, mActivityToken)).isEqualTo("label"); } + @Test + public void getCallingAppPackageName_activityServiceThrowsRemoteException_returnsNull() + throws Exception { + when(mActivityService.getLaunchedFromPackage(mActivityToken)) + .thenThrow(new RemoteException()); + + assertThat(getCallingAppPackageName(mActivityToken)).isNull(); + } + + @Test + public void getCallingAppPackageName_returnsPackageName() throws Exception { + when(mActivityService.getLaunchedFromPackage(mActivityToken)) + .thenReturn(PACKAGE_NAME); + + assertThat(getCallingAppPackageName(mActivityToken)).isEqualTo(PACKAGE_NAME); + } + @Test public void isCallingAppPermitted_permissionGranted_returnsTrue() throws Exception { when(mActivityService.getLaunchedFromUid(mActivityToken)).thenReturn(UID); diff --git a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java index d1b2b74b3c3..42320168555 100644 --- a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java +++ b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java @@ -28,17 +28,26 @@ import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_R import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.settings.SettingsEnums; import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; import android.provider.Settings; +import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowPasswordUtils; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @@ -50,11 +59,19 @@ import org.robolectric.shadows.ShadowActivity; public class SetNewPasswordActivityTest { private static final String APP_LABEL = "label"; + private static final String PKG_NAME = "packageName"; + @Mock + private MetricsFeatureProvider mockMetricsProvider; private int mProvisioned; @Before public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest(); + mockMetricsProvider = fakeFeatureFactory.getMetricsFeatureProvider(); + when(mockMetricsProvider.getAttribution(any())).thenReturn(SettingsEnums.PAGE_UNKNOWN); + mProvisioned = Settings.Global.getInt(RuntimeEnvironment.application.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0); } @@ -98,6 +115,7 @@ public class SetNewPasswordActivityTest { @Config(shadows = {ShadowPasswordUtils.class}) public void testLaunchChooseLock_setNewPasswordExtraWithoutPermission() { ShadowPasswordUtils.setCallingAppLabel(APP_LABEL); + ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME); Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1); @@ -108,12 +126,19 @@ public class SetNewPasswordActivityTest { ShadowActivity shadowActivity = Shadows.shadowOf(activity); assertThat(shadowActivity.getNextStartedActivityForResult()).isNull(); + verify(mockMetricsProvider).action( + SettingsEnums.PAGE_UNKNOWN, + SettingsEnums.ACTION_SET_NEW_PASSWORD, + SettingsEnums.SET_NEW_PASSWORD_ACTIVITY, + PKG_NAME, + PASSWORD_COMPLEXITY_HIGH); } @Test @Config(shadows = {ShadowPasswordUtils.class}) public void testLaunchChooseLock_setNewPasswordExtraWithPermission() { ShadowPasswordUtils.setCallingAppLabel(APP_LABEL); + ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME); ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY); Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1); @@ -131,12 +156,19 @@ public class SetNewPasswordActivityTest { .isEqualTo(PASSWORD_COMPLEXITY_HIGH); assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL); + verify(mockMetricsProvider).action( + SettingsEnums.PAGE_UNKNOWN, + SettingsEnums.ACTION_SET_NEW_PASSWORD, + SettingsEnums.SET_NEW_PASSWORD_ACTIVITY, + PKG_NAME, + PASSWORD_COMPLEXITY_HIGH); } @Test @Config(shadows = {ShadowPasswordUtils.class}) public void testLaunchChooseLock_setNewPasswordExtraInvalidValue() { ShadowPasswordUtils.setCallingAppLabel(APP_LABEL); + ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME); ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY); Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1); @@ -152,12 +184,19 @@ public class SetNewPasswordActivityTest { assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse(); assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL); + verify(mockMetricsProvider).action( + SettingsEnums.PAGE_UNKNOWN, + SettingsEnums.ACTION_SET_NEW_PASSWORD, + SettingsEnums.SET_NEW_PASSWORD_ACTIVITY, + PKG_NAME, + -1); } @Test @Config(shadows = {ShadowPasswordUtils.class}) public void testLaunchChooseLock_setNewPasswordExtraNoneComplexity() { ShadowPasswordUtils.setCallingAppLabel(APP_LABEL); + ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME); ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY); Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1); @@ -173,12 +212,46 @@ public class SetNewPasswordActivityTest { assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse(); assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL); + verify(mockMetricsProvider).action( + SettingsEnums.PAGE_UNKNOWN, + SettingsEnums.ACTION_SET_NEW_PASSWORD, + SettingsEnums.SET_NEW_PASSWORD_ACTIVITY, + PKG_NAME, + PASSWORD_COMPLEXITY_NONE); + } + + @Test + @Config(shadows = {ShadowPasswordUtils.class}) + public void testLaunchChooseLock_setNewPasswordWithoutExtra() { + ShadowPasswordUtils.setCallingAppLabel(APP_LABEL); + ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME); + ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY); + Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 1); + + Intent intent = new Intent(ACTION_SET_NEW_PASSWORD); + SetNewPasswordActivity activity = + Robolectric.buildActivity(SetNewPasswordActivity.class, intent).create().get(); + + ShadowActivity shadowActivity = Shadows.shadowOf(activity); + Intent actualIntent = shadowActivity.getNextStartedActivityForResult().intent; + assertThat(actualIntent.getAction()).isEqualTo(ACTION_SET_NEW_PASSWORD); + assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse(); + assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); + assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL); + verify(mockMetricsProvider).action( + SettingsEnums.PAGE_UNKNOWN, + SettingsEnums.ACTION_SET_NEW_PASSWORD, + SettingsEnums.SET_NEW_PASSWORD_ACTIVITY, + PKG_NAME, + Integer.MIN_VALUE); } @Test @Config(shadows = {ShadowPasswordUtils.class}) public void testLaunchChooseLock_setNewParentProfilePasswordExtraWithPermission() { ShadowPasswordUtils.setCallingAppLabel(APP_LABEL); + ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME); ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY); Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1); @@ -194,5 +267,38 @@ public class SetNewPasswordActivityTest { assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse(); assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL); + verify(mockMetricsProvider).action( + SettingsEnums.PAGE_UNKNOWN, + SettingsEnums.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD, + SettingsEnums.SET_NEW_PASSWORD_ACTIVITY, + PKG_NAME, + PASSWORD_COMPLEXITY_HIGH); + } + + @Test + @Config(shadows = {ShadowPasswordUtils.class}) + public void testLaunchChooseLock_setNewParentProfilePasswordWithoutExtra() { + ShadowPasswordUtils.setCallingAppLabel(APP_LABEL); + ShadowPasswordUtils.setCallingAppPackageName(PKG_NAME); + ShadowPasswordUtils.addGrantedPermission(GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY); + Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 1); + + Intent intent = new Intent(ACTION_SET_NEW_PARENT_PROFILE_PASSWORD); + SetNewPasswordActivity activity = + Robolectric.buildActivity(SetNewPasswordActivity.class, intent).create().get(); + + ShadowActivity shadowActivity = Shadows.shadowOf(activity); + Intent actualIntent = shadowActivity.getNextStartedActivityForResult().intent; + assertThat(actualIntent.getAction()).isEqualTo(ACTION_SET_NEW_PARENT_PROFILE_PASSWORD); + assertThat(actualIntent.hasExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY)).isFalse(); + assertThat(actualIntent.hasExtra(EXTRA_KEY_CALLER_APP_NAME)).isTrue(); + assertThat(actualIntent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME)).isEqualTo(APP_LABEL); + verify(mockMetricsProvider).action( + SettingsEnums.PAGE_UNKNOWN, + SettingsEnums.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD, + SettingsEnums.SET_NEW_PASSWORD_ACTIVITY, + PKG_NAME, + Integer.MIN_VALUE); } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPasswordUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPasswordUtils.java index 6a5c4ae7c57..ee5fb21832c 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPasswordUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPasswordUtils.java @@ -32,11 +32,13 @@ import java.util.Set; public class ShadowPasswordUtils { private static String sCallingAppLabel; + private static String sCallingAppPackageName; private static Set sGrantedPermissions; public static void reset() { sCallingAppLabel = null; sGrantedPermissions = null; + sCallingAppPackageName = null; } @Implementation @@ -63,4 +65,13 @@ public class ShadowPasswordUtils { public static void setCallingAppLabel(String label) { sCallingAppLabel = label; } + + @Implementation + protected static String getCallingAppPackageName(IBinder activityToken) { + return sCallingAppPackageName; + } + + public static void setCallingAppPackageName(String packageName) { + sCallingAppPackageName = packageName; + } }