diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6240175fbdd..3749692004e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -13151,6 +13151,11 @@
Permissions, account activity, personal data
+
+
+ Controls
+
+
Remove
@@ -13690,8 +13695,10 @@
Camera access
Microphone access
-
- For apps and services
+
+ Location access
+
+ For apps and services
For apps and services. If this setting is off, microphone data may still be shared when you call an emergency number.
diff --git a/res/xml/location_settings_personal.xml b/res/xml/location_settings_personal.xml
index bae1ac16db3..f8b21b98ac6 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">
-
diff --git a/res/xml/location_settings_workprofile.xml b/res/xml/location_settings_workprofile.xml
index 51d8761bc4b..bcac08482b3 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">
-
diff --git a/res/xml/privacy_controls_settings.xml b/res/xml/privacy_controls_settings.xml
new file mode 100644
index 00000000000..a477dc21b8b
--- /dev/null
+++ b/res/xml/privacy_controls_settings.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml
index 7e1d5ced190..0a7cab5af00 100644
--- a/res/xml/privacy_dashboard_settings.xml
+++ b/res/xml/privacy_dashboard_settings.xml
@@ -65,7 +65,7 @@
diff --git a/src/com/android/settings/location/LocationEnabler.java b/src/com/android/settings/location/LocationEnabler.java
index ab59b8eedfa..cbe1c779bc5 100644
--- a/src/com/android/settings/location/LocationEnabler.java
+++ b/src/com/android/settings/location/LocationEnabler.java
@@ -92,7 +92,10 @@ public class LocationEnabler implements LifecycleObserver, OnStart, OnStop {
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 @@ public class LocationEnabler implements LifecycleObserver, OnStart, OnStop {
}
}
- 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 @@ public class LocationEnabler implements LifecycleObserver, OnStart, OnStop {
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 @@ public class LocationEnabler implements LifecycleObserver, OnStart, OnStop {
*
* @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 @@ public class LocationEnabler implements LifecycleObserver, OnStart, OnStop {
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 00000000000..7d388bd3a13
--- /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 00000000000..7b33364c072
--- /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 createPreferenceControllers(Context context) {
+ final List 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;
+ }
+}