diff --git a/res/values/strings.xml b/res/values/strings.xml index ecfce4a5559..f29ed2f0b4d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3770,6 +3770,8 @@ See all Location services + + Recent work app location requests My Location diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml index 2ad155448f2..932cb658f8d 100644 --- a/res/xml/location_settings.xml +++ b/res/xml/location_settings.xml @@ -72,7 +72,8 @@ + android:title="@string/managed_profile_location_services" + settings:controller="com.android.settings.location.LocationServiceForWorkPreferenceController"/> diff --git a/res/xml/location_settings_personal.xml b/res/xml/location_settings_personal.xml new file mode 100644 index 00000000000..f07d0e89651 --- /dev/null +++ b/res/xml/location_settings_personal.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/xml/location_settings_workprofile.xml b/res/xml/location_settings_workprofile.xml new file mode 100644 index 00000000000..cb1416db235 --- /dev/null +++ b/res/xml/location_settings_workprofile.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java index a31340a53eb..8dfa93493af 100644 --- a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java +++ b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java @@ -41,7 +41,7 @@ public class AccountWorkProfileDashboardFragment extends DashboardFragment { @Override public int getMetricsCategory() { - return SettingsEnums.ACCOUNT; + return SettingsEnums.ACCOUNT_WORK; } @Override diff --git a/src/com/android/settings/dashboard/profileselector/ProfileFragmentBridge.java b/src/com/android/settings/dashboard/profileselector/ProfileFragmentBridge.java index 047f740b3c4..816decaac5a 100644 --- a/src/com/android/settings/dashboard/profileselector/ProfileFragmentBridge.java +++ b/src/com/android/settings/dashboard/profileselector/ProfileFragmentBridge.java @@ -21,6 +21,7 @@ import android.util.ArrayMap; import com.android.settings.accounts.AccountDashboardFragment; import com.android.settings.applications.manageapplications.ManageApplications; import com.android.settings.deviceinfo.StorageDashboardFragment; +import com.android.settings.location.LocationSettings; import java.util.Map; @@ -43,5 +44,7 @@ public class ProfileFragmentBridge { ProfileSelectManageApplications.class.getName()); FRAGMENT_MAP.put(StorageDashboardFragment.class.getName(), ProfileSelectStorageFragment.class.getName()); + FRAGMENT_MAP.put(LocationSettings.class.getName(), + ProfileSelectLocationFragment.class.getName()); } } diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java new file mode 100644 index 00000000000..b256157d502 --- /dev/null +++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019 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.dashboard.profileselector; + +import android.os.Bundle; + +import androidx.fragment.app.Fragment; + +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.location.LocationPersonalSettings; +import com.android.settings.location.LocationSwitchBarController; +import com.android.settings.location.LocationWorkProfileSettings; +import com.android.settings.widget.SwitchBar; + +/** + * Location Setting page for personal/managed profile. + */ +public class ProfileSelectLocationFragment extends ProfileSelectFragment { + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + final SettingsActivity activity = (SettingsActivity) getActivity(); + final SwitchBar switchBar = activity.getSwitchBar(); + switchBar.setSwitchBarText(R.string.location_settings_master_switch_title, + R.string.location_settings_master_switch_title); + final LocationSwitchBarController switchBarController = new LocationSwitchBarController( + activity, switchBar, getSettingsLifecycle()); + switchBar.show(); + } + + @Override + public Fragment[] getFragments() { + return new Fragment[]{ + new LocationPersonalSettings(), + new LocationWorkProfileSettings() + }; + } +} diff --git a/src/com/android/settings/location/LocationPersonalSettings.java b/src/com/android/settings/location/LocationPersonalSettings.java new file mode 100644 index 00000000000..503937e250f --- /dev/null +++ b/src/com/android/settings/location/LocationPersonalSettings.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 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.location; + +import android.app.settings.SettingsEnums; +import android.content.Context; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; + +/** + * Location Setting page for personal profile. + */ +public class LocationPersonalSettings extends DashboardFragment { + + private static final String TAG = "LocationPersonal"; + + @Override + public int getMetricsCategory() { + return SettingsEnums.LOCATION; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.location_settings_personal; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + + use(AppLocationPermissionPreferenceController.class).init(this); + use(RecentLocationRequestPreferenceController.class).init(this); + use(LocationServicePreferenceController.class).init(this); + use(LocationFooterPreferenceController.class).init(this); + } + + @Override + public int getHelpResource() { + return R.string.help_url_location_access; + } +} diff --git a/src/com/android/settings/location/LocationServiceForWorkPreferenceController.java b/src/com/android/settings/location/LocationServiceForWorkPreferenceController.java new file mode 100644 index 00000000000..6b172dd7ff6 --- /dev/null +++ b/src/com/android/settings/location/LocationServiceForWorkPreferenceController.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 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.location; + +import android.content.Context; +import android.os.UserHandle; + +import androidx.preference.Preference; + +import com.android.settings.widget.RestrictedAppPreference; + +import java.util.List; +import java.util.Map; + +/** + * Retrieve the Location Services used in profile user. + */ +public class LocationServiceForWorkPreferenceController extends + LocationServicePreferenceController { + private static final String TAG = "LocationWorkPrefCtrl"; + + public LocationServiceForWorkPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + public void updateState(Preference preference) { + mCategoryLocationServices.removeAll(); + final Map> prefs = getLocationServices(); + boolean show = false; + for (Map.Entry> entry : prefs.entrySet()) { + for (Preference pref : entry.getValue()) { + if (pref instanceof RestrictedAppPreference) { + ((RestrictedAppPreference) pref).checkRestrictionAndSetDisabled(); + } + } + if (entry.getKey() != UserHandle.myUserId()) { + LocationSettings.addPreferencesSorted(entry.getValue(), + mCategoryLocationServices); + show = true; + } + } + mCategoryLocationServices.setVisible(show); + } +} diff --git a/src/com/android/settings/location/LocationServicePreferenceController.java b/src/com/android/settings/location/LocationServicePreferenceController.java index 0902573de09..56a23bdacb3 100644 --- a/src/com/android/settings/location/LocationServicePreferenceController.java +++ b/src/com/android/settings/location/LocationServicePreferenceController.java @@ -39,19 +39,12 @@ import java.util.Map; public class LocationServicePreferenceController extends LocationBasePreferenceController implements LifecycleObserver, OnResume, OnPause { - private static final String TAG = "LocationServicePrefCtrl"; - /** Key for preference category "Location services" */ - @VisibleForTesting - static final String KEY_LOCATION_SERVICES = "location_services"; - /** Key for preference category "Location services for work" */ - @VisibleForTesting - static final String KEY_LOCATION_SERVICES_MANAGED = "location_services_managed_profile"; + private static final String TAG = "LocationPrefCtrl"; @VisibleForTesting static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED = new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED); - private PreferenceCategory mCategoryLocationServices; - private PreferenceCategory mCategoryLocationServicesManaged; + protected PreferenceCategory mCategoryLocationServices; @VisibleForTesting AppSettingsInjector mInjector; /** Receives UPDATE_INTENT */ @@ -71,21 +64,14 @@ public class LocationServicePreferenceController extends LocationBasePreferenceC @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - mCategoryLocationServices = screen.findPreference(KEY_LOCATION_SERVICES); - mCategoryLocationServicesManaged = screen.findPreference(KEY_LOCATION_SERVICES_MANAGED); + mCategoryLocationServices = screen.findPreference(getPreferenceKey()); } @Override public void updateState(Preference preference) { - if (mCategoryLocationServices != null) { - mCategoryLocationServices.removeAll(); - } - if (mCategoryLocationServicesManaged != null) { - mCategoryLocationServicesManaged.removeAll(); - } + mCategoryLocationServices.removeAll(); final Map> prefs = getLocationServices(); - boolean showPrimary = false; - boolean showManaged = false; + boolean show = false; for (Map.Entry> entry : prefs.entrySet()) { for (Preference pref : entry.getValue()) { if (pref instanceof RestrictedAppPreference) { @@ -97,21 +83,10 @@ public class LocationServicePreferenceController extends LocationBasePreferenceC LocationSettings.addPreferencesSorted(entry.getValue(), mCategoryLocationServices); } - showPrimary = true; - } else { - if (mCategoryLocationServicesManaged != null) { - LocationSettings.addPreferencesSorted(entry.getValue(), - mCategoryLocationServicesManaged); - } - showManaged = true; + show = true; } } - if (mCategoryLocationServices != null) { - mCategoryLocationServices.setVisible(showPrimary); - } - if (mCategoryLocationServicesManaged != null) { - mCategoryLocationServicesManaged.setVisible(showManaged); - } + mCategoryLocationServices.setVisible(show); } @Override @@ -143,7 +118,7 @@ public class LocationServicePreferenceController extends LocationBasePreferenceC mContext.unregisterReceiver(mInjectedSettingsReceiver); } - private Map> getLocationServices() { + protected Map> getLocationServices() { // If location access is locked down by device policy then we only show injected settings // for the primary profile. final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId()); diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java index 3b4c4aa2287..26a4afdc7c6 100644 --- a/src/com/android/settings/location/LocationSettings.java +++ b/src/com/android/settings/location/LocationSettings.java @@ -87,6 +87,7 @@ public class LocationSettings extends DashboardFragment { use(LocationServicePreferenceController.class).init(this); use(LocationFooterPreferenceController.class).init(this); use(LocationForWorkPreferenceController.class).init(this); + use(LocationServiceForWorkPreferenceController.class).init(this); } @Override diff --git a/src/com/android/settings/location/LocationWorkProfileSettings.java b/src/com/android/settings/location/LocationWorkProfileSettings.java new file mode 100644 index 00000000000..2c5221185b1 --- /dev/null +++ b/src/com/android/settings/location/LocationWorkProfileSettings.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 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.location; + +import android.app.settings.SettingsEnums; +import android.content.Context; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; + +/** + * Location Setting page for managed profile. + */ +public class LocationWorkProfileSettings extends DashboardFragment { + + private static final String TAG = "LocationWorkProfile"; + + @Override + public int getMetricsCategory() { + return SettingsEnums.LOCATION_WORK; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.location_settings_workprofile; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + + use(AppLocationPermissionPreferenceController.class).init(this); + use(RecentLocationRequestPreferenceController.class).init(this); + use(LocationServiceForWorkPreferenceController.class).init(this); + use(LocationFooterPreferenceController.class).init(this); + use(LocationForWorkPreferenceController.class).init(this); + } + + @Override + public int getHelpResource() { + return R.string.help_url_location_access; + } +} diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider index b14fdac292c..db4b1e930e8 100644 --- a/tests/robotests/assets/grandfather_not_implementing_index_provider +++ b/tests/robotests/assets/grandfather_not_implementing_index_provider @@ -32,6 +32,7 @@ com.android.settings.bluetooth.DevicePickerFragment com.android.settings.dashboard.profileselector.ProfileSelectAccountFragment com.android.settings.dashboard.profileselector.ProfileSelectManageApplications com.android.settings.dashboard.profileselector.ProfileSelectStorageFragment +com.android.settings.dashboard.profileselector.ProfileSelectLocationFragment com.android.settings.datausage.AppDataUsage com.android.settings.datausage.DataUsageList com.android.settings.datausage.DataUsageSummary @@ -54,6 +55,8 @@ com.android.settings.inputmethod.InputMethodAndSubtypeEnabler com.android.settings.inputmethod.KeyboardLayoutPickerFragment com.android.settings.inputmethod.SpellCheckersSettings com.android.settings.localepicker.LocaleListEditor +com.android.settings.location.LocationPersonalSettings +com.android.settings.location.LocationWorkProfileSettings com.android.settings.network.ApnEditor com.android.settings.network.ApnSettings com.android.settings.network.telephony.NetworkSelectSettings diff --git a/tests/robotests/src/com/android/settings/location/LocationServicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationServicePreferenceControllerTest.java index 29048ed55ea..62c13af849b 100644 --- a/tests/robotests/src/com/android/settings/location/LocationServicePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/location/LocationServicePreferenceControllerTest.java @@ -15,9 +15,6 @@ */ package com.android.settings.location; -import static com.android.settings.location.LocationServicePreferenceController.KEY_LOCATION_SERVICES; -import static com.android.settings.location.LocationServicePreferenceController.KEY_LOCATION_SERVICES_MANAGED; - import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -63,6 +60,8 @@ import java.util.Map; @Config(shadows = ShadowUserManager.class) public class LocationServicePreferenceControllerTest { + private static final String KEY_LOCATION_SERVICES = "location_service"; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private LocationSettings mFragment; @Mock @@ -93,10 +92,7 @@ public class LocationServicePreferenceControllerTest { mController.mInjector = mSettingsInjector; final String key = mController.getPreferenceKey(); when(mScreen.findPreference(key)).thenReturn(mCategoryPrimary); - when(mScreen.findPreference(KEY_LOCATION_SERVICES_MANAGED)).thenReturn( - mCategoryManaged); when(mCategoryPrimary.getKey()).thenReturn(key); - when(mCategoryManaged.getKey()).thenReturn(KEY_LOCATION_SERVICES_MANAGED); when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) .thenReturn(mDevicePolicyManager); }