blob: cb39635cc431a5a9deda6e91e2e738ca87b0fddc [file] [log] [blame]
Neil Fuller4a6663c2020-09-10 15:06:39 +01001/*
2 * Copyright (C) 2020 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 */
Neil Fuller21840432020-11-09 20:44:27 +000016package com.android.settings.datetime;
Neil Fuller4a6663c2020-09-10 15:06:39 +010017
Almaz Mingaleeva29a6ce2021-03-11 15:26:31 +000018import static android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED;
19import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
20import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED;
21import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
Neil Fuller4a6663c2020-09-10 15:06:39 +010022
23import android.app.time.TimeManager;
24import android.app.time.TimeZoneCapabilities;
25import android.app.time.TimeZoneCapabilitiesAndConfig;
26import android.app.time.TimeZoneConfiguration;
27import android.content.Context;
28import android.location.LocationManager;
29
30import androidx.preference.Preference;
31import androidx.preference.PreferenceScreen;
32
33import com.android.settings.R;
Almaz Mingaleevfcf1fcf2021-03-18 10:30:04 +000034import com.android.settings.core.InstrumentedPreferenceFragment;
Almaz Mingaleevab059182021-03-01 12:24:54 +000035import com.android.settings.core.TogglePreferenceController;
Neil Fuller4a6663c2020-09-10 15:06:39 +010036import com.android.settingslib.core.lifecycle.LifecycleObserver;
37import com.android.settingslib.core.lifecycle.events.OnStart;
38import com.android.settingslib.core.lifecycle.events.OnStop;
39
40import java.util.concurrent.Executor;
41
42/**
43 * The controller for the "location time zone detection" entry in the Location settings
44 * screen.
45 */
46public class LocationTimeZoneDetectionPreferenceController
Almaz Mingaleevab059182021-03-01 12:24:54 +000047 extends TogglePreferenceController
Neil Fuller4a6663c2020-09-10 15:06:39 +010048 implements LifecycleObserver, OnStart, OnStop, TimeManager.TimeZoneDetectorListener {
49
Almaz Mingaleevfcf1fcf2021-03-18 10:30:04 +000050 private static final String TAG = "location_time_zone_detection";
51
Neil Fuller4a6663c2020-09-10 15:06:39 +010052 private final TimeManager mTimeManager;
53 private final LocationManager mLocationManager;
54 private TimeZoneCapabilitiesAndConfig mTimeZoneCapabilitiesAndConfig;
Almaz Mingaleevfcf1fcf2021-03-18 10:30:04 +000055 private InstrumentedPreferenceFragment mFragment;
Neil Fuller4a6663c2020-09-10 15:06:39 +010056 private Preference mPreference;
57
Almaz Mingaleevfcf1fcf2021-03-18 10:30:04 +000058 public LocationTimeZoneDetectionPreferenceController(Context context) {
59 super(context, TAG);
Neil Fuller4a6663c2020-09-10 15:06:39 +010060 mTimeManager = context.getSystemService(TimeManager.class);
61 mLocationManager = context.getSystemService(LocationManager.class);
62 }
63
Almaz Mingaleevfcf1fcf2021-03-18 10:30:04 +000064 void setFragment(InstrumentedPreferenceFragment fragment) {
65 mFragment = fragment;
66 }
67
Neil Fuller4a6663c2020-09-10 15:06:39 +010068 @Override
Almaz Mingaleevab059182021-03-01 12:24:54 +000069 public boolean isChecked() {
70 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
71 mTimeManager.getTimeZoneCapabilitiesAndConfig();
72 TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
73 return configuration.isGeoDetectionEnabled();
74 }
75
76 @Override
77 public boolean setChecked(boolean isChecked) {
Almaz Mingaleevfcf1fcf2021-03-18 10:30:04 +000078 if (isChecked && !mLocationManager.isLocationEnabled()) {
79 new LocationToggleDisabledDialogFragment(mContext)
80 .show(mFragment.getFragmentManager(), TAG);
81 // Toggle status is not updated.
82 return false;
83 } else {
84 TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
85 .setGeoDetectionEnabled(isChecked)
86 .build();
87 return mTimeManager.updateTimeZoneConfiguration(configuration);
88 }
Almaz Mingaleevab059182021-03-01 12:24:54 +000089 }
90
91 @Override
Neil Fuller4a6663c2020-09-10 15:06:39 +010092 public void displayPreference(PreferenceScreen screen) {
93 super.displayPreference(screen);
94 mPreference = screen.findPreference(getPreferenceKey());
95 }
96
97 @Override
98 public void onStart() {
99 // Register for updates to the user's time zone capabilities or configuration which could
100 // require UI changes.
101 Executor mainExecutor = mContext.getMainExecutor();
102 mTimeManager.addTimeZoneDetectorListener(mainExecutor, this);
103 // Setup the initial state of the summary.
104 refreshUi();
105 }
106
107 @Override
108 public void onStop() {
109 mTimeManager.removeTimeZoneDetectorListener(this);
110 }
111
112 @Override
113 public int getAvailabilityStatus() {
114 TimeZoneCapabilities timeZoneCapabilities =
115 getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false).getCapabilities();
116 int capability = timeZoneCapabilities.getConfigureGeoDetectionEnabledCapability();
117
118 // The preference only has two states: present and not present. The preference is never
119 // present but disabled.
120 if (capability == CAPABILITY_NOT_SUPPORTED || capability == CAPABILITY_NOT_ALLOWED) {
121 return UNSUPPORTED_ON_DEVICE;
122 } else if (capability == CAPABILITY_NOT_APPLICABLE || capability == CAPABILITY_POSSESSED) {
123 return AVAILABLE;
124 } else {
125 throw new IllegalStateException("Unknown capability=" + capability);
126 }
127 }
128
129 @Override
130 public CharSequence getSummary() {
131 TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig =
132 getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false);
133 TimeZoneCapabilities capabilities = timeZoneCapabilitiesAndConfig.getCapabilities();
134 int configureGeoDetectionEnabledCapability =
135 capabilities.getConfigureGeoDetectionEnabledCapability();
136 TimeZoneConfiguration configuration = timeZoneCapabilitiesAndConfig.getConfiguration();
137
138 int summaryResId;
139 if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_SUPPORTED) {
140 // The preference should not be visible, but text is referenced in case this changes.
141 summaryResId = R.string.location_time_zone_detection_not_supported;
142 } else if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_ALLOWED) {
143 // The preference should not be visible, but text is referenced in case this changes.
144 summaryResId = R.string.location_time_zone_detection_not_allowed;
145 } else if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_APPLICABLE) {
146 // The TimeZoneCapabilities deliberately doesn't provide information about why the user
147 // doesn't have the capability, but the user's "location enabled" being off and the
148 // global automatic detection setting will always be considered overriding reasons why
149 // location time zone detection cannot be used.
150 if (!mLocationManager.isLocationEnabled()) {
151 summaryResId = R.string.location_app_permission_summary_location_off;
152 } else if (!configuration.isAutoDetectionEnabled()) {
153 summaryResId = R.string.location_time_zone_detection_auto_is_off;
154 } else {
155 // This is in case there are other reasons in future why location time zone
156 // detection is not applicable.
157 summaryResId = R.string.location_time_zone_detection_not_applicable;
158 }
159 } else if (configureGeoDetectionEnabledCapability == CAPABILITY_POSSESSED) {
Almaz Mingaleevab059182021-03-01 12:24:54 +0000160 // If capability is possessed, toggle status already tells all the information needed.
161 // Returning null will make previous text stick on toggling.
162 // See AbstractPreferenceController#refreshSummary.
163 return "";
Neil Fuller4a6663c2020-09-10 15:06:39 +0100164 } else {
165 // This is unexpected: getAvailabilityStatus() should ensure that the UI element isn't
166 // even shown for known cases, or the capability is unknown.
167 throw new IllegalStateException("Unexpected configureGeoDetectionEnabledCapability="
168 + configureGeoDetectionEnabledCapability);
169 }
170 return mContext.getString(summaryResId);
171 }
172
173 @Override
174 public void onChange() {
175 refreshUi();
176 }
177
178 private void refreshUi() {
179 // Force a refresh of cached user capabilities and config before refreshing the summary.
180 getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ true);
181 refreshSummary(mPreference);
182 }
183
184 /**
185 * Returns the current user capabilities and configuration. {@code forceRefresh} can be {@code
186 * true} to discard any cached copy.
187 */
188 private TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig(boolean forceRefresh) {
189 if (forceRefresh || mTimeZoneCapabilitiesAndConfig == null) {
190 mTimeZoneCapabilitiesAndConfig = mTimeManager.getTimeZoneCapabilitiesAndConfig();
191 }
192 return mTimeZoneCapabilitiesAndConfig;
193 }
194}