Merge "Changes to location settings for geotz"

This commit is contained in:
Neil Fuller
2020-10-23 09:40:45 +00:00
committed by Android (Google) Code Review
12 changed files with 751 additions and 0 deletions

View File

@@ -58,6 +58,8 @@ public class LocationPersonalSettings extends DashboardFragment {
RecentLocationRequestPreferenceController.class);
controller.init(this);
controller.setProfileType(profileType);
use(LocationTimeZoneDetectionPreferenceController.class);
}
@Override

View File

@@ -88,6 +88,7 @@ public class LocationSettings extends DashboardFragment {
use(LocationFooterPreferenceController.class).init(this);
use(LocationForWorkPreferenceController.class).init(this);
use(LocationServiceForWorkPreferenceController.class).init(this);
use(LocationTimeZoneDetectionPreferenceController.class);
}
@Override

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2020 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 static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_SUPPORTED;
import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import android.app.time.TimeManager;
import android.app.time.TimeZoneCapabilities;
import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
import android.content.Context;
import android.location.LocationManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.concurrent.Executor;
/**
* The controller for the "location time zone detection" entry in the Location settings
* screen.
*/
public class LocationTimeZoneDetectionPreferenceController
extends BasePreferenceController
implements LifecycleObserver, OnStart, OnStop, TimeManager.TimeZoneDetectorListener {
private final TimeManager mTimeManager;
private final LocationManager mLocationManager;
private TimeZoneCapabilitiesAndConfig mTimeZoneCapabilitiesAndConfig;
private Preference mPreference;
public LocationTimeZoneDetectionPreferenceController(Context context, String key) {
super(context, key);
mTimeManager = context.getSystemService(TimeManager.class);
mLocationManager = context.getSystemService(LocationManager.class);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public void onStart() {
// Register for updates to the user's time zone capabilities or configuration which could
// require UI changes.
Executor mainExecutor = mContext.getMainExecutor();
mTimeManager.addTimeZoneDetectorListener(mainExecutor, this);
// Setup the initial state of the summary.
refreshUi();
}
@Override
public void onStop() {
mTimeManager.removeTimeZoneDetectorListener(this);
}
@Override
public int getAvailabilityStatus() {
TimeZoneCapabilities timeZoneCapabilities =
getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false).getCapabilities();
int capability = timeZoneCapabilities.getConfigureGeoDetectionEnabledCapability();
// The preference only has two states: present and not present. The preference is never
// present but disabled.
if (capability == CAPABILITY_NOT_SUPPORTED || capability == CAPABILITY_NOT_ALLOWED) {
return UNSUPPORTED_ON_DEVICE;
} else if (capability == CAPABILITY_NOT_APPLICABLE || capability == CAPABILITY_POSSESSED) {
return AVAILABLE;
} else {
throw new IllegalStateException("Unknown capability=" + capability);
}
}
@Override
public CharSequence getSummary() {
TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig =
getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false);
TimeZoneCapabilities capabilities = timeZoneCapabilitiesAndConfig.getCapabilities();
int configureGeoDetectionEnabledCapability =
capabilities.getConfigureGeoDetectionEnabledCapability();
TimeZoneConfiguration configuration = timeZoneCapabilitiesAndConfig.getConfiguration();
int summaryResId;
if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_SUPPORTED) {
// The preference should not be visible, but text is referenced in case this changes.
summaryResId = R.string.location_time_zone_detection_not_supported;
} else if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_ALLOWED) {
// The preference should not be visible, but text is referenced in case this changes.
summaryResId = R.string.location_time_zone_detection_not_allowed;
} else if (configureGeoDetectionEnabledCapability == CAPABILITY_NOT_APPLICABLE) {
// The TimeZoneCapabilities deliberately doesn't provide information about why the user
// doesn't have the capability, but the user's "location enabled" being off and the
// global automatic detection setting will always be considered overriding reasons why
// location time zone detection cannot be used.
if (!mLocationManager.isLocationEnabled()) {
summaryResId = R.string.location_app_permission_summary_location_off;
} else if (!configuration.isAutoDetectionEnabled()) {
summaryResId = R.string.location_time_zone_detection_auto_is_off;
} else {
// This is in case there are other reasons in future why location time zone
// detection is not applicable.
summaryResId = R.string.location_time_zone_detection_not_applicable;
}
} else if (configureGeoDetectionEnabledCapability == CAPABILITY_POSSESSED) {
boolean isGeoDetectionEnabled = configuration.isGeoDetectionEnabled();
summaryResId = isGeoDetectionEnabled
? R.string.location_time_zone_detection_on
: R.string.location_time_zone_detection_off;
} else {
// This is unexpected: getAvailabilityStatus() should ensure that the UI element isn't
// even shown for known cases, or the capability is unknown.
throw new IllegalStateException("Unexpected configureGeoDetectionEnabledCapability="
+ configureGeoDetectionEnabledCapability);
}
return mContext.getString(summaryResId);
}
@Override
public void onChange() {
refreshUi();
}
private void refreshUi() {
// Force a refresh of cached user capabilities and config before refreshing the summary.
getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ true);
refreshSummary(mPreference);
}
/**
* Returns the current user capabilities and configuration. {@code forceRefresh} can be {@code
* true} to discard any cached copy.
*/
private TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig(boolean forceRefresh) {
if (forceRefresh || mTimeZoneCapabilitiesAndConfig == null) {
mTimeZoneCapabilitiesAndConfig = mTimeManager.getTimeZoneCapabilitiesAndConfig();
}
return mTimeZoneCapabilitiesAndConfig;
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2020 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.time.TimeManager;
import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
import android.content.Context;
import android.text.TextUtils;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController;
/**
* The controller for the "location time zone detection" switch on the location time zone detection
* screen.
*/
public class TimeZoneDetectionPreferenceController extends AbstractPreferenceController {
private static final String KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED =
"location_time_zone_detection_enabled";
private final TimeManager mTimeManager;
public TimeZoneDetectionPreferenceController(Context context) {
super(context);
mTimeManager = context.getSystemService(TimeManager.class);
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED;
}
@Override
public void updateState(Preference preference) {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
mTimeManager.getTimeZoneCapabilitiesAndConfig();
setPreferenceUiState((SwitchPreference) preference, capabilitiesAndConfig);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (TextUtils.equals(preference.getKey(), KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED)) {
SwitchPreference switchPreference = (SwitchPreference) preference;
final boolean switchState = switchPreference.isChecked();
// Update the settings to match the UI.
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setGeoDetectionEnabled(switchState)
.build();
// The return value is ignored, but the current state is read back below ensuring it
// does not matter.
mTimeManager.updateTimeZoneConfiguration(configuration);
// Configure the UI preference state from the configuration. This means that even in the
// unlikely event that the update failed, the UI should reflect current settings.
setPreferenceUiState(switchPreference, mTimeManager.getTimeZoneCapabilitiesAndConfig());
return true;
}
return false;
}
/**
* Sets the switch's checked state from the supplied {@link TimeZoneCapabilitiesAndConfig}.
*/
@android.annotation.UiThread
private void setPreferenceUiState(SwitchPreference preference,
TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig) {
TimeZoneConfiguration configuration = timeZoneCapabilitiesAndConfig.getConfiguration();
boolean checked = configuration.isGeoDetectionEnabled();
preference.setChecked(checked);
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2020 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;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
/**
* The controller for the "location time zone detection" screen.
*/
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class TimeZoneDetectionSettings extends DashboardFragment {
private static final String TAG = "LTZDetectionSettings";
@Override
public int getMetricsCategory() {
return SettingsEnums.LOCATION_TIME_ZONE_DETECTION;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.location_time_zone_detection;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new TimeZoneDetectionPreferenceController(context));
return controllers;
}
/**
* For Search.
*/
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.location_time_zone_detection) {
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context
context) {
return buildPreferenceControllers(context);
}
};
}