Replace the SlicePreference with Preference am: 794fc58235
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/22755956 Change-Id: I5e9032624347b27acb02eafd28002744d92b5f2f Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -498,6 +498,15 @@
|
||||
<!-- Slice Uri to query nearby devices. -->
|
||||
<string name="config_nearby_devices_slice_uri" translatable="false">content://com.google.android.gms.nearby.fastpair/device_status_list_item</string>
|
||||
|
||||
<!-- BT Slice intent action. To support Settings 2 panel, BT slice can't use PendingIntent.send(). Therefore, here defines the Slice intent action. -->
|
||||
<string name="config_bt_slice_intent_action" translatable="false"></string>
|
||||
<!-- BT Slice pending intent action. To support Settings 2 panel, BT slice can't use PendingIntent.send(). Therefore, here defines the Slice pending intent action. -->
|
||||
<string name="config_bt_slice_pending_intent_action" translatable="false"></string>
|
||||
<!-- BT Slice EXTRA_INTENT. To support Settings 2 panel, BT slice can't use PendingIntent.send(). Therefore, here defines the Slice EXTRA_INTENT. -->
|
||||
<string name="config_bt_slice_extra_intent" translatable="false"></string>
|
||||
<!-- BT Slice EXTRA_PENDING_INTENT. To support Settings 2 panel, BT slice can't use PendingIntent.send(). Therefore, here defines the Slice EXTRA_PENDING_INTENT. -->
|
||||
<string name="config_bt_slice_extra_pending_intent" translatable="false"></string>
|
||||
|
||||
<!-- Grayscale settings intent -->
|
||||
<string name="config_grayscale_settings_intent" translatable="false"></string>
|
||||
|
||||
|
@@ -61,11 +61,9 @@
|
||||
settings:controller="com.android.settings.slices.SlicePreferenceController"
|
||||
settings:allowDividerAbove="true"/>
|
||||
|
||||
<com.android.settings.slices.SlicePreference
|
||||
android:key="bt_device_slice"
|
||||
settings:controller="com.android.settings.slices.BlockingSlicePrefController"
|
||||
settings:allowDividerBelow="true"
|
||||
settings:allowDividerAbove="true"/>
|
||||
<PreferenceCategory
|
||||
android:key="bt_device_slice_category"
|
||||
settings:controller="com.android.settings.bluetooth.BlockingPrefWithSliceController"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="device_companion_apps"/>
|
||||
@@ -108,4 +106,4 @@
|
||||
settings:searchable="false"
|
||||
settings:controller="com.android.settings.bluetooth.BluetoothDetailsMacAddressController"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
|
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.bluetooth;
|
||||
|
||||
import static android.app.slice.Slice.HINT_PERMISSION_REQUEST;
|
||||
import static android.app.slice.Slice.HINT_TITLE;
|
||||
import static android.app.slice.SliceItem.FORMAT_ACTION;
|
||||
import static android.app.slice.SliceItem.FORMAT_IMAGE;
|
||||
import static android.app.slice.SliceItem.FORMAT_SLICE;
|
||||
import static android.app.slice.SliceItem.FORMAT_TEXT;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.SliceItem;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
import androidx.slice.widget.SliceLiveData;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
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;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The blocking preference with slice controller will make whole page invisible for a certain time
|
||||
* until {@link Slice} is fully loaded.
|
||||
*/
|
||||
public class BlockingPrefWithSliceController extends BasePreferenceController implements
|
||||
LifecycleObserver, OnStart, OnStop, Observer<Slice>, BasePreferenceController.UiBlocker{
|
||||
private static final String TAG = "BlockingPrefWithSliceController";
|
||||
|
||||
private static final String PREFIX_KEY = "slice_preference_item_";
|
||||
|
||||
@VisibleForTesting
|
||||
LiveData<Slice> mLiveData;
|
||||
private Uri mUri;
|
||||
@VisibleForTesting
|
||||
PreferenceCategory mPreferenceCategory;
|
||||
private List<Preference> mCurrentPreferencesList = new ArrayList<>();
|
||||
@VisibleForTesting
|
||||
String mSliceIntentAction = "";
|
||||
@VisibleForTesting
|
||||
String mSlicePendingIntentAction = "";
|
||||
@VisibleForTesting
|
||||
String mExtraIntent = "";
|
||||
@VisibleForTesting
|
||||
String mExtraPendingIntent = "";
|
||||
|
||||
public BlockingPrefWithSliceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreferenceCategory = screen.findPreference(getPreferenceKey());
|
||||
mSliceIntentAction = mContext.getResources().getString(
|
||||
R.string.config_bt_slice_intent_action);
|
||||
mSlicePendingIntentAction = mContext.getResources().getString(
|
||||
R.string.config_bt_slice_pending_intent_action);
|
||||
mExtraIntent = mContext.getResources().getString(R.string.config_bt_slice_extra_intent);
|
||||
mExtraPendingIntent = mContext.getResources().getString(
|
||||
R.string.config_bt_slice_extra_pending_intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return mUri != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
public void setSliceUri(Uri uri) {
|
||||
mUri = uri;
|
||||
mLiveData = SliceLiveData.fromUri(mContext, mUri, (int type, Throwable source) -> {
|
||||
Log.w(TAG, "Slice may be null. uri = " + uri + ", error = " + type);
|
||||
});
|
||||
|
||||
//TODO(b/120803703): figure out why we need to remove observer first
|
||||
mLiveData.removeObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
if (mLiveData != null) {
|
||||
mLiveData.observeForever(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
if (mLiveData != null) {
|
||||
mLiveData.removeObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(Slice slice) {
|
||||
updatePreferenceFromSlice(slice);
|
||||
if (mUiBlockListener != null) {
|
||||
mUiBlockListener.onBlockerWorkFinished(this);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updatePreferenceFromSlice(Slice slice) {
|
||||
if (TextUtils.isEmpty(mSliceIntentAction)
|
||||
|| TextUtils.isEmpty(mExtraIntent)
|
||||
|| TextUtils.isEmpty(mSlicePendingIntentAction)
|
||||
|| TextUtils.isEmpty(mExtraPendingIntent)) {
|
||||
Log.d(TAG, "No configs");
|
||||
return;
|
||||
}
|
||||
if (slice == null || slice.hasHint(HINT_PERMISSION_REQUEST)) {
|
||||
Log.d(TAG, "Current slice: " + slice);
|
||||
removePreferenceListFromPreferenceCategory();
|
||||
return;
|
||||
}
|
||||
updatePreferenceListAndPreferenceCategory(parseSliceToPreferenceList(slice));
|
||||
}
|
||||
|
||||
private List<Preference> parseSliceToPreferenceList(Slice slice) {
|
||||
List<Preference> preferenceItemsList = new ArrayList<>();
|
||||
List<SliceItem> items = slice.getItems();
|
||||
int orderLevel = 0;
|
||||
for (SliceItem sliceItem : items) {
|
||||
// Parse the slice
|
||||
if (sliceItem.getFormat().equals(FORMAT_SLICE)) {
|
||||
Optional<CharSequence> title = extractTitleFromSlice(sliceItem.getSlice());
|
||||
Optional<CharSequence> subtitle = extractSubtitleFromSlice(sliceItem.getSlice());
|
||||
Optional<SliceAction> action = extractActionFromSlice(sliceItem.getSlice());
|
||||
// Create preference
|
||||
Optional<Preference> preferenceItem = createPreferenceItem(title, subtitle, action,
|
||||
orderLevel);
|
||||
if (preferenceItem.isPresent()) {
|
||||
orderLevel++;
|
||||
preferenceItemsList.add(preferenceItem.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return preferenceItemsList;
|
||||
}
|
||||
|
||||
private Optional<Preference> createPreferenceItem(Optional<CharSequence> title,
|
||||
Optional<CharSequence> subtitle, Optional<SliceAction> sliceAction, int orderLevel) {
|
||||
Log.d(TAG, "Title: " + title.orElse("no title")
|
||||
+ ", Subtitle: " + subtitle.orElse("no Subtitle")
|
||||
+ ", Action: " + sliceAction.orElse(null));
|
||||
if (!title.isPresent()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
String key = PREFIX_KEY + title.get();
|
||||
Preference preference = mPreferenceCategory.findPreference(key);
|
||||
if (preference == null) {
|
||||
preference = new Preference(mContext);
|
||||
preference.setKey(key);
|
||||
mPreferenceCategory.addPreference(preference);
|
||||
}
|
||||
preference.setTitle(title.get());
|
||||
preference.setOrder(orderLevel);
|
||||
if (subtitle.isPresent()) {
|
||||
preference.setSummary(subtitle.get());
|
||||
}
|
||||
if (sliceAction.isPresent()) {
|
||||
// To support the settings' 2 panel feature, here can't use the slice's
|
||||
// PendingIntent.send(). Since the PendingIntent.send() always take NEW_TASK flag.
|
||||
// Therefore, transfer the slice's PendingIntent to Intent and start it
|
||||
// without NEW_TASK.
|
||||
preference.setIcon(sliceAction.get().getIcon().loadDrawable(mContext));
|
||||
Intent intentFromSliceAction = sliceAction.get().getAction().getIntent();
|
||||
Intent expectedActivityIntent = null;
|
||||
Log.d(TAG, "SliceAction: intent's Action:" + intentFromSliceAction.getAction());
|
||||
if (intentFromSliceAction.getAction().equals(mSliceIntentAction)) {
|
||||
expectedActivityIntent = intentFromSliceAction
|
||||
.getParcelableExtra(mExtraIntent, Intent.class);
|
||||
} else if (intentFromSliceAction.getAction().equals(
|
||||
mSlicePendingIntentAction)) {
|
||||
PendingIntent pendingIntent = intentFromSliceAction
|
||||
.getParcelableExtra(mExtraPendingIntent, PendingIntent.class);
|
||||
expectedActivityIntent =
|
||||
pendingIntent != null ? pendingIntent.getIntent() : null;
|
||||
} else {
|
||||
expectedActivityIntent = intentFromSliceAction;
|
||||
}
|
||||
if (expectedActivityIntent != null) {
|
||||
Log.d(TAG, "setIntent: ActivityIntent" + expectedActivityIntent);
|
||||
// Since UI needs to support the Settings' 2 panel feature, the intent can't use the
|
||||
// FLAG_ACTIVITY_NEW_TASK. The above intent may have the FLAG_ACTIVITY_NEW_TASK
|
||||
// flag, so removes it before startActivity(preference.setIntent).
|
||||
expectedActivityIntent.removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
preference.setIntent(expectedActivityIntent);
|
||||
} else {
|
||||
Log.d(TAG, "setIntent: Intent is null");
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.of(preference);
|
||||
}
|
||||
|
||||
private void removePreferenceListFromPreferenceCategory() {
|
||||
mCurrentPreferencesList.stream()
|
||||
.forEach(p -> mPreferenceCategory.removePreference(p));
|
||||
mCurrentPreferencesList.clear();
|
||||
}
|
||||
|
||||
private void updatePreferenceListAndPreferenceCategory(List<Preference> newPreferenceList) {
|
||||
List<Preference> removedItemList = new ArrayList<>(mCurrentPreferencesList);
|
||||
for (Preference item : mCurrentPreferencesList) {
|
||||
if (newPreferenceList.stream().anyMatch(p -> item.compareTo(p) == 0)) {
|
||||
removedItemList.remove(item);
|
||||
}
|
||||
}
|
||||
removedItemList.stream()
|
||||
.forEach(p -> mPreferenceCategory.removePreference(p));
|
||||
mCurrentPreferencesList = newPreferenceList;
|
||||
}
|
||||
|
||||
private Optional<CharSequence> extractTitleFromSlice(Slice slice) {
|
||||
return extractTextFromSlice(slice, HINT_TITLE);
|
||||
}
|
||||
|
||||
private Optional<CharSequence> extractSubtitleFromSlice(Slice slice) {
|
||||
// For subtitle items, there isn't a hint available.
|
||||
return extractTextFromSlice(slice, /* hint= */ null);
|
||||
}
|
||||
|
||||
private Optional<CharSequence> extractTextFromSlice(Slice slice, @Nullable String hint) {
|
||||
for (SliceItem item : slice.getItems()) {
|
||||
if (item.getFormat().equals(FORMAT_TEXT)
|
||||
&& ((TextUtils.isEmpty(hint) && item.getHints().isEmpty())
|
||||
|| (!TextUtils.isEmpty(hint) && item.hasHint(hint)))) {
|
||||
return Optional.ofNullable(item.getText());
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<SliceAction> extractActionFromSlice(Slice slice) {
|
||||
for (SliceItem item : slice.getItems()) {
|
||||
if (item.getFormat().equals(FORMAT_SLICE)) {
|
||||
if (item.hasHint(HINT_TITLE)) {
|
||||
Optional<SliceAction> result = extractActionFromSlice(item.getSlice());
|
||||
if (result.isPresent()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getFormat().equals(FORMAT_ACTION)) {
|
||||
Optional<IconCompat> icon = extractIconFromSlice(item.getSlice());
|
||||
Optional<CharSequence> title = extractTitleFromSlice(item.getSlice());
|
||||
if (icon.isPresent()) {
|
||||
return Optional.of(
|
||||
SliceAction.create(
|
||||
item.getAction(),
|
||||
icon.get(),
|
||||
ListBuilder.ICON_IMAGE,
|
||||
title.orElse(/* other= */ "")));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<IconCompat> extractIconFromSlice(Slice slice) {
|
||||
for (SliceItem item : slice.getItems()) {
|
||||
if (item.getFormat().equals(FORMAT_IMAGE)) {
|
||||
return Optional.of(item.getIcon());
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@@ -49,7 +49,6 @@ import com.android.settings.core.SettingsUIDeviceConfig;
|
||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||
import com.android.settings.inputmethod.KeyboardSettingsPreferenceController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.slices.BlockingSlicePrefController;
|
||||
import com.android.settings.slices.SlicePreferenceController;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
@@ -179,7 +178,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
final boolean sliceEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_SLICE_SETTINGS_ENABLED, true);
|
||||
|
||||
use(BlockingSlicePrefController.class).setSliceUri(sliceEnabled
|
||||
use(BlockingPrefWithSliceController.class).setSliceUri(sliceEnabled
|
||||
? featureProvider.getBluetoothDeviceSettingsUri(mCachedDevice.getDevice())
|
||||
: null);
|
||||
}
|
||||
|
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.SliceViewManager;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.ListBuilder.RowBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.bluetooth.BlockingPrefWithSliceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
public class BlockingPrefWithSliceControllerTest {
|
||||
private static final String KEY = "bt_device_slice_category";
|
||||
private static final String TEST_URI_AUTHORITY = "com.android.authority.test";
|
||||
private static final String TEST_EXTRA_INTENT = "EXTRA_INTENT";
|
||||
private static final String TEST_EXTRA_PENDING_INTENT = "EXTRA_PENDING_INTENT";
|
||||
private static final String TEST_INTENT_ACTION = "test";
|
||||
private static final String TEST_PENDING_INTENT_ACTION = "test";
|
||||
private static final String TEST_SLICE_TITLE = "Test Title";
|
||||
private static final String TEST_SLICE_SUBTITLE = "Test Subtitle";
|
||||
private static final String FAKE_ACTION = "fake_action";
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
private LiveData<Slice> mLiveData;
|
||||
@Mock
|
||||
private PreferenceCategory mPreferenceCategory;
|
||||
|
||||
private Context mContext;
|
||||
private BlockingPrefWithSliceController mController;
|
||||
private Uri mUri;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mController = spy(new BlockingPrefWithSliceController(mContext, KEY));
|
||||
mController.mLiveData = mLiveData;
|
||||
mController.mExtraIntent = TEST_EXTRA_INTENT;
|
||||
mController.mExtraPendingIntent = TEST_EXTRA_PENDING_INTENT;
|
||||
mController.mSliceIntentAction = TEST_INTENT_ACTION;
|
||||
mController.mSlicePendingIntentAction = TEST_PENDING_INTENT_ACTION;
|
||||
mController.mPreferenceCategory = mPreferenceCategory;
|
||||
mUri = Uri.EMPTY;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_uriNull_returnFalse() {
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void isAvailable_uriNotNull_returnTrue() {
|
||||
mController.setSliceUri(mUri);
|
||||
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_registerObserver() {
|
||||
mController.onStart();
|
||||
|
||||
verify(mLiveData).observeForever(mController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_unregisterObserver() {
|
||||
mController.onStop();
|
||||
|
||||
verify(mLiveData).removeObserver(mController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onChanged_nullSlice_updateSlice() {
|
||||
mController.onChanged(null);
|
||||
|
||||
verify(mController).updatePreferenceFromSlice(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onChanged_testSlice_updateSlice() {
|
||||
mController.onChanged(buildTestSlice());
|
||||
|
||||
verify(mController.mPreferenceCategory).addPreference(any());
|
||||
}
|
||||
|
||||
private Slice buildTestSlice() {
|
||||
Uri uri =
|
||||
new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(TEST_URI_AUTHORITY)
|
||||
.build();
|
||||
SliceViewManager.getInstance(mContext).pinSlice(uri);
|
||||
ListBuilder listBuilder = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
|
||||
IconCompat icon = mock(IconCompat.class);
|
||||
listBuilder.addRow(
|
||||
new RowBuilder()
|
||||
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
|
||||
.setTitle(TEST_SLICE_TITLE)
|
||||
.setSubtitle(TEST_SLICE_SUBTITLE)
|
||||
.setPrimaryAction(
|
||||
SliceAction.create(
|
||||
PendingIntent.getActivity(
|
||||
mContext,
|
||||
/*requestCode= */ 0,
|
||||
new Intent(FAKE_ACTION),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
| PendingIntent.FLAG_IMMUTABLE),
|
||||
icon,
|
||||
ListBuilder.ICON_IMAGE,
|
||||
"")));
|
||||
return listBuilder.build();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user