Snap for 6589438 from 4634271464 to mainline-release

Change-Id: I9e0a87d2378b20181f87443be37e4995a9e8a5ce
This commit is contained in:
android-build-team Robot
2020-06-15 07:09:41 +00:00
23 changed files with 468 additions and 95 deletions

View File

@@ -30,21 +30,20 @@
<LinearLayout
android:id="@+id/panel_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="94dp"
android:gravity="start|center_vertical"
android:orientation="horizontal"
android:visibility="gone">
<LinearLayout
android:layout_width="36dp"
android:layout_height="36dp"
android:gravity="center_vertical|center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginStart="16dp">
<ImageView
android:id="@+id/title_icon"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
android:layout_width="@dimen/output_switcher_panel_icon_size"
android:layout_height="@dimen/output_switcher_panel_icon_size"/>
</LinearLayout>
<LinearLayout
@@ -52,10 +51,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingBottom="9dp"
android:paddingTop="9dp">
android:orientation="vertical">
<TextView
android:id="@+id/header_title"
android:layout_width="wrap_content"

View File

@@ -422,7 +422,9 @@
<dimen name="list_preferred_item_padding">16dp</dimen>
<!-- Output switcher panel related dimensions -->
<dimen name="output_switcher_slice_padding_top">12dp</dimen>
<dimen name="output_switcher_slice_padding_top">11dp</dimen>
<dimen name="output_switcher_slice_max_height">506dp</dimen>
<dimen name="output_switcher_panel_icon_size">52dp</dimen>
<!-- Text padding for EmptyTextSettings -->
<dimen name="empty_text_padding">24dp</dimen>

View File

@@ -11816,6 +11816,8 @@
<string name="network_connection_errorstate_dialog_message">Something came up. The application has cancelled the request to choose a device.</string>
<!-- Toast message when connection is successful [CHAR LIMIT=30] -->
<string name="network_connection_connect_successful">Connection successful</string>
<!-- Toast message when connection is failure [CHAR LIMIT=30] -->
<string name="network_connection_connect_failure">Connection failed</string>
<!-- Neutral button for Network connection request Dialog [CHAR LIMIT=30] -->
<string name="network_connection_request_dialog_showall">Show all</string>
<!-- Message for Network connection searching progress Dialog. Searching for wifi ap. [CHAR LIMIT=40] -->

View File

@@ -564,16 +564,17 @@
</style>
<style name="SliceRow.Slider">
<!-- 10dp start padding for the start icon -->
<item name="titleItemStartPadding">10dp</item>
<!-- 4dp start padding for the start icon -->
<item name="titleItemStartPadding">4dp</item>
<!-- Padding between content and the start icon is 0dp -->
<item name="contentStartPadding">0dp</item>
<item name="contentEndPadding">36dp</item>
<!-- 0dp start padding for the end item -->
<item name="endItemStartPadding">0dp</item>
<!-- 24dp end padding for the end item -->
<item name="endItemEndPadding">24dp</item>
<!-- 8dp end padding for the end item -->
<item name="endItemEndPadding">8dp</item>
<!-- Align text with slider -->
<item name="titleStartPadding">11dp</item>

View File

@@ -54,6 +54,7 @@ import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.Callbacks;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
@@ -321,7 +322,7 @@ public class AppStorageSettings extends AppInfoWithHeader
.setButton1OnClickListener(v -> handleClearDataClick());
}
if (mAppsControlDisallowedBySystem) {
if (mAppsControlDisallowedBySystem || AppUtils.isMainlineModule(mPm, mPackageName)) {
mButtonsPref.setButton1Enabled(false);
}
}
@@ -579,7 +580,7 @@ public class AppStorageSettings extends AppInfoWithHeader
.setButton2OnClickListener(v -> handleClearCacheClick());
}
}
if (mAppsControlDisallowedBySystem) {
if (mAppsControlDisallowedBySystem || AppUtils.isMainlineModule(mPm, mPackageName)) {
mButtonsPref.setButton1Enabled(false).setButton2Enabled(false);
}
}

View File

@@ -744,7 +744,9 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp
}
private boolean isSystemModule() {
return mAppEntry != null && AppUtils.isSystemModule(mContext, mAppEntry.info.packageName);
return mAppEntry != null
&& (AppUtils.isSystemModule(mContext, mAppEntry.info.packageName)
|| AppUtils.isMainlineModule(mPm, mAppEntry.info.packageName));
}
/**

View File

@@ -43,7 +43,7 @@ public class AppInstallerInfoPreferenceController extends AppInfoPreferenceContr
return DISABLED_FOR_USER;
}
if (AppUtils.isMainlineModule(mContext, mPackageName)) {
if (AppUtils.isMainlineModule(mContext.getPackageManager(), mPackageName)) {
return DISABLED_FOR_USER;
}

View File

@@ -37,6 +37,7 @@ import androidx.recyclerview.widget.ItemTouchHelper;
import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.homepage.contextualcards.slices.BluetoothUpdateWorker;
import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.slice.ContextualWifiScanWorker;
@@ -67,6 +68,7 @@ public class ContextualCardsFragment extends InstrumentedFragment implements
final Context context = getContext();
if (savedInstanceState == null) {
FeatureFactory.getFactory(context).getSlicesFeatureProvider().newUiSession();
BluetoothUpdateWorker.initLocalBtManager(getContext());
}
mContextualCardManager = new ContextualCardManager(context, getSettingsLifecycle(),
savedInstanceState);

View File

@@ -81,15 +81,12 @@ public class BluetoothDevicesSlice implements CustomSliceable {
private static boolean sBluetoothEnabling;
private final Context mContext;
private final AvailableMediaBluetoothDeviceUpdater mAvailableMediaBtDeviceUpdater;
private final SavedBluetoothDeviceUpdater mSavedBtDeviceUpdater;
private AvailableMediaBluetoothDeviceUpdater mAvailableMediaBtDeviceUpdater;
private SavedBluetoothDeviceUpdater mSavedBtDeviceUpdater;
public BluetoothDevicesSlice(Context context) {
mContext = context;
mAvailableMediaBtDeviceUpdater = new AvailableMediaBluetoothDeviceUpdater(mContext,
null /* fragment */, null /* devicePreferenceCallback */);
mSavedBtDeviceUpdater = new SavedBluetoothDeviceUpdater(mContext,
null /* fragment */, null /* devicePreferenceCallback */);
BluetoothUpdateWorker.initLocalBtManager(context);
}
@Override
@@ -119,16 +116,8 @@ public class BluetoothDevicesSlice implements CustomSliceable {
// Add the header of Bluetooth on
listBuilder.addRow(getBluetoothOnHeader());
// Get row builders of Bluetooth devices.
final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilders();
// Determine the displayable row count.
final int displayableCount = Math.min(rows.size(), DEFAULT_EXPANDED_ROW_COUNT);
// Add device rows up to the count.
for (int i = 0; i < displayableCount; i++) {
listBuilder.addRow(rows.get(i));
}
// Add row builders of Bluetooth devices.
getBluetoothRowBuilders().forEach(row -> listBuilder.addRow(row));
return listBuilder.build();
}
@@ -181,19 +170,18 @@ public class BluetoothDevicesSlice implements CustomSliceable {
List<CachedBluetoothDevice> getPairedBluetoothDevices() {
final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>();
// If Bluetooth is disable, skip to get the Bluetooth devices.
// If Bluetooth is disable, skip getting the Bluetooth devices.
if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
return bluetoothDeviceList;
}
// Get the Bluetooth devices from LocalBluetoothManager.
final LocalBluetoothManager localBtManager =
com.android.settings.bluetooth.Utils.getLocalBtManager(mContext);
final LocalBluetoothManager localBtManager = BluetoothUpdateWorker.getLocalBtManager();
if (localBtManager == null) {
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is unsupported.");
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is not ready.");
return bluetoothDeviceList;
}
final Collection<CachedBluetoothDevice> cachedDevices =
localBtManager.getCachedDeviceManager().getCachedDevicesCopy();
@@ -292,8 +280,21 @@ public class BluetoothDevicesSlice implements CustomSliceable {
private List<ListBuilder.RowBuilder> getBluetoothRowBuilders() {
final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
final List<CachedBluetoothDevice> pairedDevices = getPairedBluetoothDevices();
if (pairedDevices.isEmpty()) {
return bluetoothRows;
}
// Initialize updaters without being blocked after paired devices is available because
// LocalBluetoothManager is ready.
lazyInitUpdaters();
// Create row builders based on paired devices.
for (CachedBluetoothDevice device : getPairedBluetoothDevices()) {
for (CachedBluetoothDevice device : pairedDevices) {
if (bluetoothRows.size() >= DEFAULT_EXPANDED_ROW_COUNT) {
break;
}
String summary = device.getConnectionSummary();
if (summary == null) {
summary = mContext.getString(
@@ -321,6 +322,18 @@ public class BluetoothDevicesSlice implements CustomSliceable {
return bluetoothRows;
}
private void lazyInitUpdaters() {
if (mAvailableMediaBtDeviceUpdater == null) {
mAvailableMediaBtDeviceUpdater = new AvailableMediaBluetoothDeviceUpdater(mContext,
null /* fragment */, null /* devicePreferenceCallback */);
}
if (mSavedBtDeviceUpdater == null) {
mSavedBtDeviceUpdater = new SavedBluetoothDeviceUpdater(mContext,
null /* fragment */, null /* devicePreferenceCallback */);
}
}
@VisibleForTesting
SliceAction buildPrimaryBluetoothAction(CachedBluetoothDevice bluetoothDevice) {
final Intent intent = new Intent(getUri().toString())

View File

@@ -18,9 +18,14 @@ package com.android.settings.homepage.contextualcards.slices;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.util.Log;
import com.android.settings.bluetooth.Utils;
import androidx.annotation.Nullable;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -30,29 +35,46 @@ public class BluetoothUpdateWorker extends SliceBackgroundWorker implements Blue
private static final String TAG = "BluetoothUpdateWorker";
private final LocalBluetoothManager mLocalBluetoothManager;
private static LocalBluetoothManager sLocalBluetoothManager;
private LoadBtManagerHandler mLoadBtManagerHandler;
public BluetoothUpdateWorker(Context context, Uri uri) {
super(context, uri);
mLocalBluetoothManager = Utils.getLocalBtManager(context);
mLoadBtManagerHandler = LoadBtManagerHandler.getInstance(context);
if (sLocalBluetoothManager == null) {
mLoadBtManagerHandler.startLoadingBtManager(this);
}
}
/** Initialize {@link LocalBluetoothManager} in the background */
public static void initLocalBtManager(Context context) {
if (sLocalBluetoothManager == null) {
LoadBtManagerHandler.getInstance(context).startLoadingBtManager();
}
}
@Nullable
static LocalBluetoothManager getLocalBtManager() {
return sLocalBluetoothManager;
}
@Override
protected void onSlicePinned() {
if (mLocalBluetoothManager == null) {
Log.i(TAG, "onSlicePinned() Bluetooth is unsupported.");
final LocalBluetoothManager localBtManager = mLoadBtManagerHandler.getLocalBtManager();
if (localBtManager == null) {
return;
}
mLocalBluetoothManager.getEventManager().registerCallback(this);
localBtManager.getEventManager().registerCallback(this);
}
@Override
protected void onSliceUnpinned() {
if (mLocalBluetoothManager == null) {
Log.i(TAG, "onSliceUnpinned() Bluetooth is unsupported.");
final LocalBluetoothManager localBtManager = mLoadBtManagerHandler.getLocalBtManager();
if (localBtManager == null) {
return;
}
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
localBtManager.getEventManager().unregisterCallback(this);
}
@Override
@@ -84,4 +106,59 @@ public class BluetoothUpdateWorker extends SliceBackgroundWorker implements Blue
int bluetoothProfile) {
notifySliceChange();
}
private static class LoadBtManagerHandler extends Handler {
private static LoadBtManagerHandler sHandler;
private final Runnable mLoadBtManagerTask;
private final Context mContext;
private BluetoothUpdateWorker mWorker;
private static LoadBtManagerHandler getInstance(Context context) {
if (sHandler == null) {
final HandlerThread workerThread = new HandlerThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND);
workerThread.start();
sHandler = new LoadBtManagerHandler(context, workerThread.getLooper());
}
return sHandler;
}
private LoadBtManagerHandler(Context context, Looper looper) {
super(looper);
mContext = context;
mLoadBtManagerTask = () -> {
Log.d(TAG, "LoadBtManagerHandler: start loading...");
final long startTime = System.currentTimeMillis();
sLocalBluetoothManager = getLocalBtManager();
Log.d(TAG, "LoadBtManagerHandler took " + (System.currentTimeMillis() - startTime)
+ " ms");
};
}
private LocalBluetoothManager getLocalBtManager() {
if (sLocalBluetoothManager != null) {
return sLocalBluetoothManager;
}
return LocalBluetoothManager.getInstance(mContext,
(context, btManager) -> {
if (mWorker != null) {
// notify change if the worker is ready
mWorker.notifySliceChange();
}
});
}
private void startLoadingBtManager() {
if (!hasCallbacks(mLoadBtManagerTask)) {
post(mLoadBtManagerTask);
}
}
private void startLoadingBtManager(BluetoothUpdateWorker worker) {
mWorker = worker;
startLoadingBtManager();
}
}
}

View File

@@ -33,6 +33,9 @@ import android.text.BidiFormatter;
import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import com.android.internal.telephony.OperatorInfo;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -99,6 +102,35 @@ public final class CellInfoUtil {
return cellId;
}
/**
* Creates a CellInfo object from OperatorInfo. GsmCellInfo is used here only because
* operatorInfo does not contain technology type while CellInfo is an abstract object that
* requires to specify technology type. It doesn't matter which CellInfo type to use here, since
* we only want to wrap the operator info and PLMN to a CellInfo object.
*/
public static CellInfo convertOperatorInfoToCellInfo(OperatorInfo operatorInfo) {
final String operatorNumeric = operatorInfo.getOperatorNumeric();
String mcc = null;
String mnc = null;
if (operatorNumeric != null && operatorNumeric.matches("^[0-9]{5,6}$")) {
mcc = operatorNumeric.substring(0, 3);
mnc = operatorNumeric.substring(3);
}
final CellIdentityGsm cig = new CellIdentityGsm(
Integer.MAX_VALUE /* lac */,
Integer.MAX_VALUE /* cid */,
Integer.MAX_VALUE /* arfcn */,
Integer.MAX_VALUE /* bsic */,
mcc,
mnc,
operatorInfo.getOperatorAlphaLong(),
operatorInfo.getOperatorAlphaShort(),
Collections.emptyList());
final CellInfoGsm ci = new CellInfoGsm();
ci.setCellIdentity(cig);
return ci;
}
/** Convert a list of cellInfos to readable string without sensitive info. */
public static String cellInfoListToString(List<CellInfo> cellInfos) {

View File

@@ -57,6 +57,7 @@ public class NetworkOperatorPreference extends Preference {
private List<String> mForbiddenPlmns;
private int mLevel = LEVEL_NONE;
private boolean mShow4GForLTE;
private boolean mUseNewApi;
public NetworkOperatorPreference(Context context, CellInfo cellinfo,
List<String> forbiddenPlmns, boolean show4GForLTE) {
@@ -75,6 +76,8 @@ public class NetworkOperatorPreference extends Preference {
super(context);
mForbiddenPlmns = forbiddenPlmns;
mShow4GForLTE = show4GForLTE;
mUseNewApi = context.getResources().getBoolean(
com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
}
/**
@@ -215,7 +218,7 @@ public class NetworkOperatorPreference extends Preference {
}
private void updateIcon(int level) {
if (level < 0 || level >= NUM_SIGNAL_STRENGTH_BINS) {
if (!mUseNewApi || level < 0 || level >= NUM_SIGNAL_STRENGTH_BINS) {
return;
}
final Context context = getContext();

View File

@@ -16,6 +16,7 @@
package com.android.settings.network.telephony;
import android.annotation.IntDef;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CellInfo;
import android.telephony.NetworkScan;
@@ -25,9 +26,21 @@ import android.telephony.TelephonyManager;
import android.telephony.TelephonyScanManager;
import android.util.Log;
import com.android.internal.telephony.CellNetworkScanResult;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
/**
* A helper class that builds the common interface and performs the network scan for two different
@@ -70,6 +83,33 @@ public class NetworkScanHelper {
void onError(int errorCode);
}
@Retention(RetentionPolicy.SOURCE)
@IntDef({NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS, NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS})
public @interface NetworkQueryType {}
/**
* Performs the network scan using {@link TelephonyManager#getAvailableNetworks()}. The network
* scan results won't be returned to the caller until the network scan is completed.
*
* <p> This is typically used when the modem doesn't support the new network scan api
* {@link TelephonyManager#requestNetworkScan(
* NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
*/
public static final int NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS = 1;
/**
* Performs the network scan using {@link TelephonyManager#requestNetworkScan(
* NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
* results will be returned to the caller periodically in a small time window until the network
* scan is completed. The complete results should be returned in the last called of
* {@link NetworkScanCallback#onResults(List)}.
*
* <p> This is recommended to be used if modem supports the new network scan api
* {@link TelephonyManager#requestNetworkScan(
* NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
*/
public static final int NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS = 2;
/** The constants below are used in the async network scan. */
private static final boolean INCREMENTAL_RESULTS = true;
private static final int SEARCH_PERIODICITY_SEC = 5;
@@ -83,6 +123,9 @@ public class NetworkScanHelper {
private NetworkScan mNetworkScanRequester;
/** Callbacks for sync network scan */
private ListenableFuture<List<CellInfo>> mNetworkScanFuture;
public NetworkScanHelper(TelephonyManager tm, NetworkScanCallback callback, Executor executor) {
mTelephonyManager = tm;
mNetworkScanCallback = callback;
@@ -139,38 +182,63 @@ public class NetworkScanHelper {
}
/**
* Request a network scan.
* Performs a network scan for the given type {@code type}.
* {@link #NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS} is recommended if modem supports
* {@link TelephonyManager#requestNetworkScan(
* NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
*
* Performs the network scan using {@link TelephonyManager#requestNetworkScan(
* NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
* results will be returned to the caller periodically in a small time window until the network
* scan is completed. The complete results should be returned in the last called of
* {@link NetworkScanCallback#onResults(List)}.
* @param type used to tell which network scan API should be used.
*/
public void startNetworkScan() {
if (mNetworkScanRequester != null) {
return;
}
mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
createNetworkScanForPreferredAccessNetworks(),
mExecutor,
mInternalNetworkScanCallback);
if (mNetworkScanRequester == null) {
onError(NetworkScan.ERROR_RADIO_INTERFACE_ERROR);
public void startNetworkScan(@NetworkQueryType int type) {
if (type == NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS) {
mNetworkScanFuture = SettableFuture.create();
Futures.addCallback(mNetworkScanFuture, new FutureCallback<List<CellInfo>>() {
@Override
public void onSuccess(List<CellInfo> result) {
onResults(result);
onComplete();
}
@Override
public void onFailure(Throwable t) {
if (t instanceof CancellationException) {
return;
}
int errCode = Integer.parseInt(t.getMessage());
onError(errCode);
}
}, MoreExecutors.directExecutor());
mExecutor.execute(new NetworkScanSyncTask(
mTelephonyManager, (SettableFuture) mNetworkScanFuture));
} else if (type == NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS) {
if (mNetworkScanRequester != null) {
return;
}
mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
createNetworkScanForPreferredAccessNetworks(),
mExecutor,
mInternalNetworkScanCallback);
if (mNetworkScanRequester == null) {
onError(NetworkScan.ERROR_RADIO_INTERFACE_ERROR);
}
}
}
/**
* Stops the network scan.
*
* Use this method to stop an ongoing scan. When user requests a new scan, a {@link NetworkScan}
* object will be returned, and the user can stop the scan by calling this method.
* The network scan of type {@link #NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS} can't be stopped,
* however, the result of the current network scan won't be returned to the callback after
* calling this method.
*/
public void stopNetworkQuery() {
if (mNetworkScanRequester != null) {
mNetworkScanRequester.stopScan();
mNetworkScanRequester = null;
}
if (mNetworkScanFuture != null) {
mNetworkScanFuture.cancel(true /* mayInterruptIfRunning */);
mNetworkScanFuture = null;
}
}
private void onResults(List<CellInfo> cellInfos) {
@@ -185,6 +253,23 @@ public class NetworkScanHelper {
mNetworkScanCallback.onError(errCode);
}
/**
* Converts the status code of {@link CellNetworkScanResult} to one of the
* {@link NetworkScan.ScanErrorCode}.
* @param errCode status code from {@link CellNetworkScanResult}.
*
* @return one of the scan error code from {@link NetworkScan.ScanErrorCode}.
*/
private static int convertToScanErrorCode(int errCode) {
switch (errCode) {
case CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE:
return NetworkScan.ERROR_RADIO_INTERFACE_ERROR;
case CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE:
default:
return NetworkScan.ERROR_MODEM_ERROR;
}
}
private final class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback {
public void onResults(List<CellInfo> results) {
Log.d(TAG, "Async scan onResults() results = "
@@ -202,4 +287,35 @@ public class NetworkScanHelper {
NetworkScanHelper.this.onError(errCode);
}
}
private static final class NetworkScanSyncTask implements Runnable {
private final SettableFuture<List<CellInfo>> mCallback;
private final TelephonyManager mTelephonyManager;
NetworkScanSyncTask(
TelephonyManager telephonyManager, SettableFuture<List<CellInfo>> callback) {
mTelephonyManager = telephonyManager;
mCallback = callback;
}
@Override
public void run() {
final CellNetworkScanResult result = mTelephonyManager.getAvailableNetworks();
if (result.getStatus() == CellNetworkScanResult.STATUS_SUCCESS) {
final List<CellInfo> cellInfos = result.getOperators()
.stream()
.map(operatorInfo
-> CellInfoUtil.convertOperatorInfoToCellInfo(operatorInfo))
.collect(Collectors.toList());
Log.d(TAG, "Sync network scan completed, cellInfos = "
+ CellInfoUtil.cellInfoListToString(cellInfos));
mCallback.set(cellInfos);
} else {
final Throwable error = new Throwable(
Integer.toString(convertToScanErrorCode(result.getStatus())));
mCallback.setException(error);
Log.d(TAG, "Sync network scan error, ex = " + error);
}
}
}
}

View File

@@ -93,6 +93,8 @@ public class NetworkSelectSettings extends DashboardFragment {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mUseNewApi = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
mSubId = getArguments().getInt(Settings.EXTRA_SUB_ID);
mPreferenceCategory = findPreference(PREF_KEY_NETWORK_OPERATORS);
@@ -464,7 +466,10 @@ public class NetworkSelectSettings extends DashboardFragment {
if (mNetworkScanHelper != null) {
mRequestIdManualNetworkScan = getNewRequestId();
mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED;
mNetworkScanHelper.startNetworkScan();
mNetworkScanHelper.startNetworkScan(
mUseNewApi
? NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS
: NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
}
}

View File

@@ -95,6 +95,7 @@ public class PanelFragment extends Fragment {
private ImageView mTitleIcon;
private TextView mHeaderTitle;
private TextView mHeaderSubtitle;
private int mMaxHeight;
private final Map<Uri, LiveData<Slice>> mSliceLiveData = new LinkedHashMap<>();
@@ -105,6 +106,18 @@ public class PanelFragment extends Fragment {
return false;
};
private final ViewTreeObserver.OnGlobalLayoutListener mPanelLayoutListener =
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (mLayoutView.getHeight() > mMaxHeight) {
final ViewGroup.LayoutParams params = mLayoutView.getLayoutParams();
params.height = mMaxHeight;
mLayoutView.setLayoutParams(params);
}
}
};
private final ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener =
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
@@ -123,6 +136,9 @@ public class PanelFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
mLayoutView = inflater.inflate(R.layout.panel_layout, container, false);
mLayoutView.getViewTreeObserver()
.addOnGlobalLayoutListener(mPanelLayoutListener);
mMaxHeight = getResources().getDimensionPixelSize(R.dimen.output_switcher_slice_max_height);
createPanelContent();
return mLayoutView;
}
@@ -159,6 +175,9 @@ public class PanelFragment extends Fragment {
if (mLayoutView == null) {
activity.finish();
}
final ViewGroup.LayoutParams params = mLayoutView.getLayoutParams();
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
mLayoutView.setLayoutParams(params);
mPanelSlices = mLayoutView.findViewById(R.id.panel_parent_layout);
mSeeMoreButton = mLayoutView.findViewById(R.id.see_more);
@@ -214,6 +233,12 @@ public class PanelFragment extends Fragment {
mHeaderSubtitle.setText(mPanel.getSubTitle());
if (mPanel.getHeaderIconIntent() != null) {
mTitleIcon.setOnClickListener(getHeaderIconListener());
mTitleIcon.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
} else {
final int size = getResources().getDimensionPixelSize(
R.dimen.output_switcher_panel_icon_size);
mTitleIcon.setLayoutParams(new LinearLayout.LayoutParams(size, size));
}
}
mSeeMoreButton.setOnClickListener(getSeeMoreListener());
@@ -378,6 +403,9 @@ public class PanelFragment extends Fragment {
mPanelClosedKey = PanelClosedKeys.KEY_OTHERS;
}
if (mLayoutView != null) {
mLayoutView.getViewTreeObserver().removeOnGlobalLayoutListener(mPanelLayoutListener);
}
mMetricsProvider.action(
0 /* attribution */,
SettingsEnums.PAGE_HIDE,

View File

@@ -216,13 +216,12 @@ public class NetworkRequestDialogActivity extends FragmentActivity implements
@Override
public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
if (mIsSpecifiedSsid) {
showSingleSsidRequestDialog(
WifiInfo.sanitizeSsid(mMatchedConfig.SSID), true /* isTryAgain */);
return;
if (!isFinishing()) {
Toast.makeText(this, R.string.network_connection_connect_failure, Toast.LENGTH_SHORT)
.show();
setResult(RESULT_OK);
finish();
}
mDialogFragment.onUserSelectionConnectFailure(wificonfiguration);
}
// Called when user click "Connect" button. Called by

View File

@@ -21,7 +21,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import androidx.annotation.NonNull;
@@ -91,7 +90,4 @@ abstract public class NetworkRequestDialogBaseFragment extends InstrumentedDialo
protected void onMatch(List<ScanResult> scanResults) {
}
protected void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
}
}

View File

@@ -324,11 +324,6 @@ public class NetworkRequestDialogFragment extends NetworkRequestDialogBaseFragme
}
}
@Override
public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
// Do nothing when selection is failed, let user could try again easily.
}
@VisibleForTesting
final class FilterWifiTracker {
private final List<String> mAccessPointKeys;

View File

@@ -16,9 +16,9 @@
package com.android.settings.applications;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
@@ -28,6 +28,10 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.view.View;
import android.widget.Button;
@@ -51,6 +55,8 @@ public class AppStorageSettingsTest {
private AppStorageSettings mSettings;
private Button mLeftButton;
private Button mRightButton;
@Mock
private PackageManager mPackageManager;
@Before
public void setUp() {
@@ -58,6 +64,8 @@ public class AppStorageSettingsTest {
mLeftButton = new Button(RuntimeEnvironment.application);
mRightButton = new Button(RuntimeEnvironment.application);
mSettings = spy(new AppStorageSettings());
mSettings.mPm = mPackageManager;
mSettings.mPackageName = "Package";
mSettings.mSizeController = mSizesController;
mButtonsPref = createMock();
mSettings.mButtonsPref = mButtonsPref;
@@ -77,7 +85,9 @@ public class AppStorageSettingsTest {
}
@Test
public void updateUiWithSize_noAppStats_shouldDisableClearButtons() {
public void updateUiWithSize_noAppStats_shouldDisableClearButtons()
throws PackageManager.NameNotFoundException {
mockMainlineModule(mSettings.mPackageName, false /* isMainlineModule */);
mSettings.updateUiWithSize(null);
verify(mSizesController).updateUi(nullable(Context.class));
@@ -86,12 +96,15 @@ public class AppStorageSettingsTest {
}
@Test
public void updateUiWithSize_hasDataAndCache_shouldEnableClearButtons() {
public void updateUiWithSize_hasDataAndCache_shouldEnableClearButtons()
throws PackageManager.NameNotFoundException {
final AppStorageStats stats = mock(AppStorageStats.class);
when(stats.getCacheBytes()).thenReturn(5000L);
when(stats.getDataBytes()).thenReturn(10000L);
doNothing().when(mSettings).handleClearCacheClick();
doNothing().when(mSettings).handleClearDataClick();
mockMainlineModule(mSettings.mPackageName, false /* isMainlineModule */);
mSettings.updateUiWithSize(stats);
verify(mButtonsPref).setButton1Enabled(true);
@@ -105,6 +118,22 @@ public class AppStorageSettingsTest {
verify(mSettings).handleClearCacheClick();
}
@Test
public void updateUiWithSize_mainlineModule_shouldDisableClearButtons()
throws PackageManager.NameNotFoundException {
final AppStorageStats stats = mock(AppStorageStats.class);
when(stats.getCacheBytes()).thenReturn(5000L);
when(stats.getDataBytes()).thenReturn(10000L);
doNothing().when(mSettings).handleClearCacheClick();
doNothing().when(mSettings).handleClearDataClick();
mockMainlineModule(mSettings.mPackageName, true /* isMainlineModule */);
mSettings.updateUiWithSize(stats);
verify(mButtonsPref).setButton1Enabled(false);
verify(mButtonsPref).setButton2Enabled(false);
}
private ActionButtonsPreference createMock() {
final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
when(pref.setButton1Text(anyInt())).thenReturn(pref);
@@ -121,5 +150,23 @@ public class AppStorageSettingsTest {
return pref;
}
private void mockMainlineModule(String packageName, boolean isMainlineModule)
throws PackageManager.NameNotFoundException {
final PackageInfo packageInfo = new PackageInfo();
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.sourceDir = "apex";
packageInfo.applicationInfo = applicationInfo;
if (isMainlineModule) {
when(mPackageManager.getModuleInfo(packageName, 0 /* flags */)).thenReturn(
new ModuleInfo());
} else {
when(mPackageManager.getPackageInfo(packageName, 0 /* flags */)).thenReturn(
packageInfo);
when(mPackageManager.getModuleInfo(packageName, 0 /* flags */)).thenThrow(
new PackageManager.NameNotFoundException());
}
}
}

View File

@@ -543,6 +543,19 @@ public class AppButtonsPreferenceControllerTest {
assertThat(i.getBooleanExtra(KEY_REMOVE_TASK_WHEN_FINISHING, false)).isFalse();
}
@Test
@Config(shadows = ShadowAppUtils.class)
public void isAvailable_nonMainlineModule_isTrue() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
@Config(shadows = ShadowAppUtils.class)
public void isAvailable_mainlineModule_isFalse() {
ShadowAppUtils.addMainlineModule(mController.mPackageName);
assertThat(mController.isAvailable()).isFalse();
}
/**
* The test fragment which implements
* {@link ButtonActionDialogFragment.AppButtonsDialogListener}
@@ -597,16 +610,22 @@ public class AppButtonsPreferenceControllerTest {
public static class ShadowAppUtils {
public static Set<String> sSystemModules = new ArraySet<>();
public static Set<String> sMainlineModules = new ArraySet<>();
@Resetter
public static void reset() {
sSystemModules.clear();
sMainlineModules.clear();
}
public static void addHiddenModule(String pkg) {
sSystemModules.add(pkg);
}
public static void addMainlineModule(String pkg) {
sMainlineModules.add(pkg);
}
@Implementation
protected static boolean isInstant(ApplicationInfo info) {
return false;
@@ -616,5 +635,10 @@ public class AppButtonsPreferenceControllerTest {
protected static boolean isSystemModule(Context context, String packageName) {
return sSystemModules.contains(packageName);
}
@Implementation
protected static boolean isMainlineModule(PackageManager pm, String packageName) {
return sMainlineModules.contains(packageName);
}
}
}

View File

@@ -99,12 +99,15 @@ public class AppInstallerInfoPreferenceControllerTest {
}
@Test
public void getAvailabilityStatus_hasAppLabel_shouldReturnAvailable() {
public void getAvailabilityStatus_hasAppLabel_shouldReturnAvailable()
throws PackageManager.NameNotFoundException {
final String packageName = "Package1";
when(mUserManager.isManagedProfile()).thenReturn(false);
when(mAppInfo.loadLabel(mPackageManager)).thenReturn("Label1");
mController = new AppInstallerInfoPreferenceController(mContext, "test_key");
mController.setPackageName("Package1");
mController.setPackageName(packageName);
mController.setParentFragment(mFragment);
mockMainlineModule(packageName, false /* isMainlineModule */);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
@@ -153,12 +156,31 @@ public class AppInstallerInfoPreferenceControllerTest {
@Test
public void getAvailabilityStatus_isMainlineModule_shouldReturnDisabled()
throws PackageManager.NameNotFoundException {
final String packageName = "Package";
when(mUserManager.isManagedProfile()).thenReturn(false);
when(mAppInfo.loadLabel(mPackageManager)).thenReturn("Label");
mController.setPackageName("Package");
when(mPackageManager.getModuleInfo("Package", 0 /* flags */)).thenReturn(new ModuleInfo());
mController.setPackageName(packageName);
mockMainlineModule(packageName, true /* isMainlineModule */);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.DISABLED_FOR_USER);
}
private void mockMainlineModule(String packageName, boolean isMainlineModule)
throws PackageManager.NameNotFoundException {
final PackageInfo packageInfo = new PackageInfo();
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.sourceDir = "apex";
packageInfo.applicationInfo = applicationInfo;
if (isMainlineModule) {
when(mPackageManager.getModuleInfo(packageName, 0 /* flags */)).thenReturn(
new ModuleInfo());
} else {
when(mPackageManager.getPackageInfo(packageName, 0 /* flags */)).thenReturn(
packageInfo);
when(mPackageManager.getModuleInfo(packageName, 0 /* flags */)).thenThrow(
new PackageManager.NameNotFoundException());
}
}
}

View File

@@ -164,7 +164,8 @@ public class NetworkScanHelperTest {
}
private void startNetworkScan_incremental(boolean waitForCompletion) {
mNetworkScanHelper.startNetworkScan();
mNetworkScanHelper.startNetworkScan(
NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS);
if (!waitForCompletion) {
mNetworkScanHelper.stopNetworkQuery();
}

View File

@@ -126,4 +126,13 @@ public class NetworkRequestDialogActivityTest {
verify(mActivity).finish();
}
@Test
public void updateAccessPointList_onUserSelectionConnectFailure_shouldFinishActivity() {
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
mActivity.onUserSelectionConnectFailure(config);
verify(mActivity).finish();
}
}