/* * Copyright (C) 2018 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.network.telephony; 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 android.text.TextUtils; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.FragmentManager; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.core.TogglePreferenceController; import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; /** * Preference controller for "Roaming" */ public class RoamingPreferenceController extends TogglePreferenceController implements LifecycleObserver, OnStart, OnStop { private static final String DIALOG_TAG = "MobileDataDialog"; private RestrictedSwitchPreference mSwitchPreference; private TelephonyManager mTelephonyManager; private CarrierConfigManager mCarrierConfigManager; private int mSubId; private DataContentObserver mDataContentObserver; @VisibleForTesting boolean mNeedDialog; @VisibleForTesting FragmentManager mFragmentManager; public RoamingPreferenceController(Context context, String key) { super(context, key); mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override public void onStart() { mDataContentObserver.register(mContext, mSubId); } @Override public void onStop() { mDataContentObserver.unRegister(mContext); } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mSwitchPreference = (RestrictedSwitchPreference) screen.findPreference(getPreferenceKey()); } @Override public int getAvailabilityStatus() { return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID ? AVAILABLE : AVAILABLE_UNSEARCHABLE; } @Override public boolean handlePreferenceTreeClick(Preference preference) { if (TextUtils.equals(preference.getKey(), getPreferenceKey())) { if (mNeedDialog) { showDialog(); } return true; } return false; } @Override public boolean setChecked(boolean isChecked) { mNeedDialog = isDialogNeeded(); if (!mNeedDialog) { // Update data directly if we don't need dialog mTelephonyManager.setDataRoamingEnabled(isChecked); return true; } return false; } @Override public void updateState(Preference preference) { super.updateState(preference); final RestrictedSwitchPreference switchPreference = (RestrictedSwitchPreference) preference; switchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID); switchPreference.setChecked(isChecked()); } @VisibleForTesting boolean isDialogNeeded() { final boolean isRoamingEnabled = mTelephonyManager.isDataRoamingEnabled(); final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId( mSubId); // 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; } @Override public boolean isChecked() { return mTelephonyManager.isDataRoamingEnabled(); } public void init(FragmentManager fragmentManager, int subId) { mFragmentManager = fragmentManager; mSubId = subId; mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); } private void showDialog() { final RoamingDialogFragment dialogFragment = RoamingDialogFragment.newInstance(mSubId); dialogFragment.show(mFragmentManager, DIALOG_TAG); } /** * Listener that listens data roaming change */ public class DataContentObserver extends ContentObserver { public DataContentObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); updateState(mSwitchPreference); } public void register(Context context, int subId) { Uri uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING); if (TelephonyManager.getDefault().getSimCount() != 1) { uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING + subId); } context.getContentResolver().registerContentObserver(uri, false, this); } public void unRegister(Context context) { context.getContentResolver().unregisterContentObserver(this); } } }