Remove injecting developer options into Settings itself

- It can improve performance because we use less injected item
- Also use RestrictedPreference instead just checking restrictions,
  so we follow policy transparency.

Note: Renamed DevelopmentSettingsDashboardActivity to
DevelopmentSettingsActivity,
because DevelopmentSettingsDashboardActivity could in disabled state
even after Settings upgrades, use a new name to prevent this issue.

Bug: 311604902
Test: manual - turn on / off Developer Options
Test: unit test
Change-Id: I17be117ae59e59410687e6d08fd5edd034d0508f
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 49b2174..64e3244 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -134,7 +134,7 @@
     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 3b0dd40..27a87f3 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -48,7 +48,6 @@
 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.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 @@
     private CharSequence mInitialTitle;
     private int mInitialTitleResId;
 
-    private BroadcastReceiver mDevelopmentSettingsListener;
-
     private boolean mBatteryPresent = true;
     private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
         @Override
@@ -614,15 +610,6 @@
         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 @@
     @Override
     protected void onPause() {
         super.onPause();
-        LocalBroadcastManager.getInstance(this).unregisterReceiver(mDevelopmentSettingsListener);
-        mDevelopmentSettingsListener = null;
         unregisterReceiver(mBatteryInfoReceiver);
     }
 
@@ -781,13 +766,6 @@
                 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 9c8c186..4c8b2dc 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -47,6 +47,7 @@
 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 @@
             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 9ea24da..0000000
--- 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 0000000..fe7fb4d
--- /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)),
+        )
+    }
+}