Snap for 6371019 from 44874aebd2 to mainline-release

Change-Id: Iceb71d65118f11aa79ff6d07831a6b78abdaf1c9
This commit is contained in:
android-build-team Robot
2020-04-07 07:06:36 +00:00
16 changed files with 309 additions and 16 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="@dimen/nfc_detection_point_height"
android:scaleType="centerCrop"
android:cropToPadding="true"
android:src="@drawable/nfc_detection_point"
android:contentDescription="@null" />
</FrameLayout>

View File

@@ -72,6 +72,35 @@
android:focusable="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/notification_history_off_summary" />
<TextView
android:id="@+id/history_toggled_on_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/history_image"
android:layout_marginTop="48dp"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
android:layout_gravity="center_horizontal"
android:focusable="true"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/history_toggled_on_title" />
<TextView
android:id="@+id/history_toggled_on_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/history_off_title"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
android:layout_marginTop="16dp"
android:layout_gravity="center_horizontal"
android:textAlignment="center"
android:focusable="true"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/history_toggled_on_summary" />
</LinearLayout>
<LinearLayout

View File

@@ -442,4 +442,7 @@
<!-- Package name of dialer supports RTT setting-->
<string name="config_rtt_setting_package_name" translatable="false"></string>
<!-- Whether nfc detection point preview image is available or not. -->
<bool name="config_nfc_detection_point">false</bool>
</resources>

View File

@@ -67,6 +67,8 @@
<!-- Weight of the right pane in a multi-pane preference layout. So the split is 40:60 -->
<integer name="preferences_right_pane_weight">6</integer>
<dimen name="nfc_detection_point_height">300dp</dimen>
<dimen name="notification_app_icon_size">64dp</dimen>
<dimen name="notification_app_icon_badge_size">20dp</dimen>
<dimen name="notification_app_icon_badge_margin">4dp</dimen>

View File

@@ -7185,6 +7185,8 @@
<string name="help_url_autoclick" translatable="false"></string>
<!-- Help URL, Accessibility caption preferences [DO NOT TRANSLATE] -->
<string name="help_url_caption" translatable="false"></string>
<!-- Help URL, Accessibility Timeout [DO NOT TRANSLATE] -->
<string name="help_url_timeout" translatable="false"></string>
<string name="help_url_system_dashboard" translatable="false"></string>
<string name="help_url_double_tap_screen" translatable="false"></string>
<string name="help_url_account_detail" translatable="false"></string>
@@ -8110,6 +8112,12 @@
<!-- Notification history screen; summary when history is off [CHAR LIMIT=NONE] -->
<string name="notification_history_off_summary">Turn on notification history to see recent notifications and snoozed notifications</string>
<!-- Notification history screen; title when history is newly turned on [CHAR LIMIT=200] -->
<string name="history_toggled_on_title">No recent notifications</string>
<!-- Notification history screen; summary when history is newly turned on [CHAR LIMIT=NONE] -->
<string name="history_toggled_on_summary">Your recent and snoozed notifications will appear here</string>
<!-- Notification history screen; content description describing what happens when you tap on a notification history entry [CHAR LIMIT=NONE] -->
<string name="notification_history_view_settings">view notification settings</string>

View File

@@ -19,6 +19,12 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/nfc_quick_toggle_title">
<com.android.settingslib.widget.LayoutPreference
android:key="nfc_detection_point"
android:selectable="false"
android:layout="@layout/nfc_detection_point"
settings:controller="com.android.settings.nfc.NfcDetectionPointController"/>
<SwitchPreference
android:key="toggle_nfc"
android:title="@string/nfc_quick_toggle_title"

View File

@@ -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<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
if (sControllers.size() == 0) {

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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() {

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -473,6 +473,43 @@ public class MediaOutputSliceTest {
R.string.bluetooth_pairing_pref_title))).isEqualTo(-1);
}
@Test
public void getSlice_disconnectedBtOnTransferring_containTransferringSubtitle() {
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);
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();

View File

@@ -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);
}
}