From 02a98a64b733ca90cca256105a3a4e126e236f94 Mon Sep 17 00:00:00 2001 From: Cody Northrop Date: Tue, 19 Jun 2018 09:18:04 -0600 Subject: [PATCH] Add ANGLE enable to Developer Options Allows selecting a single app to use ANGLE instead of native drivers via Developer Options. Only non-system apps will be listed via this interface. Bug: 80239516 Test: make ROBOTEST_FILTER=AngleEnabledAppPreferenceControllerTest RunSettingsRoboTests Change-Id: Iddf800cdc1a2607757ee165c456357e041c47ce5 (cherry picked from commit a3ed8214bf5903e4dea8df5f3516a95d81d8c485) --- res/values/strings.xml | 7 + res/xml/development_settings.xml | 3 + .../AngleEnabledAppPreferenceController.java | 119 +++++++++++++++ ...evelopmentOptionsActivityRequestCodes.java | 2 + .../DevelopmentSettingsDashboardFragment.java | 1 + ...gleEnabledAppPreferenceControllerTest.java | 138 ++++++++++++++++++ 6 files changed, 270 insertions(+) create mode 100644 src/com/android/settings/development/AngleEnabledAppPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 0c3caf6f21f..ab6ae931e3b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -9935,6 +9935,13 @@ Show dialog every time an app crashes + + Select ANGLE enabled app + + No ANGLE enabled application set + + ANGLE enabled application: %1$s + Directory access diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml index 5b6d215f772..5a36463016c 100644 --- a/res/xml/development_settings.xml +++ b/res/xml/development_settings.xml @@ -424,6 +424,9 @@ android:summary="%s" android:title="@string/simulate_color_space" /> + + 0) { + mPreference.setSummary(mContext.getResources().getString( + R.string.angle_enabled_app_set, + getAppLabel(angleEnabledApp))); + } else { + mPreference.setSummary(mContext.getResources().getString( + R.string.angle_enabled_app_not_set)); + } + } + + private String getAppLabel(String angleEnabledApp) { + try { + final ApplicationInfo ai = mPackageManager.getApplicationInfo(angleEnabledApp, + PackageManager.GET_DISABLED_COMPONENTS); + final CharSequence lab = mPackageManager.getApplicationLabel(ai); + return lab != null ? lab.toString() : angleEnabledApp; + } catch (PackageManager.NameNotFoundException e) { + return angleEnabledApp; + } + } +} diff --git a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java index b7b27591df9..6e3ec9323c5 100644 --- a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java +++ b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java @@ -25,4 +25,6 @@ public interface DevelopmentOptionsActivityRequestCodes { int REQUEST_CODE_DEBUG_APP = 1; int REQUEST_MOCK_LOCATION_APP = 2; + + int REQUEST_CODE_ANGLE_ENABLED_APP = 3; } diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index 873cec4bf99..cc8bd2e0918 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -405,6 +405,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra controllers.add(new SelectDebugAppPreferenceController(context, fragment)); controllers.add(new WaitForDebuggerPreferenceController(context)); controllers.add(new EnableGpuDebugLayersPreferenceController(context)); + controllers.add(new AngleEnabledAppPreferenceController(context, fragment)); controllers.add(new VerifyAppsOverUsbPreferenceController(context)); controllers.add(new LogdSizePreferenceController(context)); controllers.add(new LogPersistPreferenceController(context, fragment, lifecycle)); diff --git a/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java new file mode 100644 index 00000000000..03837c2c143 --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2018 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.development; + +import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_CODE_ANGLE_ENABLED_APP; +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.provider.Settings; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.util.ReflectionHelpers; + +@RunWith(SettingsRobolectricTestRunner.class) +public class AngleEnabledAppPreferenceControllerTest { + + @Mock + private Preference mPreference; + @Mock + private PreferenceScreen mPreferenceScreen; + @Mock + private DevelopmentSettingsDashboardFragment mFragment; + @Mock + private PackageManager mPackageManager; + + private Context mContext; + private AngleEnabledAppPreferenceController mController; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + mController = spy(new AngleEnabledAppPreferenceController(mContext, mFragment)); + ReflectionHelpers + .setField(mController, "mPackageManager" /* field name */, mPackageManager); + when(mPreferenceScreen.findPreference(mController.getPreferenceKey())) + .thenReturn(mPreference); + mController.displayPreference(mPreferenceScreen); + } + + @Test + public void handlePreferenceTreeClick_preferenceClicked_launchActivity() { + final Intent activityStartIntent = new Intent(mContext, AppPicker.class); + final String preferenceKey = mController.getPreferenceKey(); + doReturn(activityStartIntent).when(mController).getActivityStartIntent(); + when(mPreference.getKey()).thenReturn(preferenceKey); + mController.handlePreferenceTreeClick(mPreference); + + verify(mFragment).startActivityForResult(activityStartIntent, + REQUEST_CODE_ANGLE_ENABLED_APP); + } + + @Test + public void updateState_foobarAppSelected_shouldUpdateSummaryWithAngleEnabledAppLabel() { + final String angleEnabledApp = "foobar"; + final ContentResolver contentResolver = mContext.getContentResolver(); + Settings.Global.putString(contentResolver, Settings.Global.ANGLE_ENABLED_APP, + angleEnabledApp); + mController.updateState(mPreference); + + verify(mPreference).setSummary( + mContext.getString(R.string.angle_enabled_app_set, angleEnabledApp)); + } + + @Test + public void updateState_noAppSelected_shouldUpdateSummaryWithNoAppSelected() { + final String angleEnabledApp = null; + final ContentResolver contentResolver = mContext.getContentResolver(); + Settings.Global.putString(contentResolver, Settings.Global.ANGLE_ENABLED_APP, + angleEnabledApp); + mController.updateState(mPreference); + + verify(mPreference).setSummary( + mContext.getString(R.string.angle_enabled_app_not_set)); + } + + @Test + public void onActivityResult_foobarAppSelected_shouldUpdateSummaryWithAngleEnabledLabel() { + Intent activityResultIntent = new Intent(mContext, AppPicker.class); + final String appLabel = "foobar"; + activityResultIntent.setAction(appLabel); + final boolean result = mController + .onActivityResult(REQUEST_CODE_ANGLE_ENABLED_APP, Activity.RESULT_OK, + activityResultIntent); + + assertThat(result).isTrue(); + verify(mPreference).setSummary( + mContext.getString(R.string.angle_enabled_app_set, appLabel)); + } + + @Test + public void onActivityResult_badRequestCode_shouldReturnFalse() { + assertThat(mController.onActivityResult( + -1 /* requestCode */, -1 /* resultCode */, null /* intent */)).isFalse(); + } + + @Test + public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() { + mController.onDeveloperOptionsSwitchDisabled(); + + assertThat(mPreference.isEnabled()).isFalse(); + verify(mPreference).setSummary( + mContext.getString(R.string.angle_enabled_app_not_set)); + } +}