From 912c07cf58a6b968b07e71b61939feec812f889a Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Thu, 24 Jan 2019 15:53:32 -0800 Subject: [PATCH] Add a More item for Special app access page. This allows users to toggle non-exclusive roles, such as the temporary SMS access (non-exclusive) role. Bug: 110557011 Test: atest MorePreferenceControllerTest Change-Id: Id9c0338ef2996aaa741c3da8104e867f32050f3a --- res/values/strings.xml | 3 + res/xml/special_access.xml | 5 + ...MoreSpecialAccessPreferenceController.java | 64 +++++++ ...SpecialAccessPreferenceControllerTest.java | 179 ++++++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 src/com/android/settings/applications/specialaccess/MoreSpecialAccessPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/applications/specialaccess/MoreSpecialAccessPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index f77c10d577c..e8c2dad0b08 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -9551,6 +9551,9 @@ %d apps can use unrestricted data + + More + Really wipe user data and convert to file encryption? diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml index cb766935aa1..4417d0ffb43 100644 --- a/res/xml/special_access.xml +++ b/res/xml/special_access.xml @@ -135,4 +135,9 @@ android:title="@string/financial_apps_sms_access_title" android:fragment="com.android.settings.applications.specialaccess.financialapps.FinancialAppsSmsAccess" settings:keywords="@string/keywords_financial_apps_sms_access" /> + + diff --git a/src/com/android/settings/applications/specialaccess/MoreSpecialAccessPreferenceController.java b/src/com/android/settings/applications/specialaccess/MoreSpecialAccessPreferenceController.java new file mode 100644 index 00000000000..10d5c36226a --- /dev/null +++ b/src/com/android/settings/applications/specialaccess/MoreSpecialAccessPreferenceController.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.specialaccess; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.text.TextUtils; + +import androidx.preference.Preference; + +import com.android.settings.core.BasePreferenceController; + +public class MoreSpecialAccessPreferenceController extends BasePreferenceController { + + private final Intent mIntent; + + public MoreSpecialAccessPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + + final PackageManager packageManager = context.getPackageManager(); + final String packageName = packageManager.getPermissionControllerPackageName(); + if (packageName != null) { + Intent intent = new Intent(Intent.ACTION_MANAGE_SPECIAL_APP_ACCESSES) + .setPackage(packageName); + ResolveInfo resolveInfo = packageManager.resolveActivity(intent, + PackageManager.MATCH_DEFAULT_ONLY); + mIntent = resolveInfo != null ? intent : null; + } else { + mIntent = null; + } + } + + @Override + public int getAvailabilityStatus() { + return mIntent != null ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (TextUtils.equals(preference.getKey(), mPreferenceKey)) { + if (mIntent != null) { + mContext.startActivity(mIntent); + } + return true; + } + return false; + } +} diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/MoreSpecialAccessPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/MoreSpecialAccessPreferenceControllerTest.java new file mode 100644 index 00000000000..534fdaf28ba --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/specialaccess/MoreSpecialAccessPreferenceControllerTest.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.specialaccess; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; + +import androidx.preference.Preference; + +import com.android.settings.core.BasePreferenceController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class MoreSpecialAccessPreferenceControllerTest { + + private static final String PREFERENCE_KEY = "more"; + private static final String DIFFERENT_PREFERENCE_KEY = "different"; + + private static final String PERMISSION_CONTROLLER_PACKAGE_NAME = + "com.android.permissioncontroller"; + + @Mock + private Context mContext; + @Mock + private PackageManager mPackageManager; + + @Before + public void setUp() throws PackageManager.NameNotFoundException { + MockitoAnnotations.initMocks(this); + + when(mContext.getPackageManager()).thenReturn(mPackageManager); + } + + @Test + public void constructor_shouldResolveActivityWithPermissionControllerPackageName() { + when(mPackageManager.getPermissionControllerPackageName()).thenReturn( + PERMISSION_CONTROLLER_PACKAGE_NAME); + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + + ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mPackageManager).resolveActivity(intentCaptor.capture(), anyInt()); + final Intent intent = intentCaptor.getValue(); + assertThat(intent.getPackage()).isEqualTo(PERMISSION_CONTROLLER_PACKAGE_NAME); + } + + @Test + public void getAvailabilityStatus_noPermissionController_shouldReturnUnsupportedOnDevice() { + when(mPackageManager.getPermissionControllerPackageName()).thenReturn(null); + MoreSpecialAccessPreferenceController preferenceController = + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + + assertThat(preferenceController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_canNotResolveActivity_shouldReturnUnsupportedOnDevice() { + when(mPackageManager.getPermissionControllerPackageName()).thenReturn( + PERMISSION_CONTROLLER_PACKAGE_NAME); + MoreSpecialAccessPreferenceController preferenceController = + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + + assertThat(preferenceController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_canResolveActivity_shouldReturnAvailableUnsearchable() { + when(mPackageManager.getPermissionControllerPackageName()).thenReturn( + PERMISSION_CONTROLLER_PACKAGE_NAME); + when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn( + new ResolveInfo()); + MoreSpecialAccessPreferenceController preferenceController = + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + + assertThat(preferenceController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.AVAILABLE_UNSEARCHABLE); + } + + @Test + public void handlePreferenceTreeClick_differentKey_shouldReturnFalse() { + when(mPackageManager.getPermissionControllerPackageName()) + .thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME); + MoreSpecialAccessPreferenceController preferenceController = + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + Preference preference = mock(Preference.class); + when(preference.getKey()).thenReturn(DIFFERENT_PREFERENCE_KEY); + + assertThat(preferenceController.handlePreferenceTreeClick(preference)).isFalse(); + } + + @Test + public void handlePreferenceTreeClick_sameKey_shouldReturnTrue() { + when(mPackageManager.getPermissionControllerPackageName()) + .thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME); + MoreSpecialAccessPreferenceController preferenceController = + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + Preference preference = mock(Preference.class); + when(preference.getKey()).thenReturn(PREFERENCE_KEY); + + assertThat(preferenceController.handlePreferenceTreeClick(preference)).isTrue(); + } + + @Test + public void handlePreferenceTreeClick_noPermissionController_shouldNotStartActivity() { + when(mPackageManager.getPermissionControllerPackageName()).thenReturn(null); + MoreSpecialAccessPreferenceController preferenceController = + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + Preference preference = mock(Preference.class); + when(preference.getKey()).thenReturn(PREFERENCE_KEY); + preferenceController.handlePreferenceTreeClick(preference); + + verify(mContext, never()).startActivity(any(Intent.class)); + } + + @Test + public void handlePreferenceTreeClick_canNotResolveActivity_shouldNotStartActivity() { + when(mPackageManager.getPermissionControllerPackageName()).thenReturn( + PERMISSION_CONTROLLER_PACKAGE_NAME); + MoreSpecialAccessPreferenceController preferenceController = + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + Preference preference = mock(Preference.class); + when(preference.getKey()).thenReturn(PREFERENCE_KEY); + preferenceController.handlePreferenceTreeClick(preference); + + verify(mContext, never()).startActivity(any(Intent.class)); + } + + @Test + public void handlePreferenceTreeClick_canResolveActivity_shouldStartActivityWithIntent() { + when(mPackageManager.getPermissionControllerPackageName()) + .thenReturn(PERMISSION_CONTROLLER_PACKAGE_NAME); + when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn( + new ResolveInfo()); + MoreSpecialAccessPreferenceController preferenceController = + new MoreSpecialAccessPreferenceController(mContext, PREFERENCE_KEY); + Preference preference = mock(Preference.class); + when(preference.getKey()).thenReturn(PREFERENCE_KEY); + preferenceController.handlePreferenceTreeClick(preference); + ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); + + verify(mContext).startActivity(intentCaptor.capture()); + final Intent intent = intentCaptor.getValue(); + assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MANAGE_SPECIAL_APP_ACCESSES); + assertThat(intent.getPackage()).isEqualTo(PERMISSION_CONTROLLER_PACKAGE_NAME); + } +}