diff options
9 files changed, 177 insertions, 128 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1e46fdfe170..8ec5b3d405b 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2864,11 +2864,10 @@ </activity> <activity - android:name="Settings$DevelopmentSettingsDashboardActivity" + android:name="Settings$DevelopmentSettingsActivity" android:label="@string/development_settings_title" android:icon="@drawable/ic_settings_development" - android:exported="true" - android:enabled="false"> + android:exported="true"> <intent-filter android:priority="1"> <action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" /> <action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" /> @@ -2879,35 +2878,8 @@ <action android:name="com.android.settings.action.SETTINGS" /> <action android:name="com.android.intent.action.SHOW_CONTRAST_DIALOG" /> </intent-filter> - <meta-data android:name="com.android.settings.order" android:value="-40"/> - <meta-data android:name="com.android.settings.category" - android:value="com.android.settings.category.ia.system" /> - <meta-data android:name="com.android.settings.summary" - android:resource="@string/summary_empty"/> - <meta-data android:name="com.android.settings.icon" - android:resource="@drawable/ic_settings_development" /> <meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.development.DevelopmentSettingsDashboardFragment" /> - <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY" - android:value="@string/menu_key_system"/> - <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" - android:value="true" /> - </activity> - - <!-- The opposite of DevelopmentSettingsActivity, it's no-op and only enabled when the real - activity is disabled to be CTS compliant. --> - <activity - android:name=".development.DevelopmentSettingsDisabledActivity" - android:icon="@drawable/ic_settings_development" - android:label="@string/development_settings_title" - android:excludeFromRecents="true" - android:exported="true" - android:theme="@style/Transparent"> - <intent-filter android:priority="-1"> - <action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" /> - <action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> </activity> <activity diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml index 54dc19565a0..a2cb8fac541 100644 --- a/res/xml/system_dashboard_fragment.xml +++ b/res/xml/system_dashboard_fragment.xml @@ -100,6 +100,11 @@ android:fragment="com.android.settings.users.UserSettings" settings:controller="com.android.settings.users.MultiUserPreferenceController"/> + <com.android.settings.spa.preference.ComposePreference + android:key="developer_options" + android:order="-40" + settings:controller="com.android.settings.system.DeveloperOptionsController"/> + <Preference android:key="reset_dashboard" android:title="@string/reset_dashboard_title" diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 49b21747572..64e3244a910 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -134,7 +134,7 @@ public class Settings extends SettingsActivity { public static class HighPowerApplicationsActivity extends SettingsActivity { /* empty */ } public static class BackgroundCheckSummaryActivity extends SettingsActivity { /* empty */ } public static class StorageUseActivity extends SettingsActivity { /* empty */ } - public static class DevelopmentSettingsDashboardActivity extends SettingsActivity { /* empty */ } + public static class DevelopmentSettingsActivity extends SettingsActivity { /* empty */ } public static class AccessibilitySettingsActivity extends SettingsActivity { /* empty */ } public static class AccessibilityDetailsSettingsActivity extends SettingsActivity { /* empty */ } public static class CaptioningSettingsActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 3b0dd407506..27a87f3b4e2 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -48,7 +48,6 @@ import androidx.annotation.VisibleForTesting; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; @@ -70,7 +69,6 @@ import com.android.settings.wfd.WifiDisplaySettings; import com.android.settings.widget.SettingsMainSwitchBar; import com.android.settingslib.core.instrumentation.Instrumentable; import com.android.settingslib.core.instrumentation.SharedPreferencesLogger; -import com.android.settingslib.development.DevelopmentSettingsEnabler; import com.android.settingslib.drawer.DashboardCategory; import com.google.android.setupcompat.util.WizardManagerHelper; @@ -174,8 +172,6 @@ public class SettingsActivity extends SettingsBaseActivity private CharSequence mInitialTitle; private int mInitialTitleResId; - private BroadcastReceiver mDevelopmentSettingsListener; - private boolean mBatteryPresent = true; private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() { @Override @@ -614,15 +610,6 @@ public class SettingsActivity extends SettingsBaseActivity super.onResume(); setActionBarStatus(); - mDevelopmentSettingsListener = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - updateTilesList(); - } - }; - LocalBroadcastManager.getInstance(this).registerReceiver(mDevelopmentSettingsListener, - new IntentFilter(DevelopmentSettingsEnabler.DEVELOPMENT_SETTINGS_CHANGED_ACTION)); - registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); updateTilesList(); @@ -631,8 +618,6 @@ public class SettingsActivity extends SettingsBaseActivity @Override protected void onPause() { super.onPause(); - LocalBroadcastManager.getInstance(this).unregisterReceiver(mDevelopmentSettingsListener); - mDevelopmentSettingsListener = null; unregisterReceiver(mBatteryInfoReceiver); } @@ -781,13 +766,6 @@ public class SettingsActivity extends SettingsBaseActivity Utils.isBandwidthControlEnabled(), isAdmin) || somethingChanged; - final boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this) - && !Utils.isMonkeyRunning(); - somethingChanged = setTileEnabled(changedList, new ComponentName(packageName, - Settings.DevelopmentSettingsDashboardActivity.class.getName()), - showDev, isAdmin) - || somethingChanged; - somethingChanged = setTileEnabled(changedList, new ComponentName(packageName, Settings.WifiDisplaySettingsActivity.class.getName()), WifiDisplaySettings.isAvailable(this), isAdmin) diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index 9c8c186675b..4c8b2dce167 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -47,6 +47,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.Toast; import androidx.annotation.VisibleForTesting; import androidx.localbroadcastmanager.content.LocalBroadcastManager; @@ -230,6 +231,12 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra getActivity().finish(); return; } + Context context = requireContext(); + if (!DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context)) { + Toast.makeText(context, R.string.dev_settings_disabled_warning, Toast.LENGTH_SHORT) + .show(); + finish(); + } } @Override diff --git a/src/com/android/settings/development/DevelopmentSettingsDisabledActivity.java b/src/com/android/settings/development/DevelopmentSettingsDisabledActivity.java deleted file mode 100644 index 9ea24da2ce9..00000000000 --- a/src/com/android/settings/development/DevelopmentSettingsDisabledActivity.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2017 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 android.app.Activity; -import android.os.Bundle; -import android.widget.Toast; - -import com.android.settings.R; - -public class DevelopmentSettingsDisabledActivity extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Toast.makeText(this, R.string.dev_settings_disabled_warning, Toast.LENGTH_SHORT).show(); - finish(); - } -} diff --git a/src/com/android/settings/system/DeveloperOptionsController.kt b/src/com/android/settings/system/DeveloperOptionsController.kt new file mode 100644 index 00000000000..fe7fb4d43ae --- /dev/null +++ b/src/com/android/settings/system/DeveloperOptionsController.kt @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 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.system + +import android.app.settings.SettingsEnums +import android.content.Context +import android.os.Build +import android.os.UserManager +import android.provider.Settings +import androidx.annotation.VisibleForTesting +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.android.settings.R +import com.android.settings.core.SubSettingLauncher +import com.android.settings.development.DevelopmentSettingsDashboardFragment +import com.android.settings.spa.preference.ComposePreferenceController +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spa.widget.ui.SettingsIcon +import com.android.settingslib.spaprivileged.model.enterprise.Restrictions +import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBooleanFlow +import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference + +class DeveloperOptionsController(context: Context, preferenceKey: String) : + ComposePreferenceController(context, preferenceKey) { + + override fun getAvailabilityStatus() = AVAILABLE + + private val isDevelopmentSettingsEnabledFlow = context.settingsGlobalBooleanFlow( + name = Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, + defaultValue = Build.IS_ENG, + ) + + @Composable + override fun Content() { + val isDevelopmentSettingsEnabled by isDevelopmentSettingsEnabledFlow + .collectAsStateWithLifecycle(initialValue = false) + if (isDevelopmentSettingsEnabled) { + DeveloperOptionsPreference() + } + } + + @VisibleForTesting + @Composable + fun DeveloperOptionsPreference() { + RestrictedPreference( + model = object : PreferenceModel { + override val title = + stringResource(com.android.settingslib.R.string.development_settings_title) + override val icon = @Composable { + SettingsIcon(ImageVector.vectorResource(R.drawable.ic_settings_development)) + } + override val onClick = { + SubSettingLauncher(mContext).apply { + setDestination(DevelopmentSettingsDashboardFragment::class.qualifiedName) + setSourceMetricsCategory(SettingsEnums.SETTINGS_SYSTEM_CATEGORY) + }.launch() + } + }, + restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_DEBUGGING_FEATURES)), + ) + } +} diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDisabledActivityTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDisabledActivityTest.java deleted file mode 100644 index 6b4068d1d8c..00000000000 --- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDisabledActivityTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2017 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.google.common.truth.Truth.assertThat; - -import android.content.Context; - -import com.android.settings.R; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.Robolectric; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.shadows.ShadowToast; - -@RunWith(RobolectricTestRunner.class) -public class DevelopmentSettingsDisabledActivityTest { - - @Test - public void launchActivity_shouldShowToast() { - Robolectric.setupActivity(DevelopmentSettingsDisabledActivity.class); - - final Context context = RuntimeEnvironment.application; - assertThat(ShadowToast.getTextOfLatestToast()) - .isEqualTo(context.getString(R.string.dev_settings_disabled_warning)); - } -} diff --git a/tests/spa_unit/src/com/android/settings/system/DeveloperOptionsControllerTest.kt b/tests/spa_unit/src/com/android/settings/system/DeveloperOptionsControllerTest.kt new file mode 100644 index 00000000000..8707065a9f6 --- /dev/null +++ b/tests/spa_unit/src/com/android/settings/system/DeveloperOptionsControllerTest.kt @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2023 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.system + +import android.content.Context +import android.content.Intent +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.SettingsActivity +import com.android.settings.development.DevelopmentSettingsDashboardFragment +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.any +import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.doNothing +import org.mockito.kotlin.spy +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +@RunWith(AndroidJUnit4::class) +class DeveloperOptionsControllerTest { + @get:Rule + val composeTestRule = createComposeRule() + + private val context: Context = spy(ApplicationProvider.getApplicationContext()) { + doNothing().whenever(mock).startActivity(any()) + } + + private val controller = DeveloperOptionsController(context, TEST_KEY) + + @Test + fun title_isDisplayed() { + composeTestRule.setContent { + controller.DeveloperOptionsPreference() + } + + composeTestRule.onNodeWithText( + context.getString(com.android.settingslib.R.string.development_settings_title) + ).assertIsDisplayed() + } + + @Test + fun onClick_launchDevelopmentSettingsDashboardFragment() { + composeTestRule.setContent { + controller.DeveloperOptionsPreference() + } + + composeTestRule.onNodeWithText( + context.getString(com.android.settingslib.R.string.development_settings_title) + ).performClick() + + val intent = argumentCaptor<Intent> { + verify(context).startActivity(capture()) + }.firstValue + assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) + .isEqualTo(DevelopmentSettingsDashboardFragment::class.qualifiedName) + } + + private companion object { + const val TEST_KEY = "test_key" + } +} |