diff --git a/res/drawable/ic_signal_flashlight.xml b/res/drawable/ic_signal_flashlight.xml
new file mode 100644
index 00000000000..e63595300d5
--- /dev/null
+++ b/res/drawable/ic_signal_flashlight.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 37462f9ba7d..cbfc42814ab 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -268,17 +268,27 @@
-
+
+ - 0
+ - 1
+
+
+
- @string/wifi_ap_choose_2G
- @string/wifi_ap_choose_5G
-
- - @string/wifi_ap_2G
- - @string/wifi_ap_5G
+
+ - 0
+ - -1
-
+
+ - @string/wifi_ap_choose_2G
+ - @string/wifi_ap_prefer_5G
+
+
+
- @string/wifi_ap_choose_auto
- @string/wifi_ap_choose_2G
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e64bd87f8a5..773e17f8a4a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1993,8 +1993,10 @@
Auto
2.4 GHz Band
-
+
5.0 GHz Band
+
+ 5.0 GHz Band preferred
2.4 GHz
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index f563643aea4..fbb464ca938 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -56,6 +56,7 @@
android:title="@string/zen_mode_settings_title"
settings:useAdminDisabledSummary="true"
android:fragment="com.android.settings.notification.ZenModeSettings"
+ settings:controller="com.android.settings.notification.ZenModePreferenceController"
settings:allowDividerAbove="false" />
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index 650b1c44005..9f69102a3cb 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -67,6 +67,6 @@
android:key="gesture_prevent_ringing_summary"
android:title="@string/gesture_prevent_ringing_screen_title"
android:fragment="com.android.settings.gestures.PreventRingingGestureSettings"
- settings:controller="com.android.settings.gestures.PreventRingingPreferenceController" />
+ settings:controller="com.android.settings.gestures.PreventRingingParentPreferenceController" />
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 54a4190b8ef..d38a8e4dc7c 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -94,14 +94,15 @@
android:order="-120"
settings:useAdminDisabledSummary="true"
settings:keywords="@string/keywords_sounds_and_notifications_interruptions"
- settings:allowDividerAbove="true"/>
+ settings:allowDividerAbove="true"
+ settings:controller="com.android.settings.notification.ZenModePreferenceController" />
+ settings:controller="com.android.settings.gestures.PreventRingingParentPreferenceController" />
-
+ android:title="@string/wifi_hotspot_ap_band_title" />
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index c04269c1696..557c39b1648 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -17,6 +17,7 @@
package com.android.settings;
import static android.net.ConnectivityManager.NetworkCallback;
+import static android.provider.Settings.Global.PREFERRED_NETWORK_MODE;
import android.app.Activity;
import android.app.AlertDialog;
@@ -39,6 +40,7 @@ import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.CellInfo;
import android.telephony.CellInfoCdma;
@@ -1451,6 +1453,19 @@ public class RadioInfo extends Activity {
if (mPreferredNetworkTypeResult != pos && pos >= 0
&& pos <= mPreferredNetworkLabels.length - 2) {
mPreferredNetworkTypeResult = pos;
+
+ // TODO: Possibly migrate this to TelephonyManager.setPreferredNetworkType()
+ // which today still has some issues (mostly that the "set" is conditional
+ // on a successful modem call, which is not what we want). Instead we always
+ // want this setting to be set, so that if the radio hiccups and this setting
+ // is for some reason unsuccessful, future calls to the radio will reflect
+ // the users's preference which is set here.
+ final int subId = phone.getSubId();
+ if (SubscriptionManager.isUsableSubIdValue(subId)) {
+ Settings.Global.putInt(phone.getContext().getContentResolver(),
+ PREFERRED_NETWORK_MODE + subId, mPreferredNetworkTypeResult);
+ }
+ log("Calling setPreferredNetworkType(" + mPreferredNetworkTypeResult + ")");
Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
phone.setPreferredNetworkType(mPreferredNetworkTypeResult, msg);
}
diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java
index 66f9179ed64..66e8d2205c0 100644
--- a/src/com/android/settings/accounts/AccountSyncSettings.java
+++ b/src/com/android/settings/accounts/AccountSyncSettings.java
@@ -247,10 +247,13 @@ public class AccountSyncSettings extends AccountPreferenceBase {
}
if (preference instanceof SyncStateSwitchPreference) {
SyncStateSwitchPreference syncPref = (SyncStateSwitchPreference) preference;
- String authority = syncPref.getAuthority();
- Account account = syncPref.getAccount();
+ final String authority = syncPref.getAuthority();
+ if (TextUtils.isEmpty(authority)) {
+ return false;
+ }
+ final Account account = syncPref.getAccount();
final int userId = mUserHandle.getIdentifier();
- String packageName = syncPref.getPackageName();
+ final String packageName = syncPref.getPackageName();
boolean syncAutomatically = ContentResolver.getSyncAutomaticallyAsUser(account,
authority, userId);
diff --git a/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java b/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
index 8153be281b3..c243970bad0 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
@@ -17,9 +17,11 @@
package com.android.settings.applications.defaultapps;
import android.content.Context;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.util.ArraySet;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -27,6 +29,7 @@ import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Fragment for choosing default browser.
@@ -62,14 +65,20 @@ public class DefaultBrowserPicker extends DefaultAppPickerFragment {
DefaultBrowserPreferenceController.BROWSE_PROBE, PackageManager.MATCH_ALL, mUserId);
final int count = list.size();
+ final Set addedPackages = new ArraySet<>();
for (int i = 0; i < count; i++) {
ResolveInfo info = list.get(i);
if (info.activityInfo == null || !info.handleAllWebDataURI) {
continue;
}
+ final String packageName = info.activityInfo.packageName;
+ if (addedPackages.contains(packageName)) {
+ continue;
+ }
try {
candidates.add(new DefaultAppInfo(context, mPm,
- mPm.getApplicationInfoAsUser(info.activityInfo.packageName, 0, mUserId)));
+ mPm.getApplicationInfoAsUser(packageName, 0, mUserId)));
+ addedPackages.add(packageName);
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}
diff --git a/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java b/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
index bb60df929e4..27b7676a2f2 100644
--- a/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
@@ -21,11 +21,13 @@ import android.content.pm.PackageManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.SavedBluetoothDeviceUpdater;
+import com.android.settings.connecteddevice.dock.DockUpdater;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
-
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -35,10 +37,14 @@ public class PreviouslyConnectedDevicePreferenceController extends BasePreferenc
private Preference mPreference;
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
+ private DockUpdater mSavedDockUpdater;
private int mPreferenceSize;
public PreviouslyConnectedDevicePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
+
+ mSavedDockUpdater = FeatureFactory.getFactory(
+ context).getDockUpdaterFeatureProvider().getSavedDockUpdater(context, this);
}
@Override
@@ -60,12 +66,14 @@ public class PreviouslyConnectedDevicePreferenceController extends BasePreferenc
@Override
public void onStart() {
mBluetoothDeviceUpdater.registerCallback();
+ mSavedDockUpdater.registerCallback();
updatePreferenceOnSizeChanged();
}
@Override
public void onStop() {
mBluetoothDeviceUpdater.unregisterCallback();
+ mSavedDockUpdater.unregisterCallback();
}
public void init(DashboardFragment fragment) {
@@ -90,6 +98,11 @@ public class PreviouslyConnectedDevicePreferenceController extends BasePreferenc
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
}
+ @VisibleForTesting
+ void setSavedDockUpdater(DockUpdater savedDockUpdater) {
+ mSavedDockUpdater = savedDockUpdater;
+ }
+
@VisibleForTesting
void setPreferenceSize(int size) {
mPreferenceSize = size;
@@ -105,4 +118,4 @@ public class PreviouslyConnectedDevicePreferenceController extends BasePreferenc
mPreference.setEnabled(mPreferenceSize != 0);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
index 95a534cdd42..03bba42f5be 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
@@ -24,6 +24,7 @@ import androidx.annotation.Nullable;
import android.view.View;
import android.widget.Button;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -35,7 +36,8 @@ import com.android.settings.password.ChooseLockSettingsHelper;
*/
public class FingerprintEnrollFindSensor extends FingerprintEnrollBase {
- private static final int CONFIRM_REQUEST = 1;
+ @VisibleForTesting
+ static final int CONFIRM_REQUEST = 1;
private static final int ENROLLING = 2;
public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
@@ -170,7 +172,7 @@ public class FingerprintEnrollFindSensor extends FingerprintEnrollBase {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CONFIRM_REQUEST) {
- if (resultCode == RESULT_OK) {
+ if (resultCode == RESULT_OK && data != null) {
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
diff --git a/src/com/android/settings/fingerprint/FingerprintSettings.java b/src/com/android/settings/fingerprint/FingerprintSettings.java
index 0fd3f8be338..4aaf997dd85 100644
--- a/src/com/android/settings/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/fingerprint/FingerprintSettings.java
@@ -785,6 +785,7 @@ public class FingerprintSettings extends SubSettings {
if (mDeleteInProgress) {
mAlertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(false);
}
+ mDialogTextField.requestFocus();
}
});
if (mTextHadFocus == null || mTextHadFocus) {
diff --git a/src/com/android/settings/flashlight/FlashlightSliceBuilder.java b/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
new file mode 100644
index 00000000000..6317ce760f4
--- /dev/null
+++ b/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2018 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.flashlight;
+
+import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+
+import android.annotation.ColorInt;
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.net.Uri;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.provider.SettingsSlicesContract;
+import android.util.Log;
+
+import androidx.core.graphics.drawable.IconCompat;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.SliceBroadcastReceiver;
+
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+import android.app.StatusBarManager;
+
+
+/**
+ * Utility class to build a Flashlight Slice, and handle all associated actions.
+ */
+public class FlashlightSliceBuilder {
+
+ private static final String TAG = "FlashlightSliceBuilder";
+
+ public static final String KEY_FLASHLIGHT = "flashlight";
+
+ /**
+ * Backing Uri for the Flashlight Slice.
+ */
+ public static final Uri FLASHLIGHT_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(KEY_FLASHLIGHT)
+ .build();
+
+ /**
+ * Action notifying a change on the Flashlight Slice.
+ */
+ public static final String ACTION_FLASHLIGHT_SLICE_CHANGED =
+ "com.android.settings.flashlight.action.FLASHLIGHT_SLICE_CHANGED";
+
+ /**
+ * Action broadcasting a change on whether flashlight is on or off.
+ */
+ public static final String ACTION_FLASHLIGHT_CHANGED =
+ "com.android.settings.flashlight.action.FLASHLIGHT_CHANGED";
+
+ public static final IntentFilter INTENT_FILTER = new IntentFilter(ACTION_FLASHLIGHT_CHANGED);
+
+ private FlashlightSliceBuilder() {}
+
+ /**
+ * Return a Flashlight Slice bound to {@link #FLASHLIGHT_URI}.
+ */
+ public static Slice getSlice(Context context) {
+ if (!isFlashlightAvailable(context)) {
+ return null;
+ }
+ final PendingIntent toggleAction = getBroadcastIntent(context);
+ @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
+ final IconCompat icon =
+ IconCompat.createWithResource(context, R.drawable.ic_signal_flashlight);
+ return new ListBuilder(context, FLASHLIGHT_URI, ListBuilder.INFINITY)
+ .setAccentColor(color)
+ .addRow(b -> b
+ .setTitle(context.getText(R.string.power_flashlight))
+ .setTitleItem(icon, ICON_IMAGE)
+ .setPrimaryAction(
+ new SliceAction(toggleAction, null, isFlashlightEnabled(context))))
+ .build();
+ }
+
+ /**
+ * Update the current flashlight status to the boolean value keyed by
+ * {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
+ */
+ public static void handleUriChange(Context context, Intent intent) {
+ try {
+ final String cameraId = getCameraId(context);
+ if (cameraId != null) {
+ final boolean state = intent.getBooleanExtra(
+ EXTRA_TOGGLE_STATE, isFlashlightEnabled(context));
+ final CameraManager cameraManager = context.getSystemService(CameraManager.class);
+ cameraManager.setTorchMode(cameraId, state);
+ }
+ } catch (CameraAccessException e) {
+ Log.e(TAG, "Camera couldn't set torch mode.", e);
+ }
+ context.getContentResolver().notifyChange(FLASHLIGHT_URI, null);
+ }
+
+ private static String getCameraId(Context context) throws CameraAccessException {
+ final CameraManager cameraManager = context.getSystemService(CameraManager.class);
+ final String[] ids = cameraManager.getCameraIdList();
+ for (String id : ids) {
+ CameraCharacteristics c = cameraManager.getCameraCharacteristics(id);
+ Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
+ Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
+ if (flashAvailable != null && flashAvailable
+ && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
+ return id;
+ }
+ }
+ return null;
+ }
+
+ private static PendingIntent getBroadcastIntent(Context context) {
+ final Intent intent = new Intent(ACTION_FLASHLIGHT_SLICE_CHANGED);
+ intent.setClass(context, SliceBroadcastReceiver.class);
+ return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+
+ private static boolean isFlashlightAvailable(Context context) {
+ return Settings.Secure.getInt(
+ context.getContentResolver(), Secure.FLASHLIGHT_AVAILABLE, 0) == 1;
+ }
+
+ private static boolean isFlashlightEnabled(Context context) {
+ return Settings.Secure.getInt(
+ context.getContentResolver(), Secure.FLASHLIGHT_ENABLED, 0) == 1;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batterytip/StatsManagerConfig.java b/src/com/android/settings/fuelgauge/batterytip/StatsManagerConfig.java
index a0d4e9baf9d..7d81c4273d8 100644
--- a/src/com/android/settings/fuelgauge/batterytip/StatsManagerConfig.java
+++ b/src/com/android/settings/fuelgauge/batterytip/StatsManagerConfig.java
@@ -46,15 +46,181 @@ public class StatsManagerConfig {
AnomalyType.EXCESSIVE_WAKEUPS_IN_BACKGROUND,
AnomalyType.EXCESSIVE_UNOPTIMIZED_BLE_SCAN,
AnomalyType.EXCESSIVE_BACKGROUND_SERVICE,
- AnomalyType.EXCESSIVE_WIFI_SCAN})
+ AnomalyType.EXCESSIVE_WIFI_SCAN,
+ AnomalyType.EXCESSIVE_FLASH_WRITES,
+ AnomalyType.EXCESSIVE_MEMORY_IN_BACKGROUND,
+ AnomalyType.EXCESSIVE_DAVEY_RATE,
+ AnomalyType.EXCESSIVE_JANKY_FRAMES,
+ AnomalyType.SLOW_COLD_START_TIME,
+ AnomalyType.SLOW_HOT_START_TIME,
+ AnomalyType.SLOW_WARM_START_TIME,
+ AnomalyType.EXCESSIVE_BACKGROUND_SYNCS,
+ AnomalyType.EXCESSIVE_GPS_SCANS_IN_BACKGROUND,
+ AnomalyType.EXCESSIVE_JOB_SCHEDULING,
+ AnomalyType.EXCESSIVE_MOBILE_NETWORK_IN_BACKGROUND,
+ AnomalyType.EXCESSIVE_WIFI_LOCK_TIME,
+ AnomalyType.JOB_TIMED_OUT,
+ AnomalyType.LONG_UNOPTIMIZED_BLE_SCAN,
+ AnomalyType.BACKGROUND_ANR,
+ AnomalyType.BACKGROUND_CRASH_RATE,
+ AnomalyType.EXCESSIVE_ANR_LOOPING,
+ AnomalyType.EXCESSIVE_ANRS,
+ AnomalyType.EXCESSIVE_CRASH_RATE,
+ AnomalyType.EXCESSIVE_CRASH_LOOPING,
+ AnomalyType.NUMBER_OF_OPEN_FILES,
+ })
public @interface AnomalyType {
+ /**
+ * This represents an error condition in the anomaly detection.
+ */
int NULL = -1;
+
+ /**
+ * The anomaly type does not match any other defined type.
+ */
int UNKNOWN_REASON = 0;
+
+ /**
+ * The application held a partial (screen off) wake lock for a period of time that
+ * exceeded the threshold with the screen off when not charging.
+ */
int EXCESSIVE_WAKELOCK_ALL_SCREEN_OFF = 1;
+
+ /**
+ * The application exceeded the maximum number of wakeups while in the background
+ * when not charging.
+ */
int EXCESSIVE_WAKEUPS_IN_BACKGROUND = 2;
+
+ /**
+ * The application did unoptimized Bluetooth scans too frequently when not charging.
+ */
int EXCESSIVE_UNOPTIMIZED_BLE_SCAN = 3;
+
+ /**
+ * The application ran in the background for a period of time that exceeded the
+ * threshold.
+ */
int EXCESSIVE_BACKGROUND_SERVICE = 4;
+
+ /**
+ * The application exceeded the maximum number of wifi scans when not charging.
+ */
int EXCESSIVE_WIFI_SCAN = 5;
+
+ /**
+ * The application exceed the maximum number of flash writes
+ */
+ int EXCESSIVE_FLASH_WRITES = 6;
+
+ /**
+ * The application used more than the maximum memory, while not spending any time
+ * in the foreground.
+ */
+ int EXCESSIVE_MEMORY_IN_BACKGROUND = 7;
+
+ /**
+ * The application exceeded the maximum percentage of frames with a render rate of
+ * greater than 700ms.
+ */
+ int EXCESSIVE_DAVEY_RATE = 8;
+
+ /**
+ * The application exceeded the maximum percentage of frames with a render rate
+ * greater than 16ms.
+ */
+ int EXCESSIVE_JANKY_FRAMES = 9;
+
+ /**
+ * The application exceeded the maximum cold start time - the app has not been
+ * launched since last system start, died or was killed.
+ */
+ int SLOW_COLD_START_TIME = 10;
+
+ /**
+ * The application exceeded the maximum hot start time - the app and activity are
+ * already in memory.
+ */
+ int SLOW_HOT_START_TIME = 11;
+
+ /**
+ * The application exceeded the maximum warm start time - the app was already in
+ * memory but the activity wasn’t created yet or was removed from memory.
+ */
+ int SLOW_WARM_START_TIME = 12;
+
+ /**
+ * The application exceeded the maximum number of syncs while in the background.
+ */
+ int EXCESSIVE_BACKGROUND_SYNCS = 13;
+
+ /**
+ * The application exceeded the maximum number of gps scans while in the background.
+ */
+ int EXCESSIVE_GPS_SCANS_IN_BACKGROUND = 14;
+
+ /**
+ * The application scheduled more than the maximum number of jobs while not charging.
+ */
+ int EXCESSIVE_JOB_SCHEDULING = 15;
+
+ /**
+ * The application exceeded the maximum amount of mobile network traffic while in
+ * the background.
+ */
+ int EXCESSIVE_MOBILE_NETWORK_IN_BACKGROUND = 16;
+
+ /**
+ * The application held the WiFi lock for more than the maximum amount of time while
+ * not charging.
+ */
+ int EXCESSIVE_WIFI_LOCK_TIME = 17;
+
+ /**
+ * The application scheduled a job that ran longer than the maximum amount of time.
+ */
+ int JOB_TIMED_OUT = 18;
+
+ /**
+ * The application did an unoptimized Bluetooth scan that exceeded the maximum
+ * time while in the background.
+ */
+ int LONG_UNOPTIMIZED_BLE_SCAN = 19;
+
+ /**
+ * The application exceeded the maximum ANR rate while in the background.
+ */
+ int BACKGROUND_ANR = 20;
+
+ /**
+ * The application exceeded the maximum crash rate while in the background.
+ */
+ int BACKGROUND_CRASH_RATE = 21;
+
+ /**
+ * The application exceeded the maximum ANR-looping rate.
+ */
+ int EXCESSIVE_ANR_LOOPING = 22;
+
+ /**
+ * The application exceeded the maximum ANR rate.
+ */
+ int EXCESSIVE_ANRS = 23;
+
+ /**
+ * The application exceeded the maximum crash rate.
+ */
+ int EXCESSIVE_CRASH_RATE = 24;
+
+ /**
+ * The application exceeded the maximum crash-looping rate.
+ */
+ int EXCESSIVE_CRASH_LOOPING = 25;
+
+ /**
+ * The application crashed because no more file descriptors were available.
+ */
+ int NUMBER_OF_OPEN_FILES = 26;
}
}
diff --git a/src/com/android/settings/gestures/PreventRingingParentPreferenceController.java b/src/com/android/settings/gestures/PreventRingingParentPreferenceController.java
new file mode 100644
index 00000000000..88147657b27
--- /dev/null
+++ b/src/com/android/settings/gestures/PreventRingingParentPreferenceController.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 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.gestures;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class PreventRingingParentPreferenceController extends BasePreferenceController {
+
+ public PreventRingingParentPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_volumeHushGestureEnabled)
+ ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
+ }
+
+}
diff --git a/src/com/android/settings/gestures/PreventRingingPreferenceController.java b/src/com/android/settings/gestures/PreventRingingPreferenceController.java
index c6bc3aa8f26..be55151f91e 100644
--- a/src/com/android/settings/gestures/PreventRingingPreferenceController.java
+++ b/src/com/android/settings/gestures/PreventRingingPreferenceController.java
@@ -24,14 +24,8 @@ import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.VideoPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
@@ -39,8 +33,13 @@ import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
-public class PreventRingingPreferenceController extends BasePreferenceController
- implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+public class PreventRingingPreferenceController extends PreventRingingParentPreferenceController
+ implements Preference.OnPreferenceChangeListener,
LifecycleObserver, OnResume, OnPause, OnCreate, OnSaveInstanceState {
private static final String PREF_KEY_VIDEO = "gesture_prevent_ringing_video";
@@ -59,9 +58,11 @@ public class PreventRingingPreferenceController extends BasePreferenceController
@Override
public int getAvailabilityStatus() {
- return mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_volumeHushGestureEnabled)
- ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ final int status = super.getAvailabilityStatus();
+ if (status == AVAILABLE_UNSEARCHABLE) {
+ return AVAILABLE;
+ }
+ return status;
}
@Override
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index cdc02c042d8..96a4eb62a6c 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -24,8 +24,6 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.SearchIndexableResource;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -42,6 +40,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
@SearchIndexable
public class ConfigureNotificationSettings extends DashboardFragment {
private static final String TAG = "ConfigNotiSettings";
@@ -57,7 +58,6 @@ public class ConfigureNotificationSettings extends DashboardFragment {
static final String KEY_SWIPE_DOWN = "gesture_swipe_down_fingerprint_notifications";
private static final String KEY_NOTI_DEFAULT_RINGTONE = "notification_default_ringtone";
- private static final String KEY_ZEN_MODE = "zen_mode_notifications";
private RingtonePreference mRequestPreference;
private static final int REQUEST_CODE = 200;
@@ -111,7 +111,6 @@ public class ConfigureNotificationSettings extends DashboardFragment {
}
});
- controllers.add(new ZenModePreferenceController(context, lifecycle, KEY_ZEN_MODE));
return controllers;
}
@@ -220,7 +219,6 @@ public class ConfigureNotificationSettings extends DashboardFragment {
keys.add(KEY_LOCKSCREEN);
keys.add(KEY_LOCKSCREEN_WORK_PROFILE);
keys.add(KEY_LOCKSCREEN_WORK_PROFILE_HEADER);
- keys.add(KEY_ZEN_MODE);
return keys;
}
};
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 7ad22a93bd0..dbac1c264c6 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -27,10 +27,6 @@ import android.preference.SeekBarVolumizer;
import android.provider.SearchIndexableResource;
import android.text.TextUtils;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -50,13 +46,16 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
@SearchIndexable
public class SoundSettings extends DashboardFragment {
private static final String TAG = "SoundSettings";
private static final String SELECTED_PREFERENCE_KEY = "selected_preference";
private static final int REQUEST_CODE = 200;
- private static final String KEY_ZEN_MODE = "zen_mode";
private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds
@VisibleForTesting
@@ -190,7 +189,7 @@ public class SoundSettings extends DashboardFragment {
onPreferenceDataChanged(listPreference));
mMediaOutputControllerKey = use(MediaOutputPreferenceController.class).getPreferenceKey();
use(HandsFreeProfileOutputPreferenceController.class).setCallback(listPreference ->
- onPreferenceDataChanged(listPreference));
+ onPreferenceDataChanged(listPreference));
mHfpOutputControllerKey =
use(HandsFreeProfileOutputPreferenceController.class).getPreferenceKey();
@@ -235,7 +234,6 @@ public class SoundSettings extends DashboardFragment {
private static List buildPreferenceControllers(Context context,
SoundSettings fragment, Lifecycle lifecycle) {
final List controllers = new ArrayList<>();
- controllers.add(new ZenModePreferenceController(context, lifecycle, KEY_ZEN_MODE));
// Volumes are added via xml
@@ -309,15 +307,6 @@ public class SoundSettings extends DashboardFragment {
return buildPreferenceControllers(context, null /* fragment */,
null /* lifecycle */);
}
-
- @Override
- public List getNonIndexableKeys(Context context) {
- List keys = super.getNonIndexableKeys(context);
- // Duplicate results
- keys.add((new ZenModePreferenceController(context, null, KEY_ZEN_MODE))
- .getPreferenceKey());
- return keys;
- }
};
// === Work Sound Settings ===
diff --git a/src/com/android/settings/notification/ZenModePreferenceController.java b/src/com/android/settings/notification/ZenModePreferenceController.java
index 0d94029f47c..d70ffe28b8b 100644
--- a/src/com/android/settings/notification/ZenModePreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePreferenceController.java
@@ -23,38 +23,30 @@ import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-import android.util.Slog;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
-public class ZenModePreferenceController extends AbstractPreferenceController
- implements LifecycleObserver, OnResume, OnPause, PreferenceControllerMixin {
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+public class ZenModePreferenceController extends BasePreferenceController
+ implements LifecycleObserver, OnResume, OnPause {
- private final String mKey;
private SettingObserver mSettingObserver;
private ZenModeSettings.SummaryBuilder mSummaryBuilder;
- public ZenModePreferenceController(Context context, Lifecycle lifecycle, String key) {
- super(context);
+ public ZenModePreferenceController(Context context, String key) {
+ super(context, key);
mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
-
- if (lifecycle != null) {
- lifecycle.addObserver(this);
- }
- mKey = key;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- mSettingObserver = new SettingObserver(screen.findPreference(mKey));
+ mSettingObserver = new SettingObserver(screen.findPreference(getPreferenceKey()));
}
@Override
@@ -72,13 +64,8 @@ public class ZenModePreferenceController extends AbstractPreferenceController
}
@Override
- public String getPreferenceKey() {
- return mKey;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
+ public int getAvailabilityStatus() {
+ return AVAILABLE_UNSEARCHABLE;
}
@Override
diff --git a/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java b/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
index 28475b6b5e3..10a7b561353 100644
--- a/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
@@ -68,7 +68,10 @@ public class ZenModeStarredContactsPreferenceController extends
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(KEY);
- mPreference.setOnPreferenceClickListener(this);
+
+ if (mPreference != null) {
+ mPreference.setOnPreferenceClickListener(this);
+ }
}
@Override
diff --git a/src/com/android/settings/notification/ZenOnboardingActivity.java b/src/com/android/settings/notification/ZenOnboardingActivity.java
index 7b50dde157c..99bc1723c1e 100644
--- a/src/com/android/settings/notification/ZenOnboardingActivity.java
+++ b/src/com/android/settings/notification/ZenOnboardingActivity.java
@@ -157,6 +157,12 @@ public class ZenOnboardingActivity extends Activity {
// ZEN_SETTINGS_UPDATED is true for:
// - fresh P+ device
// - if zen visual effects values were changed by the user in Settings
+ NotificationManager nm = context.getSystemService(NotificationManager.class);
+ if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
+ nm.getNotificationPolicy().suppressedVisualEffects)) {
+ Settings.Global.putInt(context.getContentResolver(),
+ Settings.Global.ZEN_SETTINGS_UPDATED, 1);
+ }
return Settings.Global.getInt(context.getContentResolver(),
Settings.Global.ZEN_SETTINGS_UPDATED, 0) != 0;
}
diff --git a/src/com/android/settings/print/PrintSettingsFragment.java b/src/com/android/settings/print/PrintSettingsFragment.java
index dca1f580314..bad1e035dcc 100644
--- a/src/com/android/settings/print/PrintSettingsFragment.java
+++ b/src/com/android/settings/print/PrintSettingsFragment.java
@@ -56,6 +56,7 @@ import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.utils.ProfileSettingsPreferenceFragment;
+import com.android.settings.widget.AppPreference;
import com.android.settingslib.search.SearchIndexable;
import java.text.DateFormat;
@@ -193,7 +194,7 @@ public class PrintSettingsFragment extends ProfileSettingsPreferenceFragment
}
for (PrintServiceInfo service : services) {
- Preference preference = new Preference(context);
+ AppPreference preference = new AppPreference(context);
String title = service.getResolveInfo().loadLabel(pm).toString();
preference.setTitle(title);
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index db09a378e1b..7eda82b902f 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -34,6 +34,7 @@ import android.util.Pair;
import com.android.settings.bluetooth.BluetoothSliceBuilder;
import com.android.settings.core.BasePreferenceController;
+import com.android.settings.flashlight.FlashlightSliceBuilder;
import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.mobilenetwork.Enhanced4gLteSliceHelper;
@@ -160,6 +161,10 @@ public class SettingsSliceProvider extends SliceProvider {
} else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
registerIntentToUri(BluetoothSliceBuilder.INTENT_FILTER, sliceUri);
return;
+ } else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) {
+ registerIntentToUri(FlashlightSliceBuilder.INTENT_FILTER , sliceUri);
+ mRegisteredUris.add(sliceUri);
+ return;
}
// Start warming the slice, we expect someone will want it soon.
@@ -191,32 +196,35 @@ public class SettingsSliceProvider extends SliceProvider {
Log.e(TAG, "Requested blocked slice with Uri: " + sliceUri);
return null;
}
- // If adding a new Slice, do not directly match Slice URIs.
- // Use {@link SlicesDatabaseAccessor}.
- if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
- return FeatureFactory.getFactory(getContext())
- .getSlicesFeatureProvider()
- .getNewWifiCallingSliceHelper(getContext())
- .createWifiCallingSlice(sliceUri);
- } else if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
- return WifiSliceBuilder.getSlice(getContext());
- } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
- return ZenModeSliceBuilder.getSlice(getContext());
- } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
- return BluetoothSliceBuilder.getSlice(getContext());
- } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
- return LocationSliceBuilder.getSlice(getContext());
- } else if (Enhanced4gLteSliceHelper.SLICE_URI.equals(sliceUri)) {
- return FeatureFactory.getFactory(getContext())
- .getSlicesFeatureProvider()
- .getNewEnhanced4gLteSliceHelper(getContext())
- .createEnhanced4gLteSlice(sliceUri);
- } else if (WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
- return FeatureFactory.getFactory(getContext())
- .getSlicesFeatureProvider()
- .getNewWifiCallingSliceHelper(getContext())
- .createWifiCallingPreferenceSlice(sliceUri);
- }
+
+ // If adding a new Slice, do not directly match Slice URIs.
+ // Use {@link SlicesDatabaseAccessor}.
+ if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
+ return FeatureFactory.getFactory(getContext())
+ .getSlicesFeatureProvider()
+ .getNewWifiCallingSliceHelper(getContext())
+ .createWifiCallingSlice(sliceUri);
+ } else if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
+ return WifiSliceBuilder.getSlice(getContext());
+ } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
+ return ZenModeSliceBuilder.getSlice(getContext());
+ } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
+ return BluetoothSliceBuilder.getSlice(getContext());
+ } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
+ return LocationSliceBuilder.getSlice(getContext());
+ } else if (Enhanced4gLteSliceHelper.SLICE_URI.equals(sliceUri)) {
+ return FeatureFactory.getFactory(getContext())
+ .getSlicesFeatureProvider()
+ .getNewEnhanced4gLteSliceHelper(getContext())
+ .createEnhanced4gLteSlice(sliceUri);
+ } else if (WifiCallingSliceHelper.WIFI_CALLING_PREFERENCE_URI.equals(sliceUri)) {
+ return FeatureFactory.getFactory(getContext())
+ .getSlicesFeatureProvider()
+ .getNewWifiCallingSliceHelper(getContext())
+ .createWifiCallingPreferenceSlice(sliceUri);
+ } else if (FlashlightSliceBuilder.FLASHLIGHT_URI.equals(sliceUri)) {
+ return FlashlightSliceBuilder.getSlice(getContext());
+ }
SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
if (cachedSliceData == null) {
@@ -381,7 +389,8 @@ public class SettingsSliceProvider extends SliceProvider {
private List getSpecialCaseOemUris() {
return Arrays.asList(
- ZenModeSliceBuilder.ZEN_MODE_URI
+ ZenModeSliceBuilder.ZEN_MODE_URI,
+ FlashlightSliceBuilder.FLASHLIGHT_URI
);
}
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 9f1ef769d7d..95f053844e5 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -17,6 +17,7 @@
package com.android.settings.slices;
import static com.android.settings.bluetooth.BluetoothSliceBuilder.ACTION_BLUETOOTH_SLICE_CHANGED;
+import static com.android.settings.flashlight.FlashlightSliceBuilder.ACTION_FLASHLIGHT_SLICE_CHANGED;
import static com.android.settings.notification.ZenModeSliceBuilder.ACTION_ZEN_MODE_SLICE_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_SLIDER_CHANGED;
import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CHANGED;
@@ -45,6 +46,7 @@ import com.android.settings.bluetooth.BluetoothSliceBuilder;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SliderPreferenceController;
import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.flashlight.FlashlightSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.WifiSliceBuilder;
@@ -102,6 +104,9 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
.getNewWifiCallingSliceHelper(context)
.handleWifiCallingPreferenceChanged(intent);
break;
+ case ACTION_FLASHLIGHT_SLICE_CHANGED:
+ FlashlightSliceBuilder.handleUriChange(context, intent);
+ break;
default:
final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI);
if (!TextUtils.isEmpty(uriString)) {
diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
index f35fd60ad54..119fadbd4ba 100644
--- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java
+++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
@@ -118,7 +118,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
Log.e(TAG, "Bluetooth is not supported on this device");
return;
}
- mLocalBluetoothManager.setForegroundActivity(mContext);
mProfileManager = mLocalBluetoothManager.getProfileManager();
}
@@ -171,11 +170,13 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
@Override
public void onStart() {
+ mLocalBluetoothManager.setForegroundActivity(mContext);
register();
}
@Override
public void onStop() {
+ mLocalBluetoothManager.setForegroundActivity(null);
unregister();
}
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 52a36928c3a..a33561b3bbe 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -42,13 +42,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.provider.SearchIndexableResource;
-import android.provider.Settings.Global;
-import androidx.annotation.VisibleForTesting;
-import androidx.annotation.WorkerThread;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceClickListener;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
import android.util.Log;
import android.util.SparseArray;
import android.view.Menu;
@@ -82,6 +75,13 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceClickListener;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+
/**
* Screen that manages the list of users on the device.
* Guest user is an always visible entry, even if the guest is not currently
@@ -109,6 +109,8 @@ public class UserSettings extends SettingsPreferenceFragment
private static final int MENU_REMOVE_USER = Menu.FIRST;
+ private static final IntentFilter USER_REMOVED_INTENT_FILTER;
+
private static final int DIALOG_CONFIRM_REMOVE = 1;
private static final int DIALOG_ADD_USER = 2;
private static final int DIALOG_SETUP_USER = 3;
@@ -134,6 +136,11 @@ public class UserSettings extends SettingsPreferenceFragment
private static final String KEY_TITLE = "title";
private static final String KEY_SUMMARY = "summary";
+ static {
+ USER_REMOVED_INTENT_FILTER = new IntentFilter(Intent.ACTION_USER_REMOVED);
+ USER_REMOVED_INTENT_FILTER.addAction(Intent.ACTION_USER_INFO_CHANGED);
+ }
+
private PreferenceGroup mUserListCategory;
private UserPreference mMePreference;
private RestrictedPreference mAddUser;
@@ -195,13 +202,14 @@ public class UserSettings extends SettingsPreferenceFragment
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.user_settings);
- if (Global.getInt(getContext().getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) {
- getActivity().finish();
+ final Activity activity = getActivity();
+ if (!Utils.isDeviceProvisioned(getActivity())) {
+ activity.finish();
return;
}
- final Context context = getActivity();
+
mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController(
- context, KEY_ADD_USER_WHEN_LOCKED, getLifecycle());
+ activity, KEY_ADD_USER_WHEN_LOCKED, getLifecycle());
final PreferenceScreen screen = getPreferenceScreen();
mAddUserWhenLockedPreferenceController.displayPreference(screen);
@@ -218,8 +226,8 @@ public class UserSettings extends SettingsPreferenceFragment
mEditUserInfoController.onRestoreInstanceState(icicle);
}
- mUserCaps = UserCapabilities.create(context);
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mUserCaps = UserCapabilities.create(activity);
+ mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
if (!mUserCaps.mEnabled) {
return;
}
@@ -248,9 +256,10 @@ public class UserSettings extends SettingsPreferenceFragment
} else {
mAddUser.setVisible(false);
}
- final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
- filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
- context.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null, mHandler);
+
+ activity.registerReceiverAsUser(
+ mUserChangeReceiver, UserHandle.ALL, USER_REMOVED_INTENT_FILTER, null, mHandler);
+
loadProfile();
updateUserList();
mShouldUpdateUserList = false;
@@ -762,9 +771,11 @@ public class UserSettings extends SettingsPreferenceFragment
}
private void updateUserList() {
- if (getActivity() == null) return;
- List users = mUserManager.getUsers(true);
final Context context = getActivity();
+ if (context == null) {
+ return;
+ }
+ final List users = mUserManager.getUsers(true);
final boolean voiceCapable = Utils.isVoiceCapable(context);
final ArrayList missingIcons = new ArrayList<>();
diff --git a/src/com/android/settings/widget/HotspotApBandSelectionPreference.java b/src/com/android/settings/widget/HotspotApBandSelectionPreference.java
deleted file mode 100644
index b249b993856..00000000000
--- a/src/com/android/settings/widget/HotspotApBandSelectionPreference.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2018 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.widget;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.net.wifi.WifiConfiguration;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import androidx.annotation.VisibleForTesting;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.LinearLayout;
-
-import com.android.settings.R;
-import com.android.settingslib.CustomDialogPreference;
-
-import java.util.ArrayList;
-
-public class HotspotApBandSelectionPreference extends CustomDialogPreference implements
- CompoundButton.OnCheckedChangeListener, DialogInterface.OnShowListener {
- private static final int UNSET = Integer.MIN_VALUE;
-
- @VisibleForTesting
- static final String KEY_CHECKED_BANDS = "checked_bands";
- @VisibleForTesting
- static final String KEY_HOTSPOT_SUPER_STATE = "hotspot_super_state";
-
- @VisibleForTesting
- CheckBox mBox2G;
- @VisibleForTesting
- CheckBox mBox5G;
- @VisibleForTesting
- ArrayList mRestoredBands;
- @VisibleForTesting
- boolean mShouldRestore;
-
- private String[] mBandEntries;
- private int mExistingConfigValue = UNSET;
-
- public HotspotApBandSelectionPreference(Context context) {
- super(context);
- }
-
- public HotspotApBandSelectionPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public HotspotApBandSelectionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public HotspotApBandSelectionPreference(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- SavedState myState = (SavedState) state;
-
- super.onRestoreInstanceState(myState.getSuperState());
-
- mShouldRestore = myState.shouldRestore;
- if (mShouldRestore) {
- mRestoredBands = new ArrayList<>();
- if (myState.enabled2G) {
- mRestoredBands.add(WifiConfiguration.AP_BAND_2GHZ);
- }
- if (myState.enabled5G) {
- mRestoredBands.add(WifiConfiguration.AP_BAND_5GHZ);
- }
- } else {
- mRestoredBands = null;
- }
- updatePositiveButton();
- }
-
- @Override
- protected void onBindDialogView(View view) {
- super.onBindDialogView(view);
- final Context context = getContext();
-
- // Register so we can adjust the buttons if needed once the dialog is available.
- setOnShowListener(this);
-
- mBandEntries = context.getResources().getStringArray(R.array.wifi_ap_band_config_full);
- // add a checkbox for every band entry.
- addApBandViews((LinearLayout) view);
- // try to update the button just in case we already missed the onShow call.
- updatePositiveButton();
- // clear any saved state so it doesn't leak across multiple rotations/dialog closings
- mRestoredBands = null;
- mShouldRestore = false;
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- final Parcelable superState = super.onSaveInstanceState();
-
- SavedState myState = new SavedState(superState);
- myState.shouldRestore = getDialog() != null;
- myState.enabled2G = mBox2G != null && mBox2G.isChecked();
- myState.enabled5G = mBox5G != null && mBox5G.isChecked();
- return myState;
- }
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (!(buttonView instanceof CheckBox)) {
- return;
- }
- updatePositiveButton();
- }
-
- @Override
- protected void onClick(DialogInterface dialog, int which) {
- // we only want to persist our enabled bands if apply is clicked
- if (which == DialogInterface.BUTTON_POSITIVE) {
- if (mBox2G.isChecked() || mBox5G.isChecked()) {
- int wifiBand = getWifiBand();
- mExistingConfigValue = wifiBand;
- callChangeListener(wifiBand);
- }
- }
- }
-
- /**
- * Used to set the band selection for the preference if one already exists
- * @param band the band to set it to from {@link WifiConfiguration}
- */
- public void setExistingConfigValue(int band) {
- mExistingConfigValue = band;
- }
-
- private void addApBandViews(LinearLayout view) {
- mBox2G = view.findViewById(R.id.box_2g);
- mBox2G.setText(mBandEntries[WifiConfiguration.AP_BAND_2GHZ]);
- mBox2G.setChecked(restoreBandIfNeeded(WifiConfiguration.AP_BAND_2GHZ));
- mBox2G.setOnCheckedChangeListener(this);
-
- mBox5G = view.findViewById(R.id.box_5g);
- mBox5G.setText(mBandEntries[WifiConfiguration.AP_BAND_5GHZ]);
- mBox5G.setChecked(restoreBandIfNeeded(WifiConfiguration.AP_BAND_5GHZ));
- mBox5G.setOnCheckedChangeListener(this);
- }
-
- private boolean restoreBandIfNeeded(int band) {
- // Only use the provided config if we aren't restoring, restore if state available
- return (isBandPreviouslySelected(band) && !mShouldRestore)
- || (mShouldRestore && mRestoredBands.contains(band));
- }
-
- private void updatePositiveButton() {
- AlertDialog dialog = (AlertDialog) getDialog();
- Button button = dialog == null ? null : dialog.getButton(DialogInterface.BUTTON_POSITIVE);
- if (button != null && mBox5G != null && mBox2G != null) {
- button.setEnabled(mBox2G.isChecked() || mBox5G.isChecked());
- }
- }
-
- @VisibleForTesting
- int getWifiBand() {
- final boolean checked_2g = mBox2G.isChecked();
- final boolean checked_5g = mBox5G.isChecked();
- if (checked_2g && checked_5g) {
- return WifiConfiguration.AP_BAND_ANY;
- } else if (checked_2g && !checked_5g) {
- return WifiConfiguration.AP_BAND_2GHZ;
- } else if (checked_5g && !checked_2g) {
- return WifiConfiguration.AP_BAND_5GHZ;
- } else {
- throw new IllegalStateException("Wifi Config only supports selecting one or all bands");
- }
- }
-
- private boolean isBandPreviouslySelected(int bandIndex) {
- switch(mExistingConfigValue) {
- case WifiConfiguration.AP_BAND_ANY:
- return true;
- case WifiConfiguration.AP_BAND_2GHZ:
- return bandIndex == 0;
- case WifiConfiguration.AP_BAND_5GHZ:
- return bandIndex == 1;
- case UNSET:
- default:
- return false;
- }
- }
-
- @Override
- public void onShow(DialogInterface dialog) {
- updatePositiveButton();
- }
-
- private static class SavedState extends BaseSavedState {
- boolean shouldRestore;
- boolean enabled2G;
- boolean enabled5G;
-
- public SavedState(Parcelable source) {
- super(source);
- }
-
- private SavedState(Parcel in) {
- super(in);
- shouldRestore = in.readByte() == 1;
- enabled2G = in.readByte() == 1;
- enabled5G = in.readByte() == 1;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeByte((byte) (shouldRestore ? 1 : 0));
- dest.writeByte((byte) (enabled2G ? 1: 0));
- dest.writeByte((byte) (enabled5G ? 1 : 0));
- }
-
- @Override
- public String toString() {
- return "HotspotApBandSelectionPreference.SavedState{"
- + Integer.toHexString(System.identityHashCode(this))
- + " shouldRestore=" + shouldRestore
- + " enabled2G=" + enabled2G
- + " enabled5G=" + enabled5G + "}";
- }
-
- public static final Parcelable.Creator CREATOR
- = new Parcelable.Creator() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
index 8dde24bdb47..b1f171be3d5 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
@@ -16,36 +16,32 @@
package com.android.settings.wifi.tether;
-import static android.net.wifi.WifiConfiguration.AP_BAND_2GHZ;
-import static android.net.wifi.WifiConfiguration.AP_BAND_5GHZ;
-
import android.content.Context;
import android.content.res.Resources;
-import android.icu.text.ListFormatter;
import android.net.wifi.WifiConfiguration;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
import androidx.preference.Preference;
import android.util.Log;
import com.android.settings.R;
-import com.android.settings.widget.HotspotApBandSelectionPreference;
public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferenceController {
private static final String TAG = "WifiTetherApBandPref";
private static final String PREF_KEY = "wifi_tether_network_ap_band";
- public static final String[] BAND_VALUES =
- {String.valueOf(AP_BAND_2GHZ), String.valueOf(AP_BAND_5GHZ)};
- private final String[] mBandEntries;
- private final String[] mBandSummaries;
+ private String[] mBandEntries;
+ private String[] mBandSummaries;
private int mBandIndex;
+ private boolean isDualMode;
public WifiTetherApBandPreferenceController(Context context,
OnTetherConfigUpdateListener listener) {
super(context, listener);
- Resources res = mContext.getResources();
- mBandEntries = res.getStringArray(R.array.wifi_ap_band_config_full);
- mBandSummaries = res.getStringArray(R.array.wifi_ap_band_summary_full);
+ isDualMode = mWifiManager.isDualModeSupported();
+ updatePreferenceEntries();
}
@Override
@@ -55,7 +51,7 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
mBandIndex = 0;
Log.d(TAG, "Updating band index to 0 because no config");
} else if (is5GhzBandSupported()) {
- mBandIndex = config.apBand;
+ mBandIndex = validateSelection(config.apBand);
Log.d(TAG, "Updating band index to " + mBandIndex);
} else {
config.apBand = 0;
@@ -63,21 +59,23 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
mBandIndex = config.apBand;
Log.d(TAG, "5Ghz not supported, updating band index to " + mBandIndex);
}
- HotspotApBandSelectionPreference preference =
- (HotspotApBandSelectionPreference) mPreference;
+ ListPreference preference =
+ (ListPreference) mPreference;
+ preference.setEntries(mBandSummaries);
+ preference.setEntryValues(mBandEntries);
if (!is5GhzBandSupported()) {
preference.setEnabled(false);
preference.setSummary(R.string.wifi_ap_choose_2G);
} else {
- preference.setExistingConfigValue(config.apBand);
+ preference.setValue(Integer.toString(config.apBand));
preference.setSummary(getConfigSummary());
}
}
String getConfigSummary() {
if (mBandIndex == WifiConfiguration.AP_BAND_ANY) {
- return ListFormatter.getInstance().format((Object[]) mBandSummaries);
+ return mContext.getString(R.string.wifi_ap_prefer_5G);
}
return mBandSummaries[mBandIndex];
}
@@ -89,13 +87,46 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- mBandIndex = (Integer) newValue;
+ mBandIndex = validateSelection(Integer.parseInt((String) newValue));
Log.d(TAG, "Band preference changed, updating band index to " + mBandIndex);
preference.setSummary(getConfigSummary());
mListener.onTetherConfigUpdated();
return true;
}
+ private int validateSelection(int band) {
+ // Reset the band to 2.4 GHz if we get a weird config back to avoid a crash.
+ final boolean isDualMode = mWifiManager.isDualModeSupported();
+
+ // unsupported states:
+ // 1: no dual mode means we can't have AP_BAND_ANY - default to 5GHZ
+ // 2: no 5 GHZ support means we can't have AP_BAND_5GHZ - default to 2GHZ
+ // 3: With Dual mode support we can't have AP_BAND_5GHZ - default to ANY
+ if (!isDualMode && WifiConfiguration.AP_BAND_ANY == band) {
+ return WifiConfiguration.AP_BAND_5GHZ;
+ } else if (!mWifiManager.is5GHzBandSupported() && WifiConfiguration.AP_BAND_5GHZ == band) {
+ return WifiConfiguration.AP_BAND_2GHZ;
+ } else if (isDualMode && WifiConfiguration.AP_BAND_5GHZ == band) {
+ return WifiConfiguration.AP_BAND_ANY;
+ }
+
+ return band;
+ }
+
+ @VisibleForTesting
+ void updatePreferenceEntries() {
+ Resources res = mContext.getResources();
+ int entriesRes = R.array.wifi_ap_band_config_full;
+ int summariesRes = R.array.wifi_ap_band_summary_full;
+ // change the list options if this is a dual mode device
+ if (isDualMode) {
+ entriesRes = R.array.wifi_ap_band_dual_mode;
+ summariesRes = R.array.wifi_ap_band_dual_mode_summary;
+ }
+ mBandEntries = res.getStringArray(entriesRes);
+ mBandSummaries = res.getStringArray(summariesRes);
+ }
+
private boolean is5GhzBandSupported() {
final String countryCode = mWifiManager.getCountryCode();
if (!mWifiManager.isDualBandSupported() || countryCode == null) {
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountSyncSettingsTest.java b/tests/robotests/src/com/android/settings/accounts/AccountSyncSettingsTest.java
new file mode 100644
index 00000000000..da361852ab1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/AccountSyncSettingsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 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.accounts;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.content.Context;
+import android.os.UserHandle;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowContentResolver;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowContentResolver.class})
+public class AccountSyncSettingsTest {
+
+ @After
+ public void tearDown() {
+ ShadowContentResolver.reset();
+ }
+
+ @Test
+ public void onPreferenceTreeClick_nullAuthority_shouldNotCrash() {
+ final Context context = RuntimeEnvironment.application;
+ final AccountSyncSettings settings = spy(new AccountSyncSettings());
+ when(settings.getActivity()).thenReturn(mock(Activity.class));
+ final SyncStateSwitchPreference preference = new SyncStateSwitchPreference(context,
+ new Account("acct1", "type1"), "" /* authority */, "testPackage", 1 /* uid */);
+ preference.setOneTimeSyncMode(false);
+ ReflectionHelpers.setField(settings, "mUserHandle", UserHandle.CURRENT);
+
+ settings.onPreferenceTreeClick(preference);
+ // no crash
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPickerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPickerTest.java
index f7a21d8ed7c..bdf249d1f5e 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPickerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPickerTest.java
@@ -16,6 +16,8 @@
package com.android.settings.applications.defaultapps;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
@@ -23,10 +25,20 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
import android.os.UserManager;
+import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.DefaultAppInfo;
+
+import java.util.ArrayList;
+import java.util.List;
import org.junit.Before;
import org.junit.Test;
@@ -53,6 +65,7 @@ public class DefaultBrowserPickerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest();
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = new DefaultBrowserPicker();
@@ -72,4 +85,39 @@ public class DefaultBrowserPickerTest {
mPicker.getDefaultKey();
verify(mPackageManager).getDefaultBrowserPackageNameAsUser(anyInt());
}
+
+ @Test
+ public void getCandidates_shouldNotIncludeDuplicatePackageName() throws NameNotFoundException {
+ final List resolveInfos = new ArrayList<>();
+ final String PACKAGE_ONE = "com.first.package";
+ final String PACKAGE_TWO = "com.second.package";
+ resolveInfos.add(createResolveInfo(PACKAGE_ONE));
+ resolveInfos.add(createResolveInfo(PACKAGE_TWO));
+ resolveInfos.add(createResolveInfo(PACKAGE_ONE));
+ resolveInfos.add(createResolveInfo(PACKAGE_TWO));
+ when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+ .thenReturn(resolveInfos);
+ when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_ONE), anyInt(), anyInt()))
+ .thenReturn(createApplicationInfo(PACKAGE_ONE));
+ when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_TWO), anyInt(), anyInt()))
+ .thenReturn(createApplicationInfo(PACKAGE_TWO));
+
+ final List defaultBrowserInfo = mPicker.getCandidates();
+
+ assertThat(defaultBrowserInfo.size()).isEqualTo(2);
+ }
+
+ private ResolveInfo createResolveInfo(String packageName) {
+ final ResolveInfo info = new ResolveInfo();
+ info.handleAllWebDataURI = true;
+ info.activityInfo = new ActivityInfo();
+ info.activityInfo.packageName = packageName;
+ return info;
+ }
+
+ private ApplicationInfo createApplicationInfo(String packageName) {
+ final ApplicationInfo info = new ApplicationInfo();
+ info.packageName = packageName;
+ return info;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
index fd2ff0d8975..6e69e67ba0c 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
@@ -20,6 +20,7 @@ import android.content.pm.PackageManager;
import androidx.preference.Preference;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
+import com.android.settings.connecteddevice.dock.DockUpdater;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -45,6 +46,8 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
@Mock
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
@Mock
+ private DockUpdater mDockUpdater;
+ @Mock
private PackageManager mPackageManager;
private Context mContext;
@@ -60,6 +63,7 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
mPreConnectedDeviceController =
new PreviouslyConnectedDevicePreferenceController(mContext, KEY);
mPreConnectedDeviceController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater);
+ mPreConnectedDeviceController.setSavedDockUpdater(mDockUpdater);
mPreference = new Preference(mContext);
mPreConnectedDeviceController.setPreference(mPreference);
@@ -70,10 +74,12 @@ public class PreviouslyConnectedDevicePreferenceControllerTest {
// register the callback in onStart()
mPreConnectedDeviceController.onStart();
verify(mBluetoothDeviceUpdater).registerCallback();
+ verify(mDockUpdater).registerCallback();
// unregister the callback in onStop()
mPreConnectedDeviceController.onStop();
verify(mBluetoothDeviceUpdater).unregisterCallback();
+ verify(mDockUpdater).unregisterCallback();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
index e83e93d9bc9..1fe09310e76 100644
--- a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -22,6 +22,7 @@ import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.verify;
import static org.robolectric.RuntimeEnvironment.application;
+import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
@@ -151,4 +152,12 @@ public class FingerprintEnrollFindSensorTest {
return callbackCaptor.getValue();
}
+
+ @Test
+ public void onActivityResult_withNullIntentShouldNotCrash() {
+ // this should not crash
+ mActivity.onActivityResult(FingerprintEnrollFindSensor.CONFIRM_REQUEST, Activity.RESULT_OK,
+ null);
+ assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(Activity.RESULT_CANCELED);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java b/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java
new file mode 100644
index 00000000000..5862ab3d286
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/flashlight/FlashlightSliceBuilderTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 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.flashlight;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.SliceTester;
+
+import android.content.res.Resources;
+import android.provider.Settings;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class FlashlightSliceBuilderTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = spy(RuntimeEnvironment.application);
+
+ // Prevent crash in SliceMetadata.
+ Resources resources = spy(mContext.getResources());
+ doReturn(60).when(resources).getDimensionPixelSize(anyInt());
+ doReturn(resources).when(mContext).getResources();
+
+ // Set-up specs for SliceMetadata.
+ SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+ }
+
+ @Test
+ public void getFlashlightSlice_correctData() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
+ final Slice slice = FlashlightSliceBuilder.getSlice(mContext);
+ final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+
+ final List toggles = metadata.getToggles();
+ assertThat(toggles).hasSize(1);
+
+ final List sliceItems = slice.getItems();
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.power_flashlight));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/PreventRingingParentPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PreventRingingParentPreferenceControllerTest.java
new file mode 100644
index 00000000000..33a00fac303
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/PreventRingingParentPreferenceControllerTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.gestures;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class PreventRingingParentPreferenceControllerTest {
+
+ @Mock
+ private Resources mResources;
+
+ private Context mContext;
+ private PreventRingingParentPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getResources()).thenReturn(mResources);
+
+ mController = new PreventRingingParentPreferenceController(mContext, "test_key");
+ }
+
+ @Test
+ public void testIsAvailable_configIsTrue_shouldAvailableUnSearchable() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(true);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
+ }
+
+ @Test
+ public void testIsAvailable_configIsFalse_shouldReturnFalse() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_volumeHushGestureEnabled)).thenReturn(false);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
index 3ea4471fadc..ece25e2661b 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModePreferenceControllerTest.java
@@ -16,6 +16,7 @@
package com.android.settings.notification;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
@@ -27,7 +28,6 @@ import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
-import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -40,6 +40,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
+import androidx.preference.Preference;
+
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModePreferenceControllerTest {
@@ -61,7 +63,7 @@ public class ZenModePreferenceControllerTest {
ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
mContext = shadowApplication.getApplicationContext();
- mController = new ZenModePreferenceController(mContext, null, KEY_ZEN_MODE);
+ mController = new ZenModePreferenceController(mContext, KEY_ZEN_MODE);
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
mSummaryBuilder = spy(new ZenModeSettings.SummaryBuilder(mContext));
ReflectionHelpers.setField(mController, "mSummaryBuilder", mSummaryBuilder);
@@ -69,8 +71,8 @@ public class ZenModePreferenceControllerTest {
}
@Test
- public void isAlwaysAvailable() {
- assertThat(mController.isAvailable()).isTrue();
+ public void isAvailable_unsearchable() {
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
index 064c0911319..ad8e0de7193 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
@@ -190,4 +190,13 @@ public class ZenModeStarredContactsPreferenceControllerTest {
assertThat(contacts.get(i)).isNotNull();
}
}
+
+ @Test
+ public void nullPreference_displayPreference() {
+ when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
+ .thenReturn(null);
+
+ // should not throw a null pointer
+ mMessagesController.displayPreference(mPreferenceScreen);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java b/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
index e09dc0d2b8c..3ca9fdac779 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java
@@ -51,6 +51,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenOnboardingActivityTest {
@@ -68,6 +69,8 @@ public class ZenOnboardingActivityTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
mActivity = Robolectric.buildActivity(ZenOnboardingActivity.class)
.create()
@@ -124,6 +127,9 @@ public class ZenOnboardingActivityTest {
@Test
public void isSuggestionComplete_zenUpdated() {
+ Policy policy = new Policy(0, 0, 0, 0);
+ when(mNm.getNotificationPolicy()).thenReturn(policy);
+
setZenUpdated(true);
setShowSettingsSuggestion(false);
setWithinTimeThreshold(true);
@@ -132,6 +138,9 @@ public class ZenOnboardingActivityTest {
@Test
public void isSuggestionComplete_withinTimeThreshold() {
+ Policy policy = new Policy(0, 0, 0, 0);
+ when(mNm.getNotificationPolicy()).thenReturn(policy);
+
setZenUpdated(false);
setShowSettingsSuggestion(false);
setWithinTimeThreshold(true);
@@ -140,6 +149,9 @@ public class ZenOnboardingActivityTest {
@Test
public void isSuggestionComplete_showSettingsSuggestionTrue() {
+ Policy policy = new Policy(0, 0, 0, 0);
+ when(mNm.getNotificationPolicy()).thenReturn(policy);
+
setZenUpdated(false);
setShowSettingsSuggestion(true);
setWithinTimeThreshold(false);
@@ -148,17 +160,33 @@ public class ZenOnboardingActivityTest {
@Test
public void isSuggestionComplete_showSettingsSuggestionFalse_notWithinTimeThreshold() {
+ Policy policy = new Policy(0, 0, 0, 0);
+ when(mNm.getNotificationPolicy()).thenReturn(policy);
+
setZenUpdated(false);
setShowSettingsSuggestion(false);
setWithinTimeThreshold(false);
assertThat(isSuggestionComplete(mContext)).isTrue();
}
+
+ @Test
+ public void isSuggestionComplete_visualEffectsUpdated() {
+ // all values suppressed
+ Policy policy = new Policy(0, 0, 0, 511);
+ when(mNm.getNotificationPolicy()).thenReturn(policy);
+
+ setZenUpdated(false);
+ setShowSettingsSuggestion(true);
+ setWithinTimeThreshold(true);
+ assertThat(isSuggestionComplete(mContext)).isTrue();
+ assertThat(Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_SETTINGS_UPDATED, -1)).isEqualTo(1);
+ }
+
+
private void setZenUpdated(boolean updated) {
- int zenUpdated = 0;
- if (updated) {
- zenUpdated = 1;
- }
+ int zenUpdated = updated ? 1 : 0;
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.ZEN_SETTINGS_UPDATED, zenUpdated);
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 6b1262a1e2c..c72e9f6c542 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -33,10 +33,12 @@ import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.StrictMode;
+import android.provider.Settings;
import android.provider.SettingsSlicesContract;
import android.util.ArraySet;
import com.android.settings.bluetooth.BluetoothSliceBuilder;
+import com.android.settings.flashlight.FlashlightSliceBuilder;
import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.testutils.DatabaseTestUtils;
@@ -95,7 +97,8 @@ public class SettingsSliceProviderTest {
);
private static final List SPECIAL_CASE_OEM_URIS = Arrays.asList(
- ZenModeSliceBuilder.ZEN_MODE_URI
+ ZenModeSliceBuilder.ZEN_MODE_URI,
+ FlashlightSliceBuilder.FLASHLIGHT_URI
);
@Before
@@ -444,6 +447,16 @@ public class SettingsSliceProviderTest {
assertThat(wifiSlice.getUri()).isEqualTo(WifiSliceBuilder.WIFI_URI);
}
+ @Test
+ public void bindSlice_flashlightSlice_returnsFlashlightSlice() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
+
+ final Slice flashlightSlice = mProvider.onBindSlice(FlashlightSliceBuilder.FLASHLIGHT_URI);
+
+ assertThat(flashlightSlice.getUri()).isEqualTo(FlashlightSliceBuilder.FLASHLIGHT_URI);
+ }
+
@Test
public void onSlicePinned_noIntentRegistered_specialCaseUri_doesNotCrash() {
final Uri uri = new Uri.Builder()
diff --git a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
index 56a5aa709fe..748aa0ca302 100644
--- a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
@@ -230,6 +230,7 @@ public class AudioOutputSwitchPreferenceControllerTest {
verify(mLocalBluetoothManager.getEventManager()).registerCallback(
any(BluetoothCallback.class));
verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
+ verify(mLocalBluetoothManager).setForegroundActivity(mContext);
}
@Test
@@ -240,6 +241,7 @@ public class AudioOutputSwitchPreferenceControllerTest {
verify(mLocalBluetoothManager.getEventManager()).unregisterCallback(
any(BluetoothCallback.class));
verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
+ verify(mLocalBluetoothManager).setForegroundActivity(null);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
index f071f173633..0b29af58bad 100644
--- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
+++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
@@ -84,9 +84,9 @@ public class SettingsRobolectricTestRunner extends RobolectricTestRunner {
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/opt/setupwizard/library/recyclerview/res")), null));
paths.add(new ResourcePath(null,
- Fs.fromURL(new URL("file:frameworks/support/v7/appcompat/res")), null));
+ Fs.fromURL(new URL("file:frameworks/support/appcompat/res")), null));
paths.add(new ResourcePath(null,
- Fs.fromURL(new URL("file:frameworks/support/v7/cardview/res")), null));
+ Fs.fromURL(new URL("file:frameworks/support/cardview/res")), null));
} catch (MalformedURLException e) {
throw new RuntimeException("SettingsRobolectricTestRunner failure", e);
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
index 50c0330828a..928779b5c05 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
@@ -24,6 +24,7 @@ import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.SearchIndexablesContract;
+import android.text.TextUtils;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@@ -66,6 +67,14 @@ public class ShadowContentResolver {
return sSyncAutomatically.containsKey(authority) ? sSyncAutomatically.get(authority) : true;
}
+ @Implementation
+ public static void setSyncAutomaticallyAsUser(Account account, String authority, boolean sync,
+ int userId) {
+ if (TextUtils.isEmpty(authority)) {
+ throw new IllegalArgumentException("Authority must be non-empty");
+ }
+ }
+
@Implementation
public static boolean getMasterSyncAutomaticallyAsUser(int userId) {
return sMasterSyncAutomatically.containsKey(userId)
diff --git a/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java
deleted file mode 100644
index 0ffda3baa96..00000000000
--- a/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2018 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.widget;
-
-import static com.android.settingslib.CustomDialogPreference.CustomPreferenceDialogFragment;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.net.wifi.WifiConfiguration;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.LinearLayout;
-
-import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class HotspotApBandSelectionPreferenceTest {
- private HotspotApBandSelectionPreference mPreference;
- private Context mContext;
- private Button mSaveButton;
- private View mLayout;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- mSaveButton = spy(new Button(mContext));
-
- final CustomPreferenceDialogFragment fragment = mock(CustomPreferenceDialogFragment.class);
- final AlertDialog dialog = mock(AlertDialog.class);
- when(fragment.getDialog()).thenReturn(dialog);
- when(dialog.getButton(anyInt())).thenReturn(mSaveButton);
-
- mPreference = new HotspotApBandSelectionPreference(mContext);
- ReflectionHelpers.setField(mPreference, "mFragment", fragment);
-
- final LayoutInflater inflater = LayoutInflater.from(mContext);
- mLayout = inflater.inflate(R.layout.hotspot_ap_band_selection_dialog,
- new LinearLayout(mContext), false);
- }
-
- @Test
- public void getWifiBand_updatesBandPresetConfigProvided() {
- mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
- mPreference.onBindDialogView(mLayout);
-
- // check that the boxes are set correctly when a pre-existing config is set
- assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_ANY);
- }
-
- @Test
- public void getWifiBand_updatesBandWhenBoxesToggled() {
- mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
- mPreference.onBindDialogView(mLayout);
-
- assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_ANY);
-
- // make sure we have the expected box then toggle it
- mPreference.mBox2G.setChecked(false);
-
- // check that band is updated
- assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_5GHZ);
- }
-
- @Test
- public void onSaveInstanceState_skipWhenDialogGone() {
- mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ);
- mPreference.onBindDialogView(mLayout);
- // remove the fragment to make the dialog unavailable
- ReflectionHelpers.setField(mPreference, "mFragment", null);
-
- mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
- mPreference.onBindDialogView(mLayout);
-
- // state should only be saved when the dialog is available
- Parcelable parcelable = mPreference.onSaveInstanceState();
- mPreference.onRestoreInstanceState(parcelable);
- assertThat(mPreference.mShouldRestore).isFalse();
- }
-
- @Test
- public void onSaveInstanceState_doesNotCrashWhenViewGone() {
- mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ);
- mPreference.onBindDialogView(mLayout);
- // When the device dozes the view and dialog can become null
- mPreference.mBox5G = null;
- mPreference.mBox2G = null;
- ReflectionHelpers.setField(mPreference, "mFragment", null);
-
- // make sure it does not crash and state is not restored
- Parcelable parcelable = mPreference.onSaveInstanceState();
- mPreference.onRestoreInstanceState(parcelable);
- assertThat(mPreference.mShouldRestore).isFalse();
- }
-
- @Test
- public void onSaveInstanceState_presentWhenDialogPresent() {
- mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ);
- mPreference.onBindDialogView(mLayout);
-
- Parcelable parcelable = mPreference.onSaveInstanceState();
- mPreference.onRestoreInstanceState(parcelable);
- assertThat(mPreference.mShouldRestore).isTrue();
- }
-
- @Test
- public void positiveButton_updatedCorrectly() {
- mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
- mPreference.onBindDialogView(mLayout);
-
- // button is enabled whole time so far since we have a pre-existing selection
- verify(mSaveButton, never()).setEnabled(false);
-
- // clear all boxes and make sure it stays enabled until empty
- mPreference.mBox2G.setChecked(false);
- mPreference.mBox5G.setChecked(false);
-
- // button should be disabled now
- verify(mSaveButton, times(1)).setEnabled(false);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
index 4b81b345001..4b2aa1c6418 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
@@ -18,6 +18,7 @@ package com.android.settings.wifi.tether;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -26,16 +27,16 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+
+import androidx.preference.ListPreference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.widget.HotspotApBandSelectionPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@@ -43,8 +44,9 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class WifiTetherApBandPreferenceControllerTest {
- private static final String ALL_BANDS = "2.4 GHz and 5.0 GHz";
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private static final String ALL_BANDS = "5.0 GHz Band preferred";
+ private static final String TWO_GHZ_STRING = "2.4 GHz Band";
+ private static final String FIVE_GHZ_STRING = "5.0 GHz Band";
private Context mContext;
@Mock
private ConnectivityManager mConnectivityManager;
@@ -56,12 +58,13 @@ public class WifiTetherApBandPreferenceControllerTest {
private PreferenceScreen mScreen;
private WifiTetherApBandPreferenceController mController;
- private HotspotApBandSelectionPreference mPreference;
+ private ListPreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mPreference = new HotspotApBandSelectionPreference(RuntimeEnvironment.application);
+ mContext = spy(RuntimeEnvironment.application);
+ mPreference = new ListPreference(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(mConnectivityManager);
@@ -71,6 +74,7 @@ public class WifiTetherApBandPreferenceControllerTest {
WifiConfiguration config = new WifiConfiguration();
config.apBand = WifiConfiguration.AP_BAND_ANY;
when(mWifiManager.getWifiApConfiguration()).thenReturn(new WifiConfiguration());
+ when(mWifiManager.isDualModeSupported()).thenReturn(false);
mController = new WifiTetherApBandPreferenceController(mContext, mListener);
}
@@ -79,9 +83,10 @@ public class WifiTetherApBandPreferenceControllerTest {
public void display_5GhzSupported_shouldDisplayFullList() {
when(mWifiManager.getCountryCode()).thenReturn("US");
when(mWifiManager.isDualBandSupported()).thenReturn(true);
+ when(mWifiManager.isDualModeSupported()).thenReturn(true);
mController.displayPreference(mScreen);
- mController.onPreferenceChange(mPreference, -1);
+ mController.onPreferenceChange(mPreference, "-1");
assertThat(mPreference.getSummary()).isEqualTo(ALL_BANDS);
}
@@ -110,24 +115,54 @@ public class WifiTetherApBandPreferenceControllerTest {
}
@Test
- public void changePreference_shouldUpdateValue() {
+ public void changePreference_noDualModeWith5G_shouldUpdateValue() {
when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
mController.displayPreference(mScreen);
+ // -1 is WifiConfiguration.AP_BAND_ANY, for 'Auto' option. This should be prevented from
+ // being set since it is invalid for this configuration
+ mController.onPreferenceChange(mPreference, "-1");
+ assertThat(mController.getBandIndex()).isEqualTo(1);
+ assertThat(mPreference.getSummary()).isEqualTo(FIVE_GHZ_STRING);
+ verify(mListener, times(1)).onTetherConfigUpdated();
+
+ // set to 5 Ghz
+ mController.onPreferenceChange(mPreference, "1");
+ assertThat(mController.getBandIndex()).isEqualTo(1);
+ assertThat(mPreference.getSummary()).isEqualTo(FIVE_GHZ_STRING);
+ verify(mListener, times(2)).onTetherConfigUpdated();
+
+ // set to 2 Ghz
+ mController.onPreferenceChange(mPreference, "0");
+ assertThat(mController.getBandIndex()).isEqualTo(0);
+ assertThat(mPreference.getSummary()).isEqualTo(TWO_GHZ_STRING);
+ verify(mListener, times(3)).onTetherConfigUpdated();
+ }
+
+ @Test
+ public void changePreference_dualModeWith5G_shouldUpdateValue() {
+ when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
+ when(mWifiManager.isDualModeSupported()).thenReturn(true);
+
+ mController.displayPreference(mScreen);
+
// -1 is WifiConfiguration.AP_BAND_ANY, for 'Auto' option.
- mController.onPreferenceChange(mPreference, -1);
+ mController.onPreferenceChange(mPreference, "-1");
assertThat(mController.getBandIndex()).isEqualTo(-1);
assertThat(mPreference.getSummary()).isEqualTo(ALL_BANDS);
+ verify(mListener, times(1)).onTetherConfigUpdated();
- mController.onPreferenceChange(mPreference, 1);
- assertThat(mController.getBandIndex()).isEqualTo(1);
- assertThat(mPreference.getSummary()).isEqualTo("5.0 GHz");
+ // should revert to the default for 5 Ghz only since this is not supported with this config
+ mController.onPreferenceChange(mPreference, "1");
+ assertThat(mController.getBandIndex()).isEqualTo(-1);
+ assertThat(mPreference.getSummary()).isEqualTo(ALL_BANDS);
+ verify(mListener, times(2)).onTetherConfigUpdated();
- mController.onPreferenceChange(mPreference, 0);
+ // set to 2 Ghz
+ mController.onPreferenceChange(mPreference, "0");
assertThat(mController.getBandIndex()).isEqualTo(0);
- assertThat(mPreference.getSummary()).isEqualTo("2.4 GHz");
-
+ assertThat(mPreference.getSummary()).isEqualTo(TWO_GHZ_STRING);
verify(mListener, times(3)).onTetherConfigUpdated();
}
@@ -136,7 +171,7 @@ public class WifiTetherApBandPreferenceControllerTest {
// Set controller band index to 1 and verify is set.
when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
mController.displayPreference(mScreen);
- mController.onPreferenceChange(mPreference, 1);
+ mController.onPreferenceChange(mPreference, "1");
assertThat(mController.getBandIndex()).isEqualTo(1);
// Disable 5Ghz band