• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.car.settings.network;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.Context;
21 import android.database.ContentObserver;
22 import android.net.Uri;
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.os.PersistableBundle;
26 import android.provider.Settings;
27 import android.telephony.CarrierConfigManager;
28 import android.telephony.SubscriptionManager;
29 import android.telephony.TelephonyManager;
30 
31 import androidx.preference.TwoStatePreference;
32 
33 import com.android.car.settings.R;
34 import com.android.car.settings.common.ConfirmationDialogFragment;
35 import com.android.car.settings.common.FragmentController;
36 
37 /** Business logic for toggling the roaming state. */
38 // TODO: This preference should be available but unsearchable if subscription id is invalid.
39 public class RoamingPreferenceController extends
40         NetworkBasePreferenceController<TwoStatePreference> implements
41         MobileNetworkUpdateManager.MobileNetworkUpdateListener {
42 
43     private final CarrierConfigManager mCarrierConfigManager;
44     private final RoamingStateChangeObserver mRoamingStateChangeObserver;
45 
46     private final ConfirmationDialogFragment.ConfirmListener mConfirmListener =
47             arguments -> setRoamingEnabled(true);
48 
RoamingPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)49     public RoamingPreferenceController(Context context, String preferenceKey,
50             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
51         super(context, preferenceKey, fragmentController, uxRestrictions);
52         mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
53         mRoamingStateChangeObserver = new RoamingStateChangeObserver(
54                 new Handler(Looper.getMainLooper()), this::refreshUi);
55     }
56 
57     @Override
getPreferenceType()58     protected Class<TwoStatePreference> getPreferenceType() {
59         return TwoStatePreference.class;
60     }
61 
62     @Override
onStartInternal()63     protected void onStartInternal() {
64         mRoamingStateChangeObserver.register(getContext(), getSubId());
65 
66         ConfirmationDialogFragment.resetListeners(
67                 (ConfirmationDialogFragment) getFragmentController().findDialogByTag(
68                         ConfirmationDialogFragment.TAG),
69                 mConfirmListener,
70                 /* rejectListener= */ null,
71                 /* neutralListener= */ null);
72     }
73 
74     @Override
onStopInternal()75     protected void onStopInternal() {
76         mRoamingStateChangeObserver.unregister(getContext());
77     }
78 
79     @Override
updateState(TwoStatePreference preference)80     protected void updateState(TwoStatePreference preference) {
81         preference.setEnabled(getSubId() != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
82         preference.setChecked(getTelephonyManager() != null
83                 ? getTelephonyManager().isDataRoamingEnabled() : false);
84     }
85 
86     @Override
handlePreferenceChanged(TwoStatePreference preference, Object newValue)87     protected boolean handlePreferenceChanged(TwoStatePreference preference, Object newValue) {
88         boolean isEnabled = (boolean) newValue;
89         if (isEnabled && isDialogNeeded()) {
90             getFragmentController().showDialog(getRoamingAlertDialog(),
91                     ConfirmationDialogFragment.TAG);
92             return false;
93         }
94 
95         setRoamingEnabled(isEnabled);
96         return true;
97     }
98 
99     @Override
onMobileNetworkUpdated(int subId)100     public void onMobileNetworkUpdated(int subId) {
101         setFields(subId);
102         refreshUi();
103     }
104 
setRoamingEnabled(boolean enabled)105     private void setRoamingEnabled(boolean enabled) {
106         getTelephonyManager().setDataRoamingEnabled(enabled);
107         refreshUi();
108     }
109 
isDialogNeeded()110     private boolean isDialogNeeded() {
111         boolean isRoamingEnabled = getTelephonyManager().isDataRoamingEnabled();
112         PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(getSubId());
113 
114         // Need dialog if we need to turn on roaming and the roaming charge indication is allowed.
115         if (!isRoamingEnabled && (carrierConfig == null || !carrierConfig.getBoolean(
116                 CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL))) {
117             return true;
118         }
119         return false;
120     }
121 
getRoamingAlertDialog()122     private ConfirmationDialogFragment getRoamingAlertDialog() {
123         return new ConfirmationDialogFragment.Builder(getContext())
124                 .setTitle(R.string.roaming_alert_title)
125                 .setMessage(R.string.roaming_warning)
126                 .setPositiveButton(android.R.string.ok, mConfirmListener)
127                 .setNegativeButton(android.R.string.cancel, /* rejectListener= */ null)
128                 .build();
129     }
130 
131     /** Observer that listens to data roaming change. */
132     private static class RoamingStateChangeObserver extends ContentObserver {
133 
134         private Runnable mChangeListener;
135 
RoamingStateChangeObserver(Handler handler, Runnable changeListener)136         RoamingStateChangeObserver(Handler handler, Runnable changeListener) {
137             super(handler);
138             mChangeListener = changeListener;
139         }
140 
141         @Override
onChange(boolean selfChange)142         public void onChange(boolean selfChange) {
143             super.onChange(selfChange);
144             mChangeListener.run();
145         }
146 
147         /** Register this observer to listen for updates to {@link Settings.Global#DATA_ROAMING}. */
register(Context context, int subId)148         public void register(Context context, int subId) {
149             Uri uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING);
150             if (TelephonyManager.from(context).getSimCount() != 1) {
151                 uri = Settings.Global.getUriFor(Settings.Global.DATA_ROAMING + subId);
152             }
153             context.getContentResolver().registerContentObserver(uri,
154                     /* notifyForDescendants= */ false, /* observer= */ this);
155         }
156 
157         /** Unregister this observer. */
unregister(Context context)158         public void unregister(Context context) {
159             context.getContentResolver().unregisterContentObserver(/* observer= */ this);
160         }
161     }
162 }
163