• 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.developeroptions.network.telephony;
18 
19 import android.content.Context;
20 import android.database.ContentObserver;
21 import android.net.Uri;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.provider.Settings;
25 import android.telephony.SubscriptionInfo;
26 import android.telephony.SubscriptionManager;
27 import android.telephony.TelephonyManager;
28 import android.text.TextUtils;
29 
30 import com.android.settingslib.core.lifecycle.LifecycleObserver;
31 import com.android.settingslib.core.lifecycle.events.OnStart;
32 import com.android.settingslib.core.lifecycle.events.OnStop;
33 
34 import androidx.annotation.VisibleForTesting;
35 import androidx.fragment.app.FragmentManager;
36 import androidx.preference.Preference;
37 import androidx.preference.PreferenceScreen;
38 import androidx.preference.SwitchPreference;
39 
40 /**
41  * Preference controller for "Mobile data"
42  */
43 public class MobileDataPreferenceController extends TelephonyTogglePreferenceController
44         implements LifecycleObserver, OnStart, OnStop {
45 
46     private static final String DIALOG_TAG = "MobileDataDialog";
47 
48     private SwitchPreference mPreference;
49     private TelephonyManager mTelephonyManager;
50     private SubscriptionManager mSubscriptionManager;
51     private DataContentObserver mDataContentObserver;
52     private FragmentManager mFragmentManager;
53     @VisibleForTesting
54     int mDialogType;
55     @VisibleForTesting
56     boolean mNeedDialog;
57 
MobileDataPreferenceController(Context context, String key)58     public MobileDataPreferenceController(Context context, String key) {
59         super(context, key);
60         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
61         mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper()));
62     }
63 
64     @Override
getAvailabilityStatus(int subId)65     public int getAvailabilityStatus(int subId) {
66         return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
67                 ? AVAILABLE
68                 : CONDITIONALLY_UNAVAILABLE;
69     }
70 
71     @Override
displayPreference(PreferenceScreen screen)72     public void displayPreference(PreferenceScreen screen) {
73         super.displayPreference(screen);
74         mPreference = screen.findPreference(getPreferenceKey());
75     }
76 
77     @Override
onStart()78     public void onStart() {
79         if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
80             mDataContentObserver.register(mContext, mSubId);
81         }
82     }
83 
84     @Override
onStop()85     public void onStop() {
86         if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
87             mDataContentObserver.unRegister(mContext);
88         }
89     }
90 
91     @Override
handlePreferenceTreeClick(Preference preference)92     public boolean handlePreferenceTreeClick(Preference preference) {
93         if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
94             if (mNeedDialog) {
95                 showDialog(mDialogType);
96             }
97             return true;
98         }
99 
100         return false;
101     }
102 
103     @Override
setChecked(boolean isChecked)104     public boolean setChecked(boolean isChecked) {
105         mNeedDialog = isDialogNeeded();
106 
107         if (!mNeedDialog) {
108             // Update data directly if we don't need dialog
109             MobileNetworkUtils.setMobileDataEnabled(mContext, mSubId, isChecked, false);
110             return true;
111         }
112 
113         return false;
114     }
115 
116     @Override
isChecked()117     public boolean isChecked() {
118         return mTelephonyManager.isDataEnabled();
119     }
120 
121     @Override
updateState(Preference preference)122     public void updateState(Preference preference) {
123         super.updateState(preference);
124         preference.setEnabled(!isOpportunistic());
125     }
126 
isOpportunistic()127     private boolean isOpportunistic() {
128         SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
129         return info != null && info.isOpportunistic();
130     }
131 
getObservableUri(int subId)132     public static Uri getObservableUri(int subId) {
133         Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
134         if (TelephonyManager.getDefault().getSimCount() != 1) {
135             uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
136         }
137         return uri;
138     }
139 
init(FragmentManager fragmentManager, int subId)140     public void init(FragmentManager fragmentManager, int subId) {
141         mFragmentManager = fragmentManager;
142         mSubId = subId;
143         mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
144     }
145 
146     @VisibleForTesting
isDialogNeeded()147     boolean isDialogNeeded() {
148         final boolean enableData = !isChecked();
149         final boolean isMultiSim = (mTelephonyManager.getSimCount() > 1);
150         final int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId();
151         final boolean needToDisableOthers = mSubscriptionManager
152                 .isActiveSubscriptionId(defaultSubId) && defaultSubId != mSubId;
153         if (enableData) {
154             if (isMultiSim && needToDisableOthers) {
155                 mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG;
156                 return true;
157             }
158         } else {
159             if (!isMultiSim) {
160                 mDialogType = MobileDataDialogFragment.TYPE_DISABLE_DIALOG;
161                 return true;
162             }
163         }
164 
165         return false;
166     }
167 
showDialog(int type)168     private void showDialog(int type) {
169         final MobileDataDialogFragment dialogFragment = MobileDataDialogFragment.newInstance(type,
170                 mSubId);
171         dialogFragment.show(mFragmentManager, DIALOG_TAG);
172     }
173 
174     /**
175      * Listener that listens mobile data state change.
176      */
177     public class DataContentObserver extends ContentObserver {
178 
DataContentObserver(Handler handler)179         public DataContentObserver(Handler handler) {
180             super(handler);
181         }
182 
183         @Override
onChange(boolean selfChange)184         public void onChange(boolean selfChange) {
185             super.onChange(selfChange);
186             updateState(mPreference);
187         }
188 
register(Context context, int subId)189         public void register(Context context, int subId) {
190             final Uri uri = getObservableUri(subId);
191             context.getContentResolver().registerContentObserver(uri, false, this);
192 
193         }
194 
unRegister(Context context)195         public void unRegister(Context context) {
196             context.getContentResolver().unregisterContentObserver(this);
197         }
198     }
199 }
200