• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.location;
18 
19 import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LOCATION_SWITCH_TITLE;
20 
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.database.ContentObserver;
24 import android.location.SettingInjectorService;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.os.Looper;
28 import android.os.SystemProperties;
29 import android.provider.Settings;
30 import android.util.Log;
31 
32 import androidx.annotation.NonNull;
33 import androidx.annotation.Nullable;
34 import androidx.preference.Preference;
35 import androidx.preference.PreferenceGroup;
36 
37 import com.android.settings.R;
38 import com.android.settings.SettingsActivity;
39 import com.android.settings.dashboard.DashboardFragment;
40 import com.android.settings.search.BaseSearchIndexProvider;
41 import com.android.settings.widget.SettingsMainSwitchBar;
42 import com.android.settingslib.location.RecentLocationApps;
43 import com.android.settingslib.search.SearchIndexable;
44 
45 import java.util.Collections;
46 import java.util.Comparator;
47 import java.util.List;
48 
49 /**
50  * System location settings (Settings > Location). The screen has three parts:
51  * <ul>
52  *     <li>Platform location controls</li>
53  *     <ul>
54  *         <li>In switch bar: location primary switch. Used to toggle location on and off.
55  *         </li>
56  *     </ul>
57  *     <li>Recent location requests: automatically populated by {@link RecentLocationApps}</li>
58  *     <li>Location services: multi-app settings provided from outside the Android framework. Each
59  *     is injected by a system-partition app via the {@link SettingInjectorService} API.</li>
60  * </ul>
61  * <p>
62  * Note that as of KitKat, the {@link SettingInjectorService} is the preferred method for OEMs to
63  * add their own settings to this page, rather than directly modifying the framework code. Among
64  * other things, this simplifies integration with future changes to the default (AOSP)
65  * implementation.
66  */
67 @SearchIndexable
68 public class LocationSettings extends DashboardFragment implements
69         LocationEnabler.LocationModeChangeListener {
70 
71     private static final String TAG = "LocationSettings";
72     private static final String RECENT_LOCATION_ACCESS_PREF_KEY = "recent_location_access";
73 
74     private LocationSwitchBarController mSwitchBarController;
75     private LocationEnabler mLocationEnabler;
76     private RecentLocationAccessPreferenceController mController;
77     private ContentObserver mContentObserver;
78 
79     /**
80      * Read-only boot property used to enable/disable geolocation toggle as part of privacy hub
81      * feature for chrome.
82      */
83     private static final String RO_BOOT_ENABLE_PRIVACY_HUB_FOR_CHROME =
84             "ro.boot.enable_privacy_hub_for_chrome";
85 
86     @Override
getMetricsCategory()87     public int getMetricsCategory() {
88         return SettingsEnums.LOCATION;
89     }
90 
91     @Override
onActivityCreated(Bundle savedInstanceState)92     public void onActivityCreated(Bundle savedInstanceState) {
93         super.onActivityCreated(savedInstanceState);
94         final SettingsActivity activity = (SettingsActivity) getActivity();
95         final SettingsMainSwitchBar switchBar = activity.getSwitchBar();
96         switchBar.setTitle(getContext().getString(R.string.location_settings_primary_switch_title));
97         updateChromeSwitchBarPreference(switchBar);
98         switchBar.show();
99         mSwitchBarController = new LocationSwitchBarController(activity, switchBar,
100                 getSettingsLifecycle());
101         mLocationEnabler = new LocationEnabler(getContext(), this, getSettingsLifecycle());
102         mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
103             @Override
104             public void onChange(boolean selfChange) {
105                 mController.updateShowSystem();
106             }
107         };
108         getContentResolver().registerContentObserver(
109                 Settings.Secure.getUriFor(
110                         Settings.Secure.LOCATION_SHOW_SYSTEM_OPS), /* notifyForDescendants= */
111                 false, mContentObserver);
112     }
113 
114     @Override
onAttach(Context context)115     public void onAttach(Context context) {
116         super.onAttach(context);
117 
118         use(AppLocationPermissionPreferenceController.class).init(this);
119         mController = use(RecentLocationAccessPreferenceController.class);
120         mController.init(this);
121         use(RecentLocationAccessSeeAllButtonPreferenceController.class).init(this);
122         use(LocationForWorkPreferenceController.class).init(this);
123         use(LocationSettingsFooterPreferenceController.class).init(this);
124         use(LocationForPrivateProfilePreferenceController.class).init(this);
125     }
126 
127     @Override
onDestroy()128     public void onDestroy() {
129         super.onDestroy();
130         getContentResolver().unregisterContentObserver(mContentObserver);
131     }
132 
133     @Override
getPreferenceScreenResId()134     protected int getPreferenceScreenResId() {
135         return R.xml.location_settings;
136     }
137 
138     @Override
onCreate(Bundle icicle)139     public void onCreate(Bundle icicle) {
140         super.onCreate(icicle);
141 
142         replaceEnterpriseStringTitle("managed_profile_location_switch",
143                 WORK_PROFILE_LOCATION_SWITCH_TITLE, R.string.managed_profile_location_switch_title);
144     }
145 
146     @Override
getLogTag()147     protected String getLogTag() {
148         return TAG;
149     }
150 
151     @Override
onLocationModeChanged(int mode, boolean restricted)152     public void onLocationModeChanged(int mode, boolean restricted) {
153         if (mLocationEnabler.isEnabled(mode)) {
154             scrollToPreference(RECENT_LOCATION_ACCESS_PREF_KEY);
155         }
156     }
157 
addPreferencesSorted(List<Preference> prefs, PreferenceGroup container)158     static void addPreferencesSorted(List<Preference> prefs, PreferenceGroup container) {
159         // If there's some items to display, sort the items and add them to the container.
160         Collections.sort(prefs,
161                 Comparator.comparing(lhs -> lhs.getTitle().toString()));
162         for (Preference entry : prefs) {
163             container.addPreference(entry);
164         }
165     }
166 
167     @Override
getHelpResource()168     public int getHelpResource() {
169         return R.string.help_url_location_access;
170     }
171 
172     /**
173      * For Search.
174      */
175     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
176             new BaseSearchIndexProvider(R.xml.location_settings);
177 
178     /**
179      * Update switchbar config in case of Chrome devices and location is managed by chrome.
180      */
updateChromeSwitchBarPreference(final SettingsMainSwitchBar switchBar)181     private void updateChromeSwitchBarPreference(final SettingsMainSwitchBar switchBar) {
182         if (getContext().getResources().getBoolean(R.bool.config_disable_location_toggle_for_chrome)
183                 && SystemProperties.getBoolean(RO_BOOT_ENABLE_PRIVACY_HUB_FOR_CHROME, false)) {
184             Log.i(TAG, "Disabling location toggle for chrome devices");
185             switchBar.setClickable(false);
186             switchBar.setTooltipText(getResources().getString(
187                     R.string.location_settings_tooltip_text_for_chrome));
188         }
189     }
190 
191     @Override
getPreferenceScreenBindingKey(@onNull Context context)192     public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
193         return LocationScreen.KEY;
194     }
195 }
196