blob: a16c9bbd7921beed4a0436fd4104f8ac54a4bb14 [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 */
16package com.android.settings.location;
17
18import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
19import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
20import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_SUPPORTED;
21import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
22
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;
34import com.android.settings.core.BasePreferenceController;
35import com.android.settingslib.core.lifecycle.LifecycleObserver;
36import com.android.settingslib.core.lifecycle.events.OnStart;
37import com.android.settingslib.core.lifecycle.events.OnStop;
38
39import java.util.concurrent.Executor;
40
41/**
42 * The controller for the "location time zone detection" entry in the Location settings
43 * screen.
44 */
45public class LocationTimeZoneDetectionPreferenceController
46 extends BasePreferenceController
47 implements LifecycleObserver, OnStart, OnStop, TimeManager.TimeZoneDetectorListener {
48
49 private final TimeManager mTimeManager;
50 private final LocationManager mLocationManager;
51 private TimeZoneCapabilitiesAndConfig mTimeZoneCapabilitiesAndConfig;
52 private Preference mPreference;
53
54 public LocationTimeZoneDetectionPreferenceController(Context context, String key) {
55 super(context, key);
56 mTimeManager = context.getSystemService(TimeManager.class);
57 mLocationManager = context.getSystemService(LocationManager.class);
58 }
59
60 @Override
61 public void displayPreference(PreferenceScreen screen) {
62 super.displayPreference(screen);
63 mPreference = screen.findPreference(getPreferenceKey());
64 }
65
66 @Override
67 public void onStart() {
68 // Register for updates to the user's time zone capabilities or configuration which could
69 // require UI changes.
70 Executor mainExecutor = mContext.getMainExecutor();
71 mTimeManager.addTimeZoneDetectorListener(mainExecutor, this);
72 // Setup the initial state of the summary.
73 refreshUi();
74 }
75
76 @Override
77 public void onStop() {
78 mTimeManager.removeTimeZoneDetectorListener(this);
79 }
80
81 @Override
82 public int getAvailabilityStatus() {
83 TimeZoneCapabilities timeZoneCapabilities =
84 getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false).getCapabilities();
85 int capability = timeZoneCapabilities.getConfigureGeoDetectionEnabledCapability();
86
87 // The preference only has two states: present and not present. The preference is never
88 // present but disabled.
89 if (capability == CAPABILITY_NOT_SUPPORTED || capability == CAPABILITY_NOT_ALLOWED) {
90 return UNSUPPORTED_ON_DEVICE;
91 } else if (capability == CAPABILITY_NOT_APPLICABLE || capability == CAPABILITY_POSSESSED) {
92 return AVAILABLE;
93 } else {
94 throw new IllegalStateException("Unknown capability=" + capability);
95 }
96 }
97
98 @Override
99 public CharSequence getSummary() {
100 TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig =
101 getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false);
102 TimeZoneCapabilities capabilities = timeZoneCapabilitiesAndConfig.getCapabilities();
103 int configureGeoDetectionEnabledCapability =
104 capabilities.getConfigureGeoDetectionEnabledCapability();
105 TimeZoneConfiguration configuration = timeZoneCapabilitiesAndConfig.getConfiguration();
106
107 int summaryResId;
108 if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_SUPPORTED) {
109 // The preference should not be visible, but text is referenced in case this changes.
110 summaryResId = R.string.location_time_zone_detection_not_supported;
111 } else if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_ALLOWED) {
112 // The preference should not be visible, but text is referenced in case this changes.
113 summaryResId = R.string.location_time_zone_detection_not_allowed;
114 } else if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_APPLICABLE) {
115 // The TimeZoneCapabilities deliberately doesn't provide information about why the user
116 // doesn't have the capability, but the user's "location enabled" being off and the
117 // global automatic detection setting will always be considered overriding reasons why
118 // location time zone detection cannot be used.
119 if (!mLocationManager.isLocationEnabled()) {
120 summaryResId = R.string.location_app_permission_summary_location_off;
121 } else if (!configuration.isAutoDetectionEnabled()) {
122 summaryResId = R.string.location_time_zone_detection_auto_is_off;
123 } else {
124 // This is in case there are other reasons in future why location time zone
125 // detection is not applicable.
126 summaryResId = R.string.location_time_zone_detection_not_applicable;
127 }
128 } else if (configureGeoDetectionEnabledCapability == CAPABILITY_POSSESSED) {
129 boolean isGeoDetectionEnabled = configuration.isGeoDetectionEnabled();
130 summaryResId = isGeoDetectionEnabled
131 ? R.string.location_time_zone_detection_on
132 : R.string.location_time_zone_detection_off;
133 } else {
134 // This is unexpected: getAvailabilityStatus() should ensure that the UI element isn't
135 // even shown for known cases, or the capability is unknown.
136 throw new IllegalStateException("Unexpected configureGeoDetectionEnabledCapability="
137 + configureGeoDetectionEnabledCapability);
138 }
139 return mContext.getString(summaryResId);
140 }
141
142 @Override
143 public void onChange() {
144 refreshUi();
145 }
146
147 private void refreshUi() {
148 // Force a refresh of cached user capabilities and config before refreshing the summary.
149 getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ true);
150 refreshSummary(mPreference);
151 }
152
153 /**
154 * Returns the current user capabilities and configuration. {@code forceRefresh} can be {@code
155 * true} to discard any cached copy.
156 */
157 private TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig(boolean forceRefresh) {
158 if (forceRefresh || mTimeZoneCapabilitiesAndConfig == null) {
159 mTimeZoneCapabilitiesAndConfig = mTimeManager.getTimeZoneCapabilitiesAndConfig();
160 }
161 return mTimeZoneCapabilitiesAndConfig;
162 }
163}