Merge "Cleanup notification channel slice" into rvc-dev
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index a1fb076..8d6e07d 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -26,7 +26,6 @@
import com.android.settings.fuelgauge.batterytip.detectors.EarlyWarningDetector;
import com.android.settings.fuelgauge.batterytip.detectors.HighUsageDetector;
import com.android.settings.fuelgauge.batterytip.detectors.LowBatteryDetector;
-import com.android.settings.fuelgauge.batterytip.detectors.RestrictAppDetector;
import com.android.settings.fuelgauge.batterytip.detectors.SmartBatteryDetector;
import com.android.settings.fuelgauge.batterytip.detectors.SummaryDetector;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
@@ -74,7 +73,9 @@
tips.add(new SmartBatteryDetector(policy, context.getContentResolver()).detect());
tips.add(new EarlyWarningDetector(policy, context).detect());
tips.add(new SummaryDetector(policy, batteryInfo.averageTimeToDischarge).detect());
- tips.add(new RestrictAppDetector(context, policy).detect());
+ // Disable this feature now since it introduces false positive cases. We will try to improve
+ // it in the future.
+ // tips.add(new RestrictAppDetector(context, policy).detect());
Collections.sort(tips);
return tips;
diff --git a/src/com/android/settings/media/MediaOutputIndicatorWorker.java b/src/com/android/settings/media/MediaOutputIndicatorWorker.java
index 0c6c434..f094d47 100644
--- a/src/com/android/settings/media/MediaOutputIndicatorWorker.java
+++ b/src/com/android/settings/media/MediaOutputIndicatorWorker.java
@@ -38,6 +38,7 @@
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.MediaDevice;
+import com.android.settingslib.utils.ThreadUtils;
import com.google.common.annotations.VisibleForTesting;
@@ -81,25 +82,29 @@
mContext.registerReceiver(mReceiver, intentFilter);
mLocalBluetoothManager.getEventManager().registerCallback(this);
- final MediaController controller = getActiveLocalMediaController();
- if (controller == null) {
- mPackageName = null;
- } else {
- mPackageName = controller.getPackageName();
- }
- if (mLocalMediaManager == null || !TextUtils.equals(mPackageName,
- mLocalMediaManager.getPackageName())) {
- mLocalMediaManager = new LocalMediaManager(mContext, mPackageName,
- null /* notification */);
- }
- mLocalMediaManager.registerCallback(this);
- mLocalMediaManager.startScan();
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final MediaController controller = getActiveLocalMediaController();
+ if (controller == null) {
+ mPackageName = null;
+ } else {
+ mPackageName = controller.getPackageName();
+ }
+ if (mLocalMediaManager == null || !TextUtils.equals(mPackageName,
+ mLocalMediaManager.getPackageName())) {
+ mLocalMediaManager = new LocalMediaManager(mContext, mPackageName,
+ null /* notification */);
+ }
+ mLocalMediaManager.registerCallback(this);
+ mLocalMediaManager.startScan();
+ });
}
@Override
protected void onSliceUnpinned() {
- mLocalMediaManager.unregisterCallback(this);
- mLocalMediaManager.stopScan();
+ if (mLocalMediaManager != null) {
+ mLocalMediaManager.unregisterCallback(this);
+ mLocalMediaManager.stopScan();
+ }
if (mLocalBluetoothManager == null) {
Log.e(TAG, "Bluetooth is not supported on this device");
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index 4e54d7b..5a1afda 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -287,11 +287,16 @@
if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
&& !device.isConnected()) {
- if (device.getState() == LocalMediaManager.MediaDeviceState.STATE_CONNECTING) {
+ final int state = device.getState();
+ if (state == LocalMediaManager.MediaDeviceState.STATE_CONNECTING
+ || state == LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED) {
rowBuilder.setTitle(deviceName);
rowBuilder.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
ListBuilder.ICON_IMAGE, deviceName));
- rowBuilder.setSubtitle(mContext.getText(R.string.media_output_switching));
+ rowBuilder.setSubtitle(
+ (state == LocalMediaManager.MediaDeviceState.STATE_CONNECTING)
+ ? mContext.getText(R.string.media_output_switching)
+ : mContext.getText(R.string.bluetooth_connect_failed));
} else {
// Append status to title only for the disconnected Bluetooth device.
final SpannableString spannableTitle = new SpannableString(
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index f55d65c..81d5036 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -297,7 +297,8 @@
getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
// Can only run during setup if factory reset protection has already been cleared
- return (pdbm != null && pdbm.getDataBlockSize() == 0);
+ // or if the device does not support FRP.
+ return (pdbm == null || pdbm.getDataBlockSize() == 0);
}
protected Class<? extends ChooseLockGeneric.InternalActivity> getInternalActivityClass() {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
index 2f5fa1a..116033b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
@@ -32,7 +32,6 @@
import com.android.settings.fuelgauge.batterytip.tips.AppLabelPredicate;
import com.android.settings.fuelgauge.batterytip.tips.AppRestrictionPredicate;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
-import com.android.settings.testutils.BatteryTestUtils;
import org.junit.After;
import org.junit.Before;
@@ -43,15 +42,14 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
import java.util.List;
-import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class BatteryTipLoaderTest {
private static final int[] TIP_ORDER = {
- BatteryTip.TipType.APP_RESTRICTION,
BatteryTip.TipType.BATTERY_SAVER,
BatteryTip.TipType.HIGH_DEVICE_USAGE,
BatteryTip.TipType.LOW_BATTERY,
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
index dd3a236..0aec952 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
@@ -103,7 +103,13 @@
@Test
public void onSlicePinned_registerCallback() {
mMediaOutputIndicatorWorker.mLocalMediaManager = mLocalMediaManager;
+ initPlayback();
+ when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
+ when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
+ when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(mLocalMediaManager.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
mMediaOutputIndicatorWorker.onSlicePinned();
+ waitForLocalMediaManagerInit();
verify(mBluetoothEventManager).registerCallback(mMediaOutputIndicatorWorker);
verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
@@ -119,11 +125,14 @@
when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
mMediaOutputIndicatorWorker.onSlicePinned();
+ waitForLocalMediaManagerInit();
assertThat(mMediaOutputIndicatorWorker.mLocalMediaManager.getPackageName()).matches(
TEST_PACKAGE_NAME);
when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME2);
+ mMediaOutputIndicatorWorker.mLocalMediaManager = null;
mMediaOutputIndicatorWorker.onSlicePinned();
+ waitForLocalMediaManagerInit();
assertThat(mMediaOutputIndicatorWorker.mLocalMediaManager.getPackageName()).matches(
TEST_PACKAGE_NAME2);
@@ -134,14 +143,35 @@
mMediaControllers.clear();
mMediaOutputIndicatorWorker.onSlicePinned();
+ waitForLocalMediaManagerInit();
assertThat(mMediaOutputIndicatorWorker.mLocalMediaManager.getPackageName()).isNull();
}
+ private void waitForLocalMediaManagerInit() {
+ for (int i = 0; i < 20; i++) {
+ if (mMediaOutputIndicatorWorker.mLocalMediaManager != null) {
+ return;
+ }
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
@Test
public void onSliceUnpinned_unRegisterCallback() {
mMediaOutputIndicatorWorker.mLocalMediaManager = mLocalMediaManager;
+ initPlayback();
+ when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
+ when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
+ when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(mLocalMediaManager.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
mMediaOutputIndicatorWorker.onSlicePinned();
+ waitForLocalMediaManagerInit();
mMediaOutputIndicatorWorker.onSliceUnpinned();
verify(mBluetoothEventManager).unregisterCallback(mMediaOutputIndicatorWorker);
@@ -153,6 +183,7 @@
@Test
public void onReceive_shouldNotifyChange() {
mMediaOutputIndicatorWorker.onSlicePinned();
+ waitForLocalMediaManagerInit();
// onSlicePinned will registerCallback() and get first callback. Callback triggers this at
// the first time.
verify(mResolver, times(1)).notifyChange(URI, null);
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
index 4e25801..0a8ffa7 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
@@ -513,6 +513,44 @@
}
@Test
+ public void getSlice_disconnectedBtOnTransferringFailed_containTransferringFailedSubtitle() {
+ final List<MediaDevice> mSelectedDevices = new ArrayList<>();
+ final List<MediaDevice> mSelectableDevices = new ArrayList<>();
+ mDevices.clear();
+ final MediaDevice device = mock(MediaDevice.class);
+ when(device.getName()).thenReturn(TEST_DEVICE_1_NAME);
+ when(device.getIcon()).thenReturn(mTestDrawable);
+ when(device.getMaxVolume()).thenReturn(100);
+ when(device.isConnected()).thenReturn(true);
+ when(device.getDeviceType()).thenReturn(MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE);
+ when(device.getId()).thenReturn(TEST_DEVICE_1_ID);
+ final MediaDevice device2 = mock(MediaDevice.class);
+ when(device2.getName()).thenReturn(TEST_DEVICE_2_NAME);
+ when(device2.getIcon()).thenReturn(mTestDrawable);
+ when(device2.getMaxVolume()).thenReturn(100);
+ when(device2.isConnected()).thenReturn(false);
+ when(device2.getState()).thenReturn(
+ LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED);
+ when(device2.getDeviceType()).thenReturn(MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE);
+ when(device2.getId()).thenReturn(TEST_DEVICE_2_ID);
+ mSelectedDevices.add(device);
+ mSelectableDevices.add(device2);
+ when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(device);
+ mDevices.add(device);
+ mDevices.add(device2);
+ when(mLocalMediaManager.getSelectedMediaDevice()).thenReturn(mSelectedDevices);
+ when(mLocalMediaManager.getSelectableMediaDevice()).thenReturn(mSelectableDevices);
+ mMediaDeviceUpdateWorker.onDeviceListUpdate(mDevices);
+
+ final Slice mediaSlice = mMediaOutputSlice.getSlice();
+ final String sliceInfo = SliceQuery.findAll(mediaSlice, FORMAT_SLICE, HINT_LIST_ITEM,
+ null).toString();
+
+ assertThat(TextUtils.indexOf(sliceInfo,
+ mContext.getText(R.string.bluetooth_connect_failed))).isNotEqualTo(-1);
+ }
+
+ @Test
public void onNotifyChange_foundMediaDevice_connect() {
mDevices.clear();
final MediaDevice device = mock(MediaDevice.class);
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
index b535bc1..036df2c 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
@@ -34,6 +34,7 @@
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings.Global;
@@ -48,7 +49,6 @@
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
-import com.android.settings.testutils.shadow.ShadowPersistentDataBlockManager;
import com.android.settings.testutils.shadow.ShadowStorageManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -62,6 +62,8 @@
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowPersistentDataBlockManager;
@RunWith(RobolectricTestRunner.class)
@Config(
@@ -100,6 +102,17 @@
}
@Test
+ public void onCreate_deviceNotProvisioned_persistentDataServiceNotAvailable_shouldNotFinish() {
+ Global.putInt(application.getContentResolver(), Global.DEVICE_PROVISIONED, 0);
+ ShadowPersistentDataBlockManager.setDataBlockSize(1000);
+ ShadowApplication.getInstance().setSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE,
+ null);
+
+ initActivity(null);
+ assertThat(mActivity.isFinishing()).isFalse();
+ }
+
+ @Test
public void onActivityResult_nullIntentData_shouldNotCrash() {
initActivity(null);
mFragment.onActivityResult(
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPersistentDataBlockManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPersistentDataBlockManager.java
deleted file mode 100644
index dbbdd3d..0000000
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPersistentDataBlockManager.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.testutils.shadow;
-
-import android.service.persistentdata.PersistentDataBlockManager;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.Resetter;
-
-@Implements(PersistentDataBlockManager.class)
-public class ShadowPersistentDataBlockManager {
- private static int sDataBlockSize = 0;
-
- @Resetter
- public static void reset() {
- sDataBlockSize = 0;
- }
-
- @Implementation
- protected int getDataBlockSize() {
- return sDataBlockSize;
- }
-
- public static void setDataBlockSize(int dataBlockSize) {
- sDataBlockSize = dataBlockSize;
- }
-}