diff --git a/res/drawable-nodpi/nfc_detection_point.png b/res/drawable-nodpi/nfc_detection_point.png
new file mode 100644
index 00000000000..1914264c087
Binary files /dev/null and b/res/drawable-nodpi/nfc_detection_point.png differ
diff --git a/res/layout/nfc_detection_point.xml b/res/layout/nfc_detection_point.xml
new file mode 100644
index 00000000000..8f938d1926e
--- /dev/null
+++ b/res/layout/nfc_detection_point.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
diff --git a/res/layout/notification_history.xml b/res/layout/notification_history.xml
index b397eef6540..0e7f6b0210d 100644
--- a/res/layout/notification_history.xml
+++ b/res/layout/notification_history.xml
@@ -72,6 +72,35 @@
android:focusable="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/notification_history_off_summary" />
+
+
+
+
+
+
+ false
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index aadd62d5696..c2539fa9fea 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -67,6 +67,8 @@
6
+ 300dp
+
64dp
20dp
4dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 588223a7599..8a642ac1fa9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7185,6 +7185,8 @@
+
+
@@ -8110,6 +8112,12 @@
Turn on notification history to see recent notifications and snoozed notifications
+
+ No recent notifications
+
+
+ Your recent and snoozed notifications will appear here
+
view notification settings
diff --git a/res/xml/nfc_and_payment_settings.xml b/res/xml/nfc_and_payment_settings.xml
index f240388279a..8ff4983579b 100644
--- a/res/xml/nfc_and_payment_settings.xml
+++ b/res/xml/nfc_and_payment_settings.xml
@@ -19,6 +19,12 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/nfc_quick_toggle_title">
+
+
-
\ No newline at end of file
+
diff --git a/src/com/android/settings/accessibility/AccessibilityControlTimeoutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityControlTimeoutPreferenceFragment.java
index b37fdfb8519..0550908f3f2 100644
--- a/src/com/android/settings/accessibility/AccessibilityControlTimeoutPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityControlTimeoutPreferenceFragment.java
@@ -19,7 +19,6 @@ package com.android.settings.accessibility;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Resources;
-import android.provider.SearchIndexableResource;
import androidx.preference.Preference;
@@ -31,7 +30,6 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
@SearchIndexable
@@ -88,6 +86,11 @@ public final class AccessibilityControlTimeoutPreferenceFragment extends Dashboa
return buildPreferenceControllers(context, getSettingsLifecycle());
}
+ @Override
+ public int getHelpResource() {
+ return R.string.help_url_timeout;
+ }
+
private static List buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
if (sControllers.size() == 0) {
diff --git a/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java b/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java
index 12393ad13f7..cf0be207472 100644
--- a/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java
@@ -19,6 +19,7 @@ package com.android.settings.applications.appinfo;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.icu.text.ListFormatter;
import android.util.Log;
@@ -28,15 +29,24 @@ import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settingslib.applications.PermissionsSummaryHelper;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.ArrayList;
import java.util.List;
-public class AppPermissionPreferenceController extends AppInfoPreferenceControllerBase {
+/**
+ * A PreferenceController handling the logic for permissions of apps.
+ */
+public class AppPermissionPreferenceController extends AppInfoPreferenceControllerBase implements
+ LifecycleObserver, OnStart, OnStop {
private static final String TAG = "PermissionPrefControl";
private static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton";
+ private final PackageManager mPackageManager;
+
private String mPackageName;
@VisibleForTesting
@@ -73,8 +83,22 @@ public class AppPermissionPreferenceController extends AppInfoPreferenceControll
}
};
+ private final PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
+ uid -> updateState(mPreference);
+
public AppPermissionPreferenceController(Context context, String key) {
super(context, key);
+ mPackageManager = context.getPackageManager();
+ }
+
+ @Override
+ public void onStart() {
+ mPackageManager.addOnPermissionsChangeListener(mOnPermissionsChangedListener);
+ }
+
+ @Override
+ public void onStop() {
+ mPackageManager.removeOnPermissionsChangeListener(mOnPermissionsChangedListener);
}
@Override
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index 9dbf948ec99..27960e123ea 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -197,6 +197,8 @@ public class MediaOutputSlice implements CustomSliceable {
}
listBuilder.addInputRange(builder);
} else {
+ Log.d(TAG, "addRow device = " + device.getName() + " MaxVolume = "
+ + device.getMaxVolume());
final ListBuilder.RowBuilder builder = getMediaDeviceRow(device);
// Check end item visibility
if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE
@@ -266,16 +268,24 @@ public class MediaOutputSlice implements CustomSliceable {
if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
&& !device.isConnected()) {
- // Append status to title only for the disconnected Bluetooth device.
- final SpannableString spannableTitle = new SpannableString(
- mContext.getString(R.string.media_output_disconnected_status, deviceName));
- spannableTitle.setSpan(new ForegroundColorSpan(
- Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorSecondary)),
- deviceName.length(),
- spannableTitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
- rowBuilder.setTitle(spannableTitle);
- rowBuilder.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
- ListBuilder.ICON_IMAGE, spannableTitle));
+ if (device.getState() == LocalMediaManager.MediaDeviceState.STATE_CONNECTING) {
+ rowBuilder.setTitle(deviceName);
+ rowBuilder.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
+ ListBuilder.ICON_IMAGE, deviceName));
+ rowBuilder.setSubtitle(mContext.getText(R.string.media_output_switching));
+ } else {
+ // Append status to title only for the disconnected Bluetooth device.
+ final SpannableString spannableTitle = new SpannableString(
+ mContext.getString(R.string.media_output_disconnected_status, deviceName));
+ spannableTitle.setSpan(new ForegroundColorSpan(
+ Utils.getColorAttrDefaultColor(mContext,
+ android.R.attr.textColorSecondary)),
+ deviceName.length(),
+ spannableTitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
+ rowBuilder.setTitle(spannableTitle);
+ rowBuilder.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
+ ListBuilder.ICON_IMAGE, spannableTitle));
+ }
} else {
rowBuilder.setTitle(deviceName);
rowBuilder.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
diff --git a/src/com/android/settings/nfc/NfcDetectionPointController.java b/src/com/android/settings/nfc/NfcDetectionPointController.java
new file mode 100644
index 00000000000..b2e8f6abdea
--- /dev/null
+++ b/src/com/android/settings/nfc/NfcDetectionPointController.java
@@ -0,0 +1,48 @@
+/*
+ * 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.nfc;
+
+import android.content.Context;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+/**
+ * Controller that used to show nfc detection point guidance
+ */
+public class NfcDetectionPointController extends BasePreferenceController {
+ private boolean mEnabled;
+
+ public NfcDetectionPointController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ mEnabled = mContext.getResources().getBoolean(R.bool.config_nfc_detection_point);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!mEnabled) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ return AVAILABLE;
+ }
+
+ @VisibleForTesting
+ public void setConfig(boolean value) {
+ mEnabled = value;
+ }
+}
diff --git a/src/com/android/settings/notification/history/NotificationHistoryActivity.java b/src/com/android/settings/notification/history/NotificationHistoryActivity.java
index 8d7695ff3d8..d41268dcc53 100644
--- a/src/com/android/settings/notification/history/NotificationHistoryActivity.java
+++ b/src/com/android/settings/notification/history/NotificationHistoryActivity.java
@@ -70,6 +70,8 @@ public class NotificationHistoryActivity extends Activity {
private PackageManager mPm;
private HistoryLoader.OnHistoryLoaderListener mOnHistoryLoaderListener = notifications -> {
+ findViewById(R.id.today_list).setVisibility(
+ notifications.isEmpty() ? View.GONE : View.VISIBLE);
// for each package, new header and recycler view
for (NotificationHistoryPackage nhp : notifications) {
View viewForPackage = LayoutInflater.from(this)
@@ -182,6 +184,10 @@ public class NotificationHistoryActivity extends Activity {
} else {
mHistoryOn.setVisibility(View.GONE);
mHistoryOff.setVisibility(View.VISIBLE);
+ mHistoryOff.findViewById(R.id.history_off_title).setVisibility(View.VISIBLE);
+ mHistoryOff.findViewById(R.id.history_off_summary).setVisibility(View.VISIBLE);
+ mHistoryOff.findViewById(R.id.history_toggled_on_title).setVisibility(View.GONE);
+ mHistoryOff.findViewById(R.id.history_toggled_on_summary).setVisibility(View.GONE);
mTodayView.removeAllViews();
}
}
@@ -232,7 +238,17 @@ public class NotificationHistoryActivity extends Activity {
Settings.Secure.putInt(getContentResolver(),
NOTIFICATION_HISTORY_ENABLED,
isChecked ? 1 : 0);
- toggleViews(isChecked);
+ mHistoryOn.setVisibility(View.GONE);
+ mHistoryOff.findViewById(R.id.history_off_title).setVisibility(
+ isChecked ? View.GONE : View.VISIBLE);
+ mHistoryOff.findViewById(R.id.history_off_summary).setVisibility(
+ isChecked ? View.GONE : View.VISIBLE);
+ mHistoryOff.findViewById(R.id.history_toggled_on_title).setVisibility(
+ isChecked ? View.VISIBLE : View.GONE);
+ mHistoryOff.findViewById(R.id.history_toggled_on_summary).setVisibility(
+ isChecked ? View.VISIBLE : View.GONE);
+ mTodayView.removeAllViews();
+ mHistoryOff.setVisibility(View.VISIBLE);
};
private final NotificationListenerService mListener = new NotificationListenerService() {
diff --git a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
index 6ad4c94a8d9..1b54e1a2f31 100644
--- a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
+++ b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
@@ -235,6 +235,13 @@ public class WifiNetworkDetailsFragment2 extends DashboardFragment implements
public void refreshPreferences() {
final PreferenceScreen screen = getPreferenceScreen();
for (AbstractPreferenceController controller : mControllers) {
+ // WifiDetailPreferenceController2 gets the callback WifiEntryCallback#onUpdated,
+ // it can control the visibility change by itself.
+ // And WifiDetailPreferenceController2#updatePreference renew mEntityHeaderController
+ // instance which will cause icon reset.
+ if (controller instanceof WifiDetailPreferenceController2) {
+ continue;
+ }
controller.displayPreference(screen);
}
}
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppPermissionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppPermissionPreferenceControllerTest.java
index 022de97cbb0..f00471d9ecc 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppPermissionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppPermissionPreferenceControllerTest.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -43,6 +44,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
@@ -57,6 +59,8 @@ public class AppPermissionPreferenceControllerTest {
private PreferenceScreen mScreen;
@Mock
private Preference mPreference;
+ @Mock
+ private PackageManager mPackageManager;
private Context mContext;
private AppPermissionPreferenceController mController;
@@ -68,6 +72,7 @@ public class AppPermissionPreferenceControllerTest {
mController = new AppPermissionPreferenceController(mContext, "permission_settings");
mController.setPackageName("package1");
mController.setParentFragment(mFragment);
+ ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
when(mScreen.findPreference(any())).thenReturn(mPreference);
final String key = mController.getPreferenceKey();
@@ -75,10 +80,26 @@ public class AppPermissionPreferenceControllerTest {
when(mFragment.getActivity()).thenReturn(mActivity);
}
+ @Test
+ public void onStart_shouldAddPermissionsChangeListener() {
+ mController.onStart();
+
+ verify(mPackageManager).addOnPermissionsChangeListener(
+ any(PackageManager.OnPermissionsChangedListener.class));
+ }
+
+ @Test
+ public void onStop_shouldRemovePermissionsChangeListener() {
+ mController.onStop();
+
+ verify(mPackageManager).removeOnPermissionsChangeListener(
+ any(PackageManager.OnPermissionsChangedListener.class));
+ }
+
@Test
public void getAvailabilityStatus_isAlwaysAvailable() {
assertThat(mController.getAvailabilityStatus())
- .isEqualTo(AppPermissionPreferenceController.AVAILABLE);
+ .isEqualTo(AppPermissionPreferenceController.AVAILABLE);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
index 305d1ab72b9..d4590b5a455 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
@@ -473,6 +473,43 @@ public class MediaOutputSliceTest {
R.string.bluetooth_pairing_pref_title))).isEqualTo(-1);
}
+ @Test
+ public void getSlice_disconnectedBtOnTransferring_containTransferringSubtitle() {
+ final List mSelectedDevices = new ArrayList<>();
+ final List 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);
+ 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.media_output_switching)))
+ .isNotEqualTo(-1);
+ }
+
@Test
public void onNotifyChange_foundMediaDevice_connect() {
mDevices.clear();
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcDetectionPointControllerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcDetectionPointControllerTest.java
new file mode 100644
index 00000000000..31ac7d67e02
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/nfc/NfcDetectionPointControllerTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.nfc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class NfcDetectionPointControllerTest {
+
+ private NfcDetectionPointController mController;
+
+ @Before
+ public void setUp() {
+ mController = new NfcDetectionPointController(RuntimeEnvironment.application, "fakeKey");
+ }
+
+ @Test
+ public void getAvailabilityStatus_withConfigIsTrue_returnAvailable() {
+ mController.setConfig(true);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(NfcDetectionPointController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_withConfigIsFalse_returnUnavailable() {
+ mController.setConfig(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isNotEqualTo(NfcDetectionPointController.AVAILABLE);
+ }
+}