Merge "Create PrivacyControls page in settings"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a5a5501..7f26c8d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -13045,6 +13045,11 @@
     <!-- Summary for the top level Privacy Settings [CHAR LIMIT=NONE]-->
     <string name="privacy_dashboard_summary">Permissions, account activity, personal data</string>
 
+
+    <!-- Title for the privacy controls page [CHAR LIMIT=30]-->
+    <string name="privacy_controls_title">Controls</string>
+
+
     <!-- Label for button in contextual card for users to remove the card [CHAR LIMIT=30] -->
     <string name="contextual_card_dismiss_remove">Remove</string>
     <!-- Label for button in contextual card for users to keep the card [CHAR LIMIT=30] -->
@@ -13592,8 +13597,10 @@
     <string name="camera_toggle_title">Camera access</string>
     <!-- Label for the camera use toggle [CHAR LIMIT=40] -->
     <string name="mic_toggle_title">Microphone access</string>
-    <!-- Describes what is affected by the camera toggle [CHAR LIMIT=NONE] -->
-    <string name="cam_toggle_description">For apps and services</string>
+    <!-- Label for the location use toggle [CHAR LIMIT=40] -->
+    <string name="location_toggle_title">Location access</string>
+    <!-- Describes what is affected by a permission toggle [CHAR LIMIT=NONE] -->
+    <string name="perm_toggle_description">For apps and services</string>
     <!-- Describes what is affected by the mic toggle [CHAR LIMIT=NONE] -->
     <string name="mic_toggle_description">For apps and services. If this setting is off, microphone data may still be shared when you call an emergency number.</string>
 
diff --git a/res/xml/location_settings_personal.xml b/res/xml/location_settings_personal.xml
index bae1ac1..f8b21b9 100644
--- a/res/xml/location_settings_personal.xml
+++ b/res/xml/location_settings_personal.xml
@@ -42,7 +42,7 @@
         android:title="@string/location_app_level_permissions"
         settings:controller="com.android.settings.location.AppLocationPermissionPreferenceController">
         <intent android:action="android.intent.action.MANAGE_PERMISSION_APPS">
-            <extra android:name="android.intent.extra.PERMISSION_NAME"
+            <extra android:name="android.intent.extra.PERMISSION_GROUP_NAME"
                    android:value="android.permission-group.LOCATION"/>
         </intent>
     </Preference>
diff --git a/res/xml/location_settings_workprofile.xml b/res/xml/location_settings_workprofile.xml
index 51d8761..bcac084 100644
--- a/res/xml/location_settings_workprofile.xml
+++ b/res/xml/location_settings_workprofile.xml
@@ -50,7 +50,7 @@
         android:title="@string/location_app_level_permissions"
         settings:controller="com.android.settings.location.AppLocationPermissionPreferenceController">
         <intent android:action="android.intent.action.MANAGE_PERMISSION_APPS">
-            <extra android:name="android.intent.extra.PERMISSION_NAME"
+            <extra android:name="android.intent.extra.PERMISSION_GROUP_NAME"
                    android:value="android.permission-group.LOCATION"/>
         </intent>
     </Preference>
diff --git a/res/xml/privacy_controls_settings.xml b/res/xml/privacy_controls_settings.xml
new file mode 100644
index 0000000..a477dc2
--- /dev/null
+++ b/res/xml/privacy_controls_settings.xml
@@ -0,0 +1,50 @@
+<!--
+  ~ Copyright (C) 2022 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.
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="privacy_controls_page"
+    android:title="@string/privacy_controls_title">
+
+    <!-- Camera toggle -->
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="privacy_camera_toggle"
+        android:title="@string/camera_toggle_title"
+        android:summary="@string/perm_toggle_description"
+        settings:controller="com.android.settings.privacy.CameraToggleController"/>
+
+    <!-- Microphone toggle -->
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="privacy_mic_toggle"
+        android:title="@string/mic_toggle_title"
+        android:summary="@string/mic_toggle_description"
+        settings:controller="com.android.settings.privacy.MicToggleController"/>
+
+    <!-- Location toggle -->
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="privacy_location_toggle"
+        android:title="@string/location_toggle_title"
+        android:summary="@string/perm_toggle_description"/>
+
+    <!-- Clipboard access notifications -->
+    <SwitchPreference
+        android:key="show_clip_access_notification"
+        android:title="@string/show_clip_access_notification"
+        android:summary="@string/show_clip_access_notification_summary"
+        settings:controller="com.android.settings.privacy.ShowClipAccessNotificationPreferenceController"/>
+
+</PreferenceScreen>
diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml
index 7e1d5ce..0a7cab5 100644
--- a/res/xml/privacy_dashboard_settings.xml
+++ b/res/xml/privacy_dashboard_settings.xml
@@ -65,7 +65,7 @@
     <com.android.settingslib.RestrictedSwitchPreference
         android:key="privacy_camera_toggle"
         android:title="@string/camera_toggle_title"
-        android:summary="@string/cam_toggle_description"
+        android:summary="@string/perm_toggle_description"
         settings:controller="com.android.settings.privacy.CameraToggleController"/>
 
     <!-- Microphone toggle -->
diff --git a/src/com/android/settings/location/LocationEnabler.java b/src/com/android/settings/location/LocationEnabler.java
index ab59b8e..cbe1c77 100644
--- a/src/com/android/settings/location/LocationEnabler.java
+++ b/src/com/android/settings/location/LocationEnabler.java
@@ -92,7 +92,10 @@
         mContext.unregisterReceiver(mReceiver);
     }
 
-    void refreshLocationMode() {
+    /**
+     * Get the current location enable state, and update listeners
+     */
+    public void refreshLocationMode() {
         final int mode = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
         if (Log.isLoggable(TAG, Log.INFO)) {
@@ -103,7 +106,10 @@
         }
     }
 
-    void setLocationEnabled(boolean enabled) {
+    /**
+     * Set the device's location enable state
+     */
+    public void setLocationEnabled(boolean enabled) {
         final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
             Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
 
@@ -123,7 +129,10 @@
         refreshLocationMode();
     }
 
-    boolean isEnabled(int mode) {
+    /**
+     * Checks if location is enabled, based on mode and restrictions.
+     */
+    public boolean isEnabled(int mode) {
         return mode != Settings.Secure.LOCATION_MODE_OFF && !isRestricted();
     }
 
@@ -132,13 +141,16 @@
      *
      * @return true if device policy has put a location access lock-down on the managed profile
      */
-    boolean isManagedProfileRestrictedByBase() {
+    public boolean isManagedProfileRestrictedByBase() {
         final UserHandle managedProfile = Utils.getManagedProfile(mUserManager);
         return managedProfile != null
                 && hasShareLocationRestriction(managedProfile.getIdentifier());
     }
 
-    RestrictedLockUtils.EnforcedAdmin getShareLocationEnforcedAdmin(int userId) {
+    /**
+     * Gets the admin enforcement for location for the current user
+     */
+    public RestrictedLockUtils.EnforcedAdmin getShareLocationEnforcedAdmin(int userId) {
         RestrictedLockUtils.EnforcedAdmin admin =  checkIfRestrictionEnforced(
                 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId);
 
@@ -149,7 +161,10 @@
         return admin;
     }
 
-    boolean hasShareLocationRestriction(int userId) {
+    /**
+     * Check if the current user has a location restriction
+     */
+    public boolean hasShareLocationRestriction(int userId) {
         return RestrictedLockUtilsInternal.hasBaseUserRestriction(
                 mContext, UserManager.DISALLOW_SHARE_LOCATION, userId);
     }
diff --git a/src/com/android/settings/privacy/LocationToggleController.java b/src/com/android/settings/privacy/LocationToggleController.java
new file mode 100644
index 0000000..7d388bd
--- /dev/null
+++ b/src/com/android/settings/privacy/LocationToggleController.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 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.privacy;
+
+import android.content.Context;
+import android.os.UserHandle;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.location.LocationEnabler;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+/**
+ * Controller for location toggle
+ */
+public class LocationToggleController extends TogglePreferenceController
+        implements LocationEnabler.LocationModeChangeListener {
+
+    private final LocationEnabler mLocationEnabler;
+    private RestrictedSwitchPreference mPreference;
+
+    private boolean mIsLocationEnabled = true;
+
+    public LocationToggleController(Context context, String preferenceKey, Lifecycle lifecycle) {
+        super(context, preferenceKey);
+        mLocationEnabler = new LocationEnabler(context, this, lifecycle);
+        mLocationEnabler.refreshLocationMode();
+    }
+    @Override
+    public void onLocationModeChanged(int mode, boolean restricted) {
+        if (mPreference == null) {
+            return;
+        }
+
+        mIsLocationEnabled = mLocationEnabler.isEnabled(mode);
+        final int userId = UserHandle.myUserId();
+        final RestrictedLockUtils.EnforcedAdmin admin =
+                mLocationEnabler.getShareLocationEnforcedAdmin(userId);
+        final boolean hasBaseUserRestriction =
+                mLocationEnabler.hasShareLocationRestriction(userId);
+        // Disable the whole switch bar instead of the switch itself. If we disabled the switch
+        // only, it would be re-enabled again if the switch bar is not disabled.
+        if (!hasBaseUserRestriction && admin != null) {
+            mPreference.setDisabledByAdmin(admin);
+        } else {
+            mPreference.setEnabled(!restricted);
+        }
+        updateState(mPreference);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return mIsLocationEnabled;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        mLocationEnabler.setLocationEnabled(isChecked);
+        return true;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+        mLocationEnabler.refreshLocationMode();
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return 0;
+    }
+}
diff --git a/src/com/android/settings/privacy/PrivacyControlsFragment.java b/src/com/android/settings/privacy/PrivacyControlsFragment.java
new file mode 100644
index 0000000..7b33364
--- /dev/null
+++ b/src/com/android/settings/privacy/PrivacyControlsFragment.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2022 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.privacy;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fragment that shows several privacy toggle controls
+ */
+public class PrivacyControlsFragment extends DashboardFragment {
+    private static final String TAG = "PrivacyDashboardFrag";
+    private static final String CAMERA_KEY = "privacy_camera_toggle";
+    private static final String MIC_KEY = "privacy_mic_toggle";
+    private static final String LOCATION_KEY = "privacy_location_toggle";
+
+    @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        final List<AbstractPreferenceController> controllers = new ArrayList<>();
+        controllers.add(new CameraToggleController(context, CAMERA_KEY));
+        controllers.add(new MicToggleController(context, MIC_KEY));
+        controllers.add(new LocationToggleController(context, LOCATION_KEY,
+                getSettingsLifecycle()));
+        controllers.add(new ShowClipAccessNotificationPreferenceController(context));
+        return controllers;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.TOP_LEVEL_PRIVACY;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.privacy_controls_settings;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+}