Merge "Change UI for wireless AP tether band selection"
diff --git a/res/drawable/ic_signal_flashlight.xml b/res/drawable/ic_signal_flashlight.xml
new file mode 100644
index 0000000..e635953
--- /dev/null
+++ b/res/drawable/ic_signal_flashlight.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18,2H6v6l2,3v11h8V11l2,-3L18,2zM16,4l0,1H8V4H16zM14,10.4V20h-4v-9.61l-2,-3V7h8l0,0.39L14,10.4z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,14m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
+</vector>
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index f563643..fbb464c 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" />
<!-- Empty category to draw divider -->
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index 650b1c4..9f69102 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" />
</PreferenceScreen>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 54a4190..d38a8e4 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" />
<Preference
android:key="gesture_prevent_ringing_sound"
android:title="@string/gesture_prevent_ringing_sound_title"
android:order="-110"
android:fragment="com.android.settings.gestures.PreventRingingGestureSettings"
- settings:controller="com.android.settings.gestures.PreventRingingPreferenceController" />
+ settings:controller="com.android.settings.gestures.PreventRingingParentPreferenceController" />
<!-- Phone ringtone -->
<com.android.settings.DefaultRingtonePreference
diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java
index 66f9179..66e8d22 100644
--- a/src/com/android/settings/accounts/AccountSyncSettings.java
+++ b/src/com/android/settings/accounts/AccountSyncSettings.java
@@ -247,10 +247,13 @@
}
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 8153be2..c243970 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 java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Fragment for choosing default browser.
@@ -62,14 +65,20 @@
DefaultBrowserPreferenceController.BROWSE_PROBE, PackageManager.MATCH_ALL, mUserId);
final int count = list.size();
+ final Set<String> 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 bb60df9..27b7676 100644
--- a/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
@@ -21,11 +21,13 @@
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 @@
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 @@
@Override
public void onStart() {
mBluetoothDeviceUpdater.registerCallback();
+ mSavedDockUpdater.registerCallback();
updatePreferenceOnSizeChanged();
}
@Override
public void onStop() {
mBluetoothDeviceUpdater.unregisterCallback();
+ mSavedDockUpdater.unregisterCallback();
}
public void init(DashboardFragment fragment) {
@@ -91,6 +99,11 @@
}
@VisibleForTesting
+ void setSavedDockUpdater(DockUpdater savedDockUpdater) {
+ mSavedDockUpdater = savedDockUpdater;
+ }
+
+ @VisibleForTesting
void setPreferenceSize(int size) {
mPreferenceSize = size;
}
@@ -105,4 +118,4 @@
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 95a534c..03bba42 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
@@ -24,6 +24,7 @@
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 @@
*/
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 @@
@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/flashlight/FlashlightSliceBuilder.java b/src/com/android/settings/flashlight/FlashlightSliceBuilder.java
new file mode 100644
index 0000000..6317ce7
--- /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/gestures/PreventRingingParentPreferenceController.java b/src/com/android/settings/gestures/PreventRingingParentPreferenceController.java
new file mode 100644
index 0000000..8814765
--- /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 c6bc3aa..be55151 100644
--- a/src/com/android/settings/gestures/PreventRingingPreferenceController.java
+++ b/src/com/android/settings/gestures/PreventRingingPreferenceController.java
@@ -24,14 +24,8 @@
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.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 @@
@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 cdc02c0..96a4eb6 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -24,8 +24,6 @@
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.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 @@
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 @@
}
});
- controllers.add(new ZenModePreferenceController(context, lifecycle, KEY_ZEN_MODE));
return controllers;
}
@@ -220,7 +219,6 @@
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 7ad22a9..dbac1c2 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -27,10 +27,6 @@
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.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 @@
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 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
SoundSettings fragment, Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new ZenModePreferenceController(context, lifecycle, KEY_ZEN_MODE));
// Volumes are added via xml
@@ -309,15 +307,6 @@
return buildPreferenceControllers(context, null /* fragment */,
null /* lifecycle */);
}
-
- @Override
- public List<String> getNonIndexableKeys(Context context) {
- List<String> 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 0d94029..d70ffe2 100644
--- a/src/com/android/settings/notification/ZenModePreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePreferenceController.java
@@ -23,38 +23,30 @@
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;
- private final String mKey;
+public class ZenModePreferenceController extends BasePreferenceController
+ implements LifecycleObserver, OnResume, OnPause {
+
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 @@
}
@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 28475b6..10a7b56 100644
--- a/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
@@ -68,7 +68,10 @@
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 7b50dde..99bc172 100644
--- a/src/com/android/settings/notification/ZenOnboardingActivity.java
+++ b/src/com/android/settings/notification/ZenOnboardingActivity.java
@@ -157,6 +157,12 @@
// 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/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index db09a37..7eda82b 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -34,6 +34,7 @@
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 @@
} 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 @@
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 @@
private List<Uri> 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 9f1ef76..95f0538 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.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 @@
.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/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 52a3692..a33561b 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -42,13 +42,6 @@
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.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 @@
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 @@
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 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 @@
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 @@
} 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 @@
}
private void updateUserList() {
- if (getActivity() == null) return;
- List<UserInfo> users = mUserManager.getUsers(true);
final Context context = getActivity();
+ if (context == null) {
+ return;
+ }
+ final List<UserInfo> users = mUserManager.getUsers(true);
final boolean voiceCapable = Utils.isVoiceCapable(context);
final ArrayList<Integer> missingIcons = new ArrayList<>();
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 0000000..da36185
--- /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 f7a21d8..bdf249d 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 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 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest();
when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mPicker = new DefaultBrowserPicker();
@@ -72,4 +85,39 @@
mPicker.getDefaultKey();
verify(mPackageManager).getDefaultBrowserPackageNameAsUser(anyInt());
}
+
+ @Test
+ public void getCandidates_shouldNotIncludeDuplicatePackageName() throws NameNotFoundException {
+ final List<ResolveInfo> 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<DefaultAppInfo> 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 fd2ff0d..6e69e67 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 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 @@
@Mock
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
@Mock
+ private DockUpdater mDockUpdater;
+ @Mock
private PackageManager mPackageManager;
private Context mContext;
@@ -60,6 +63,7 @@
mPreConnectedDeviceController =
new PreviouslyConnectedDevicePreferenceController(mContext, KEY);
mPreConnectedDeviceController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater);
+ mPreConnectedDeviceController.setSavedDockUpdater(mDockUpdater);
mPreference = new Preference(mContext);
mPreConnectedDeviceController.setPreference(mPreference);
@@ -70,10 +74,12 @@
// 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 e83e93d..1fe0931 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.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 @@
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 0000000..5862ab3
--- /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<SliceAction> toggles = metadata.getToggles();
+ assertThat(toggles).hasSize(1);
+
+ final List<SliceItem> 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 0000000..33a00fa
--- /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 3ea4471..ece25e2 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 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.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
+import androidx.preference.Preference;
+
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModePreferenceControllerTest {
@@ -61,7 +63,7 @@
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 @@
}
@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 064c091..ad8e0de 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 @@
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 e09dc0d..3ca9fda 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.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenOnboardingActivityTest {
@@ -68,6 +69,8 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 6b1262a..c72e9f6 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.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 @@
);
private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
- ZenModeSliceBuilder.ZEN_MODE_URI
+ ZenModeSliceBuilder.ZEN_MODE_URI,
+ FlashlightSliceBuilder.FLASHLIGHT_URI
);
@Before
@@ -445,6 +448,16 @@
}
@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()
.scheme(ContentResolver.SCHEME_CONTENT)
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 50c0330..928779b 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.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;
@@ -67,6 +68,14 @@
}
@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)
? sMasterSyncAutomatically.get(userId) : true;