1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.bluetooth; 18 19 import static androidx.slice.builders.ListBuilder.ICON_IMAGE; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.verify; 27 28 import android.app.PendingIntent; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.net.Uri; 33 34 import androidx.core.graphics.drawable.IconCompat; 35 import androidx.lifecycle.LiveData; 36 import androidx.preference.Preference; 37 import androidx.preference.PreferenceCategory; 38 import androidx.slice.Slice; 39 import androidx.slice.SliceViewManager; 40 import androidx.slice.builders.ListBuilder; 41 import androidx.slice.builders.ListBuilder.RowBuilder; 42 import androidx.slice.builders.SliceAction; 43 import androidx.test.annotation.UiThreadTest; 44 import androidx.test.core.app.ApplicationProvider; 45 import androidx.test.ext.junit.runners.AndroidJUnit4; 46 47 import org.junit.Before; 48 import org.junit.Rule; 49 import org.junit.Test; 50 import org.junit.runner.RunWith; 51 import org.mockito.ArgumentCaptor; 52 import org.mockito.Captor; 53 import org.mockito.Mock; 54 import org.mockito.junit.MockitoJUnit; 55 import org.mockito.junit.MockitoRule; 56 57 @RunWith(AndroidJUnit4.class) 58 public class BlockingPrefWithSliceControllerTest { 59 private static final String KEY = "bt_device_slice_category"; 60 private static final String TEST_URI_AUTHORITY = "com.android.settings"; 61 private static final String TEST_EXTRA_INTENT = "EXTRA_INTENT"; 62 private static final String TEST_EXTRA_PENDING_INTENT = "EXTRA_PENDING_INTENT"; 63 private static final String TEST_INTENT_ACTION = "test"; 64 private static final String TEST_PENDING_INTENT_ACTION = "test"; 65 private static final String TEST_SLICE_TITLE = "Test Title"; 66 private static final String TEST_SLICE_SUBTITLE = "Test Subtitle"; 67 private static final String FAKE_ACTION = "fake_action"; 68 69 @Rule 70 public final MockitoRule mMockitoRule = MockitoJUnit.rule(); 71 72 @Mock 73 private LiveData<Slice> mLiveData; 74 @Mock 75 private PreferenceCategory mPreferenceCategory; 76 @Captor 77 ArgumentCaptor<Preference> mPreferenceArgumentCaptor; 78 79 private Context mContext; 80 private BlockingPrefWithSliceController mController; 81 private Uri mUri; 82 83 @Before setUp()84 public void setUp() { 85 mContext = spy(ApplicationProvider.getApplicationContext()); 86 mController = spy(new BlockingPrefWithSliceController(mContext, KEY)); 87 mController.mLiveData = mLiveData; 88 mController.mExtraIntent = TEST_EXTRA_INTENT; 89 mController.mExtraPendingIntent = TEST_EXTRA_PENDING_INTENT; 90 mController.mSliceIntentAction = TEST_INTENT_ACTION; 91 mController.mSlicePendingIntentAction = TEST_PENDING_INTENT_ACTION; 92 mController.mPreferenceCategory = mPreferenceCategory; 93 mUri = Uri.EMPTY; 94 } 95 96 @Test isAvailable_uriNull_returnFalse()97 public void isAvailable_uriNull_returnFalse() { 98 assertThat(mController.isAvailable()).isFalse(); 99 } 100 101 @Test 102 @UiThreadTest isAvailable_uriNotNull_returnTrue()103 public void isAvailable_uriNotNull_returnTrue() { 104 mController.setSliceUri(mUri); 105 106 assertThat(mController.isAvailable()).isTrue(); 107 } 108 109 @Test onStart_registerObserver()110 public void onStart_registerObserver() { 111 mController.onStart(); 112 113 verify(mLiveData).observeForever(mController); 114 } 115 116 @Test onStop_unregisterObserver()117 public void onStop_unregisterObserver() { 118 mController.onStop(); 119 120 verify(mLiveData).removeObserver(mController); 121 } 122 123 @Test onChanged_nullSlice_updateSlice()124 public void onChanged_nullSlice_updateSlice() { 125 mController.onChanged(null); 126 127 verify(mController).updatePreferenceFromSlice(null); 128 } 129 130 @Test onChanged_testSlice_updateSlice()131 public void onChanged_testSlice_updateSlice() { 132 mController.onChanged(buildTestSlice()); 133 134 verify(mController.mPreferenceCategory).addPreference(any()); 135 } 136 137 @Test onChanged_sliceWithoutValidIntent_makePreferenceUnselectable()138 public void onChanged_sliceWithoutValidIntent_makePreferenceUnselectable() { 139 mController.onChanged(buildTestSlice()); 140 141 verify(mController.mPreferenceCategory).addPreference(mPreferenceArgumentCaptor.capture()); 142 assertThat(mPreferenceArgumentCaptor.getValue().isSelectable()).isFalse(); 143 } 144 buildTestSlice()145 private Slice buildTestSlice() { 146 Uri uri = 147 new Uri.Builder() 148 .scheme(ContentResolver.SCHEME_CONTENT) 149 .authority(TEST_URI_AUTHORITY) 150 .build(); 151 SliceViewManager.getInstance(mContext).pinSlice(uri); 152 ListBuilder listBuilder = new ListBuilder(mContext, uri, ListBuilder.INFINITY); 153 IconCompat icon = mock(IconCompat.class); 154 listBuilder.addRow( 155 new RowBuilder() 156 .setTitleItem(icon, ICON_IMAGE) 157 .setTitle(TEST_SLICE_TITLE) 158 .setSubtitle(TEST_SLICE_SUBTITLE) 159 .setPrimaryAction( 160 SliceAction.create( 161 PendingIntent.getActivity( 162 mContext, 163 /*requestCode= */ 0, 164 new Intent(FAKE_ACTION), 165 PendingIntent.FLAG_UPDATE_CURRENT 166 | PendingIntent.FLAG_IMMUTABLE), 167 icon, 168 ICON_IMAGE, 169 ""))); 170 return listBuilder.build(); 171 } 172 } 173