blob: 369218b86adc155354fbe2404446fda15242a43b [file] [log] [blame]
/*
* Copyright (C) 2020 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 static com.android.settings.network.InternetUpdater.INTERNET_ETHERNET;
import static com.android.settingslib.mobile.MobileMappings.getIconKey;
import static com.android.settingslib.mobile.MobileMappings.mapIconSets;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.network.InternetUpdater;
import com.android.settings.network.MobileDataContentObserver;
import com.android.settings.network.MobileDataEnabledListener;
import com.android.settings.network.SubscriptionsChangeListener;
import com.android.settings.wifi.slice.WifiScanWorker;
import com.android.settingslib.SignalIcon.MobileIconGroup;
import com.android.settingslib.mobile.MobileMappings;
import com.android.settingslib.mobile.MobileMappings.Config;
import com.android.settingslib.mobile.TelephonyIcons;
import java.util.Collections;
/**
* BackgroundWorker for Provider Model slice.
*/
public class NetworkProviderWorker extends WifiScanWorker implements
SignalStrengthListener.Callback, MobileDataEnabledListener.Client,
DataConnectivityListener.Client, InternetUpdater.InternetChangeListener,
SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
private static final String TAG = "NetworkProviderWorker";
private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 5;
private DataContentObserver mMobileDataObserver;
private SignalStrengthListener mSignalStrengthListener;
private SubscriptionsChangeListener mSubscriptionsListener;
private MobileDataEnabledListener mDataEnabledListener;
private DataConnectivityListener mConnectivityListener;
private int mDefaultDataSubid = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private final Context mContext;
final Handler mHandler;
@VisibleForTesting
final NetworkProviderTelephonyCallback mTelephonyCallback;
private TelephonyManager mTelephonyManager;
private Config mConfig = null;
private TelephonyDisplayInfo mTelephonyDisplayInfo =
new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
private InternetUpdater mInternetUpdater;
private @InternetUpdater.InternetType int mInternetType;
public NetworkProviderWorker(Context context, Uri uri) {
super(context, uri);
// Mobile data worker
mHandler = new Handler(Looper.getMainLooper());
mMobileDataObserver = new DataContentObserver(mHandler, this);
mContext = context;
mDefaultDataSubid = getDefaultDataSubscriptionId();
mTelephonyManager = mContext.getSystemService(
TelephonyManager.class).createForSubscriptionId(mDefaultDataSubid);
mTelephonyCallback = new NetworkProviderTelephonyCallback();
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
mDataEnabledListener = new MobileDataEnabledListener(context, this);
mConnectivityListener = new DataConnectivityListener(context, this);
mSignalStrengthListener = new SignalStrengthListener(context, this);
mConfig = getConfig(mContext);
mInternetUpdater = new InternetUpdater(mContext, getLifecycle(), this);
mInternetType = mInternetUpdater.getInternetType();
}
@Override
protected void onSlicePinned() {
Log.d(TAG, "onSlicePinned");
mMobileDataObserver.register(mContext, mDefaultDataSubid);
mSubscriptionsListener.start();
mDataEnabledListener.start(mDefaultDataSubid);
mConnectivityListener.start();
mSignalStrengthListener.resume();
mTelephonyManager.registerTelephonyCallback(mHandler::post, mTelephonyCallback);
super.onSlicePinned();
}
@Override
protected void onSliceUnpinned() {
Log.d(TAG, "onSliceUnpinned");
mMobileDataObserver.unregister(mContext);
mSubscriptionsListener.stop();
mDataEnabledListener.stop();
mConnectivityListener.stop();
mSignalStrengthListener.pause();
mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
super.onSliceUnpinned();
}
@Override
public void close() {
mMobileDataObserver = null;
super.close();
}
@Override
public int getApRowCount() {
return PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT;
}
/**
* To update the Slice.
*/
public void updateSlice() {
notifySliceChange();
}
@Override
public void onSubscriptionsChanged() {
int defaultDataSubId = getDefaultDataSubscriptionId();
if (mDefaultDataSubid == defaultDataSubId) {
Log.d(TAG, "onSubscriptionsChanged: no change");
return;
}
Log.d(TAG, "onSubscriptionsChanged: defaultDataSubId:" + defaultDataSubId);
if (SubscriptionManager.isUsableSubscriptionId(defaultDataSubId)) {
mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
mMobileDataObserver.unregister(mContext);
mSignalStrengthListener.updateSubscriptionIds(Collections.singleton(defaultDataSubId));
mTelephonyManager = mTelephonyManager.createForSubscriptionId(defaultDataSubId);
mTelephonyManager.registerTelephonyCallback(mHandler::post, mTelephonyCallback);
mMobileDataObserver.register(mContext, defaultDataSubId);
mConfig = getConfig(mContext);
} else {
mSignalStrengthListener.updateSubscriptionIds(Collections.emptySet());
}
updateSlice();
}
@Override
public void onSignalStrengthChanged() {
Log.d(TAG, "onSignalStrengthChanged");
updateSlice();
}
@Override
public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
Log.d(TAG, "onAirplaneModeChanged");
updateSlice();
}
@Override
public void onMobileDataEnabledChange() {
Log.d(TAG, "onMobileDataEnabledChange");
updateSlice();
}
@Override
public void onDataConnectivityChange() {
Log.d(TAG, "onDataConnectivityChange");
updateSlice();
}
/**
* Listen to update of mobile data change.
*/
public class DataContentObserver extends ContentObserver {
private final NetworkProviderWorker mNetworkProviderWorker;
public DataContentObserver(Handler handler, NetworkProviderWorker backgroundWorker) {
super(handler);
Log.d(TAG, "DataContentObserver: init");
mNetworkProviderWorker = backgroundWorker;
}
@Override
public void onChange(boolean selfChange) {
Log.d(TAG, "DataContentObserver: onChange");
mNetworkProviderWorker.updateSlice();
}
/**
* To register the observer for mobile data changed.
*
* @param context the Context object.
* @param subId the default data subscription id.
*/
public void register(Context context, int subId) {
final Uri uri = MobileDataContentObserver.getObservableUri(context, subId);
Log.d(TAG, "DataContentObserver: register uri:" + uri);
context.getContentResolver().registerContentObserver(uri, false, this);
}
/**
* To unregister the observer for mobile data changed.
*
* @param context the Context object.
*/
public void unregister(Context context) {
Log.d(TAG, "DataContentObserver: unregister");
context.getContentResolver().unregisterContentObserver(this);
}
}
class NetworkProviderTelephonyCallback extends TelephonyCallback implements
TelephonyCallback.DataConnectionStateListener,
TelephonyCallback.DisplayInfoListener,
TelephonyCallback.ServiceStateListener {
@Override
public void onServiceStateChanged(ServiceState state) {
Log.d(TAG, "onServiceStateChanged voiceState=" + state.getState()
+ " dataState=" + state.getDataRegistrationState());
updateSlice();
}
@Override
public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
Log.d(TAG, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo);
mTelephonyDisplayInfo = telephonyDisplayInfo;
updateSlice();
}
@Override
public void onDataConnectionStateChanged(int state, int networkType) {
Log.d(TAG,
"onDataConnectionStateChanged: networkType=" + networkType + " state=" + state);
updateSlice();
}
}
@VisibleForTesting
int getDefaultDataSubscriptionId() {
return SubscriptionManager.getDefaultDataSubscriptionId();
}
private String updateNetworkTypeName(Context context, Config config,
TelephonyDisplayInfo telephonyDisplayInfo, int subId) {
String iconKey = getIconKey(telephonyDisplayInfo);
int resId = mapIconSets(config).get(iconKey).dataContentDescription;
if (mWifiPickerTrackerHelper != null
&& mWifiPickerTrackerHelper.isActiveCarrierNetwork()) {
MobileIconGroup carrierMergedWifiIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI;
resId = carrierMergedWifiIconGroup.dataContentDescription;
return resId != 0
? SubscriptionManager.getResourcesForSubId(context, subId)
.getString(resId) : "";
}
return resId != 0
? SubscriptionManager.getResourcesForSubId(context, subId).getString(resId) : "";
}
@VisibleForTesting
Config getConfig(Context context) {
return MobileMappings.Config.readConfig(context);
}
/**
* Get currently description of mobile network type.
*/
public String getNetworkTypeDescription() {
return updateNetworkTypeName(mContext, mConfig, mTelephonyDisplayInfo,
mDefaultDataSubid);
}
/**
* Called when internet type is changed.
*
* @param internetType the internet type
*/
public void onInternetTypeChanged(@InternetUpdater.InternetType int internetType) {
if (mInternetType == internetType) {
return;
}
boolean changeWithEthernet =
mInternetType == INTERNET_ETHERNET || internetType == INTERNET_ETHERNET;
mInternetType = internetType;
if (changeWithEthernet) {
updateSlice();
}
}
/**
* Returns the internet type.
*/
public @InternetUpdater.InternetType int getInternetType() {
return mInternetType;
}
}