From 232962c3f2cc4f397cf6b65b0b6b8c93f13b0b42 Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Thu, 13 Jan 2022 12:03:39 -0800 Subject: [PATCH] Create PrivacyControls page in settings Current strings are WIP, no entry point. Also updates a few remaining EXTRA_PERMISSION lines to EXTRA_PERMISSION_GROUP Test: build Bug: 194816787 Change-Id: I347b3011e1f51bd11dca92471ba8ba77e2d758e5 --- res/values/strings.xml | 11 ++- res/xml/location_settings_personal.xml | 2 +- res/xml/location_settings_workprofile.xml | 2 +- res/xml/privacy_controls_settings.xml | 50 ++++++++++ res/xml/privacy_dashboard_settings.xml | 2 +- .../settings/location/LocationEnabler.java | 27 ++++-- .../privacy/LocationToggleController.java | 95 +++++++++++++++++++ .../privacy/PrivacyControlsFragment.java | 63 ++++++++++++ 8 files changed, 241 insertions(+), 11 deletions(-) create mode 100644 res/xml/privacy_controls_settings.xml create mode 100644 src/com/android/settings/privacy/LocationToggleController.java create mode 100644 src/com/android/settings/privacy/PrivacyControlsFragment.java 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; + } +}