blob: 4aefaafba8d54be8b6ab52ef2ca49553c3c85daa [file] [log] [blame]
/*
* Copyright (C) 2019 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.car.settings.network;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.preference.TwoStatePreference;
import com.android.car.settings.R;
import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
/** Business logic for toggling the roaming state. */
// TODO: This preference should be available but unsearchable if subscription id is invalid.
public class RoamingPreferenceController extends
NetworkBasePreferenceController<TwoStatePreference> implements
MobileNetworkUpdateManager.MobileNetworkUpdateListener {
private final CarrierConfigManager mCarrierConfigManager;
private final RoamingStateChangeObserver mRoamingStateChangeObserver;
private final ConfirmationDialogFragment.ConfirmListener mConfirmListener =
arguments -> setRoamingEnabled(true);
public RoamingPreferenceController(Context context, String preferenceKey,
FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
super(context, preferenceKey, fragmentController, uxRestrictions);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
mRoamingStateChangeObserver = new RoamingStateChangeObserver(
new Handler(Looper.getMainLooper()), this::refreshUi);
}
@Override
protected Class<TwoStatePreference> getPreferenceType() {
return TwoStatePreference.class;
}
@Override
protected void onStartInternal() {
mRoamingStateChangeObserver.register(getContext(), getSubId());
ConfirmationDialogFragment.resetListeners(
(ConfirmationDialogFragment) getFragmentController().findDialogByTag(
ConfirmationDialogFragment.TAG),
mConfirmListener,
/* rejectListener= */ null,
/* neutralListener= */ null);
}
@Override
protected void onStopInternal() {
mRoamingStateChangeObserver.unregister(getContext());
}
@Override
protected void updateState(TwoStatePreference preference) {
preference.setEnabled(getSubId() != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
preference.setChecked(getTelephonyManager() != null
? getTelephonyManager().isDataRoamingEnabled() : false);
}
@Override
protected boolean handlePreferenceChanged(TwoStatePreference preference, Object newValue) {
boolean isEnabled = (boolean) newValue;
if (isEnabled && isDialogNeeded()) {
getFragmentController().showDialog(getRoamingAlertDialog(),
ConfirmationDialogFragment.TAG);
return false;
}
setRoamingEnabled(isEnabled);
return true;
}
@Override
public void onMobileNetworkUpdated(int subId) {
setFields(subId);
refreshUi();
}
private void setRoamingEnabled(boolean enabled) {
getTelephonyManager().setDataRoamingEnabled(enabled);
refreshUi();
}
private boolean isDialogNeeded() {
boolean isRoamingEnabled = getTelephonyManager().isDataRoamingEnabled();
PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(getSubId());
// Need dialog if we need to turn on roaming and the roaming charge indication is allowed.
if (!isRoamingEnabled && (carrierConfig == null || !carrierConfig.getBoolean(
CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL))) {
return true;
}
return false;
}
private ConfirmationDialogFragment getRoamingAlertDialog() {
return new ConfirmationDialogFragment.Builder(getContext())
.setTitle(R.string.roaming_alert_title)
.setMessage(R.string.roaming_warning)
.setPositiveButton(android.R.string.ok, mConfirmListener)
.setNegativeButton(android.R.string.cancel, /* rejectListener= */ null)
.build();
}
/** Observer that listens to data roaming change. */
private static class RoamingStateChangeObserver extends ContentObserver {
private Runnable mChangeListener;
RoamingStateChangeObserver(Handler handler, Runnable changeListener) {
super(handler);
mChangeListener = changeListener;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
mChangeListener.run();
}
/** Register this observer to listen for updates to {@link Settings.Global#DATA_ROAMING}. */
public void register(Context context, int subId) {
Uri uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING);
if (TelephonyManager.from(context).getSimCount() != 1) {
uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING + subId);
}
context.getContentResolver().registerContentObserver(uri,
/* notifyForDescendants= */ false, /* observer= */ this);
}
/** Unregister this observer. */
public void unregister(Context context) {
context.getContentResolver().unregisterContentObserver(/* observer= */ this);
}
}
}