1 /* 2 * Copyright (C) 2016 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.datetime; 18 19 import static android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED; 20 import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE; 21 import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED; 22 import static android.app.time.Capabilities.CAPABILITY_POSSESSED; 23 24 import android.app.time.TimeManager; 25 import android.app.time.TimeZoneCapabilities; 26 import android.app.time.TimeZoneCapabilitiesAndConfig; 27 import android.app.time.TimeZoneConfiguration; 28 import android.content.Context; 29 import android.util.Log; 30 31 import androidx.preference.Preference; 32 33 import com.android.internal.annotations.VisibleForTesting; 34 import com.android.settings.R; 35 import com.android.settings.core.TogglePreferenceController; 36 37 public class AutoTimeZonePreferenceController extends TogglePreferenceController { 38 39 private static final String TAG = "AutoTimeZonePreferenceController"; 40 41 private boolean mIsFromSUW; 42 private UpdateTimeAndDateCallback mCallback; 43 private final TimeManager mTimeManager; 44 AutoTimeZonePreferenceController(Context context, String preferenceKey)45 public AutoTimeZonePreferenceController(Context context, String preferenceKey) { 46 super(context, preferenceKey); 47 mTimeManager = context.getSystemService(TimeManager.class); 48 // This is a no-op implementation of UpdateTimeAndDateCallback to avoid a NPE when 49 // setTimeAndDateCallback() isn't called, e.g. for slices and other cases where the 50 // controller is instantiated outside of the context of the real Date & Time settings 51 // screen. 52 mCallback = (c) -> {}; 53 } 54 55 /** 56 * Set the Time and Date callback 57 */ setTimeAndDateCallback( UpdateTimeAndDateCallback callback)58 public AutoTimeZonePreferenceController setTimeAndDateCallback( 59 UpdateTimeAndDateCallback callback) { 60 mCallback = callback; 61 return this; 62 } 63 64 /** 65 * Set if current fragment is launched via SUW 66 */ setFromSUW(boolean isFromSUW)67 public AutoTimeZonePreferenceController setFromSUW(boolean isFromSUW) { 68 mIsFromSUW = isFromSUW; 69 return this; 70 } 71 72 @Override getAvailabilityStatus()73 public int getAvailabilityStatus() { 74 if (mIsFromSUW) { 75 return DISABLED_DEPENDENT_SETTING; 76 } 77 78 TimeZoneCapabilities timeZoneCapabilities = 79 getTimeZoneCapabilitiesAndConfig().getCapabilities(); 80 int capability = timeZoneCapabilities.getConfigureAutoDetectionEnabledCapability(); 81 82 // The preference has three states: visible, not visible, and visible but disabled. 83 // This method handles the "is visible?" check. 84 switch (capability) { 85 case CAPABILITY_NOT_SUPPORTED: 86 return DISABLED_DEPENDENT_SETTING; 87 case CAPABILITY_POSSESSED: 88 case CAPABILITY_NOT_ALLOWED: 89 // This case is expected for enterprise restrictions, where the toggle should be 90 // present but disabled. Disabling is handled declaratively via the 91 // settings:userRestriction attribute in .xml. The client-side logic is expected to 92 // concur with the capabilities logic in the system server. 93 case CAPABILITY_NOT_APPLICABLE: 94 // CAPABILITY_NOT_APPLICABLE is not currently expected, so this is return value is 95 // arbitrary. 96 return AVAILABLE; 97 default: 98 Log.e(TAG, "Unknown capability=" + capability); 99 return UNSUPPORTED_ON_DEVICE; 100 } 101 } 102 103 @Override isChecked()104 public boolean isChecked() { 105 return isEnabled(); 106 } 107 108 @Override setChecked(boolean isChecked)109 public boolean setChecked(boolean isChecked) { 110 TimeZoneConfiguration.Builder configuration = new TimeZoneConfiguration.Builder() 111 .setAutoDetectionEnabled(isChecked); 112 113 // "Use location for time zone" is only used if "Automatic time zone" is enabled. If 114 // the user toggles off automatic time zone, set the toggle off and disable the toggle. 115 int geoDetectionCapability = mTimeManager 116 .getTimeZoneCapabilitiesAndConfig() 117 .getCapabilities() 118 .getConfigureGeoDetectionEnabledCapability(); 119 120 if (!isChecked 121 && (geoDetectionCapability == CAPABILITY_NOT_APPLICABLE 122 || geoDetectionCapability == CAPABILITY_POSSESSED)) { 123 configuration.setGeoDetectionEnabled(false); 124 } 125 126 boolean result = mTimeManager.updateTimeZoneConfiguration(configuration.build()); 127 128 mCallback.updateTimeAndDateDisplay(mContext); 129 return result; 130 } 131 132 @Override getSliceHighlightMenuRes()133 public int getSliceHighlightMenuRes() { 134 return R.string.menu_key_system; 135 } 136 137 @Override updateState(Preference preference)138 public void updateState(Preference preference) { 139 super.updateState(preference); 140 refreshSummary(preference); 141 } 142 143 @Override getSummary()144 public CharSequence getSummary() { 145 // If auto time zone cannot enable telephony fallback and is capable of location, then auto 146 // time zone must use location. 147 if (LocationProviderStatusPreferenceController.hasLocationTimeZoneNoTelephonyFallback( 148 mTimeManager.getTimeZoneCapabilitiesAndConfig().getDetectorStatus())) { 149 return mContext.getString(R.string.auto_zone_requires_location_summary); 150 } 151 152 // If the user has a dedicated toggle to control location use, explain what it does. 153 return mContext.getString(R.string.zone_auto_title_summary); 154 } 155 156 @VisibleForTesting isEnabled()157 boolean isEnabled() { 158 return mTimeManager 159 .getTimeZoneCapabilitiesAndConfig() 160 .getConfiguration() 161 .isAutoDetectionEnabled(); 162 } 163 getTimeZoneCapabilitiesAndConfig()164 private TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig() { 165 return mTimeManager.getTimeZoneCapabilitiesAndConfig(); 166 } 167 } 168