diff --git a/res/values/dimens.xml b/res/values/dimens.xml index abd45af62e8..dc23c3d8d06 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -423,8 +423,9 @@ 11dp - 506dp + 458dp 52dp + 16dp 24dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 9a562643e6f..1dbc0a05898 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11322,7 +11322,7 @@ Default disabled changes Enabled for targetSdkVersion > %d - + No apps available App compatibility changes can only be modified for debuggable apps. Install a debuggable app and try again. @@ -12135,7 +12135,7 @@ Media - + Hide player when the media session has ended The player allows you to resume a session from the expanded Quick Settings panel. diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index e5fd340485c..64919d9e809 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -92,8 +92,11 @@ import android.widget.EditText; import android.widget.ListView; import android.widget.TabWidget; +import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.core.graphics.drawable.IconCompat; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; import androidx.fragment.app.Fragment; import androidx.lifecycle.Lifecycle; import androidx.preference.Preference; @@ -1113,4 +1116,25 @@ public final class Utils extends com.android.settingslib.Utils { context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; return currentNightMode == Configuration.UI_MODE_NIGHT_YES; } + + /** + * Returns a bitmap with rounded corner. + * + * @param context application context. + * @param source bitmap to apply round corner. + * @param cornerRadius corner radius value. + */ + public static Bitmap convertCornerRadiusBitmap(@NonNull Context context, + @NonNull Bitmap source, @NonNull float cornerRadius) { + final Bitmap roundedBitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), + Bitmap.Config.ARGB_8888); + final RoundedBitmapDrawable drawable = + RoundedBitmapDrawableFactory.create(context.getResources(), source); + drawable.setAntiAlias(true); + drawable.setCornerRadius(cornerRadius); + final Canvas canvas = new Canvas(roundedBitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return roundedBitmap; + } } diff --git a/src/com/android/settings/display/TwilightLocationPreferenceController.java b/src/com/android/settings/display/TwilightLocationPreferenceController.java index 131b0a8812f..31845c0eb52 100644 --- a/src/com/android/settings/display/TwilightLocationPreferenceController.java +++ b/src/com/android/settings/display/TwilightLocationPreferenceController.java @@ -21,7 +21,6 @@ import android.content.Intent; import android.location.LocationManager; import android.view.View; -import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; @@ -57,13 +56,9 @@ public class TwilightLocationPreferenceController extends BasePreferenceControll }); } - @Override - public void updateState(Preference preference) { - preference.setVisible(!mLocationManager.isLocationEnabled()); - } - @Override public int getAvailabilityStatus() { - return AVAILABLE_UNSEARCHABLE; + return mLocationManager.isLocationEnabled() ? CONDITIONALLY_UNAVAILABLE + : AVAILABLE_UNSEARCHABLE; } } diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java index d30fe59a51d..e4a644cf780 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java @@ -184,6 +184,10 @@ public class ContextualCardLoader extends AsyncLoaderCompat @VisibleForTesting List filterEligibleCards(List candidates) { + if (candidates.isEmpty()) { + return candidates; + } + final ExecutorService executor = Executors.newFixedThreadPool(candidates.size()); final List cards = new ArrayList<>(); List> eligibleCards = new ArrayList<>(); diff --git a/src/com/android/settings/panel/MediaOutputPanel.java b/src/com/android/settings/panel/MediaOutputPanel.java index d8dbb34d0e1..6a296b73c06 100644 --- a/src/com/android/settings/panel/MediaOutputPanel.java +++ b/src/com/android/settings/panel/MediaOutputPanel.java @@ -116,7 +116,11 @@ public class MediaOutputPanel implements PanelContent, LocalMediaManager.DeviceC if (metadata != null) { final Bitmap bitmap = metadata.getDescription().getIconBitmap(); if (bitmap != null) { - return IconCompat.createWithBitmap(bitmap); + final Bitmap roundBitmap = Utils.convertCornerRadiusBitmap(mContext, bitmap, + (float) mContext.getResources().getDimensionPixelSize( + R.dimen.output_switcher_panel_icon_corner_radius)); + + return IconCompat.createWithBitmap(roundBitmap); } } Log.d(TAG, "Media meta data does not contain icon information"); diff --git a/src/com/android/settings/slices/SlicesDatabaseAccessor.java b/src/com/android/settings/slices/SlicesDatabaseAccessor.java index e31715d3858..c0bb8de63da 100644 --- a/src/com/android/settings/slices/SlicesDatabaseAccessor.java +++ b/src/com/android/settings/slices/SlicesDatabaseAccessor.java @@ -127,10 +127,12 @@ public class SlicesDatabaseAccessor { int numResults = resultCursor.getCount(); if (numResults == 0) { + resultCursor.close(); throw new IllegalStateException("Invalid Slices key from path: " + path); } if (numResults > 1) { + resultCursor.close(); throw new IllegalStateException( "Should not match more than 1 slice with path: " + path); } diff --git a/tests/robotests/src/com/android/settings/display/TwilightLocationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/TwilightLocationPreferenceControllerTest.java new file mode 100644 index 00000000000..983fc519bb9 --- /dev/null +++ b/tests/robotests/src/com/android/settings/display/TwilightLocationPreferenceControllerTest.java @@ -0,0 +1,68 @@ +/* + * 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.display; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.location.LocationManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class TwilightLocationPreferenceControllerTest { + private static final String TEST_KEY = "test_key"; + + private Context mContext; + private TwilightLocationPreferenceController mController; + + @Mock + private LocationManager mLocationManager; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager); + mController = new TwilightLocationPreferenceController(mContext, TEST_KEY); + } + + @Test + public void getAvailabilityStatus_locationEnabled_shouldBeCONDITIONALLY_UNAVAILABLE() { + when(mLocationManager.isLocationEnabled()).thenReturn(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_locationDisabled_shouldBeAVAILABLE_UNSEARCHABLE() { + when(mLocationManager.isLocationEnabled()).thenReturn(false); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); + } +} diff --git a/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java index be86b6e3984..7a3243b55f9 100644 --- a/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java +++ b/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java @@ -232,13 +232,20 @@ public class MediaDeviceUpdateWorkerTest { public void onSlicePinned_packageUpdated_checkPackageName() { ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager; when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); + mMediaDeviceUpdateWorker = new MediaDeviceUpdateWorker(mContext, URI1); + mMediaDeviceUpdateWorker.mLocalMediaManager = mock(LocalMediaManager.class); + when(mMediaDeviceUpdateWorker.mLocalMediaManager.getPackageName()) + .thenReturn(TEST_DEVICE_PACKAGE_NAME1); mMediaDeviceUpdateWorker.onSlicePinned(); assertThat(mMediaDeviceUpdateWorker.mLocalMediaManager.getPackageName()).matches( TEST_DEVICE_PACKAGE_NAME1); mMediaDeviceUpdateWorker = new MediaDeviceUpdateWorker(mContext, URI2); + mMediaDeviceUpdateWorker.mLocalMediaManager = mock(LocalMediaManager.class); + when(mMediaDeviceUpdateWorker.mLocalMediaManager.getPackageName()) + .thenReturn(TEST_DEVICE_PACKAGE_NAME2); mMediaDeviceUpdateWorker.onSlicePinned(); assertThat(mMediaDeviceUpdateWorker.mLocalMediaManager.getPackageName()).matches( diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java index 423c7acf098..d9b224796ab 100644 --- a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java +++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java @@ -121,10 +121,12 @@ public class MediaOutputIndicatorWorkerTest { @Test public void onSlicePinned_packageUpdated_checkPackageName() { + 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(); @@ -132,7 +134,7 @@ public class MediaOutputIndicatorWorkerTest { TEST_PACKAGE_NAME); when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME2); - mMediaOutputIndicatorWorker.mLocalMediaManager = null; + when(mLocalMediaManager.getPackageName()).thenReturn(TEST_PACKAGE_NAME2); mMediaOutputIndicatorWorker.onSlicePinned(); waitForLocalMediaManagerInit(); diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java index 0fa249d8fb7..2f0d60aaf97 100644 --- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java +++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java @@ -270,23 +270,27 @@ public class SettingsSliceProviderTest { @Test public void onBindSlice_nightModeChanged_shouldReloadTheme() { - mContext.getResources().getConfiguration().uiMode = UI_MODE_NIGHT_YES; - + mContext.getResources().getConfiguration().uiMode = UI_MODE_NIGHT_NO; final SliceData data = getDummyData(); mProvider.mSliceWeakDataCache.put(data.getUri(), data); mProvider.onBindSlice(data.getUri()); + mContext.getResources().getConfiguration().uiMode = UI_MODE_NIGHT_YES; + mProvider.onBindSlice(data.getUri()); + assertThat(ShadowTheme.isThemeRebased()).isTrue(); } @Test public void onBindSlice_nightModeNotChanged_shouldNotReloadTheme() { mContext.getResources().getConfiguration().uiMode = UI_MODE_NIGHT_NO; - SliceData data = getDummyData(); mProvider.mSliceWeakDataCache.put(data.getUri(), data); mProvider.onBindSlice(data.getUri()); + mContext.getResources().getConfiguration().uiMode = UI_MODE_NIGHT_NO; + mProvider.onBindSlice(data.getUri()); + assertThat(ShadowTheme.isThemeRebased()).isFalse(); }