1 /*
2  * Copyright (C) 2020 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.settings.network.telephony;
18 
19 import static com.android.settings.network.InternetUpdater.INTERNET_ETHERNET;
20 import static com.android.settingslib.mobile.MobileMappings.getIconKey;
21 import static com.android.settingslib.mobile.MobileMappings.mapIconSets;
22 
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.database.ContentObserver;
28 import android.net.Uri;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.telephony.ServiceState;
32 import android.telephony.SubscriptionManager;
33 import android.telephony.TelephonyCallback;
34 import android.telephony.TelephonyDisplayInfo;
35 import android.telephony.TelephonyManager;
36 import android.util.Log;
37 
38 import androidx.annotation.VisibleForTesting;
39 
40 import com.android.settings.network.InternetUpdater;
41 import com.android.settings.network.MobileDataContentObserver;
42 import com.android.settings.network.MobileDataEnabledListener;
43 import com.android.settings.network.SubscriptionsChangeListener;
44 import com.android.settings.wifi.slice.WifiScanWorker;
45 import com.android.settingslib.SignalIcon.MobileIconGroup;
46 import com.android.settingslib.mobile.MobileMappings;
47 import com.android.settingslib.mobile.MobileMappings.Config;
48 import com.android.settingslib.mobile.TelephonyIcons;
49 
50 import java.util.Collections;
51 
52 /**
53  * BackgroundWorker for Provider Model slice.
54  */
55 public class NetworkProviderWorker extends WifiScanWorker implements
56         SignalStrengthListener.Callback, MobileDataEnabledListener.Client,
57         DataConnectivityListener.Client, InternetUpdater.InternetChangeListener,
58         SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
59     private static final String TAG = "NetworkProviderWorker";
60     private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 6;
61     private DataContentObserver mMobileDataObserver;
62     private SignalStrengthListener mSignalStrengthListener;
63     private SubscriptionsChangeListener mSubscriptionsListener;
64     private MobileDataEnabledListener mDataEnabledListener;
65     private DataConnectivityListener mConnectivityListener;
66     private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
67     private final Context mContext;
68     final Handler mHandler;
69     @VisibleForTesting
70     final NetworkProviderTelephonyCallback mTelephonyCallback;
71     private final BroadcastReceiver mConnectionChangeReceiver = new BroadcastReceiver() {
72         @Override
73         public void onReceive(Context context, Intent intent) {
74             final String action = intent.getAction();
75             if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
76                 Log.d(TAG, "ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED");
77                 updateListener();
78             }
79         }
80     };
81 
82     private TelephonyManager mTelephonyManager;
83     private Config mConfig = null;
84     private TelephonyDisplayInfo mTelephonyDisplayInfo =
85             new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
86                     TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
87     private InternetUpdater mInternetUpdater;
88     private @InternetUpdater.InternetType int mInternetType;
89 
NetworkProviderWorker(Context context, Uri uri)90     public NetworkProviderWorker(Context context, Uri uri) {
91         super(context, uri);
92         // Mobile data worker
93         mHandler = new Handler(Looper.getMainLooper());
94         mMobileDataObserver = new DataContentObserver(mHandler, this);
95 
96         mContext = context;
97         mDefaultDataSubId = getDefaultDataSubscriptionId();
98         Log.d(TAG, "Init, SubId: " + mDefaultDataSubId);
99         mTelephonyManager = mContext.getSystemService(
100                 TelephonyManager.class).createForSubscriptionId(mDefaultDataSubId);
101         mTelephonyCallback = new NetworkProviderTelephonyCallback();
102         mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
103         mDataEnabledListener = new MobileDataEnabledListener(context, this);
104         mConnectivityListener = new DataConnectivityListener(context, this);
105         mSignalStrengthListener = new SignalStrengthListener(context, this);
106         mConfig = getConfig(mContext);
107 
108         mInternetUpdater = new InternetUpdater(mContext, getLifecycle(), this);
109         mInternetType = mInternetUpdater.getInternetType();
110     }
111 
112     @Override
onSlicePinned()113     protected void onSlicePinned() {
114         Log.d(TAG, "onSlicePinned");
115         mMobileDataObserver.register(mContext, mDefaultDataSubId);
116         mSubscriptionsListener.start();
117         mDataEnabledListener.start(mDefaultDataSubId);
118         mConnectivityListener.start();
119         mSignalStrengthListener.resume();
120         mTelephonyManager.registerTelephonyCallback(mHandler::post, mTelephonyCallback);
121         IntentFilter filter = new IntentFilter();
122         filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
123         mContext.registerReceiver(mConnectionChangeReceiver, filter);
124         super.onSlicePinned();
125     }
126 
127     @Override
onSliceUnpinned()128     protected void onSliceUnpinned() {
129         Log.d(TAG, "onSliceUnpinned");
130         mMobileDataObserver.unregister(mContext);
131         mSubscriptionsListener.stop();
132         mDataEnabledListener.stop();
133         mConnectivityListener.stop();
134         mSignalStrengthListener.pause();
135         mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
136         if (mConnectionChangeReceiver != null) {
137             mContext.unregisterReceiver(mConnectionChangeReceiver);
138         }
139         super.onSliceUnpinned();
140     }
141 
142     @Override
close()143     public void close() {
144         mMobileDataObserver = null;
145         super.close();
146     }
147 
148     @Override
getApRowCount()149     public int getApRowCount() {
150         return PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT;
151     }
152 
153     /**
154      * To update the Slice.
155      */
updateSlice()156     public void updateSlice() {
157         notifySliceChange();
158     }
159 
updateListener()160     private void updateListener() {
161         int defaultDataSubId = getDefaultDataSubscriptionId();
162         if (mDefaultDataSubId == defaultDataSubId) {
163             Log.d(TAG, "DDS: no change");
164             return;
165         }
166         mDefaultDataSubId = defaultDataSubId;
167         Log.d(TAG, "DDS: defaultDataSubId:" + mDefaultDataSubId);
168         if (SubscriptionManager.isUsableSubscriptionId(defaultDataSubId)) {
169             mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
170             mMobileDataObserver.unregister(mContext);
171 
172             mSignalStrengthListener.updateSubscriptionIds(Collections.singleton(defaultDataSubId));
173             mTelephonyManager = mTelephonyManager.createForSubscriptionId(defaultDataSubId);
174             mTelephonyManager.registerTelephonyCallback(mHandler::post, mTelephonyCallback);
175             mMobileDataObserver.register(mContext, defaultDataSubId);
176             mConfig = getConfig(mContext);
177         } else {
178             mSignalStrengthListener.updateSubscriptionIds(Collections.emptySet());
179         }
180         updateSlice();
181     }
182 
183     @Override
onSubscriptionsChanged()184     public void onSubscriptionsChanged() {
185         Log.d(TAG, "onSubscriptionsChanged");
186         updateListener();
187     }
188 
189     @Override
onSignalStrengthChanged()190     public void onSignalStrengthChanged() {
191         Log.d(TAG, "onSignalStrengthChanged");
192         updateSlice();
193     }
194 
195     @Override
onAirplaneModeChanged(boolean airplaneModeEnabled)196     public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
197         Log.d(TAG, "onAirplaneModeChanged");
198         updateSlice();
199     }
200 
201     @Override
onMobileDataEnabledChange()202     public void onMobileDataEnabledChange() {
203         Log.d(TAG, "onMobileDataEnabledChange");
204         updateSlice();
205     }
206 
207     @Override
onDataConnectivityChange()208     public void onDataConnectivityChange() {
209         Log.d(TAG, "onDataConnectivityChange");
210         updateSlice();
211     }
212 
213     /**
214      * Listen to update of mobile data change.
215      */
216     public class DataContentObserver extends ContentObserver {
217         private final NetworkProviderWorker mNetworkProviderWorker;
218 
DataContentObserver(Handler handler, NetworkProviderWorker backgroundWorker)219         public DataContentObserver(Handler handler, NetworkProviderWorker backgroundWorker) {
220             super(handler);
221             Log.d(TAG, "DataContentObserver: init");
222             mNetworkProviderWorker = backgroundWorker;
223         }
224 
225         @Override
onChange(boolean selfChange)226         public void onChange(boolean selfChange) {
227             Log.d(TAG, "DataContentObserver: onChange");
228             mNetworkProviderWorker.updateSlice();
229         }
230 
231         /**
232          * To register the observer for mobile data changed.
233          *
234          * @param context the Context object.
235          * @param subId the default data subscription id.
236          */
register(Context context, int subId)237         public void register(Context context, int subId) {
238             final Uri uri = MobileDataContentObserver.getObservableUri(context, subId);
239             Log.d(TAG, "DataContentObserver: register uri:" + uri);
240             context.getContentResolver().registerContentObserver(uri, false, this);
241         }
242 
243         /**
244          * To unregister the observer for mobile data changed.
245          *
246          * @param context the Context object.
247          */
unregister(Context context)248         public void unregister(Context context) {
249             Log.d(TAG, "DataContentObserver: unregister");
250             context.getContentResolver().unregisterContentObserver(this);
251         }
252     }
253 
254     class NetworkProviderTelephonyCallback extends TelephonyCallback implements
255             TelephonyCallback.DataConnectionStateListener,
256             TelephonyCallback.DisplayInfoListener,
257             TelephonyCallback.ServiceStateListener {
258         @Override
onServiceStateChanged(ServiceState state)259         public void onServiceStateChanged(ServiceState state) {
260             Log.d(TAG, "onServiceStateChanged voiceState=" + state.getState()
261                     + " dataState=" + state.getDataRegistrationState());
262             updateSlice();
263         }
264 
265         @Override
onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo)266         public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
267             Log.d(TAG, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo);
268             mTelephonyDisplayInfo = telephonyDisplayInfo;
269             updateSlice();
270         }
271 
272         @Override
onDataConnectionStateChanged(int state, int networkType)273         public void onDataConnectionStateChanged(int state, int networkType) {
274             Log.d(TAG,
275                     "onDataConnectionStateChanged: networkType=" + networkType + " state=" + state);
276             updateSlice();
277         }
278     }
279 
280     @VisibleForTesting
getDefaultDataSubscriptionId()281     int getDefaultDataSubscriptionId() {
282         return SubscriptionManager.getDefaultDataSubscriptionId();
283     }
284 
updateNetworkTypeName(Context context, Config config, TelephonyDisplayInfo telephonyDisplayInfo, int subId)285     private String updateNetworkTypeName(Context context, Config config,
286             TelephonyDisplayInfo telephonyDisplayInfo, int subId) {
287         String iconKey = getIconKey(telephonyDisplayInfo);
288         int resId = mapIconSets(config).get(iconKey).dataContentDescription;
289         if (mWifiPickerTrackerHelper != null
290                 && mWifiPickerTrackerHelper.isCarrierNetworkActive()) {
291             MobileIconGroup carrierMergedWifiIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI;
292             resId = carrierMergedWifiIconGroup.dataContentDescription;
293             return resId != 0
294                     ? SubscriptionManager.getResourcesForSubId(context, subId)
295                     .getString(resId) : "";
296         }
297 
298         return resId != 0
299                 ? SubscriptionManager.getResourcesForSubId(context, subId).getString(resId) : "";
300     }
301 
302     @VisibleForTesting
getConfig(Context context)303     Config getConfig(Context context) {
304         return MobileMappings.Config.readConfig(context);
305     }
306 
307     /**
308      * Get currently description of mobile network type.
309      */
getNetworkTypeDescription()310     public String getNetworkTypeDescription() {
311         return updateNetworkTypeName(mContext, mConfig, mTelephonyDisplayInfo,
312                 mDefaultDataSubId);
313     }
314 
315     /**
316      * Called when internet type is changed.
317      *
318      * @param internetType the internet type
319      */
onInternetTypeChanged(@nternetUpdater.InternetType int internetType)320     public void onInternetTypeChanged(@InternetUpdater.InternetType int internetType) {
321         if (mInternetType == internetType) {
322             return;
323         }
324         boolean changeWithEthernet =
325                 mInternetType == INTERNET_ETHERNET || internetType == INTERNET_ETHERNET;
326         mInternetType = internetType;
327         if (changeWithEthernet) {
328             updateSlice();
329         }
330     }
331 
332     /**
333      * Returns the internet type.
334      */
getInternetType()335     public @InternetUpdater.InternetType int getInternetType() {
336         return mInternetType;
337     }
338 }
339