From 77f3973d975251ec10b81954e39e6b8ce675957c Mon Sep 17 00:00:00 2001 From: Beverly Date: Fri, 18 May 2018 17:09:07 -0400 Subject: [PATCH 01/22] Update DND strings Test: manual Bug: 79525632 Change-Id: Ia6106d03499fa546df51dc80f086c7cd684acad4 --- res/values/strings.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index f617df17217..ed2b341f5e9 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7253,15 +7253,15 @@ Notifications - Show notifications silently + No sound from notifications - Notifications will be muted + You will see notifications on your screen When notifications arrive, your phone won\u2019t make a sound or vibrate. - Hide notifications + No visuals or sound from notifications - You won\u2019t see new or existing notifications + You won\u2019t see or hear notifications Your phone won\u2019t show new or existing notifications, and won\u2019t make a sound or vibrate. Notifications won\u2019t appear when you swipe down from the top of your screen.\n\nKeep in mind, critical notifications for phone activity and status will still appear. @@ -7271,11 +7271,11 @@ Remove custom setting - Will appear + No sound from notifications Partially hidden - - Hidden + + No visuals or sound from notifications Custom restrictions @@ -7418,7 +7418,7 @@ Settings - No visuals or sounds from notifications + No visuals or sound from notifications No sound from notifications @@ -9919,7 +9919,7 @@ Update Do Not Disturb - Hide notifications to stay focused + Pause notifications to stay focused What\'s new and exciting? From f6d54bc6c52d88270d599544f15f716f492e7ca2 Mon Sep 17 00:00:00 2001 From: Beverly Date: Fri, 18 May 2018 18:02:14 -0400 Subject: [PATCH 02/22] Don't give onboarding dialog a fixed width Test: visual inspection (display and font largest) Change-Id: Ia81cfa41c125d088d95db2e29f83248dc6819396 Fixes: 79960996 --- res/layout/zen_onboarding.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/layout/zen_onboarding.xml b/res/layout/zen_onboarding.xml index 82951bd264d..33cdbdd35fd 100644 --- a/res/layout/zen_onboarding.xml +++ b/res/layout/zen_onboarding.xml @@ -16,8 +16,8 @@ --> + android:layout_width="match_parent" + android:layout_height="wrap_content"> Date: Sat, 19 May 2018 07:34:52 +0800 Subject: [PATCH 03/22] Move getLocalBtManager into FutureTask Utils.getLocalBtManager in constructor violate StrictMode ThreadPolicy, move it into FutureTask. Bug: 79985175 Test: make RunSettingsRoboTests ROBOTEST_FILTER="MediaOutputPreferenceControllerTest" -j28 Test: make RunSettingsRoboTests ROBOTEST_FILTER="HandsFreeProfileOutputPreferenceControllerTest" -j28 Test: make RunSettingsRoboTests ROBOTEST_FILTER="AudioOutputSwitchPreferenceControllerTest" -j28 Change-Id: I0a14be18e4766245e7d165239d47ab54fa5e4acb --- .../AudioSwitchPreferenceController.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java index 62f345370a7..b0ee649b1ae 100644 --- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java +++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java @@ -41,6 +41,7 @@ import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.util.FeatureFlagUtils; +import android.util.Log; import com.android.settings.R; import com.android.settings.bluetooth.Utils; @@ -59,6 +60,8 @@ import com.android.settingslib.core.lifecycle.events.OnStop; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; /** * Abstract class for audio switcher controller to notify subclass @@ -70,21 +73,22 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont implements Preference.OnPreferenceChangeListener, BluetoothCallback, LifecycleObserver, OnStart, OnStop { + private static final String TAG = "AudioSwitchPreferenceController"; private static final int INVALID_INDEX = -1; protected final List mConnectedDevices; protected final AudioManager mAudioManager; protected final MediaRouter mMediaRouter; - protected final LocalBluetoothProfileManager mProfileManager; protected int mSelectedIndex; protected Preference mPreference; + protected LocalBluetoothProfileManager mProfileManager; protected AudioSwitchCallback mAudioSwitchPreferenceCallback; private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback; - private final LocalBluetoothManager mLocalBluetoothManager; private final MediaRouterCallback mMediaRouterCallback; private final WiredHeadsetBroadcastReceiver mReceiver; private final Handler mHandler; + private LocalBluetoothManager mLocalBluetoothManager; public interface AudioSwitchCallback { void onPreferenceDataChanged(ListPreference preference); @@ -94,14 +98,23 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont super(context, preferenceKey); mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); - mLocalBluetoothManager = Utils.getLocalBtManager(mContext); - mLocalBluetoothManager.setForegroundActivity(context); - mProfileManager = mLocalBluetoothManager.getProfileManager(); mHandler = new Handler(Looper.getMainLooper()); mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); mReceiver = new WiredHeadsetBroadcastReceiver(); mMediaRouterCallback = new MediaRouterCallback(); mConnectedDevices = new ArrayList<>(); + final FutureTask localBtManagerFutureTask = new FutureTask<>( + // Avoid StrictMode ThreadPolicy violation + () -> Utils.getLocalBtManager(mContext)); + try { + localBtManagerFutureTask.run(); + mLocalBluetoothManager = localBtManagerFutureTask.get(); + } catch (InterruptedException | ExecutionException e) { + Log.w(TAG, "Error getting LocalBluetoothManager.", e); + return; + } + mLocalBluetoothManager.setForegroundActivity(mContext); + mProfileManager = mLocalBluetoothManager.getProfileManager(); } /** From 29c96ed090e651a1ca892e05ebd9051d5755a078 Mon Sep 17 00:00:00 2001 From: hughchen Date: Wed, 16 May 2018 17:12:29 +0800 Subject: [PATCH 04/22] Dynamically showing "driving mode" * For fix the TreeHugger error in pi-dev, cherry pick the ag/4062037 in master and fix TreeHugger "Automatic merge failed" error * Dynamically showing "driving mode" in "Connection preferences" summary. In cl/196700988, when driving mode is available/not available will using Settings.System to set flag. Example : driving mode is available : Settings.System.putInt(mContentResolver, DRIVING_MODE_SETTINGS_ENABLED, 1) driving mode is not available : Settings.System.putInt(mContentResolver, DRIVING_MODE_SETTINGS_ENABLED, 0); This CL using Settings.System to get driving mode state that used to dynamically showing "driving mode" Bug: 79299421 Test: make -j50 RunSettingsRoboTests ROBOTEST_FILTER=AdvancedConnectedDeviceControllerTest Change-Id: I702fa4fbc752c7b470184cf58f2e604f9f28c057 --- .../AdvancedConnectedDeviceController.java | 14 ++++++-- ...AdvancedConnectedDeviceControllerTest.java | 32 ++++++++++++++----- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java index a3de6faa11d..76e79018c83 100644 --- a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java +++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java @@ -16,7 +16,9 @@ package com.android.settings.connecteddevice; import android.content.Context; +import android.provider.Settings; import androidx.annotation.VisibleForTesting; + import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settings.nfc.NfcPreferenceController; @@ -26,6 +28,9 @@ import com.android.settings.nfc.NfcPreferenceController; */ public class AdvancedConnectedDeviceController extends BasePreferenceController { + private static final String DRIVING_MODE_SETTINGS_ENABLED = + "gearhead:driving_mode_settings_enabled"; + public AdvancedConnectedDeviceController(Context context, String preferenceKey) { super(context, preferenceKey); } @@ -47,10 +52,15 @@ public class AdvancedConnectedDeviceController extends BasePreferenceController public static int getConnectedDevicesSummaryResourceId(Context context) { final NfcPreferenceController nfcPreferenceController = new NfcPreferenceController(context); - final boolean isDrivingModeAvailable = false; return getConnectedDevicesSummaryResourceId(nfcPreferenceController, - isDrivingModeAvailable); + isDrivingModeAvailable(context)); + } + + @VisibleForTesting + static boolean isDrivingModeAvailable(Context context) { + return Settings.System. + getInt(context.getContentResolver(), DRIVING_MODE_SETTINGS_ENABLED, 0) == 1; } @VisibleForTesting diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java index 84588fd29d9..ceea81eae8e 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java @@ -17,7 +17,9 @@ package com.android.settings.connecteddevice; import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import android.content.ContentResolver; import android.content.Context; +import android.provider.Settings; import com.android.settings.R; import com.android.settings.nfc.NfcPreferenceController; import com.android.settings.testutils.SettingsRobolectricTestRunner; @@ -39,16 +41,20 @@ import static org.robolectric.Shadows.shadowOf; public class AdvancedConnectedDeviceControllerTest { private static final String KEY = "test_key"; + private static final String DRIVING_MODE_SETTINGS_ENABLED = + "gearhead:driving_mode_settings_enabled"; private Context mContext; private NfcPreferenceController mNfcController; private ShadowNfcAdapter mShadowNfcAdapter; + private ContentResolver mContentResolver; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); + mContentResolver = mContext.getContentResolver(); mNfcController = new NfcPreferenceController(mContext); mShadowNfcAdapter = shadowOf(ShadowNfcAdapter.getNfcAdapter(mContext)); } @@ -62,43 +68,53 @@ public class AdvancedConnectedDeviceControllerTest { AVAILABLE); } + @Test + public void isDrivingModeAvailable_returnTrue() { + Settings.System.putInt(mContentResolver, DRIVING_MODE_SETTINGS_ENABLED, 1); + + assertThat(AdvancedConnectedDeviceController.isDrivingModeAvailable(mContext)).isTrue(); + } + + @Test + public void isDrivingModeAvailable_returnFalse() { + Settings.System.putInt(mContentResolver, DRIVING_MODE_SETTINGS_ENABLED, 0); + + assertThat(AdvancedConnectedDeviceController.isDrivingModeAvailable(mContext)).isFalse(); + } + @Test public void getConnectedDevicesSummaryResourceId_NFCAndDrivingModeAvailable() { // NFC available, driving mode available - final boolean isDrivingModeAvailable = true; mShadowNfcAdapter.setEnabled(true); assertThat(AdvancedConnectedDeviceController - .getConnectedDevicesSummaryResourceId(mNfcController, isDrivingModeAvailable)) + .getConnectedDevicesSummaryResourceId(mNfcController, true)) .isEqualTo(R.string.connected_devices_dashboard_summary); } @Test public void getConnectedDevicesSummaryResourceId_NFCAvailableAndDrivingModeNotAvailable() { // NFC is available, driving mode not available - final boolean isDrivingModeAvailable = false; mShadowNfcAdapter.setEnabled(true); assertThat(AdvancedConnectedDeviceController - .getConnectedDevicesSummaryResourceId(mNfcController, isDrivingModeAvailable)) + .getConnectedDevicesSummaryResourceId(mNfcController, false)) .isEqualTo(R.string.connected_devices_dashboard_no_driving_mode_summary); } @Test public void getConnectedDevicesSummaryResourceId_NFCNotAvailableDrivingModeAvailable() { // NFC not available, driving mode available - final boolean isDrivingModeAvailable = true; ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null); assertThat(AdvancedConnectedDeviceController - .getConnectedDevicesSummaryResourceId(mNfcController, isDrivingModeAvailable)) + .getConnectedDevicesSummaryResourceId(mNfcController, true)) .isEqualTo(R.string.connected_devices_dashboard_no_nfc_summary); } @Test public void getConnectedDevicesSummaryResourceId_NFCAndDrivingModeNotAvailable() { // NFC not available, driving mode not available - final boolean isDrivingModeAvailable = false; ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null); assertThat(AdvancedConnectedDeviceController - .getConnectedDevicesSummaryResourceId(mNfcController, isDrivingModeAvailable)) + .getConnectedDevicesSummaryResourceId(mNfcController, false)) .isEqualTo(R.string.connected_devices_dashboard_no_driving_mode_no_nfc_summary); } } From a76797e756b68f99b1fca5a8dac4bc598829724d Mon Sep 17 00:00:00 2001 From: Jason Chang Date: Thu, 3 May 2018 11:08:20 +0800 Subject: [PATCH 05/22] [SettingsLib] Update Utils.getColorAccent() and Utils.getColorError() to return ColorStateLists instead of colors. Update Utils.getColorAccent() and Utils.getColorError() to return ColorStateLists instead of colors and change every callers entry. Bug: 78215054 Test: manually test for UI Change-Id: Ie201aee439bd9e8337eca989b4cdc836a6e8e917 --- .../settings/applications/RunningProcessesView.java | 3 +-- .../settings/dashboard/suggestions/SuggestionAdapter.java | 2 +- .../android/settings/deviceinfo/StorageWizardBase.java | 2 +- .../fingerprint/FingerprintLocationAnimationView.java | 2 +- .../android/settings/fuelgauge/BatteryHistoryChart.java | 2 +- .../settings/notification/ZenModeSliceBuilder.java | 2 +- src/com/android/settings/slices/SliceBuilderUtils.java | 8 ++++---- src/com/android/settings/widget/DonutView.java | 4 ++-- src/com/android/settings/wifi/WifiSliceBuilder.java | 2 +- .../wifi/details/WifiDetailPreferenceController.java | 2 +- .../dashboard/suggestions/SuggestionAdapterTest.java | 8 +++++--- .../src/com/android/settings/testutils/SliceTester.java | 8 ++++---- 12 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/com/android/settings/applications/RunningProcessesView.java b/src/com/android/settings/applications/RunningProcessesView.java index c065af4cfad..5491ad14c6c 100644 --- a/src/com/android/settings/applications/RunningProcessesView.java +++ b/src/com/android/settings/applications/RunningProcessesView.java @@ -452,8 +452,7 @@ public class RunningProcessesView extends FrameLayout final Context context = getContext(); mColorBar.setProgressTintList( ColorStateList.valueOf(context.getColor(R.color.running_processes_system_ram))); - mColorBar.setSecondaryProgressTintList( - ColorStateList.valueOf(Utils.getColorAccent(context))); + mColorBar.setSecondaryProgressTintList(Utils.getColorAccent(context)); mColorBar.setSecondaryProgressTintMode(PorterDuff.Mode.SRC); mColorBar.setProgressBackgroundTintList( ColorStateList.valueOf(context.getColor(R.color.running_processes_free_ram))); diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java index 4a3bc334645..da0991bf7a2 100644 --- a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java +++ b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java @@ -120,7 +120,7 @@ public class SuggestionAdapter extends RecyclerView.Adapter final Icon icon = suggestion.getIcon(); final Drawable drawable = mCache.getIcon(icon); if (drawable != null && (suggestion.getFlags() & Suggestion.FLAG_ICON_TINTABLE) != 0) { - drawable.setTint(Utils.getColorAccent(mContext)); + drawable.setTintList(Utils.getColorAccent(mContext)); } holder.icon.setImageDrawable(drawable); holder.title.setText(suggestion.getTitle()); diff --git a/src/com/android/settings/deviceinfo/StorageWizardBase.java b/src/com/android/settings/deviceinfo/StorageWizardBase.java index 40fc249f697..47481f38c86 100644 --- a/src/com/android/settings/deviceinfo/StorageWizardBase.java +++ b/src/com/android/settings/deviceinfo/StorageWizardBase.java @@ -162,7 +162,7 @@ public abstract class StorageWizardBase extends Activity { protected void setIcon(int resId) { final GlifLayout layout = getGlifLayout(); final Drawable icon = getDrawable(resId).mutate(); - icon.setTint(Utils.getColorAccent(layout.getContext())); + icon.setTintList(Utils.getColorAccent(layout.getContext())); layout.setIcon(icon); } diff --git a/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java b/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java index a26883a04b9..0812f2d1475 100644 --- a/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java +++ b/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java @@ -62,7 +62,7 @@ public class FingerprintLocationAnimationView extends View implements R.fraction.fingerprint_sensor_location_fraction_x, 1, 1); mFractionCenterY = getResources().getFraction( R.fraction.fingerprint_sensor_location_fraction_y, 1, 1); - @ColorInt int colorAccent = Utils.getColorAccent(context); + @ColorInt int colorAccent = Utils.getColorAccentDefaultColor(context); mDotPaint.setAntiAlias(true); mPulsePaint.setAntiAlias(true); mDotPaint.setColor(colorAccent); diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java index 5003254bf12..e442a071bd1 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java +++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java @@ -363,7 +363,7 @@ public class BatteryHistoryChart extends View { mThinLineWidth = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics()); - int accentColor = Utils.getColorAccent(mContext); + int accentColor = Utils.getColorAccentDefaultColor(mContext); mBatteryBackgroundPaint.setColor(accentColor); mBatteryBackgroundPaint.setStyle(Paint.Style.FILL); mBatteryGoodPaint.setARGB(128, 0, 128, 0); diff --git a/src/com/android/settings/notification/ZenModeSliceBuilder.java b/src/com/android/settings/notification/ZenModeSliceBuilder.java index bd435464a02..7e6c11e1a32 100644 --- a/src/com/android/settings/notification/ZenModeSliceBuilder.java +++ b/src/com/android/settings/notification/ZenModeSliceBuilder.java @@ -84,7 +84,7 @@ public class ZenModeSliceBuilder { public static Slice getSlice(Context context) { final boolean isZenModeEnabled = isZenModeEnabled(context); final CharSequence title = context.getText(R.string.zen_mode_settings_title); - @ColorInt final int color = Utils.getColorAccent(context); + @ColorInt final int color = Utils.getColorAccentDefaultColor(context); final PendingIntent toggleAction = getBroadcastIntent(context); final PendingIntent primaryAction = getPrimaryAction(context); final SliceAction primarySliceAction = new SliceAction(primaryAction, diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java index b7f51344208..0913e2ab159 100644 --- a/src/com/android/settings/slices/SliceBuilderUtils.java +++ b/src/com/android/settings/slices/SliceBuilderUtils.java @@ -238,7 +238,7 @@ public class SliceBuilderUtils { final PendingIntent contentIntent = getContentPendingIntent(context, sliceData); final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource()); final CharSequence subtitleText = getSubtitleText(context, controller, sliceData); - @ColorInt final int color = Utils.getColorAccent(context); + @ColorInt final int color = Utils.getColorAccentDefaultColor(context); final TogglePreferenceController toggleController = (TogglePreferenceController) controller; final SliceAction sliceAction = getToggleAction(context, sliceData, @@ -262,7 +262,7 @@ public class SliceBuilderUtils { final PendingIntent contentIntent = getContentPendingIntent(context, sliceData); final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource()); final CharSequence subtitleText = getSubtitleText(context, controller, sliceData); - @ColorInt final int color = Utils.getColorAccent(context); + @ColorInt final int color = Utils.getColorAccentDefaultColor(context); final List keywords = buildSliceKeywords(sliceData); return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY) @@ -282,7 +282,7 @@ public class SliceBuilderUtils { final PendingIntent actionIntent = getSliderAction(context, sliceData); final PendingIntent contentIntent = getContentPendingIntent(context, sliceData); final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource()); - @ColorInt final int color = Utils.getColorAccent(context); + @ColorInt final int color = Utils.getColorAccentDefaultColor(context); final SliceAction primaryAction = new SliceAction(contentIntent, icon, sliceData.getTitle()); final List keywords = buildSliceKeywords(sliceData); @@ -359,7 +359,7 @@ public class SliceBuilderUtils { BasePreferenceController controller) { final String title = data.getTitle(); final List keywords = buildSliceKeywords(data); - @ColorInt final int color = Utils.getColorAccent(context); + @ColorInt final int color = Utils.getColorAccentDefaultColor(context); final String summary; final SliceAction primaryAction; final IconCompat icon = IconCompat.createWithResource(context, data.getIconResource()); diff --git a/src/com/android/settings/widget/DonutView.java b/src/com/android/settings/widget/DonutView.java index 261c85d2657..0acb81ca576 100644 --- a/src/com/android/settings/widget/DonutView.java +++ b/src/com/android/settings/widget/DonutView.java @@ -122,7 +122,7 @@ public class DonutView extends View { : Paint.BIDI_RTL; mTextPaint = new TextPaint(); - mTextPaint.setColor(Utils.getColorAccent(getContext())); + mTextPaint.setColor(Utils.getColorAccentDefaultColor(getContext())); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize( resources.getDimension(R.dimen.storage_donut_view_label_text_size)); @@ -130,7 +130,7 @@ public class DonutView extends View { mTextPaint.setBidiFlags(bidiFlags); mBigNumberPaint = new TextPaint(); - mBigNumberPaint.setColor(Utils.getColorAccent(getContext())); + mBigNumberPaint.setColor(Utils.getColorAccentDefaultColor(getContext())); mBigNumberPaint.setAntiAlias(true); mBigNumberPaint.setTextSize( resources.getDimension(R.dimen.storage_donut_view_percent_text_size)); diff --git a/src/com/android/settings/wifi/WifiSliceBuilder.java b/src/com/android/settings/wifi/WifiSliceBuilder.java index 82038a59126..312f01b2c8e 100644 --- a/src/com/android/settings/wifi/WifiSliceBuilder.java +++ b/src/com/android/settings/wifi/WifiSliceBuilder.java @@ -87,7 +87,7 @@ public class WifiSliceBuilder { R.drawable.ic_settings_wireless); final String title = context.getString(R.string.wifi_settings); final CharSequence summary = getSummary(context); - @ColorInt final int color = Utils.getColorAccent(context); + @ColorInt final int color = Utils.getColorAccentDefaultColor(context); final PendingIntent toggleAction = getBroadcastIntent(context); final PendingIntent primaryAction = getPrimaryAction(context); final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title); diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java index fda5ce49347..d3ea7471a00 100644 --- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java +++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java @@ -406,7 +406,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController mRssiSignalLevel = signalLevel; Drawable wifiIcon = mIconInjector.getIcon(mRssiSignalLevel); - wifiIcon.setTint(Utils.getColorAccent(mContext)); + wifiIcon.setTintList(Utils.getColorAccent(mContext)); mEntityHeaderController.setIcon(wifiIcon).done(mFragment.getActivity(), true /* rebind */); Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate(); diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java index dc492a93907..586bbd10015 100644 --- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java @@ -29,6 +29,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; +import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.service.settings.suggestions.Suggestion; @@ -47,6 +48,7 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.ShadowCardView; import com.android.settingslib.suggestions.SuggestionControllerMixin; import com.android.settingslib.utils.IconCache; +import com.android.settingslib.Utils; import org.junit.Before; import org.junit.Test; @@ -282,13 +284,13 @@ public class SuggestionAdapterTest { when(cache.getIcon(icon)).thenReturn(drawable); ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache); TypedArray typedArray = mock(TypedArray.class); - final int colorAccent = 1234; + final ColorStateList colorAccentState = Utils.getColorAccent(mContext); when(mActivity.obtainStyledAttributes(any())).thenReturn(typedArray); - when(typedArray.getColor(anyInt(), anyInt())).thenReturn(colorAccent); + when(typedArray.getColorStateList(anyInt())).thenReturn(colorAccentState); mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - verify(drawable).setTint(colorAccent); + verify(drawable).setTintList(colorAccentState); } @Test diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java index d71abb3bcf6..e92d2a06c18 100644 --- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java +++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java @@ -75,7 +75,7 @@ public class SliceTester { final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); final int color = colorItem.getInt(); - assertThat(color).isEqualTo(Utils.getColorAccent(context)); + assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); final List toggles = metadata.getToggles(); assertThat(toggles).isEmpty(); @@ -105,7 +105,7 @@ public class SliceTester { final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); final int color = colorItem.getInt(); - assertThat(color).isEqualTo(Utils.getColorAccent(context)); + assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); final List toggles = metadata.getToggles(); assertThat(toggles).hasSize(1); @@ -148,7 +148,7 @@ public class SliceTester { final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); final int color = colorItem.getInt(); - assertThat(color).isEqualTo(Utils.getColorAccent(context)); + assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); final IconCompat expectedToggleIcon = IconCompat.createWithResource(context, sliceData.getIconResource()); @@ -185,7 +185,7 @@ public class SliceTester { final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); final int color = colorItem.getInt(); - assertThat(color).isEqualTo(Utils.getColorAccent(context)); + assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); final List toggles = metadata.getToggles(); assertThat(toggles).isEmpty(); From dd2d5c192fa3a779a0ef01de4945a20bb43dcee7 Mon Sep 17 00:00:00 2001 From: timhypeng Date: Fri, 11 May 2018 14:38:22 +0800 Subject: [PATCH 06/22] Add bluetooth discoverable footer preference in connected devices page * For fix the TreeHugger error in pi-dev, cherry pick the ag/4042014 in master and fix TreeHugger error. Change android.support.v7.* to androidx.* * Dynamicly add preference in controller * Add test cases for DiscoverableFooterPreferenceController Bug: 79294219 Test: make -j50 RunSettingsRoboTests Change-Id: Id4c1e86c9a0a0cd69d8106a18f2cf4a0fa31782b --- .../ConnectedDeviceDashboardFragment.java | 17 ++++ ...iscoverableFooterPreferenceController.java | 68 +++++++++++++ ...verableFooterPreferenceControllerTest.java | 96 +++++++++++++++++++ .../shadow/ShadowBluetoothAdapter.java | 36 +++++++ .../shadow/ShadowLocalBluetoothAdapter.java | 36 +++++++ 5 files changed, 253 insertions(+) create mode 100644 src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowBluetoothAdapter.java create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowLocalBluetoothAdapter.java diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java index d958b38409b..1ff1fcd0a96 100644 --- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java @@ -26,8 +26,10 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.SummaryLoader; import com.android.settings.nfc.NfcPreferenceController; import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.search.SearchIndexable; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -61,12 +63,27 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { return R.xml.connected_devices; } + @Override + protected List createPreferenceControllers(Context context) { + return buildPreferenceControllers(context); + } + + private static List buildPreferenceControllers(Context context) { + final List controllers = new ArrayList<>(); + final DiscoverableFooterPreferenceController discoverableFooterPreferenceController = + new DiscoverableFooterPreferenceController(context); + controllers.add(discoverableFooterPreferenceController); + + return controllers; + } + @Override public void onAttach(Context context) { super.onAttach(context); use(AvailableMediaDeviceGroupController.class).init(this); use(ConnectedDeviceGroupController.class).init(this); use(PreviouslyConnectedDevicePreferenceController.class).init(this); + use(DiscoverableFooterPreferenceController.class).init(this); } @VisibleForTesting diff --git a/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceController.java b/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceController.java new file mode 100644 index 00000000000..71e5409c1f6 --- /dev/null +++ b/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceController.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018 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.connecteddevice; + +import android.content.Context; +import android.content.pm.PackageManager; +import androidx.annotation.VisibleForTesting; +import androidx.preference.PreferenceScreen; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.widget.FooterPreference; +import com.android.settingslib.widget.FooterPreferenceMixin; + +/** + * Controller that shows and updates the bluetooth device name + */ +public class DiscoverableFooterPreferenceController extends BasePreferenceController { + private static final String KEY = "discoverable_footer_preference"; + + private FooterPreference mPreference; + private FooterPreferenceMixin mFooterPreferenceMixin; + + + public DiscoverableFooterPreferenceController(Context context) { super(context, KEY); } + + public void init(DashboardFragment fragment) { + mFooterPreferenceMixin = new FooterPreferenceMixin(fragment, fragment.getLifecycle()); + } + + @VisibleForTesting + void init(FooterPreferenceMixin footerPreferenceMixin, FooterPreference preference) { + mFooterPreferenceMixin = footerPreferenceMixin; + mPreference = preference; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + addFooterPreference(screen); + } + + @Override + public int getAvailabilityStatus() { + return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH) + ? AVAILABLE + : UNSUPPORTED_ON_DEVICE; + } + + private void addFooterPreference(PreferenceScreen screen) { + mPreference = mFooterPreferenceMixin.createFooterPreference(); + mPreference.setKey(KEY); + screen.addPreference(mPreference); + } +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceControllerTest.java new file mode 100644 index 00000000000..42fdeb95b37 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceControllerTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2018 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.connecteddevice; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.PackageManager; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; +import com.android.settings.testutils.shadow.ShadowBluetoothPan; +import com.android.settings.testutils.shadow.ShadowLocalBluetoothAdapter; +import com.android.settingslib.widget.FooterPreference; +import com.android.settingslib.widget.FooterPreferenceMixin; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(shadows = {ShadowBluetoothPan.class, ShadowBluetoothAdapter.class, + ShadowLocalBluetoothAdapter.class}) +public class DiscoverableFooterPreferenceControllerTest { + @Mock + private PackageManager mPackageManager; + @Mock + private PreferenceScreen mScreen; + @Mock + private FooterPreferenceMixin mFooterPreferenceMixin; + + private Context mContext; + private DiscoverableFooterPreferenceController mDiscoverableFooterPreferenceController; + private FooterPreference mPreference; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + doReturn(mPackageManager).when(mContext).getPackageManager(); + mDiscoverableFooterPreferenceController = + new DiscoverableFooterPreferenceController(mContext); + mPreference = spy(new FooterPreference(mContext)); + mDiscoverableFooterPreferenceController.init(mFooterPreferenceMixin, mPreference); + } + + @Test + public void getAvailabilityStatus_noBluetoothFeature_returnUnSupported() { + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(false); + + assertThat(mDiscoverableFooterPreferenceController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_BluetoothFeature_returnSupported() { + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(true); + + assertThat(mDiscoverableFooterPreferenceController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.AVAILABLE); + } + + @Test + public void displayPreference() { + when(mFooterPreferenceMixin.createFooterPreference()).thenReturn(mPreference); + mDiscoverableFooterPreferenceController.displayPreference(mScreen); + + verify(mPreference).setKey(anyString()); + verify(mScreen).addPreference(mPreference); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowBluetoothAdapter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowBluetoothAdapter.java new file mode 100644 index 00000000000..2bd2ec33aaa --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowBluetoothAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 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.testutils.shadow; + +import android.bluetooth.BluetoothAdapter; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +import java.util.ArrayList; +import java.util.List; + +@Implements(value = BluetoothAdapter.class, inheritImplementationMethods = true) +public class ShadowBluetoothAdapter extends org.robolectric.shadows.ShadowBluetoothAdapter { + /** + * Do nothing, implement it to avoid null pointer error inside BluetoothAdapter + */ + @Implementation + public List getSupportedProfiles() { + return new ArrayList(); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLocalBluetoothAdapter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLocalBluetoothAdapter.java new file mode 100644 index 00000000000..d215e2abfeb --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLocalBluetoothAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 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.testutils.shadow; + +import com.android.settingslib.bluetooth.LocalBluetoothAdapter; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@Implements(LocalBluetoothAdapter.class) +public class ShadowLocalBluetoothAdapter { + + private static String sName; + + @Implementation + public String getName() { + return sName; + } + + public static void setName(String name) { + sName = name; + } +} From 444d490e7f11bdcfa5f5cfc9e063cf29c59cf070 Mon Sep 17 00:00:00 2001 From: timhypeng Date: Fri, 11 May 2018 15:41:10 +0800 Subject: [PATCH 07/22] Make device discoverable in Connected Devices settings page * For fix the TreeHugger error in pi-dev, cherry pick the ag/4042235 in master and fix TreeHugger error. Change android.support.v7.* to androidx.* * Set preference title by bluetooth state * Enable bluetooth discoverable mode in Connected device page * Add more test cases for DiscoverableFooterPreferenceController Bug: 79294219 Test: make -j50 RunSettingsRoboTests Change-Id: I6d4f8ec3870c43bf48e9666eabd60068aa8950bb --- .../ConnectedDeviceDashboardFragment.java | 16 ++- ...iscoverableFooterPreferenceController.java | 85 +++++++++++++++- .../ConnectedDeviceDashboardFragmentTest.java | 3 +- ...verableFooterPreferenceControllerTest.java | 98 +++++++++++++++++-- 4 files changed, 188 insertions(+), 14 deletions(-) diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java index 1ff1fcd0a96..a17dd878fa8 100644 --- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java @@ -27,6 +27,7 @@ import com.android.settings.dashboard.SummaryLoader; import com.android.settings.nfc.NfcPreferenceController; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; @@ -65,15 +66,20 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { @Override protected List createPreferenceControllers(Context context) { - return buildPreferenceControllers(context); + return buildPreferenceControllers(context, getLifecycle()); } - private static List buildPreferenceControllers(Context context) { + private static List buildPreferenceControllers(Context context, + Lifecycle lifecycle) { final List controllers = new ArrayList<>(); final DiscoverableFooterPreferenceController discoverableFooterPreferenceController = new DiscoverableFooterPreferenceController(context); controllers.add(discoverableFooterPreferenceController); + if (lifecycle != null) { + lifecycle.addObserver(discoverableFooterPreferenceController); + } + return controllers; } @@ -128,6 +134,12 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { return Arrays.asList(sir); } + @Override + public List createPreferenceControllers(Context + context) { + return buildPreferenceControllers(context, null /* lifecycle */); + } + @Override public List getNonIndexableKeys(Context context) { List keys = super.getNonIndexableKeys(context); diff --git a/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceController.java b/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceController.java index 71e5409c1f6..a1fb4c1d2bc 100644 --- a/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceController.java +++ b/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceController.java @@ -16,35 +16,79 @@ package com.android.settings.connecteddevice; +import android.bluetooth.BluetoothAdapter; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.text.BidiFormatter; +import android.text.TextUtils; import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceScreen; + +import com.android.settings.bluetooth.AlwaysDiscoverable; +import com.android.settings.bluetooth.Utils; import com.android.settings.core.BasePreferenceController; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.R; +import com.android.settingslib.bluetooth.LocalBluetoothAdapter; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.core.lifecycle.events.OnPause; +import com.android.settingslib.core.lifecycle.events.OnResume; +import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.FooterPreferenceMixin; /** * Controller that shows and updates the bluetooth device name */ -public class DiscoverableFooterPreferenceController extends BasePreferenceController { +public class DiscoverableFooterPreferenceController extends BasePreferenceController + implements LifecycleObserver, OnResume, OnPause { private static final String KEY = "discoverable_footer_preference"; - private FooterPreference mPreference; + @VisibleForTesting + BroadcastReceiver mBluetoothChangedReceiver; private FooterPreferenceMixin mFooterPreferenceMixin; + private FooterPreference mPreference; + private LocalBluetoothManager mLocalManager; + private LocalBluetoothAdapter mLocalAdapter; + private AlwaysDiscoverable mAlwaysDiscoverable; + public DiscoverableFooterPreferenceController(Context context) { + super(context, KEY); + mLocalManager = Utils.getLocalBtManager(context); + if (mLocalManager == null) { + return; + } + mLocalAdapter = mLocalManager.getBluetoothAdapter(); + mAlwaysDiscoverable = new AlwaysDiscoverable(context, mLocalAdapter); + initReceiver(); + } - public DiscoverableFooterPreferenceController(Context context) { super(context, KEY); } + private void initReceiver() { + mBluetoothChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { + final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, + BluetoothAdapter.ERROR); + updateFooterPreferenceTitle(state); + } + } + }; + } public void init(DashboardFragment fragment) { mFooterPreferenceMixin = new FooterPreferenceMixin(fragment, fragment.getLifecycle()); } @VisibleForTesting - void init(FooterPreferenceMixin footerPreferenceMixin, FooterPreference preference) { + void init(FooterPreferenceMixin footerPreferenceMixin, FooterPreference preference, + AlwaysDiscoverable alwaysDiscoverable) { mFooterPreferenceMixin = footerPreferenceMixin; mPreference = preference; + mAlwaysDiscoverable = alwaysDiscoverable; } @Override @@ -65,4 +109,37 @@ public class DiscoverableFooterPreferenceController extends BasePreferenceContro mPreference.setKey(KEY); screen.addPreference(mPreference); } + + @Override + public void onResume() { + mContext.registerReceiver(mBluetoothChangedReceiver, + new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); + mAlwaysDiscoverable.start(); + updateFooterPreferenceTitle(mLocalAdapter.getState()); + } + + @Override + public void onPause() { + mContext.unregisterReceiver(mBluetoothChangedReceiver); + mAlwaysDiscoverable.stop(); + } + + private void updateFooterPreferenceTitle (int bluetoothState) { + if (bluetoothState == BluetoothAdapter.STATE_ON) { + mPreference.setTitle(getPreferenceTitle()); + } else { + mPreference.setTitle(R.string.bluetooth_off_footer); + } + } + + private CharSequence getPreferenceTitle() { + final String deviceName = mLocalAdapter.getName(); + if (TextUtils.isEmpty(deviceName)) { + return null; + } + + return TextUtils.expandTemplate( + mContext.getText(R.string.bluetooth_device_name_summary), + BidiFormatter.getInstance().unicodeWrap(deviceName)); + } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java index cea258d67ce..eecbca5afe2 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java @@ -31,6 +31,7 @@ import android.provider.SearchIndexableResource; import com.android.settings.R; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; import com.android.settings.testutils.shadow.ShadowBluetoothPan; import com.android.settings.testutils.shadow.ShadowConnectivityManager; import com.android.settings.testutils.shadow.ShadowUserManager; @@ -47,7 +48,7 @@ import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) @Config(shadows = {ShadowBluetoothPan.class, ShadowUserManager.class, - ShadowConnectivityManager.class}) + ShadowConnectivityManager.class, ShadowBluetoothAdapter.class}) public class ConnectedDeviceDashboardFragmentTest { @Mock private PackageManager mPackageManager; diff --git a/tests/robotests/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceControllerTest.java index 42fdeb95b37..978db987d07 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/DiscoverableFooterPreferenceControllerTest.java @@ -16,18 +16,23 @@ package com.android.settings.connecteddevice; import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.bluetooth.BluetoothAdapter; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; +import android.text.BidiFormatter; +import android.text.TextUtils; import androidx.preference.PreferenceScreen; import com.android.settings.core.BasePreferenceController; +import com.android.settings.bluetooth.AlwaysDiscoverable; +import com.android.settings.R; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; import com.android.settings.testutils.shadow.ShadowBluetoothPan; @@ -41,32 +46,49 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; +import org.robolectric.Shadows; import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import java.util.ArrayList; +import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) @Config(shadows = {ShadowBluetoothPan.class, ShadowBluetoothAdapter.class, ShadowLocalBluetoothAdapter.class}) public class DiscoverableFooterPreferenceControllerTest { + private static final String DEVICE_NAME = "device name"; + private static final String KEY = "discoverable_footer_preference"; + @Mock private PackageManager mPackageManager; @Mock private PreferenceScreen mScreen; @Mock private FooterPreferenceMixin mFooterPreferenceMixin; + @Mock + private AlwaysDiscoverable mAlwaysDiscoverable; private Context mContext; - private DiscoverableFooterPreferenceController mDiscoverableFooterPreferenceController; private FooterPreference mPreference; + private DiscoverableFooterPreferenceController mDiscoverableFooterPreferenceController; + private BroadcastReceiver mBluetoothChangedReceiver; + private ShadowApplication mShadowApplication; @Before public void setUp() { MockitoAnnotations.initMocks(this); + mShadowApplication = Shadows.shadowOf(RuntimeEnvironment.application); mContext = spy(RuntimeEnvironment.application); + doReturn(mPackageManager).when(mContext).getPackageManager(); mDiscoverableFooterPreferenceController = new DiscoverableFooterPreferenceController(mContext); mPreference = spy(new FooterPreference(mContext)); - mDiscoverableFooterPreferenceController.init(mFooterPreferenceMixin, mPreference); + mDiscoverableFooterPreferenceController.init(mFooterPreferenceMixin, mPreference, + mAlwaysDiscoverable); + mBluetoothChangedReceiver = mDiscoverableFooterPreferenceController + .mBluetoothChangedReceiver; } @Test @@ -78,7 +100,7 @@ public class DiscoverableFooterPreferenceControllerTest { } @Test - public void getAvailabilityStatus_BluetoothFeature_returnSupported() { + public void getAvailabilityStatus_BluetoothFeature_returnAvailable() { when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(true); assertThat(mDiscoverableFooterPreferenceController.getAvailabilityStatus()).isEqualTo( @@ -90,7 +112,69 @@ public class DiscoverableFooterPreferenceControllerTest { when(mFooterPreferenceMixin.createFooterPreference()).thenReturn(mPreference); mDiscoverableFooterPreferenceController.displayPreference(mScreen); - verify(mPreference).setKey(anyString()); + verify(mPreference).setKey(KEY); verify(mScreen).addPreference(mPreference); } -} + + @Test + public void onResume() { + mDiscoverableFooterPreferenceController.onResume(); + assertThat(getRegisteredBroadcastReceivers()).contains(mBluetoothChangedReceiver); + verify(mAlwaysDiscoverable).start(); + } + + @Test + public void onPause() { + mDiscoverableFooterPreferenceController.onResume(); + mDiscoverableFooterPreferenceController.onPause(); + + assertThat(getRegisteredBroadcastReceivers()).doesNotContain(mBluetoothChangedReceiver); + verify(mAlwaysDiscoverable).stop(); + } + + @Test + public void onBluetoothStateChanged_bluetoothOn_updateTitle() { + ShadowLocalBluetoothAdapter.setName(DEVICE_NAME); + sendBluetoothStateChangedIntent(BluetoothAdapter.STATE_ON); + + assertThat(mPreference.getTitle()).isEqualTo(generateTitle(DEVICE_NAME)); + } + + @Test + public void onBluetoothStateChanged_bluetoothOff_updateTitle(){ + ShadowLocalBluetoothAdapter.setName(DEVICE_NAME); + sendBluetoothStateChangedIntent(BluetoothAdapter.STATE_OFF); + + assertThat(mPreference.getTitle()).isEqualTo(generateTitle(null)); + } + + private CharSequence generateTitle(String deviceName) { + if (deviceName == null) { + return mContext.getString(R.string.bluetooth_off_footer); + + } else { + return TextUtils.expandTemplate( + mContext.getText(R.string.bluetooth_device_name_summary), + BidiFormatter.getInstance().unicodeWrap(deviceName)); + } + } + + private void sendBluetoothStateChangedIntent(int state) { + Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); + intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); + mBluetoothChangedReceiver.onReceive(mContext, intent); + } + + /** + * Return a list of all the registered broadcast receivers + */ + private List getRegisteredBroadcastReceivers() { + List registeredBroadcastReceivers = new ArrayList(); + List registeredReceivers = + mShadowApplication.getRegisteredReceivers(); + for (ShadowApplication.Wrapper wrapper : registeredReceivers) { + registeredBroadcastReceivers.add(wrapper.getBroadcastReceiver()); + } + return registeredBroadcastReceivers; + } +} \ No newline at end of file From 14a6856d376e3dc58bd02bb2b394649c26a50790 Mon Sep 17 00:00:00 2001 From: Beverly Date: Fri, 18 May 2018 14:33:36 -0400 Subject: [PATCH 08/22] Set click listeners on displayPreference Cherry-picked from pi-dev Test: manual (tap options multiple times with talkback on) Test: ZenModeVisEffectsCustomPreferenceControllerTest, robotests Change-Id: Iffa701fb486bd9eeda7d2c4c46cb30392a09a5df Fixes: 79728671 --- ...ModeVisEffectsAllPreferenceController.java | 21 ++++++----- ...eVisEffectsCustomPreferenceController.java | 36 +++++++++++-------- ...odeVisEffectsNonePreferenceController.java | 21 ++++++----- ...EffectsCustomPreferenceControllerTest.java | 1 + 4 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/com/android/settings/notification/ZenModeVisEffectsAllPreferenceController.java b/src/com/android/settings/notification/ZenModeVisEffectsAllPreferenceController.java index 757fde7f731..d7de0d95e9f 100644 --- a/src/com/android/settings/notification/ZenModeVisEffectsAllPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeVisEffectsAllPreferenceController.java @@ -28,6 +28,8 @@ public class ZenModeVisEffectsAllPreferenceController extends AbstractZenModePreferenceController implements ZenCustomRadioButtonPreference.OnRadioButtonClickListener { + private ZenCustomRadioButtonPreference mPreference; + protected static final int EFFECTS = Policy.SUPPRESSED_EFFECT_SCREEN_OFF | Policy.SUPPRESSED_EFFECT_SCREEN_ON | Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT @@ -43,6 +45,13 @@ public class ZenModeVisEffectsAllPreferenceController super(context, key, lifecycle); } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey()); + mPreference.setOnRadioButtonClickListener(this); + } + @Override public boolean isAvailable() { return true; @@ -54,17 +63,7 @@ public class ZenModeVisEffectsAllPreferenceController boolean everythingBlocked = Policy.areAllVisualEffectsSuppressed( mBackend.mPolicy.suppressedVisualEffects); - ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference; - pref.setOnRadioButtonClickListener(this); - pref.setChecked(everythingBlocked); - } - - protected void deselect(PreferenceScreen screen) { - ZenCustomRadioButtonPreference preference = - (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey()); - if (preference != null) { - preference.setChecked(false); - } + mPreference.setChecked(everythingBlocked); } @Override diff --git a/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceController.java b/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceController.java index 5dd99f61568..228530874f0 100644 --- a/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceController.java @@ -16,9 +16,8 @@ package com.android.settings.notification; -import android.app.NotificationManager.Policy; +import android.app.NotificationManager; import android.content.Context; - import androidx.preference.Preference; import androidx.preference.PreferenceScreen; @@ -30,10 +29,13 @@ import com.android.settingslib.core.lifecycle.Lifecycle; public class ZenModeVisEffectsCustomPreferenceController extends AbstractZenModePreferenceController { - protected static final int INTERRUPTIVE_EFFECTS = Policy.SUPPRESSED_EFFECT_AMBIENT - | Policy.SUPPRESSED_EFFECT_PEEK - | Policy.SUPPRESSED_EFFECT_LIGHTS - | Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; + private ZenCustomRadioButtonPreference mPreference; + + protected static final int INTERRUPTIVE_EFFECTS = + NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT + | NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK + | NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS + | NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; public ZenModeVisEffectsCustomPreferenceController(Context context, Lifecycle lifecycle, String key) { @@ -46,25 +48,31 @@ public class ZenModeVisEffectsCustomPreferenceController } @Override - public void updateState(Preference preference) { - super.updateState(preference); + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey()); - ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference; - pref.setChecked(areCustomOptionsSelected()); - - pref.setOnGearClickListener(p -> { + mPreference.setOnGearClickListener(p -> { launchCustomSettings(); }); - pref.setOnRadioButtonClickListener(p -> { + mPreference.setOnRadioButtonClickListener(p -> { launchCustomSettings(); }); } + @Override + public void updateState(Preference preference) { + super.updateState(preference); + + mPreference.setChecked(areCustomOptionsSelected()); + } + protected boolean areCustomOptionsSelected() { boolean allEffectsSuppressed = - Policy.areAllVisualEffectsSuppressed(mBackend.mPolicy.suppressedVisualEffects); + NotificationManager.Policy.areAllVisualEffectsSuppressed( + mBackend.mPolicy.suppressedVisualEffects); boolean noEffectsSuppressed = mBackend.mPolicy.suppressedVisualEffects == 0; return !(allEffectsSuppressed || noEffectsSuppressed); diff --git a/src/com/android/settings/notification/ZenModeVisEffectsNonePreferenceController.java b/src/com/android/settings/notification/ZenModeVisEffectsNonePreferenceController.java index abfbd01686f..580fb5d0520 100644 --- a/src/com/android/settings/notification/ZenModeVisEffectsNonePreferenceController.java +++ b/src/com/android/settings/notification/ZenModeVisEffectsNonePreferenceController.java @@ -28,6 +28,8 @@ public class ZenModeVisEffectsNonePreferenceController extends AbstractZenModePreferenceController implements ZenCustomRadioButtonPreference.OnRadioButtonClickListener { + private ZenCustomRadioButtonPreference mPreference; + protected static final int EFFECTS = Policy.SUPPRESSED_EFFECT_SCREEN_OFF | Policy.SUPPRESSED_EFFECT_SCREEN_ON | Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT @@ -43,6 +45,13 @@ public class ZenModeVisEffectsNonePreferenceController super(context, key, lifecycle); } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey()); + mPreference.setOnRadioButtonClickListener(this); + } + @Override public boolean isAvailable() { return true; @@ -53,9 +62,7 @@ public class ZenModeVisEffectsNonePreferenceController super.updateState(preference); boolean nothingBlocked = mBackend.mPolicy.suppressedVisualEffects == 0; - ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference; - pref.setOnRadioButtonClickListener(this); - pref.setChecked(nothingBlocked); + mPreference.setChecked(nothingBlocked); } @Override @@ -64,12 +71,4 @@ public class ZenModeVisEffectsNonePreferenceController MetricsProto.MetricsEvent.ACTION_ZEN_SOUND_ONLY, true); mBackend.saveVisualEffectsPolicy(EFFECTS, false); } - - protected void deselect(PreferenceScreen screen) { - ZenCustomRadioButtonPreference preference = - (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey()); - if (preference != null) { - preference.setChecked(false); - } - } } diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceControllerTest.java index 45446229930..9f8e91ac7a4 100644 --- a/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceControllerTest.java @@ -85,6 +85,7 @@ public class ZenModeVisEffectsCustomPreferenceControllerTest { ReflectionHelpers.setField(mController, "mBackend", mBackend); when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref); + mController.displayPreference(mScreen); } @Test From 77b59860322be8a7afb3015003de84b6ec6855fa Mon Sep 17 00:00:00 2001 From: Beverly Date: Mon, 21 May 2018 13:27:09 -0400 Subject: [PATCH 09/22] DO NOT MERGE styleActionBar when updating header If the activity has started, style the actionBar when the header is being updated Test: manual Change-Id: Ide69fc0f6e8e5046105bd290d22d9f9a3df5c1ae Bug: 79983080 --- .../notification/HeaderPreferenceController.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/notification/HeaderPreferenceController.java b/src/com/android/settings/notification/HeaderPreferenceController.java index c6f6a80621f..0a4cca1934f 100644 --- a/src/com/android/settings/notification/HeaderPreferenceController.java +++ b/src/com/android/settings/notification/HeaderPreferenceController.java @@ -18,6 +18,7 @@ package com.android.settings.notification; import static com.android.settings.widget.EntityHeaderController.PREF_KEY_APP_HEADER; +import android.app.Activity; import android.arch.lifecycle.LifecycleObserver; import android.arch.lifecycle.OnLifecycleEvent; import android.content.Context; @@ -26,6 +27,7 @@ import android.support.v7.preference.Preference; import android.text.BidiFormatter; import android.text.SpannableStringBuilder; import android.text.TextUtils; +import android.util.Slog; import android.view.View; import com.android.settings.R; @@ -33,15 +35,13 @@ import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.core.lifecycle.events.OnStart; - -import java.util.Objects; public class HeaderPreferenceController extends NotificationPreferenceController implements PreferenceControllerMixin, LifecycleObserver { private final PreferenceFragment mFragment; private EntityHeaderController mHeaderController; + private boolean mStarted = false; public HeaderPreferenceController(Context context, PreferenceFragment fragment) { super(context, null); @@ -61,6 +61,13 @@ public class HeaderPreferenceController extends NotificationPreferenceController @Override public void updateState(Preference preference) { if (mAppRow != null && mFragment != null) { + + Activity activity = null; + if (mStarted) { + // don't call done on an activity if it hasn't started yet + activity = mFragment.getActivity(); + } + LayoutPreference pref = (LayoutPreference) preference; mHeaderController = EntityHeaderController.newInstance( mFragment.getActivity(), mFragment, pref.findViewById(R.id.entity_header)); @@ -72,7 +79,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController .setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE, EntityHeaderController.ActionType.ACTION_NONE) .setHasAppInfoLink(true) - .done(null, mContext); + .done(activity, mContext); pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE); } } @@ -108,6 +115,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { + mStarted = true; if (mHeaderController != null) { mHeaderController.styleActionBar(mFragment.getActivity()); } From 6394a1425cf05901a7cc2fddc5431c5c4f542316 Mon Sep 17 00:00:00 2001 From: Matthew Fritze Date: Mon, 21 May 2018 13:36:45 -0700 Subject: [PATCH 10/22] Change Night Display slice title to "NightDisplay" Fixes: 80093098 Test: Slice browser for UI change Change-Id: I4999d375f76d914095d4af234aaeb31e32fe798f --- res/xml/night_display_settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/xml/night_display_settings.xml b/res/xml/night_display_settings.xml index 7b00ea02567..d83fcc6d3cb 100644 --- a/res/xml/night_display_settings.xml +++ b/res/xml/night_display_settings.xml @@ -45,7 +45,7 @@ Date: Mon, 21 May 2018 13:27:09 -0400 Subject: [PATCH 11/22] styleActionBar when updating header Cherry-picked from pi-dev If the activity has started, style the actionBar when the header is being updated Test: manual Change-Id: Ide69fc0f6e8e5046105bd290d22d9f9a3df5c1ae Fixes: 79983080 --- .../HeaderPreferenceController.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/notification/HeaderPreferenceController.java b/src/com/android/settings/notification/HeaderPreferenceController.java index 311dcf72092..1ff3c9a60c1 100644 --- a/src/com/android/settings/notification/HeaderPreferenceController.java +++ b/src/com/android/settings/notification/HeaderPreferenceController.java @@ -18,30 +18,30 @@ package com.android.settings.notification; import static com.android.settings.widget.EntityHeaderController.PREF_KEY_APP_HEADER; -import androidx.lifecycle.LifecycleObserver; -import androidx.lifecycle.OnLifecycleEvent; +import android.app.Activity; import android.content.Context; -import androidx.preference.PreferenceFragment; -import androidx.preference.Preference; import android.text.BidiFormatter; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.view.View; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; +import androidx.preference.PreferenceFragment; +import androidx.preference.Preference; + import com.android.settings.R; import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.core.lifecycle.events.OnStart; - -import java.util.Objects; public class HeaderPreferenceController extends NotificationPreferenceController implements PreferenceControllerMixin, LifecycleObserver { private final PreferenceFragment mFragment; private EntityHeaderController mHeaderController; + private boolean mStarted = false; public HeaderPreferenceController(Context context, PreferenceFragment fragment) { super(context, null); @@ -61,6 +61,13 @@ public class HeaderPreferenceController extends NotificationPreferenceController @Override public void updateState(Preference preference) { if (mAppRow != null && mFragment != null) { + + Activity activity = null; + if (mStarted) { + // don't call done on an activity if it hasn't started yet + activity = mFragment.getActivity(); + } + LayoutPreference pref = (LayoutPreference) preference; mHeaderController = EntityHeaderController.newInstance( mFragment.getActivity(), mFragment, pref.findViewById(R.id.entity_header)); @@ -72,7 +79,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController .setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE, EntityHeaderController.ActionType.ACTION_NONE) .setHasAppInfoLink(true) - .done(null, mContext); + .done(activity, mContext); pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE); } } @@ -108,6 +115,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { + mStarted = true; if (mHeaderController != null) { mHeaderController.styleActionBar(mFragment.getActivity()); } From 71c402b152b8948def547aa8401d440cf15b96b9 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Mon, 21 May 2018 12:07:28 -0700 Subject: [PATCH 12/22] Misc GAR fixes - Use colorPrimary for EntityHeader background. - Update data usage header text to be 87% black. Change-Id: Ic361155d7cd36a2f1cca96e918af0e3855fb8ced Fixes: 79773433 Test: robotests Test: visual --- res/drawable/selectable_card_grey.xml | 22 ------------------- res/layout/battery_header.xml | 1 - res/layout/data_usage_summary_preference.xml | 3 +-- res/layout/radio_info.xml | 14 ++++++------ .../widget/EntityHeaderController.java | 2 ++ .../shadow/SettingsShadowResources.java | 3 --- .../shadow/SettingsShadowResourcesImpl.java | 2 -- 7 files changed, 10 insertions(+), 37 deletions(-) delete mode 100644 res/drawable/selectable_card_grey.xml diff --git a/res/drawable/selectable_card_grey.xml b/res/drawable/selectable_card_grey.xml deleted file mode 100644 index e74ae8d7eeb..00000000000 --- a/res/drawable/selectable_card_grey.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - diff --git a/res/layout/battery_header.xml b/res/layout/battery_header.xml index db90e2e0fc8..df45d15fd6d 100644 --- a/res/layout/battery_header.xml +++ b/res/layout/battery_header.xml @@ -24,7 +24,6 @@ android:orientation="horizontal" android:paddingTop="24dp" android:paddingBottom="24dp" - android:background="@drawable/selectable_card_grey" style="@style/EntityHeader"> @@ -31,7 +30,7 @@ android:id="@+id/usage_title" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textColor="?android:attr/colorAccent" + android:textColor="?android:attr/textColorPrimary" android:text="@string/data_usage_title" /> + android:background="?android:attr/listDivider" /> + android:background="?android:attr/listDivider" /> + android:background="?android:attr/listDivider" />