Merge changes from topic "Slice of Provider Model"
* changes: Slice of Provider Model: add slice structure The helper for slice of carrier and non-Carrier, used by ProviderModelSlice.
This commit is contained in:
committed by
Android (Google) Code Review
commit
a12003a9ac
@@ -1156,5 +1156,4 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
public static boolean isProviderModelEnabled(Context context) {
|
||||
return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -103,8 +103,10 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
|
||||
implements Indexable, WifiPickerTracker.WifiPickerTrackerCallback,
|
||||
WifiDialog2.WifiDialog2Listener, DialogInterface.OnDismissListener {
|
||||
|
||||
private static final String TAG = "NetworkProviderSettings";
|
||||
public static final String ACTION_NETWORK_PROVIDER_SETTINGS =
|
||||
"android.settings.NETWORK_PROVIDER_SETTINGS";
|
||||
|
||||
private static final String TAG = "NetworkProviderSettings";
|
||||
// IDs of context menu
|
||||
static final int MENU_ID_CONNECT = Menu.FIRST + 1;
|
||||
@VisibleForTesting
|
||||
|
204
src/com/android/settings/network/ProviderModelSlice.java
Normal file
204
src/com/android/settings/network/ProviderModelSlice.java
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
|
||||
|
||||
import static com.android.settings.slices.CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.network.telephony.MobileNetworkUtils;
|
||||
import com.android.settings.network.telephony.NetworkProviderWorker;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
import com.android.settings.slices.SliceBackgroundWorker;
|
||||
import com.android.settings.slices.SliceBuilderUtils;
|
||||
import com.android.settings.wifi.slice.WifiSlice;
|
||||
import com.android.settings.wifi.slice.WifiSliceItem;
|
||||
import com.android.wifitrackerlib.WifiEntry;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* {@link CustomSliceable} for Wi-Fi and mobile data connection, used by generic clients.
|
||||
*/
|
||||
// ToDo If the provider model become default design in the future, the code needs to refactor
|
||||
// the whole structure and use new "data object", and then split provider model out of old design.
|
||||
public class ProviderModelSlice extends WifiSlice {
|
||||
|
||||
private static final String TAG = "ProviderModelSlice";
|
||||
private final ProviderModelSliceHelper mHelper;
|
||||
|
||||
public ProviderModelSlice(Context context) {
|
||||
super(context);
|
||||
mHelper = getHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return PROVIDER_MODEL_SLICE_URI;
|
||||
}
|
||||
|
||||
private static void log(String s) {
|
||||
Log.d(TAG, s);
|
||||
}
|
||||
|
||||
protected boolean isApRowCollapsed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice getSlice() {
|
||||
// The provider model slice step:
|
||||
// First section: Add a Wi-Fi item which state is connected.
|
||||
// Second section: Add a carrier item.
|
||||
// Third section: Add the Wi-Fi items which are not connected.
|
||||
// Fourth section: If device has connection problem, this row show the message for user.
|
||||
|
||||
if (mHelper.isAirplaneModeEnabled()) {
|
||||
log("Airplane mode is enabled.");
|
||||
// ToDo Next CL will add the Airplane mode Message.
|
||||
return mHelper.createListBuilder(getUri()).build();
|
||||
}
|
||||
|
||||
int maxListSize = 0;
|
||||
List<WifiSliceItem> wifiList = null;
|
||||
final NetworkProviderWorker worker = getWorker();
|
||||
if (worker != null) {
|
||||
// get Wi-Fi list.
|
||||
wifiList = worker.getResults();
|
||||
maxListSize = worker.getApRowCount();
|
||||
} else {
|
||||
log("network provider worker is null.");
|
||||
}
|
||||
|
||||
final boolean hasCarrier = mHelper.hasCarrier();
|
||||
log("hasCarrier: " + hasCarrier);
|
||||
|
||||
|
||||
final ListBuilder listBuilder = mHelper.createListBuilder(getUri());
|
||||
|
||||
// First section: Add a Wi-Fi item which state is connected.
|
||||
final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList);
|
||||
if (connectedWifiItem != null) {
|
||||
log("get Wi-Fi item witch is connected");
|
||||
listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem));
|
||||
maxListSize--;
|
||||
}
|
||||
|
||||
// Second section: Add a carrier item.
|
||||
if (hasCarrier) {
|
||||
listBuilder.addRow(mHelper.createCarrierRow());
|
||||
maxListSize--;
|
||||
}
|
||||
|
||||
// Third section: Add the Wi-Fi items which are not connected.
|
||||
if (wifiList != null) {
|
||||
log("get Wi-Fi items which are not connected");
|
||||
final List<WifiSliceItem> disconnectedWifiList = wifiList.stream()
|
||||
.filter(wifiSliceItem -> wifiSliceItem.getConnectedState()
|
||||
!= WifiEntry.CONNECTED_STATE_CONNECTED)
|
||||
.limit(maxListSize)
|
||||
.collect(Collectors.toList());
|
||||
for (WifiSliceItem item : disconnectedWifiList) {
|
||||
listBuilder.addRow(getWifiSliceItemRow(item));
|
||||
}
|
||||
}
|
||||
|
||||
// Fourth section: If device has connection problem, this row show the message for user.
|
||||
// 1) show non_carrier_network_unavailable:
|
||||
// - while no wifi item
|
||||
// 2) show all_network_unavailable:
|
||||
// - while no wifi item + no carrier
|
||||
// - while no wifi item + no data capability
|
||||
if (worker == null || wifiList == null) {
|
||||
log("wifiList is null");
|
||||
int resId = R.string.non_carrier_network_unavailable;
|
||||
if (!hasCarrier || mHelper.isNoCarrierData()) {
|
||||
log("No carrier item or no carrier data.");
|
||||
resId = R.string.all_network_unavailable;
|
||||
}
|
||||
|
||||
if (!hasCarrier) {
|
||||
// If there is no item in ProviderModelItem, slice needs a header.
|
||||
listBuilder.setHeader(mHelper.createHeader());
|
||||
}
|
||||
listBuilder.addGridRow(mHelper.createMessageGridRow(resId));
|
||||
}
|
||||
|
||||
return listBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current carrier's mobile data status.
|
||||
*/
|
||||
@Override
|
||||
public void onNotifyChange(Intent intent) {
|
||||
final SubscriptionManager subscriptionManager = mHelper.getSubscriptionManager();
|
||||
if (subscriptionManager == null) {
|
||||
return;
|
||||
}
|
||||
final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
|
||||
mHelper.isMobileDataEnabled());
|
||||
final int defaultSubId = subscriptionManager.getDefaultDataSubscriptionId();
|
||||
log("defaultSubId:" + defaultSubId);
|
||||
if (!SubscriptionManager.isUsableSubscriptionId(defaultSubId)) {
|
||||
return; // No subscription - do nothing.
|
||||
}
|
||||
|
||||
MobileNetworkUtils.setMobileDataEnabled(mContext, defaultSubId, newState,
|
||||
false /* disableOtherSubscriptions */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
final String screenTitle = mContext.getText(R.string.provider_internet_settings).toString();
|
||||
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
|
||||
NetworkProviderSettings.class.getName(), "" /* key */, screenTitle,
|
||||
SettingsEnums.SLICE)
|
||||
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
|
||||
.setData(getUri());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getBackgroundWorkerClass() {
|
||||
return NetworkProviderWorker.class;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ProviderModelSliceHelper getHelper() {
|
||||
return new ProviderModelSliceHelper(mContext, this);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
NetworkProviderWorker getWorker() {
|
||||
return SliceBackgroundWorker.getInstance(getUri());
|
||||
}
|
||||
}
|
275
src/com/android/settings/network/ProviderModelSliceHelper.java
Normal file
275
src/com/android/settings/network/ProviderModelSliceHelper.java
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static com.android.settings.network.telephony.MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SignalStrength;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.builders.GridRowBuilder;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.network.telephony.MobileNetworkUtils;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
import com.android.settings.wifi.slice.WifiSliceItem;
|
||||
import com.android.settingslib.WirelessUtils;
|
||||
import com.android.settingslib.net.SignalStrengthUtil;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
import com.android.wifitrackerlib.WifiEntry;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* The helper is for slice of carrier and non-Carrier, used by ProviderModelSlice.
|
||||
*/
|
||||
public class ProviderModelSliceHelper {
|
||||
private static final String TAG = "ProviderModelSlice";
|
||||
private final SubscriptionManager mSubscriptionManager;
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
protected final Context mContext;
|
||||
private CustomSliceable mSliceable;
|
||||
|
||||
public ProviderModelSliceHelper(Context context, CustomSliceable sliceable) {
|
||||
mContext = context;
|
||||
mSliceable = sliceable;
|
||||
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
|
||||
mTelephonyManager = context.getSystemService(TelephonyManager.class);
|
||||
}
|
||||
|
||||
private static void log(String s) {
|
||||
Log.d(TAG, s);
|
||||
}
|
||||
|
||||
protected ListBuilder.HeaderBuilder createHeader() {
|
||||
return new ListBuilder.HeaderBuilder()
|
||||
.setTitle(mContext.getText(R.string.summary_placeholder))
|
||||
.setPrimaryAction(getPrimarySliceAction());
|
||||
}
|
||||
|
||||
protected ListBuilder createListBuilder(Uri uri) {
|
||||
final ListBuilder builder = new ListBuilder(mContext, uri, ListBuilder.INFINITY)
|
||||
.setAccentColor(-1)
|
||||
.setKeywords(getKeywords());
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected GridRowBuilder createMessageGridRow(int messageResId) {
|
||||
final CharSequence title = mContext.getText(messageResId);
|
||||
return new GridRowBuilder()
|
||||
// Add cells to the grid row.
|
||||
.addCell(new GridRowBuilder.CellBuilder().addTitleText(title))
|
||||
.setPrimaryAction(getPrimarySliceAction());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected WifiSliceItem getConnectedWifiItem(List<WifiSliceItem> wifiList) {
|
||||
if (wifiList == null) {
|
||||
return null;
|
||||
}
|
||||
Optional<WifiSliceItem> item = wifiList.stream()
|
||||
.filter(x -> x.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED)
|
||||
.findFirst();
|
||||
return item.isPresent() ? item.get() : null;
|
||||
}
|
||||
|
||||
protected boolean hasCarrier() {
|
||||
if (isAirplaneModeEnabled()
|
||||
|| mSubscriptionManager == null || mTelephonyManager == null
|
||||
|| mSubscriptionManager.getDefaultDataSubscriptionId()
|
||||
== mSubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected ListBuilder.RowBuilder createCarrierRow() {
|
||||
final String title = getMobileTitle();
|
||||
final String summary = getMobileSummary();
|
||||
Drawable drawable = mContext.getDrawable(
|
||||
R.drawable.ic_signal_strength_zero_bar_no_internet);
|
||||
try {
|
||||
drawable = getMobileDrawable(drawable);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
final IconCompat levelIcon = Utils.createIconWithDrawable(drawable);
|
||||
final PendingIntent toggleAction = mSliceable.getBroadcastIntent(mContext);
|
||||
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
|
||||
"mobile_toggle" /* actionTitle */, isMobileDataEnabled());
|
||||
final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
|
||||
.setTitle(title)
|
||||
.setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
|
||||
.addEndItem(toggleSliceAction)
|
||||
.setPrimaryAction(toggleSliceAction)
|
||||
.setSubtitle(summary);
|
||||
return rowBuilder;
|
||||
}
|
||||
|
||||
protected SliceAction getPrimarySliceAction() {
|
||||
return SliceAction.createDeeplink(
|
||||
getPrimaryAction(),
|
||||
Utils.createIconWithDrawable(new ColorDrawable(Color.TRANSPARENT)),
|
||||
ListBuilder.ICON_IMAGE, mContext.getText(R.string.summary_placeholder));
|
||||
}
|
||||
|
||||
private PendingIntent getPrimaryAction() {
|
||||
final Intent intent = new Intent("android.settings.NETWORK_PROVIDER_SETTINGS")
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
return PendingIntent.getActivity(mContext, 0 /* requestCode */,
|
||||
intent, PendingIntent.FLAG_IMMUTABLE /* flags */);
|
||||
}
|
||||
|
||||
private boolean shouldInflateSignalStrength(int subId) {
|
||||
return SignalStrengthUtil.shouldInflateSignalStrength(mContext, subId);
|
||||
}
|
||||
|
||||
protected boolean isAirplaneModeEnabled() {
|
||||
return WirelessUtils.isAirplaneModeOn(mContext);
|
||||
}
|
||||
|
||||
protected boolean isMobileDataEnabled() {
|
||||
if (mTelephonyManager == null) {
|
||||
return false;
|
||||
}
|
||||
return mTelephonyManager.isDataEnabled();
|
||||
}
|
||||
|
||||
protected boolean isDataSimActive() {
|
||||
return MobileNetworkUtils.activeNetworkIsCellular(mContext);
|
||||
}
|
||||
|
||||
protected boolean isNoCarrierData() {
|
||||
if (mTelephonyManager == null) {
|
||||
return false;
|
||||
}
|
||||
boolean mobileDataOnAndNoData = isMobileDataEnabled()
|
||||
&& mTelephonyManager.getDataState() != mTelephonyManager.DATA_CONNECTED;
|
||||
ServiceState serviceState = mTelephonyManager.getServiceState();
|
||||
boolean mobileDataOffAndOutOfService = !isMobileDataEnabled() && serviceState != null
|
||||
&& serviceState.getState() == serviceState.STATE_OUT_OF_SERVICE;
|
||||
log("mobileDataOnAndNoData: " + mobileDataOnAndNoData
|
||||
+ ",mobileDataOffAndOutOfService: " + mobileDataOffAndOutOfService);
|
||||
return mobileDataOnAndNoData || mobileDataOffAndOutOfService;
|
||||
}
|
||||
|
||||
private boolean isAirplaneSafeNetworksModeEnabled() {
|
||||
// TODO: isAirplaneSafeNetworksModeEnabled is not READY
|
||||
return false;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Drawable getMobileDrawable(Drawable drawable) throws Throwable {
|
||||
// set color and drawable
|
||||
if (mTelephonyManager == null) {
|
||||
log("mTelephonyManager == null");
|
||||
return drawable;
|
||||
}
|
||||
if (!isNoCarrierData()) {
|
||||
Semaphore lock = new Semaphore(0);
|
||||
AtomicReference<Drawable> shared = new AtomicReference<>();
|
||||
ThreadUtils.postOnMainThread(() -> {
|
||||
shared.set(getDrawableWithSignalStrength());
|
||||
lock.release();
|
||||
});
|
||||
lock.acquire();
|
||||
drawable = shared.get();
|
||||
}
|
||||
|
||||
if (isDataSimActive()) {
|
||||
drawable.setTint(Utils.getColorAccentDefaultColor(mContext));
|
||||
}
|
||||
return drawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* To get the signal bar icon with level.
|
||||
*
|
||||
* @return The Drawable which is a signal bar icon with level.
|
||||
*/
|
||||
public Drawable getDrawableWithSignalStrength() {
|
||||
final SignalStrength strength = mTelephonyManager.getSignalStrength();
|
||||
int level = (strength == null) ? 0 : strength.getLevel();
|
||||
int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
|
||||
if (mSubscriptionManager != null && shouldInflateSignalStrength(
|
||||
mSubscriptionManager.getDefaultDataSubscriptionId())) {
|
||||
level += 1;
|
||||
numLevels += 1;
|
||||
}
|
||||
return MobileNetworkUtils.getSignalStrengthIcon(mContext, level, numLevels,
|
||||
NO_CELL_DATA_TYPE_ICON, false);
|
||||
}
|
||||
|
||||
private String getMobileSummary() {
|
||||
String summary = "";
|
||||
//TODO: get radio technology.
|
||||
String networkType = "";
|
||||
if (isDataSimActive()) {
|
||||
summary = mContext.getString(R.string.mobile_data_connection_active, networkType);
|
||||
} else if (!isMobileDataEnabled()) {
|
||||
summary = mContext.getString(R.string.mobile_data_off_summary);
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
|
||||
private String getMobileTitle() {
|
||||
String title = mContext.getText(R.string.mobile_data_settings_title).toString();
|
||||
if (mSubscriptionManager == null) {
|
||||
return title;
|
||||
}
|
||||
final SubscriptionInfo defaultSubscription = mSubscriptionManager.getActiveSubscriptionInfo(
|
||||
mSubscriptionManager.getDefaultDataSubscriptionId());
|
||||
if (defaultSubscription != null) {
|
||||
title = defaultSubscription.getDisplayName().toString();
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
protected SubscriptionManager getSubscriptionManager() {
|
||||
return mSubscriptionManager;
|
||||
}
|
||||
|
||||
private Set<String> getKeywords() {
|
||||
final String keywords = mContext.getString(R.string.keywords_internet);
|
||||
return Arrays.stream(TextUtils.split(keywords, ","))
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyDisplayInfo;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
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 java.util.Collections;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
|
||||
/**
|
||||
* BackgroundWorker for Provider Model slice.
|
||||
*/
|
||||
public class NetworkProviderWorker extends WifiScanWorker implements
|
||||
SignalStrengthListener.Callback, MobileDataEnabledListener.Client,
|
||||
DataConnectivityListener.Client,
|
||||
SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
|
||||
private static final String TAG = "NetworkProviderWorker";
|
||||
private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 4;
|
||||
private DataContentObserver mMobileDataObserver;
|
||||
private SignalStrengthListener mSignalStrengthListener;
|
||||
private SubscriptionsChangeListener mSubscriptionsListener;
|
||||
private MobileDataEnabledListener mDataEnabledListener;
|
||||
private DataConnectivityListener mConnectivityListener;
|
||||
|
||||
private final Context mContext;
|
||||
@VisibleForTesting
|
||||
final PhoneStateListener mPhoneStateListener;
|
||||
private final SubscriptionManager mSubscriptionManager;
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
|
||||
public NetworkProviderWorker(Context context, Uri uri) {
|
||||
super(context, uri);
|
||||
// Mobile data worker
|
||||
final Handler handler = new Handler(Looper.getMainLooper());
|
||||
mMobileDataObserver = new DataContentObserver(handler, this);
|
||||
|
||||
mContext = context;
|
||||
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
|
||||
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
|
||||
|
||||
mPhoneStateListener = new NetworkProviderPhoneStateListener(handler::post);
|
||||
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
|
||||
mDataEnabledListener = new MobileDataEnabledListener(context, this);
|
||||
mConnectivityListener = new DataConnectivityListener(context, this);
|
||||
mSignalStrengthListener = new SignalStrengthListener(context, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSlicePinned() {
|
||||
mMobileDataObserver.register(mContext,
|
||||
getDefaultSubscriptionId(mSubscriptionManager));
|
||||
|
||||
mSubscriptionsListener.start();
|
||||
mDataEnabledListener.start(SubscriptionManager.getDefaultDataSubscriptionId());
|
||||
mConnectivityListener.start();
|
||||
mSignalStrengthListener.resume();
|
||||
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE
|
||||
| PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE
|
||||
| PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED);
|
||||
|
||||
super.onSlicePinned();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSliceUnpinned() {
|
||||
mMobileDataObserver.unregister(mContext);
|
||||
mSubscriptionsListener.stop();
|
||||
mDataEnabledListener.stop();
|
||||
mConnectivityListener.stop();
|
||||
mSignalStrengthListener.pause();
|
||||
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||
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 = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||
Log.d(TAG, "onSubscriptionsChanged: defaultDataSubId:" + defaultDataSubId);
|
||||
|
||||
mSignalStrengthListener.updateSubscriptionIds(
|
||||
SubscriptionManager.isUsableSubscriptionId(defaultDataSubId)
|
||||
? Collections.singleton(defaultDataSubId) : Collections.emptySet());
|
||||
if (defaultDataSubId != mDataEnabledListener.getSubId()) {
|
||||
mDataEnabledListener.stop();
|
||||
mDataEnabledListener.start(defaultDataSubId);
|
||||
}
|
||||
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);
|
||||
mNetworkProviderWorker = backgroundWorker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
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);
|
||||
context.getContentResolver().registerContentObserver(uri, false, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* To unregister the observer for mobile data changed.
|
||||
* @param context the Context object.
|
||||
*/
|
||||
public void unregister(Context context) {
|
||||
context.getContentResolver().unregisterContentObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NetworkProviderPhoneStateListener extends PhoneStateListener {
|
||||
NetworkProviderPhoneStateListener(Executor executor) {
|
||||
super(executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceStateChanged(ServiceState state) {
|
||||
Log.d(TAG, "onServiceStateChanged voiceState=" + state.getState()
|
||||
+ " dataState=" + state.getDataRegistrationState());
|
||||
updateSlice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActiveDataSubscriptionIdChanged(int subId) {
|
||||
Log.d(TAG, "onActiveDataSubscriptionIdChanged: subId=" + subId);
|
||||
updateSlice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
|
||||
Log.d(TAG, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo);
|
||||
updateSlice();
|
||||
}
|
||||
}
|
||||
|
||||
protected static int getDefaultSubscriptionId(SubscriptionManager subscriptionManager) {
|
||||
final SubscriptionInfo defaultSubscription = subscriptionManager.getActiveSubscriptionInfo(
|
||||
subscriptionManager.getDefaultDataSubscriptionId());
|
||||
|
||||
if (defaultSubscription == null) {
|
||||
return SubscriptionManager.INVALID_SUBSCRIPTION_ID; // No default subscription
|
||||
}
|
||||
return defaultSubscription.getSubscriptionId();
|
||||
}
|
||||
}
|
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.panel;
|
||||
|
||||
import static com.android.settings.network.NetworkProviderSettings.ACTION_NETWORK_PROVIDER_SETTINGS;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -51,17 +53,19 @@ public class InternetConnectivityPanel implements PanelContent {
|
||||
|
||||
@Override
|
||||
public CharSequence getTitle() {
|
||||
return mContext.getText(R.string.internet_connectivity_panel_title);
|
||||
return mContext.getText(Utils.isProviderModelEnabled(mContext)
|
||||
? R.string.provider_internet_settings : R.string.internet_connectivity_panel_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Uri> getSlices() {
|
||||
final List<Uri> uris = new ArrayList<>();
|
||||
uris.add(CustomSliceRegistry.WIFI_SLICE_URI);
|
||||
uris.add(CustomSliceRegistry.MOBILE_DATA_SLICE_URI);
|
||||
if (Utils.isProviderModelEnabled(mContext)) {
|
||||
uris.add(CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI);
|
||||
uris.add(CustomSliceRegistry.AIRPLANE_SAFE_NETWORKS_SLICE_URI);
|
||||
} else {
|
||||
uris.add(CustomSliceRegistry.WIFI_SLICE_URI);
|
||||
uris.add(CustomSliceRegistry.MOBILE_DATA_SLICE_URI);
|
||||
uris.add(AirplaneModePreferenceController.SLICE_URI);
|
||||
}
|
||||
return uris;
|
||||
@@ -69,7 +73,8 @@ public class InternetConnectivityPanel implements PanelContent {
|
||||
|
||||
@Override
|
||||
public Intent getSeeMoreIntent() {
|
||||
return new Intent(Settings.ACTION_WIRELESS_SETTINGS)
|
||||
return new Intent(Utils.isProviderModelEnabled(mContext)
|
||||
? ACTION_NETWORK_PROVIDER_SETTINGS : Settings.ACTION_WIRELESS_SETTINGS)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
|
||||
|
@@ -40,6 +40,7 @@ import com.android.settings.location.LocationSlice;
|
||||
import com.android.settings.media.MediaOutputIndicatorSlice;
|
||||
import com.android.settings.media.RemoteMediaSlice;
|
||||
import com.android.settings.network.AirplaneSafeNetworksSlice;
|
||||
import com.android.settings.network.ProviderModelSlice;
|
||||
import com.android.settings.network.telephony.MobileDataSlice;
|
||||
import com.android.settings.notification.zen.ZenModeButtonPreferenceController;
|
||||
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
|
||||
@@ -167,6 +168,17 @@ public class CustomSliceRegistry {
|
||||
.appendEncodedPath(SettingsSlicesContract.PATH_SETTING_ACTION)
|
||||
.appendPath("mobile_data")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Full {@link Uri} for the Provider Model Slice.
|
||||
*/
|
||||
public static final Uri PROVIDER_MODEL_SLICE_URI = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
|
||||
.appendEncodedPath(SettingsSlicesContract.PATH_SETTING_ACTION)
|
||||
.appendPath("provider_model")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Full {@link Uri} for the Alarm volume Slice.
|
||||
*/
|
||||
@@ -176,6 +188,7 @@ public class CustomSliceRegistry {
|
||||
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
|
||||
.appendPath("alarm_volume")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Full {@link Uri} for the Call Volume Slice.
|
||||
*/
|
||||
@@ -319,6 +332,7 @@ public class CustomSliceRegistry {
|
||||
sUriToSlice.put(LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
|
||||
sUriToSlice.put(MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
|
||||
sUriToSlice.put(PROVIDER_MODEL_SLICE_URI, ProviderModelSlice.class);
|
||||
sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
|
||||
sUriToSlice.put(DARK_THEME_SLICE_URI, DarkThemeSlice.class);
|
||||
sUriToSlice.put(REMOTE_MEDIA_SLICE_URI, RemoteMediaSlice.class);
|
||||
|
@@ -61,7 +61,7 @@ public class WifiScanWorker extends SliceBackgroundWorker<WifiSliceItem> impleme
|
||||
@VisibleForTesting
|
||||
final LifecycleRegistry mLifecycleRegistry;
|
||||
@VisibleForTesting
|
||||
WifiPickerTracker mWifiPickerTracker;
|
||||
protected WifiPickerTracker mWifiPickerTracker;
|
||||
// Worker thread used for WifiPickerTracker work
|
||||
private final HandlerThread mWorkerThread;
|
||||
|
||||
|
@@ -147,7 +147,7 @@ public class WifiSlice implements CustomSliceable {
|
||||
return builder;
|
||||
}
|
||||
|
||||
private ListBuilder.RowBuilder getWifiSliceItemRow(WifiSliceItem wifiSliceItem) {
|
||||
protected ListBuilder.RowBuilder getWifiSliceItemRow(WifiSliceItem wifiSliceItem) {
|
||||
final CharSequence title = wifiSliceItem.getTitle();
|
||||
final IconCompat levelIcon = getWifiSliceItemLevelIcon(wifiSliceItem);
|
||||
final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
|
||||
|
Reference in New Issue
Block a user