diff --git a/res/values/strings.xml b/res/values/strings.xml
index 413dc00d9cc..06163b8e2ef 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9941,6 +9941,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/AppPicker.java b/src/com/android/settings/development/AppPicker.java
index 433f31a23ef..04f318ffa50 100644
--- a/src/com/android/settings/development/AppPicker.java
+++ b/src/com/android/settings/development/AppPicker.java
@@ -45,9 +45,11 @@ public class AppPicker extends ListActivity {
public static final String EXTRA_REQUESTIING_PERMISSION
= "com.android.settings.extra.REQUESTIING_PERMISSION";
public static final String EXTRA_DEBUGGABLE = "com.android.settings.extra.DEBUGGABLE";
+ public static final String EXTRA_NON_SYSTEM = "com.android.settings.extra.NON_SYSTEM";
private String mPermissionName;
private boolean mDebuggableOnly;
+ private boolean mNonSystemOnly;
@Override
protected void onCreate(Bundle icicle) {
@@ -55,6 +57,7 @@ public class AppPicker extends ListActivity {
mPermissionName = getIntent().getStringExtra(EXTRA_REQUESTIING_PERMISSION);
mDebuggableOnly = getIntent().getBooleanExtra(EXTRA_DEBUGGABLE, false);
+ mNonSystemOnly = getIntent().getBooleanExtra(EXTRA_NON_SYSTEM, false);
mAdapter = new AppListAdapter(this);
if (mAdapter.getCount() <= 0) {
@@ -113,6 +116,11 @@ public class AppPicker extends ListActivity {
}
}
+ // Filter out apps that are system apps if requested
+ if (mNonSystemOnly && ai.isSystemApp()) {
+ continue;
+ }
+
// Filter out apps that do not request the permission if required.
if (mPermissionName != null) {
boolean requestsPermission = false;
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));
+ }
+}