From 76dbb21cb527463a62b8b999541d24700f2a0e01 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Thu, 5 Apr 2018 14:44:13 -0700 Subject: [PATCH 01/17] Protect against invalid authority in account sync pref. Some apps might contain account synclets with empty authority. Settings UI should protect against this type of synclets. Otherwise clicking on these synclets will crash. (Also removed some strings that are no longer needed) Change-Id: I364b45fc67679aa287ff1e04e6f5ac749116543a Fixes: 74240862 Test: robotests --- res/values/strings.xml | 4 -- .../accounts/AccountSyncSettings.java | 9 ++- .../accounts/SyncStateSwitchPreference.java | 2 + .../SyncStateSwitchPreferenceTest.java | 62 +++++++++++++++++++ 4 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/accounts/SyncStateSwitchPreferenceTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 7507de2dee8..650f9d9d282 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5922,10 +5922,6 @@ Removing this account will delete all of its messages, contacts, and other data from the device! This change isn\'t allowed by your admin - - Push subscriptions - - %s Can\u2019t manually sync diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java index d83694da449..6b60e87f85c 100644 --- a/src/com/android/settings/accounts/AccountSyncSettings.java +++ b/src/com/android/settings/accounts/AccountSyncSettings.java @@ -194,25 +194,24 @@ public class AccountSyncSettings extends AccountPreferenceBase { } else { item.setup(account, authority, packageName, uid); } + final PackageManager packageManager = getPackageManager(); item.setPersistent(false); - final ProviderInfo providerInfo = getPackageManager().resolveContentProviderAsUser( + final ProviderInfo providerInfo = packageManager.resolveContentProviderAsUser( authority, 0, mUserHandle.getIdentifier()); if (providerInfo == null) { return; } - CharSequence providerLabel = providerInfo.loadLabel(getPackageManager()); + final CharSequence providerLabel = providerInfo.loadLabel(packageManager); if (TextUtils.isEmpty(providerLabel)) { Log.e(TAG, "Provider needs a label for authority '" + authority + "'"); return; } - String title = getString(R.string.sync_item_title, providerLabel); - item.setTitle(title); + item.setTitle(providerLabel); item.setKey(authority); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - MenuItem syncNow = menu.add(0, MENU_SYNC_NOW_ID, 0, getString(R.string.sync_menu_sync_now)) .setIcon(R.drawable.ic_menu_refresh_holo_dark); diff --git a/src/com/android/settings/accounts/SyncStateSwitchPreference.java b/src/com/android/settings/accounts/SyncStateSwitchPreference.java index 058fedd9e7d..456edbabc2d 100644 --- a/src/com/android/settings/accounts/SyncStateSwitchPreference.java +++ b/src/com/android/settings/accounts/SyncStateSwitchPreference.java @@ -21,6 +21,7 @@ import android.app.ActivityManager; import android.content.Context; import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.PreferenceViewHolder; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.View; @@ -64,6 +65,7 @@ public class SyncStateSwitchPreference extends SwitchPreference { mAuthority = authority; mPackageName = packageName; mUid = uid; + setVisible(!TextUtils.isEmpty(mAuthority)); notifyChanged(); } diff --git a/tests/robotests/src/com/android/settings/accounts/SyncStateSwitchPreferenceTest.java b/tests/robotests/src/com/android/settings/accounts/SyncStateSwitchPreferenceTest.java new file mode 100644 index 00000000000..0d454181f7e --- /dev/null +++ b/tests/robotests/src/com/android/settings/accounts/SyncStateSwitchPreferenceTest.java @@ -0,0 +1,62 @@ +/* + * 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.accounts; + +import static com.google.common.truth.Truth.assertThat; + +import android.accounts.Account; +import android.content.Context; +import android.os.UserHandle; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class SyncStateSwitchPreferenceTest { + + private Context mContext; + private SyncStateSwitchPreference mPreference; + + @Before + public void setup() { + mContext = RuntimeEnvironment.application; + } + + @Test + public void setup_validAuthority_shouldBeVisible() { + mPreference = new SyncStateSwitchPreference(mContext, null /* attrs */); + + mPreference.setup(new Account("name", "type"), "authority", mContext.getPackageName(), + UserHandle.USER_CURRENT); + + assertThat(mPreference.isVisible()).isTrue(); + } + + @Test + public void setup_emptyAuthority_shouldBeInvisible() { + mPreference = new SyncStateSwitchPreference(mContext, null /* attrs */); + + mPreference.setup(new Account("name", "type"), null /* authority */, + mContext.getPackageName(), UserHandle.USER_CURRENT); + + assertThat(mPreference.isVisible()).isFalse(); + } +} From 7a2f9dcc342e58fb77625a58d31d184dda720879 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Fri, 6 Apr 2018 10:08:26 -0700 Subject: [PATCH 02/17] Marking dictionary activity as visibleToInstantApps Without this change, prompts to the user to add a word entered into one of the text fields within an instant app would result in a crash. Change-Id: I98c9dd21d4fbf6f65c519b7e34bcc11f43b6a92e Fixes: 77273200 Test: manual - trigger add word launch from instant app --- AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index b892dee2653..76ad913b637 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -700,6 +700,7 @@ Date: Fri, 6 Apr 2018 14:12:41 -0700 Subject: [PATCH 03/17] Add test flags for battery tips. When this flag is true, we will show related battery tip by force. Then we can manually test and verify the UI behavior. Following CL will add test flag for "app restriction" since it is a little tricky. Bug: 77477035 Test: RunSettingsRoboTests Change-Id: Ib12ff4aa8bcc998ea6a73f461c3d5f7fcc39b019 --- .../batterytip/BatteryTipPolicy.java | 32 +++++++++++++++++++ .../detectors/EarlyWarningDetector.java | 2 +- .../detectors/HighUsageDetector.java | 11 ++++++- .../detectors/SmartBatteryDetector.java | 6 ++-- .../batterytip/BatteryTipPolicyTest.java | 11 ++++++- .../detectors/EarlyWarningDetectorTest.java | 10 ++++++ .../detectors/HighUsageDetectorTest.java | 9 ++++++ .../detectors/SmartBatteryDetectorTest.java | 14 ++++++-- 8 files changed, 87 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java index 17284a0de26..5520bf3f3dd 100644 --- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java +++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java @@ -47,6 +47,10 @@ public class BatteryTipPolicy { private static final String KEY_DATA_HISTORY_RETAIN_DAY = "data_history_retain_day"; private static final String KEY_EXCESSIVE_BG_DRAIN_PERCENTAGE = "excessive_bg_drain_percentage"; + private static final String KEY_TEST_BATTERY_SAVER_TIP = "test_battery_saver_tip"; + private static final String KEY_TEST_HIGH_USAGE_TIP = "test_high_usage_tip"; + private static final String KEY_TEST_SMART_BATTERY_TIP = "test_smart_battery_tip"; + /** * {@code true} if general battery tip is enabled * @@ -164,6 +168,30 @@ public class BatteryTipPolicy { */ public final int excessiveBgDrainPercentage; + /** + * {@code true} if we want to test battery saver tip. + * + * @see Settings.Global#BATTERY_TIP_CONSTANTS + * @see #KEY_TEST_BATTERY_SAVER_TIP + */ + public final boolean testBatterySaverTip; + + /** + * {@code true} if we want to test high usage tip. + * + * @see Settings.Global#BATTERY_TIP_CONSTANTS + * @see #KEY_TEST_HIGH_USAGE_TIP + */ + public final boolean testHighUsageTip; + + /** + * {@code true} if we want to test smart battery tip. + * + * @see Settings.Global#BATTERY_TIP_CONSTANTS + * @see #KEY_TEST_SMART_BATTERY_TIP + */ + public final boolean testSmartBatteryTip; + private final KeyValueListParser mParser; public BatteryTipPolicy(Context context) { @@ -197,6 +225,10 @@ public class BatteryTipPolicy { lowBatteryHour = mParser.getInt(KEY_LOW_BATTERY_HOUR, 16); dataHistoryRetainDay = mParser.getInt(KEY_DATA_HISTORY_RETAIN_DAY, 30); excessiveBgDrainPercentage = mParser.getInt(KEY_EXCESSIVE_BG_DRAIN_PERCENTAGE, 10); + + testBatterySaverTip = mParser.getBoolean(KEY_TEST_BATTERY_SAVER_TIP, false); + testHighUsageTip = mParser.getBoolean(KEY_TEST_HIGH_USAGE_TIP, false); + testSmartBatteryTip = mParser.getBoolean(KEY_TEST_SMART_BATTERY_TIP, false); } } diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetector.java index a10c8f1daf1..9b6b9b5d969 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetector.java @@ -53,7 +53,7 @@ public class EarlyWarningDetector implements BatteryTipDetector { batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0; final boolean powerSaveModeOn = mPowerManager.isPowerSaveMode(); final boolean earlyWarning = mPowerUsageFeatureProvider.getEarlyWarningSignal(mContext, - EarlyWarningDetector.class.getName()); + EarlyWarningDetector.class.getName()) || mPolicy.testBatterySaverTip; final int state = powerSaveModeOn ? BatteryTip.StateType.HANDLED diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java index 1b6e2f03ae3..8435c52671d 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java @@ -34,6 +34,7 @@ import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.TimeUnit; /** * Detector whether to show summary tip. This detector should be executed as the last @@ -65,7 +66,7 @@ public class HighUsageDetector implements BatteryTipDetector { final long screenUsageTimeMs = mBatteryUtils.calculateScreenUsageTime(mBatteryStatsHelper); if (mPolicy.highUsageEnabled) { parseBatteryData(); - if (mDataParser.isDeviceHeavilyUsed()) { + if (mDataParser.isDeviceHeavilyUsed() || mPolicy.testHighUsageTip) { final List batterySippers = mBatteryStatsHelper.getUsageList(); for (int i = 0, size = batterySippers.size(); i < size; i++) { final BatterySipper batterySipper = batterySippers.get(i); @@ -84,6 +85,14 @@ public class HighUsageDetector implements BatteryTipDetector { } } + // When in test mode, add an app if necessary + if (mPolicy.testHighUsageTip && mHighUsageAppList.isEmpty()) { + mHighUsageAppList.add(new AppInfo.Builder() + .setPackageName("com.android.settings") + .setScreenOnTimeMs(TimeUnit.HOURS.toMillis(3)) + .build()); + } + Collections.sort(mHighUsageAppList, Collections.reverseOrder()); mHighUsageAppList = mHighUsageAppList.subList(0, Math.min(mPolicy.highUsageAppCount, mHighUsageAppList.size())); diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetector.java index bff324d3633..ecd595e1ce6 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetector.java @@ -38,10 +38,10 @@ public class SmartBatteryDetector implements BatteryTipDetector { @Override public BatteryTip detect() { // Show it if there is no other tips shown - final boolean smartBatteryOn = Settings.Global.getInt(mContentResolver, - Settings.Global.APP_STANDBY_ENABLED, 1) != 0; + final boolean smartBatteryOff = Settings.Global.getInt(mContentResolver, + Settings.Global.APP_STANDBY_ENABLED, 1) == 0 || mPolicy.testSmartBatteryTip; final int state = - smartBatteryOn ? BatteryTip.StateType.INVISIBLE : BatteryTip.StateType.NEW; + smartBatteryOff ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE; return new SmartBatteryTip(state); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java index c52b73e2336..654b247d9df 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java @@ -45,7 +45,10 @@ public class BatteryTipPolicyTest { + ",low_battery_enabled=false" + ",low_battery_hour=10" + ",data_history_retain_day=24" - + ",excessive_bg_drain_percentage=25"; + + ",excessive_bg_drain_percentage=25" + + ",test_battery_saver_tip=true" + + ",test_high_usage_tip=false" + + ",test_smart_battery_tip=true"; private Context mContext; @Before @@ -74,6 +77,9 @@ public class BatteryTipPolicyTest { assertThat(batteryTipPolicy.lowBatteryHour).isEqualTo(10); assertThat(batteryTipPolicy.dataHistoryRetainDay).isEqualTo(24); assertThat(batteryTipPolicy.excessiveBgDrainPercentage).isEqualTo(25); + assertThat(batteryTipPolicy.testBatterySaverTip).isTrue(); + assertThat(batteryTipPolicy.testHighUsageTip).isFalse(); + assertThat(batteryTipPolicy.testSmartBatteryTip).isTrue(); } @Test @@ -97,5 +103,8 @@ public class BatteryTipPolicyTest { assertThat(batteryTipPolicy.lowBatteryHour).isEqualTo(16); assertThat(batteryTipPolicy.dataHistoryRetainDay).isEqualTo(30); assertThat(batteryTipPolicy.excessiveBgDrainPercentage).isEqualTo(10); + assertThat(batteryTipPolicy.testBatterySaverTip).isFalse(); + assertThat(batteryTipPolicy.testHighUsageTip).isFalse(); + assertThat(batteryTipPolicy.testSmartBatteryTip).isFalse(); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetectorTest.java index 21ef8a358d1..c4c3d021b18 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetectorTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/EarlyWarningDetectorTest.java @@ -74,6 +74,16 @@ public class EarlyWarningDetectorTest { assertThat(mEarlyWarningDetector.detect().isVisible()).isFalse(); } + @Test + public void testDetect_testFeatureOn_tipNew() { + doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider) + .getEarlyWarningSignal(any(), any()); + ReflectionHelpers.setField(mPolicy, "testBatterySaverTip", true); + + assertThat(mEarlyWarningDetector.detect().getState()) + .isEqualTo(BatteryTip.StateType.NEW); + } + @Test public void testDetect_batterySaverOn_tipHandled() { doReturn(true).when(mPowerManager).isPowerSaveMode(); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java index d983dfc7eed..2a2420d7f0c 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java @@ -34,6 +34,7 @@ import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.batterytip.AppInfo; import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy; import com.android.settings.fuelgauge.batterytip.HighUsageDataParser; +import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip; import com.android.settings.testutils.SettingsRobolectricTestRunner; @@ -108,6 +109,14 @@ public class HighUsageDetectorTest { assertThat(mHighUsageDetector.detect().isVisible()).isFalse(); } + @Test + public void testDetect_testFeatureOn_tipNew() { + doReturn(false).when(mDataParser).isDeviceHeavilyUsed(); + ReflectionHelpers.setField(mPolicy, "testHighUsageTip", true); + + assertThat(mHighUsageDetector.detect().getState()).isEqualTo(BatteryTip.StateType.NEW); + } + @Test public void testDetect_containsHighUsageApp_tipVisible() { doReturn(true).when(mDataParser).isDeviceHeavilyUsed(); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetectorTest.java index 91343191e52..ad08a22cda5 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetectorTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SmartBatteryDetectorTest.java @@ -24,6 +24,7 @@ import android.content.Context; import android.provider.Settings; import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy; +import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.testutils.SettingsRobolectricTestRunner; import org.junit.Before; @@ -31,6 +32,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; +import org.robolectric.util.ReflectionHelpers; @RunWith(SettingsRobolectricTestRunner.class) public class SmartBatteryDetectorTest { @@ -38,6 +40,7 @@ public class SmartBatteryDetectorTest { private Context mContext; private ContentResolver mContentResolver; private SmartBatteryDetector mSmartBatteryDetector; + private BatteryTipPolicy mPolicy; @Before public void setUp() { @@ -45,8 +48,15 @@ public class SmartBatteryDetectorTest { mContext = RuntimeEnvironment.application; mContentResolver = mContext.getContentResolver(); - final BatteryTipPolicy policy = spy(new BatteryTipPolicy(mContext)); - mSmartBatteryDetector = new SmartBatteryDetector(policy, mContentResolver); + mPolicy = spy(new BatteryTipPolicy(mContext)); + mSmartBatteryDetector = new SmartBatteryDetector(mPolicy, mContentResolver); + } + + @Test + public void testDetect_testFeatureOn_tipNew() { + ReflectionHelpers.setField(mPolicy, "testSmartBatteryTip", true); + + assertThat(mSmartBatteryDetector.detect().getState()).isEqualTo(BatteryTip.StateType.NEW); } @Test From e35464711ea3dc8bf36b2fda6e43fb27caf5400a Mon Sep 17 00:00:00 2001 From: ryanywlin Date: Tue, 3 Apr 2018 15:23:26 +0800 Subject: [PATCH 04/17] Add new string for audio switcher Bug: 74130772 Test: rebuild Change-Id: I31760046ca1754145dfa40049428213f985e8175 --- res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/res/values/strings.xml b/res/values/strings.xml index 31b4f902adc..26fd854e5af 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -9825,6 +9825,9 @@ Play media to + + This device + Phone From 4964685a2eb355ace51dda38e3149620c01dd5ac Mon Sep 17 00:00:00 2001 From: caxtonchan Date: Mon, 9 Apr 2018 16:15:45 +0800 Subject: [PATCH 05/17] [Settings] Align volume slider with other preference Update padding to align with other preference. Bug: 77606803 Test: Robotest and manual test Change-Id: I3f81bf0a6c796465128d05260f4a50e23db45385 --- res/layout/preference_volume_slider.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/res/layout/preference_volume_slider.xml b/res/layout/preference_volume_slider.xml index 4bed21850b7..7e146b88ba8 100644 --- a/res/layout/preference_volume_slider.xml +++ b/res/layout/preference_volume_slider.xml @@ -56,7 +56,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:paddingStart="16dp" + android:paddingStart="12dp" android:singleLine="true" android:textAppearance="@android:style/TextAppearance.Material.Subhead" android:textColor="?android:attr/textColorPrimary" @@ -68,7 +68,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="end|center_vertical" - android:paddingStart="16dp" + android:paddingStart="12dp" android:orientation="vertical"/> @@ -80,6 +80,7 @@ @@ -87,7 +88,7 @@ android:id="@+id/suppression_text" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="16dp" + android:paddingStart="12dp" android:layout_gravity="center_vertical|start" android:textAlignment="viewStart" android:singleLine="true" From 9d2c7e822bde2bdf47b51fdb984feaa682963d17 Mon Sep 17 00:00:00 2001 From: Lei Yu Date: Mon, 9 Apr 2018 11:25:31 -0700 Subject: [PATCH 06/17] Hide preference when no app restricted Change-Id: I37135bce5354ce7380441f86f94cb79d89cc500c Fixes: 77799629 Test: RunSettingsRoboTests --- .../fuelgauge/RestrictAppPreferenceController.java | 4 ++-- .../fuelgauge/RestrictAppPreferenceControllerTest.java | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java index fce8a65e215..7fdf8294cb9 100644 --- a/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java +++ b/src/com/android/settings/fuelgauge/RestrictAppPreferenceController.java @@ -72,8 +72,8 @@ public class RestrictAppPreferenceController extends BasePreferenceController { mAppInfos = BatteryTipUtils.getRestrictedAppsList(mAppOpsManager, mUserManager); final int num = mAppInfos.size(); - // Enable the preference if some apps already been restricted, otherwise disable it - preference.setEnabled(num > 0); + // Don't show it if no app been restricted + preference.setVisible(num > 0); preference.setSummary( mContext.getResources().getQuantityString(R.plurals.restricted_app_summary, num, num)); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java index 6a97fe187ff..7d26755deec 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictAppPreferenceControllerTest.java @@ -125,7 +125,7 @@ public class RestrictAppPreferenceControllerTest { } @Test - public void testUpdateState_twoRestrictedAppsForPrimaryUser_showCorrectSummary() { + public void testUpdateState_twoRestrictedAppsForPrimaryUser_visibleAndShowCorrectSummary() { mPackageOpsList.add(mRestrictedPackageOps); mPackageOpsList.add(mRestrictedPackageOps); mPackageOpsList.add(mAllowedPackageOps); @@ -135,6 +135,7 @@ public class RestrictAppPreferenceControllerTest { mRestrictAppPreferenceController.updateState(mPreference); assertThat(mPreference.getSummary()).isEqualTo("Limiting battery usage for 2 apps"); + assertThat(mPreference.isVisible()).isTrue(); } @Test @@ -155,13 +156,13 @@ public class RestrictAppPreferenceControllerTest { } @Test - public void testUpdateState_zeroRestrictApp_disabled() { + public void testUpdateState_zeroRestrictApp_inVisible() { mPackageOpsList.add(mAllowedPackageOps); doReturn(mPackageOpsList).when(mAppOpsManager).getPackagesForOps(any()); mRestrictAppPreferenceController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isFalse(); + assertThat(mPreference.isVisible()).isFalse(); } @Test From d7815fe18fff943abfef39e55839bb16e93dc022 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Fri, 30 Mar 2018 14:04:55 -0400 Subject: [PATCH 07/17] Notification settings updates - smaller icons - text update - fx header - fix category header Test: make -j RunSettingsRoboTests Change-Id: If822d6db31a8dccf20ee88182cda1aee34aa7675 Fixes: 77325154 Fixes: 77323406 Fixes: 77324677 Fixes: 74408368 --- res/layout/preference_app.xml | 4 ++-- res/values/strings.xml | 4 ++-- .../notification/AppNotificationSettings.java | 6 ++--- .../BadgePreferenceController.java | 2 +- .../BlockPreferenceController.java | 3 +-- .../HeaderPreferenceController.java | 6 +++-- .../ImportancePreferenceController.java | 2 +- .../LightsPreferenceController.java | 5 ++-- .../NotificationPreferenceController.java | 7 ++++++ ...centNotifyingAppsPreferenceController.java | 4 ++-- .../SoundPreferenceController.java | 3 +-- .../VibrationPreferenceController.java | 2 +- .../HeaderPreferenceControllerTest.java | 10 ++++++++ .../NotificationPreferenceControllerTest.java | 24 +++++++++++++++++++ 14 files changed, 62 insertions(+), 20 deletions(-) diff --git a/res/layout/preference_app.xml b/res/layout/preference_app.xml index 2e134dee207..66050410847 100644 --- a/res/layout/preference_app.xml +++ b/res/layout/preference_app.xml @@ -95,8 +95,8 @@ android:id="@android:id/widget_frame" android:layout_width="wrap_content" android:layout_height="match_parent" - android:gravity="end|center_vertical" - android:paddingStart="16dp" + android:gravity="center" + android:minWidth="64dp" android:orientation="vertical" /> diff --git a/res/values/strings.xml b/res/values/strings.xml index 0922ebb13c3..d7179d51824 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7513,9 +7513,9 @@ Notification assistant - ~%1$s sent daily + ~%1$s per day - ~%1$s sent weekly + ~%1$s per week Never diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java index d334b9217b7..c028298e0bd 100644 --- a/src/com/android/settings/notification/AppNotificationSettings.java +++ b/src/com/android/settings/notification/AppNotificationSettings.java @@ -167,9 +167,9 @@ public class AppNotificationSettings extends NotificationSettingsBase { getPreferenceScreen().addPreference(groupCategory); mDynamicPreferences.add(groupCategory); if (group.getId() == null) { - groupCategory.setTitle(mChannelGroupList.size() > 1 - ? R.string.notification_channels_other - : R.string.notification_channels); + if (mChannelGroupList.size() > 1) { + groupCategory.setTitle(R.string.notification_channels_other); + } groupCategory.setKey(KEY_GENERAL_CATEGORY); } else { groupCategory.setTitle(group.getName()); diff --git a/src/com/android/settings/notification/BadgePreferenceController.java b/src/com/android/settings/notification/BadgePreferenceController.java index 8f0376c0627..e768ad18090 100644 --- a/src/com/android/settings/notification/BadgePreferenceController.java +++ b/src/com/android/settings/notification/BadgePreferenceController.java @@ -57,7 +57,7 @@ public class BadgePreferenceController extends NotificationPreferenceController return false; } if (mChannel != null) { - if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) { + if (isDefaultChannel()) { return true; } else { return mAppRow.showBadge; diff --git a/src/com/android/settings/notification/BlockPreferenceController.java b/src/com/android/settings/notification/BlockPreferenceController.java index 9ea29feccca..7c6201eeedf 100644 --- a/src/com/android/settings/notification/BlockPreferenceController.java +++ b/src/com/android/settings/notification/BlockPreferenceController.java @@ -98,8 +98,7 @@ public class BlockPreferenceController extends NotificationPreferenceController // it was blocked and we are unblocking it. if (blocked || originalImportance == IMPORTANCE_NONE) { final int importance = blocked ? IMPORTANCE_NONE - : DEFAULT_CHANNEL_ID.equals(mChannel.getId()) - ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_DEFAULT; + : isDefaultChannel() ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_DEFAULT; mChannel.setImportance(importance); saveChannel(); } diff --git a/src/com/android/settings/notification/HeaderPreferenceController.java b/src/com/android/settings/notification/HeaderPreferenceController.java index ff687e8049f..d5e289b3173 100644 --- a/src/com/android/settings/notification/HeaderPreferenceController.java +++ b/src/com/android/settings/notification/HeaderPreferenceController.java @@ -31,6 +31,8 @@ import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.widget.EntityHeaderController; +import java.util.Objects; + public class HeaderPreferenceController extends NotificationPreferenceController implements PreferenceControllerMixin { @@ -72,7 +74,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController } CharSequence getLabel() { - return mChannel != null ? mChannel.getName() + return (mChannel != null && !isDefaultChannel()) ? mChannel.getName() : mChannelGroup != null ? mChannelGroup.getName() : mAppRow.label; @@ -80,7 +82,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController @Override public CharSequence getSummary() { - if (mChannel != null) { + if (mChannel != null && !isDefaultChannel()) { if (mChannelGroup != null && !TextUtils.isEmpty(mChannelGroup.getName())) { final SpannableStringBuilder summary = new SpannableStringBuilder(); diff --git a/src/com/android/settings/notification/ImportancePreferenceController.java b/src/com/android/settings/notification/ImportancePreferenceController.java index f95c34ae6ae..60b2ebe0250 100644 --- a/src/com/android/settings/notification/ImportancePreferenceController.java +++ b/src/com/android/settings/notification/ImportancePreferenceController.java @@ -58,7 +58,7 @@ public class ImportancePreferenceController extends NotificationPreferenceContro if (mChannel == null) { return false; } - return !NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId()); + return !isDefaultChannel(); } @Override diff --git a/src/com/android/settings/notification/LightsPreferenceController.java b/src/com/android/settings/notification/LightsPreferenceController.java index 230c3e295d2..9d5a6c55d74 100644 --- a/src/com/android/settings/notification/LightsPreferenceController.java +++ b/src/com/android/settings/notification/LightsPreferenceController.java @@ -50,8 +50,9 @@ public class LightsPreferenceController extends NotificationPreferenceController if (mChannel == null) { return false; } - return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && canPulseLight() - && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId()); + return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) + && canPulseLight() + && !isDefaultChannel(); } public void updateState(Preference preference) { diff --git a/src/com/android/settings/notification/NotificationPreferenceController.java b/src/com/android/settings/notification/NotificationPreferenceController.java index c0bb7050045..1a65351659e 100644 --- a/src/com/android/settings/notification/NotificationPreferenceController.java +++ b/src/com/android/settings/notification/NotificationPreferenceController.java @@ -184,4 +184,11 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc protected boolean hasValidGroup() { return mChannelGroup != null; } + + protected final boolean isDefaultChannel() { + if (mChannel == null) { + return false; + } + return Objects.equals(NotificationChannel.DEFAULT_CHANNEL_ID, mChannel.getId()); + } } diff --git a/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java b/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java index 3867640c86f..4079099f8ec 100644 --- a/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java +++ b/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java @@ -37,14 +37,13 @@ import android.util.Log; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.applications.AppInfoBase; -import com.android.settings.applications.InstalledAppCounter; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.SubSettingLauncher; +import com.android.settingslib.TwoTargetPreference; import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.utils.StringUtil; -import com.android.settingslib.wrapper.PackageManagerWrapper; import java.util.ArrayList; import java.util.Arrays; @@ -211,6 +210,7 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC pref.setKey(pkgName); pref.setTitle(appEntry.label); pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info)); + pref.setIconSize(TwoTargetPreference.ICON_SIZE_SMALL); pref.setSummary(StringUtil.formatRelativeTime(mContext, System.currentTimeMillis() - app.getLastNotified(), true)); pref.setOrder(i); diff --git a/src/com/android/settings/notification/SoundPreferenceController.java b/src/com/android/settings/notification/SoundPreferenceController.java index e4414b6908a..4ae6ebe99c6 100644 --- a/src/com/android/settings/notification/SoundPreferenceController.java +++ b/src/com/android/settings/notification/SoundPreferenceController.java @@ -59,8 +59,7 @@ public class SoundPreferenceController extends NotificationPreferenceController if (mChannel == null) { return false; } - return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) - && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId()); + return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && !isDefaultChannel(); } @Override diff --git a/src/com/android/settings/notification/VibrationPreferenceController.java b/src/com/android/settings/notification/VibrationPreferenceController.java index f9b786dc2d8..9df8e04013f 100644 --- a/src/com/android/settings/notification/VibrationPreferenceController.java +++ b/src/com/android/settings/notification/VibrationPreferenceController.java @@ -47,7 +47,7 @@ public class VibrationPreferenceController extends NotificationPreferenceControl return false; } return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) - && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId()) + && !isDefaultChannel() && mVibrator != null && mVibrator.hasVibrator(); } diff --git a/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java index 29773d2cc1a..9a766470836 100644 --- a/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java @@ -109,6 +109,11 @@ public class HeaderPreferenceControllerTest { NotificationChannel channel = new NotificationChannel("cid", "cname", IMPORTANCE_NONE); mController.onResume(appRow, channel, group, null); assertEquals(channel.getName(), mController.getLabel()); + + NotificationChannel defaultChannel = new NotificationChannel( + NotificationChannel.DEFAULT_CHANNEL_ID, "", IMPORTANCE_NONE); + mController.onResume(appRow, defaultChannel, null, null); + assertEquals(appRow.label, mController.getLabel()); } @Test @@ -130,5 +135,10 @@ public class HeaderPreferenceControllerTest { mController.onResume(appRow, channel, null, null); assertFalse(mController.getSummary().toString().contains(group.getName())); assertTrue(mController.getSummary().toString().contains(appRow.label)); + + NotificationChannel defaultChannel = new NotificationChannel( + NotificationChannel.DEFAULT_CHANNEL_ID, "", IMPORTANCE_NONE); + mController.onResume(appRow, defaultChannel, null, null); + assertEquals("", mController.getSummary()); } } diff --git a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java index 3ead72a2f31..4fe384e981b 100644 --- a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java @@ -294,6 +294,30 @@ public class NotificationPreferenceControllerTest { assertTrue(mController.isChannelGroupBlockable()); } + @Test + public void testIsDefaultChannel_noChannel() { + mController.onResume(mock(NotificationBackend.AppRow.class), null, null, null); + + assertFalse(mController.isDefaultChannel()); + } + + @Test + public void testIsDefaultChannel_nonDefaultChannel() { + NotificationChannel channel = mock(NotificationChannel.class); + mController.onResume(mock(NotificationBackend.AppRow.class), channel, null, null); + + assertFalse(mController.isDefaultChannel()); + } + + @Test + public void testIsDefaultChannel() { + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.getId()).thenReturn(NotificationChannel.DEFAULT_CHANNEL_ID); + mController.onResume(mock(NotificationBackend.AppRow.class), channel, null, null); + + assertTrue(mController.isDefaultChannel()); + } + private final class TestPreferenceController extends NotificationPreferenceController { private TestPreferenceController(Context context, NotificationBackend backend) { From c7b58b699760b51595d0688e251ac1e987823de7 Mon Sep 17 00:00:00 2001 From: Lei Yu Date: Mon, 9 Apr 2018 10:10:15 -0700 Subject: [PATCH 08/17] Update field for ACTION_ANOMALY_TRIGGERED Use new field FIELD_ANOMALY_TYPE Bug: 75976625 Test: RunSettingsRoboTests Change-Id: Ifb67c687d25e1e35afaadb05f2e9883e8dcf8049 --- .../fuelgauge/batterytip/AnomalyDetectionJobService.java | 2 +- .../fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java b/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java index 2b041734b80..5bf393ad7cb 100644 --- a/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java +++ b/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java @@ -172,7 +172,7 @@ public class AnomalyDetectionJobService extends JobService { metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_ANOMALY_TRIGGERED, packageName, - Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, + Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE, anomalyInfo.anomalyType)); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java index dbca602a567..d1a85cea4d7 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java @@ -169,7 +169,7 @@ public class AnomalyDetectionJobServiceTest { verify(mFeatureFactory.metricsFeatureProvider).action(mContext, MetricsProto.MetricsEvent.ACTION_ANOMALY_TRIGGERED, SYSTEM_PACKAGE, - Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_TYPE)); + Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE, ANOMALY_TYPE)); } @@ -194,6 +194,6 @@ public class AnomalyDetectionJobServiceTest { verify(mFeatureFactory.metricsFeatureProvider).action(mContext, MetricsProto.MetricsEvent.ACTION_ANOMALY_TRIGGERED, SYSTEM_PACKAGE, - Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_TYPE)); + Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE, ANOMALY_TYPE)); } } From 81ca3dd4c0bb4c7918cadbb8378f9b96acb5babb Mon Sep 17 00:00:00 2001 From: Salvador Martinez Date: Mon, 9 Apr 2018 15:27:02 -0700 Subject: [PATCH 09/17] Remove provisioning dialog from wifi-tethering We no longer want this dialog to show when a user toggles tethering. Failures to set up the AP will still be handled correctly. Test: robotests pass Bug: 62629055 Change-Id: Id3d0bf9694a1c8b6ae353bfd6634dd0b56813497 --- .../settings/wifi/tether/WifiTetherSwitchBarController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java index bdad9e6040b..ab08fdb6299 100644 --- a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java +++ b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java @@ -102,7 +102,7 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS void startTether() { mSwitchBar.setEnabled(false); - mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */, + mConnectivityManager.startTethering(TETHERING_WIFI, false /* showProvisioningUi */, mOnStartTetheringCallback, new Handler(Looper.getMainLooper())); } From dba7d1c4b3f1cc8ae48c7b86b2259377d2fe6fbc Mon Sep 17 00:00:00 2001 From: Matthew Fritze Date: Fri, 6 Apr 2018 10:20:05 -0700 Subject: [PATCH 10/17] Unavailable Slices includes DISABLED_DEPENDENT settings In the change to mark disabled_dependent as available, it did not change the check in SliceBuilderUtils for the unavailable Slices. In the case of DISABLED_DEPENDENT, the setting is available but the Slice is not. Though it is a simple change, we can now properly test the contents of Slices, so this change includes tests which should have been in place earlier and would have caught this bug - duh. Bug: 71640747 Test: Robotests Change-Id: I8db5bc80edb337cbf907ce3669aa2bfd9c72f74a --- .../settings/slices/SliceBuilderUtils.java | 104 ++++++----- .../slices/SliceBuilderUtilsTest.java | 94 +++++++--- .../settings/testutils/SliceTester.java | 170 ++++++++++++++++++ 3 files changed, 297 insertions(+), 71 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/testutils/SliceTester.java diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java index c54d138e942..05f0974f277 100644 --- a/src/com/android/settings/slices/SliceBuilderUtils.java +++ b/src/com/android/settings/slices/SliceBuilderUtils.java @@ -17,6 +17,8 @@ package com.android.settings.slices; import static androidx.slice.builders.ListBuilder.ICON_IMAGE; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER; import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED; @@ -47,7 +49,9 @@ import com.android.settings.search.DatabaseIndexingUtils; import com.android.settingslib.core.AbstractPreferenceController; import android.support.v4.graphics.drawable.IconCompat; + import androidx.slice.Slice; +import androidx.slice.SliceMetadata; import androidx.slice.builders.ListBuilder; import androidx.slice.builders.SliceAction; @@ -75,7 +79,8 @@ public class SliceBuilderUtils { // action name). FeatureFactory.getFactory(context).getMetricsFeatureProvider() .action(context, MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED, sliceNamePair); - if (!controller.isAvailable()) { + + if (controller.getAvailabilityStatus() != AVAILABLE) { return buildUnavailableSlice(context, sliceData, controller); } @@ -145,6 +150,60 @@ public class SliceBuilderUtils { sliceData.getKey()); } + /** + * @return {@link PendingIntent} for a non-primary {@link SliceAction}. + */ + public static PendingIntent getActionIntent(Context context, String action, SliceData data) { + Intent intent = new Intent(action); + intent.setClass(context, SliceBroadcastReceiver.class); + intent.putExtra(EXTRA_SLICE_KEY, data.getKey()); + intent.putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined()); + return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent, + PendingIntent.FLAG_CANCEL_CURRENT); + } + + /** + * @return {@link PendingIntent} for the primary {@link SliceAction}. + */ + public static PendingIntent getContentIntent(Context context, SliceData sliceData) { + Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context, + sliceData.getFragmentClassName(), sliceData.getKey(), sliceData.getScreenTitle(), + 0 /* TODO */); + intent.setClassName("com.android.settings", SubSettings.class.getName()); + return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */); + } + + /** + * @return {@link PendingIntent} to the Settings home page. + */ + public static PendingIntent getSettingsIntent(Context context) { + final PackageManager manager = context.getPackageManager(); + final Intent intent = manager.getLaunchIntentForPackage(context.getPackageName()); + return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */); + } + + /** + * @return the summary text for a {@link Slice} built for {@param sliceData}. + */ + public static CharSequence getSubtitleText(Context context, + AbstractPreferenceController controller, SliceData sliceData) { + CharSequence summaryText; + if (controller != null) { + summaryText = controller.getSummary(); + + if (isValidSummary(context, summaryText)) { + return summaryText; + } + } + + summaryText = sliceData.getSummary(); + if (isValidSummary(context, summaryText)) { + return summaryText; + } + + return ""; + } + public static Uri getUri(String path, boolean isPlatformSlice) { final String authority = isPlatformSlice ? SettingsSlicesContract.AUTHORITY @@ -227,49 +286,6 @@ public class SliceBuilderUtils { return getActionIntent(context, SettingsSliceProvider.ACTION_SLIDER_CHANGED, sliceData); } - private static PendingIntent getActionIntent(Context context, String action, SliceData data) { - Intent intent = new Intent(action); - intent.setClass(context, SliceBroadcastReceiver.class); - intent.putExtra(EXTRA_SLICE_KEY, data.getKey()); - intent.putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined()); - return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent, - PendingIntent.FLAG_CANCEL_CURRENT); - } - - private static PendingIntent getContentIntent(Context context, SliceData sliceData) { - Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context, - sliceData.getFragmentClassName(), sliceData.getKey(), sliceData.getScreenTitle(), - 0 /* TODO */); - intent.setClassName("com.android.settings", SubSettings.class.getName()); - return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */); - } - - private static PendingIntent getSettingsIntent(Context context) { - final PackageManager manager = context.getPackageManager(); - final Intent intent = manager.getLaunchIntentForPackage(context.getPackageName()); - return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */); - } - - @VisibleForTesting - static CharSequence getSubtitleText(Context context, AbstractPreferenceController controller, - SliceData sliceData) { - CharSequence summaryText; - if (controller != null) { - summaryText = controller.getSummary(); - - if (isValidSummary(context, summaryText)) { - return summaryText; - } - } - - summaryText = sliceData.getSummary(); - if (isValidSummary(context, summaryText)) { - return summaryText; - } - - return ""; - } - private static boolean isValidSummary(Context context, CharSequence summary) { if (summary == null || TextUtils.isEmpty(summary.toString().trim())) { return false; diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java index 1f3f40ffb04..58ee9696dc4 100644 --- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java +++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java @@ -17,6 +17,8 @@ package com.android.settings.slices; import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -24,6 +26,7 @@ import static org.mockito.Mockito.verify; import android.content.ContentResolver; import android.content.Context; +import android.content.res.Resources; import android.net.Uri; import android.provider.Settings; import android.provider.SettingsSlicesContract; @@ -36,6 +39,7 @@ import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeSliderController; import com.android.settings.testutils.FakeToggleController; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.SliceTester; import org.junit.Before; import org.junit.Test; @@ -44,6 +48,8 @@ import org.mockito.ArgumentCaptor; import org.robolectric.RuntimeEnvironment; import androidx.slice.Slice; +import androidx.slice.SliceProvider; +import androidx.slice.widget.SliceLiveData; @RunWith(SettingsRobolectricTestRunner.class) public class SliceBuilderUtilsTest { @@ -55,8 +61,9 @@ public class SliceBuilderUtilsTest { private final String FRAGMENT_NAME = "fragment name"; private final int ICON = 1234; // I declare a thumb war private final Uri URI = Uri.parse("content://com.android.settings.slices/test"); - private final Class PREF_CONTROLLER = FakeToggleController.class; - private final Class PREF_CONTROLLER2 = FakeContextOnlyPreferenceController.class; + private final Class TOGGLE_CONTROLLER = FakeToggleController.class; + private final Class SLIDER_CONTROLLER = FakeSliderController.class; + private final Class CONTEXT_CONTROLLER = FakeContextOnlyPreferenceController.class; private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY; private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY; @@ -67,23 +74,50 @@ public class SliceBuilderUtilsTest { @Before public void setUp() { - mContext = RuntimeEnvironment.application; + mContext = spy(RuntimeEnvironment.application); mFeatureFactory = FakeFeatureFactory.setupForTest(); mLoggingArgumentCatpor = ArgumentCaptor.forClass(Pair.class); + + // Prevent crash in SliceMetadata. + Resources resources = spy(mContext.getResources()); + doReturn(60).when(resources).getDimensionPixelSize(anyInt()); + doReturn(resources).when(mContext).getResources(); + + // Set-up specs for SliceMetadata. + SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); } @Test - public void testBuildSlice_returnsMatchingSlice() { - Slice slice = SliceBuilderUtils.buildSlice(mContext, getDummyData()); + public void buildIntentSlice_returnsMatchingSlice() { + final SliceData sliceData = getDummyData(CONTEXT_CONTROLLER, SliceData.SliceType.INTENT); + final Slice slice = SliceBuilderUtils.buildSlice(mContext, sliceData); - assertThat(slice).isNotNull(); // TODO improve test for Slice content + SliceTester.testSettingsIntentSlice(mContext, slice, sliceData); } @Test - public void testSliderSlice_returnsSeekBarSlice() { - final SliceData data = getDummyData(FakeSliderController.class); + public void buildToggleSlice_returnsMatchingSlice() { + final SliceData dummyData = getDummyData(TOGGLE_CONTROLLER, SliceData.SliceType.SWITCH); + + final Slice slice = SliceBuilderUtils.buildSlice(mContext, dummyData); + verify(mFeatureFactory.metricsFeatureProvider) + .action(eq(mContext), eq(MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED), + mLoggingArgumentCatpor.capture()); + final Pair capturedLoggingPair = mLoggingArgumentCatpor.getValue(); + + assertThat(capturedLoggingPair.first) + .isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME); + assertThat(capturedLoggingPair.second) + .isEqualTo(dummyData.getKey()); + SliceTester.testSettingsToggleSlice(mContext, slice, dummyData); + } + + @Test + public void buildSliderSlice_returnsMatchingSlice() { + final SliceData data = getDummyData(SLIDER_CONTROLLER, SliceData.SliceType.SLIDER); + + final Slice slice = SliceBuilderUtils.buildSlice(mContext, data); - verify(mFeatureFactory.metricsFeatureProvider) .action(eq(mContext), eq(MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED), mLoggingArgumentCatpor.capture()); @@ -93,7 +127,7 @@ public class SliceBuilderUtilsTest { .isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME); assertThat(capturedLoggingPair.second) .isEqualTo(data.getKey()); - assertThat(slice).isNotNull(); + SliceTester.testSettingsSliderSlice(mContext, slice, data); } @Test @@ -159,7 +193,8 @@ public class SliceBuilderUtilsTest { @Test public void testGetPreferenceController_contextOnly_buildsMatchingController() { final BasePreferenceController controller = - SliceBuilderUtils.getPreferenceController(mContext, getDummyData(PREF_CONTROLLER2)); + SliceBuilderUtils.getPreferenceController(mContext, + getDummyData(CONTEXT_CONTROLLER, 0)); assertThat(controller).isInstanceOf(FakeContextOnlyPreferenceController.class); } @@ -176,7 +211,7 @@ public class SliceBuilderUtilsTest { @Test public void testDynamicSummary_returnsFragmentSummary() { - final SliceData data = getDummyData((String) null); + final SliceData data = getDummyData(null); final FakePreferenceController controller = spy( new FakePreferenceController(mContext, KEY)); final String controllerSummary = "new_Summary"; @@ -189,7 +224,7 @@ public class SliceBuilderUtilsTest { @Test public void testDynamicSummary_returnsSliceEmptyString() { - final SliceData data = getDummyData((String) null); + final SliceData data = getDummyData(null); final FakePreferenceController controller = new FakePreferenceController(mContext, KEY); final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); @@ -285,31 +320,34 @@ public class SliceBuilderUtilsTest { @Test public void testUnsupportedSlice_validTitleSummary() { - final SliceData data = getDummyData(FakeUnavailablePreferenceController.class.getName()); + final SliceData data = getDummyData(FakeUnavailablePreferenceController.class, + SliceData.SliceType.SWITCH); Settings.System.putInt(mContext.getContentResolver(), FakeUnavailablePreferenceController.AVAILABILITY_KEY, BasePreferenceController.DISABLED_UNSUPPORTED); final Slice slice = SliceBuilderUtils.buildSlice(mContext, data); - assertThat(slice).isNotNull(); + SliceTester.testSettingsUnavailableSlice(mContext, slice, data); } @Test public void testDisabledForUserSlice_validTitleSummary() { - final SliceData data = getDummyData(FakeUnavailablePreferenceController.class.getName()); + final SliceData data = getDummyData(FakeUnavailablePreferenceController.class, + SliceData.SliceType.SWITCH); Settings.System.putInt(mContext.getContentResolver(), FakeUnavailablePreferenceController.AVAILABILITY_KEY, BasePreferenceController.DISABLED_FOR_USER); final Slice slice = SliceBuilderUtils.buildSlice(mContext, data); - assertThat(slice).isNotNull(); + SliceTester.testSettingsUnavailableSlice(mContext, slice, data); } @Test - public void testDisabledDependententSettingSlice_validTitleSummary() { - final SliceData data = getDummyData(FakeUnavailablePreferenceController.class.getName()); + public void testDisabledDependentSettingSlice_validTitleSummary() { + final SliceData data = getDummyData(FakeUnavailablePreferenceController.class, + SliceData.SliceType.INTENT); Settings.System.putInt(mContext.getContentResolver(), FakeUnavailablePreferenceController.AVAILABILITY_KEY, BasePreferenceController.DISABLED_DEPENDENT_SETTING); @@ -325,12 +363,13 @@ public class SliceBuilderUtilsTest { .isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME); assertThat(capturedLoggingPair.second) .isEqualTo(data.getKey()); - assertThat(slice).isNotNull(); + SliceTester.testSettingsUnavailableSlice(mContext, slice, data); } @Test public void testUnavailableUnknownSlice_validTitleSummary() { - final SliceData data = getDummyData(FakeUnavailablePreferenceController.class.getName()); + final SliceData data = getDummyData(FakeUnavailablePreferenceController.class, + SliceData.SliceType.SWITCH); Settings.System.putInt(mContext.getContentResolver(), FakeUnavailablePreferenceController.AVAILABILITY_KEY, BasePreferenceController.UNAVAILABLE_UNKNOWN); @@ -347,22 +386,22 @@ public class SliceBuilderUtilsTest { .isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME); assertThat(capturedLoggingPair.second) .isEqualTo(data.getKey()); - assertThat(slice).isNotNull(); + SliceTester.testSettingsUnavailableSlice(mContext, slice, data); } private SliceData getDummyData() { - return getDummyData(PREF_CONTROLLER, SUMMARY); + return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH); } private SliceData getDummyData(String summary) { - return getDummyData(PREF_CONTROLLER, summary); + return getDummyData(TOGGLE_CONTROLLER, summary, SliceData.SliceType.SWITCH); } - private SliceData getDummyData(Class prefController) { - return getDummyData(prefController, SUMMARY); + private SliceData getDummyData(Class prefController, int sliceType) { + return getDummyData(prefController, SUMMARY, sliceType); } - private SliceData getDummyData(Class prefController, String summary) { + private SliceData getDummyData(Class prefController, String summary, int sliceType) { return new SliceData.Builder() .setKey(KEY) .setTitle(TITLE) @@ -372,6 +411,7 @@ public class SliceBuilderUtilsTest { .setFragmentName(FRAGMENT_NAME) .setUri(URI) .setPreferenceControllerClassName(prefController.getName()) + .setSliceType(sliceType) .build(); } } diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java new file mode 100644 index 00000000000..ef62d77e27a --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java @@ -0,0 +1,170 @@ +/* + * 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; + +import static android.app.slice.Slice.HINT_TITLE; +import static android.app.slice.SliceItem.FORMAT_TEXT; + +import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; +import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER; +import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED; +import static com.android.settings.core.BasePreferenceController.UNAVAILABLE_UNKNOWN; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.PendingIntent; +import android.content.Context; + +import java.util.List; + +import androidx.slice.Slice; +import androidx.slice.SliceItem; +import androidx.slice.SliceMetadata; +import androidx.slice.core.SliceAction; +import androidx.slice.core.SliceQuery; + +import android.support.v4.graphics.drawable.IconCompat; + +import com.android.settings.slices.SettingsSliceProvider; +import com.android.settings.slices.SliceBuilderUtils; +import com.android.settings.slices.SliceData; + +/** + * Testing utility class to verify the contents of the different Settings Slices. + * + * TODO (77712944) check Summary, range (metadata.getRange()), toggle icons. + */ +public class SliceTester { + + /** + * Test the contents of an intent based slice, including: + * - No toggles + * - Correct intent + * - Correct title + */ + public static void testSettingsIntentSlice(Context context, Slice slice, SliceData sliceData) { + final SliceMetadata metadata = SliceMetadata.from(context, slice); + + final List toggles = metadata.getToggles(); + assertThat(toggles).isEmpty(); + + final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); + assertThat(primaryPendingIntent).isEqualTo( + SliceBuilderUtils.getContentIntent(context, sliceData)); + + final List sliceItems = slice.getItems(); + assertTitle(sliceItems, sliceData.getTitle()); + } + + /** + * Test the contents of an toggle based slice, including: + * - Contains one toggle + * - Correct toggle intent + * - Correct content intent + * - Correct title + */ + public static void testSettingsToggleSlice(Context context, Slice slice, SliceData sliceData) { + final SliceMetadata metadata = SliceMetadata.from(context, slice); + + final List toggles = metadata.getToggles(); + assertThat(toggles).hasSize(1); + + final SliceAction mainToggleAction = toggles.get(0); + + final IconCompat expectedToggleIcon = IconCompat.createWithResource(context, + sliceData.getIconResource()); + assertThat(mainToggleAction.getIcon()).isNull(); + + // Check intent in Toggle Action + final PendingIntent togglePendingIntent = mainToggleAction.getAction(); + assertThat(togglePendingIntent).isEqualTo(SliceBuilderUtils.getActionIntent(context, + SettingsSliceProvider.ACTION_TOGGLE_CHANGED, sliceData)); + + // Check primary intent + final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); + assertThat(primaryPendingIntent).isEqualTo( + SliceBuilderUtils.getContentIntent(context, sliceData)); + + final List sliceItems = slice.getItems(); + assertTitle(sliceItems, sliceData.getTitle()); + } + + /** + * Test the contents of an slider based slice, including: + * - No intent + * - Correct title + */ + public static void testSettingsSliderSlice(Context context, Slice slice, SliceData sliceData) { + final SliceMetadata metadata = SliceMetadata.from(context, slice); + + final IconCompat expectedToggleIcon = IconCompat.createWithResource(context, + sliceData.getIconResource()); + + // Check primary intent + final SliceAction primaryAction = metadata.getPrimaryAction(); + assertThat(primaryAction).isNull(); + + final List sliceItems = slice.getItems(); + assertTitle(sliceItems, sliceData.getTitle()); + } + + /** + * Test the contents of an unavailable slice, including: + * - No toggles + * - Correct title + * - Correct intent + */ + public static void testSettingsUnavailableSlice(Context context, Slice slice, + SliceData sliceData) { + final SliceMetadata metadata = SliceMetadata.from(context, slice); + + final List toggles = metadata.getToggles(); + assertThat(toggles).isEmpty(); + + final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); + final int availabilityStatus = SliceBuilderUtils.getPreferenceController(context, + sliceData).getAvailabilityStatus(); + switch (availabilityStatus) { + case DISABLED_UNSUPPORTED: + case UNAVAILABLE_UNKNOWN: + assertThat(primaryPendingIntent).isEqualTo( + SliceBuilderUtils.getSettingsIntent(context)); + break; + case DISABLED_FOR_USER: + case DISABLED_DEPENDENT_SETTING: + assertThat(primaryPendingIntent).isEqualTo( + SliceBuilderUtils.getContentIntent(context, sliceData)); + break; + } + + final List sliceItems = slice.getItems(); + assertTitle(sliceItems, sliceData.getTitle()); + } + + private static void assertTitle(List sliceItems, String title) { + boolean hasTitle = false; + for (SliceItem item : sliceItems) { + List titles = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE, + null /* non-hints */); + if (titles != null & titles.size() == 1) { + assertThat(titles.get(0).getText()).isEqualTo(title); + hasTitle = true; + } + } + assertThat(hasTitle).isTrue(); + } +} \ No newline at end of file From fbe8a1318bc3f3fd79281defd85402a14a5a0a83 Mon Sep 17 00:00:00 2001 From: Daniel Solomon Date: Mon, 9 Apr 2018 15:09:13 -0700 Subject: [PATCH 11/17] Hide color mode preference depending on Accessibility settings Currently, when certain Accessibility color transforms are enabled, the color mode preference radio buttons are disabled. To avoid confusing users, hide the color mode preference entirely. If the color mode settings screen is already open when the Accessibility transforms are enabled, return the user back to the previous screen. Bug: 77695840 Test: make ROBOTEST_FILTER=ColorModePreferenceFragmentTest RunSettingsRoboTests -j40 Change-Id: I44812713bdc739b843e5806711d25ea950aa6250 --- .../ColorModePreferenceController.java | 4 +- .../display/ColorModePreferenceFragment.java | 23 +++----- .../ColorModePreferenceFragmentTest.java | 54 ++----------------- 3 files changed, 15 insertions(+), 66 deletions(-) diff --git a/src/com/android/settings/display/ColorModePreferenceController.java b/src/com/android/settings/display/ColorModePreferenceController.java index 7fa978209d7..31f53930a7e 100644 --- a/src/com/android/settings/display/ColorModePreferenceController.java +++ b/src/com/android/settings/display/ColorModePreferenceController.java @@ -41,7 +41,9 @@ public class ColorModePreferenceController extends BasePreferenceController { @Override public int getAvailabilityStatus() { - return mConfigWrapper.isScreenWideColorGamut() ? AVAILABLE : DISABLED_FOR_USER; + return mConfigWrapper.isScreenWideColorGamut() + && !getColorDisplayController().getAccessibilityTransformActivated() ? + AVAILABLE : DISABLED_FOR_USER; } @Override diff --git a/src/com/android/settings/display/ColorModePreferenceFragment.java b/src/com/android/settings/display/ColorModePreferenceFragment.java index 089a5a608ba..9f947e9e97a 100644 --- a/src/com/android/settings/display/ColorModePreferenceFragment.java +++ b/src/com/android/settings/display/ColorModePreferenceFragment.java @@ -16,7 +16,6 @@ package com.android.settings.display; import android.content.Context; import android.graphics.drawable.Drawable; import android.support.annotation.VisibleForTesting; -import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import com.android.internal.app.ColorDisplayController; @@ -25,7 +24,6 @@ import com.android.internal.logging.nano.MetricsProto; import com.android.settings.applications.LayoutPreference; import com.android.settings.R; import com.android.settings.widget.RadioButtonPickerFragment; -import com.android.settings.widget.RadioButtonPreference; import com.android.settingslib.widget.CandidateInfo; import java.util.Arrays; @@ -81,14 +79,13 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment @Override protected List getCandidates() { Context c = getContext(); - final boolean enabled = !mController.getAccessibilityTransformActivated(); return Arrays.asList( new ColorModeCandidateInfo(c.getText(R.string.color_mode_option_natural), - KEY_COLOR_MODE_NATURAL, enabled), + KEY_COLOR_MODE_NATURAL, true /* enabled */), new ColorModeCandidateInfo(c.getText(R.string.color_mode_option_boosted), - KEY_COLOR_MODE_BOOSTED, enabled), + KEY_COLOR_MODE_BOOSTED, true /* enabled */), new ColorModeCandidateInfo(c.getText(R.string.color_mode_option_saturated), - KEY_COLOR_MODE_SATURATED, enabled) + KEY_COLOR_MODE_SATURATED, true /* enabled */) ); } @@ -153,16 +150,10 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment @Override public void onAccessibilityTransformChanged(boolean state) { - // Disable controls when a11y transforms are enabled, and vice versa - final PreferenceScreen screen = getPreferenceScreen(); - if (screen != null) { - final int count = screen.getPreferenceCount(); - for (int i = 0; i < count; i++) { - final Preference pref = screen.getPreference(i); - if (pref instanceof RadioButtonPreference) { - pref.setEnabled(!state); - } - } + // Color modes are no not configurable when Accessibility transforms are enabled. Close + // this fragment in that case. + if (state) { + getActivity().onBackPressed(); } } } diff --git a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java index a9f4151d226..4264daa2835 100644 --- a/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/display/ColorModePreferenceFragmentTest.java @@ -16,7 +16,6 @@ package com.android.settings.display; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; @@ -25,6 +24,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.Activity; import android.os.Bundle; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; @@ -34,7 +34,6 @@ import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.applications.LayoutPreference; import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.widget.RadioButtonPreference; import com.android.settingslib.widget.CandidateInfo; import org.junit.Before; @@ -46,7 +45,6 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.util.ReflectionHelpers; -import java.util.ArrayList; import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) @@ -58,13 +56,13 @@ public class ColorModePreferenceFragmentTest { private ColorDisplayController mController; @Mock - private PreferenceScreen mScreen; + private Activity mActivity; @Before public void setup() { MockitoAnnotations.initMocks(this); - mFragment = spy(new ColorModePreferenceFragmentTestable(mScreen)); + mFragment = spy(new ColorModePreferenceFragment()); ReflectionHelpers.setField(mFragment, "mController", mController); } @@ -159,50 +157,8 @@ public class ColorModePreferenceFragmentTest { @Test public void onAccessibilityTransformChanged_toggles() { - final int radioPrefsCount = 3; - List radioPrefs = new ArrayList<>(); - for (int i = 0; i < radioPrefsCount; i++) { - radioPrefs.add(mock(RadioButtonPreference.class)); - } - - when(mScreen.getPreferenceCount()).thenReturn(radioPrefs.size()); - when(mScreen.getPreference(anyInt())).thenAnswer(invocation -> { - final Object[] args = invocation.getArguments(); - return radioPrefs.get((int) args[0]); - }); - + when(mFragment.getActivity()).thenReturn(mActivity); mFragment.onAccessibilityTransformChanged(true /* state */); - for (int i = 0; i < radioPrefsCount; i++) { - verify(radioPrefs.get(i)).setEnabled(false); - } - - mFragment.onAccessibilityTransformChanged(false /* state */); - for (int i = 0; i < radioPrefsCount; i++) { - verify(radioPrefs.get(i)).setEnabled(true); - } - } - - private static class ColorModePreferenceFragmentTestable - extends ColorModePreferenceFragment { - - private final PreferenceScreen mPreferenceScreen; - - private ColorModePreferenceFragmentTestable(PreferenceScreen screen) { - mPreferenceScreen = screen; - } - - /** - * A method to return a mock PreferenceScreen. - * A real ColorModePreferenceFragment calls super.getPreferenceScreen() to get its - * PreferenceScreen handle, which internally dereferenced a PreferenceManager. But in this - * test scenario, the PreferenceManager object is uninitialized, so we need to supply the - * PreferenceScreen directly. - * - * @return a mock PreferenceScreen - */ - @Override - public PreferenceScreen getPreferenceScreen() { - return mPreferenceScreen; - } + verify(mActivity).onBackPressed(); } } From af6fa02810466c92c9b7d17f8200550bcfdf7adc Mon Sep 17 00:00:00 2001 From: hughchen Date: Tue, 10 Apr 2018 17:10:45 +0800 Subject: [PATCH 12/17] Change string * Change "Available media devices" to "Available devices" Bug: 77607383 Test: build Change-Id: I49cb6c3269eb3847a92403184e2691f7334df96e --- res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 26210d9f48a..c4607c08690 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1592,7 +1592,7 @@ Paired devices - Available media devices + Available devices No devices available From 4b8fe09d72417f41c864989a19b5b76087d0734d Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Mon, 9 Apr 2018 15:24:55 -0400 Subject: [PATCH 13/17] Add zen onboarding screen Bug: 77658931 Test: make -j RunSettingsRoboTests Change-Id: Ifc886148ed742d72b5606a9ce7eb19d0da234c9e --- AndroidManifest.xml | 18 ++ res/layout/zen_onboarding.xml | 167 +++++++++++++ res/values/strings.xml | 10 + .../notification/ZenOnboardingActivity.java | 106 +++++++++ .../ZenOnboardingActivityTest.java | 222 ++++++++++++++++++ 5 files changed, 523 insertions(+) create mode 100644 res/layout/zen_onboarding.xml create mode 100644 src/com/android/settings/notification/ZenOnboardingActivity.java create mode 100644 tests/robotests/src/com/android/settings/notification/ZenOnboardingActivityTest.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1a0c3a1fd73..5a2e01a8163 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -742,12 +742,30 @@ android:exported="true" android:taskAffinity="com.android.settings" android:parentActivityName="Settings"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +