From 3737da3ae6a3bbc045d86c44bf54f24eb7d08a10 Mon Sep 17 00:00:00 2001 From: Kiyoung Kim Date: Tue, 22 Jan 2019 10:19:29 +0900 Subject: [PATCH 01/19] Schematize Crypto system properties Properties accessed across partitions are now schematized and will become APIs to make explicit interfaces among partitions. Bug: 117924132 Test: m -j Change-Id: I65a6ce1a682687702f4c8b5c2e054eaaf91c389b --- .../FileEncryptionPreferenceController.java | 9 ++------- .../FileEncryptionPreferenceControllerTest.java | 10 +++------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/com/android/settings/development/FileEncryptionPreferenceController.java b/src/com/android/settings/development/FileEncryptionPreferenceController.java index a0628b0f637..8aadfb95e43 100644 --- a/src/com/android/settings/development/FileEncryptionPreferenceController.java +++ b/src/com/android/settings/development/FileEncryptionPreferenceController.java @@ -19,10 +19,9 @@ package com.android.settings.development; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; import android.os.storage.IStorageManager; import android.text.TextUtils; - +import android.sysprop.CryptoProperties; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; @@ -36,9 +35,6 @@ public class FileEncryptionPreferenceController extends DeveloperOptionsPreferen private static final String KEY_CONVERT_FBE = "convert_to_file_encryption"; private static final String KEY_STORAGE_MANAGER = "mount"; - @VisibleForTesting - static final String FILE_ENCRYPTION_PROPERTY_KEY = "ro.crypto.type"; - private final IStorageManager mStorageManager; public FileEncryptionPreferenceController(Context context) { @@ -67,8 +63,7 @@ public class FileEncryptionPreferenceController extends DeveloperOptionsPreferen @Override public void updateState(Preference preference) { - if (!TextUtils.equals("file", - SystemProperties.get(FILE_ENCRYPTION_PROPERTY_KEY, "none" /* default */))) { + if (!TextUtils.equals("file", CryptoProperties.type().orElse("none"))) { return; } diff --git a/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java index 68cbd320303..61e650f2b3c 100644 --- a/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java @@ -16,9 +16,6 @@ package com.android.settings.development; -import static com.android.settings.development.FileEncryptionPreferenceController - .FILE_ENCRYPTION_PROPERTY_KEY; - import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -29,9 +26,8 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.RemoteException; -import android.os.SystemProperties; import android.os.storage.IStorageManager; - +import android.sysprop.CryptoProperties; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; @@ -96,7 +92,7 @@ public class FileEncryptionPreferenceControllerTest { ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager); when(mStorageManager.isConvertibleToFBE()).thenReturn(true); mController.displayPreference(mPreferenceScreen); - SystemProperties.set(FILE_ENCRYPTION_PROPERTY_KEY, "foobar"); + CryptoProperties.type("foobar"); mController.updateState(mPreference); @@ -110,7 +106,7 @@ public class FileEncryptionPreferenceControllerTest { ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager); when(mStorageManager.isConvertibleToFBE()).thenReturn(true); mController.displayPreference(mPreferenceScreen); - SystemProperties.set(FILE_ENCRYPTION_PROPERTY_KEY, "file"); + CryptoProperties.type("file"); mController.updateState(mPreference); From 896cfd538cac78c66db18cf722ef2e122482f18f Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Wed, 23 Jan 2019 15:43:35 -0800 Subject: [PATCH 02/19] AccessPoint: App attribution for suggestion/specifier Bug: 115504887 Bug: 113878056 Test: atest AccessPointTest WifiTrackerTest Test: Manual UI verification Change-Id: I104fb6f428e66ab15ab1e0d0358da39652c28115 --- .../android/settings/wifi/WifiConfigController.java | 10 +++++++++- src/com/android/settings/wifi/WifiStatusTest.java | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index b0d09e4c12a..7bdd77ca67c 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -355,8 +355,16 @@ public class WifiConfigController implements TextWatcher, if (config != null && config.isPasspoint()) { providerFriendlyName = config.providerFriendlyName; } + String suggestionOrSpecifierPackageName = null; + if (config != null + && (config.fromWifiNetworkSpecifier + || config.fromWifiNetworkSuggestion)) { + suggestionOrSpecifierPackageName = config.creatorName; + } String summary = AccessPoint.getSummary( - mConfigUi.getContext(), state, isEphemeral, providerFriendlyName); + mConfigUi.getContext(), state, isEphemeral, + suggestionOrSpecifierPackageName, + providerFriendlyName); addRow(group, R.string.wifi_status, summary); } diff --git a/src/com/android/settings/wifi/WifiStatusTest.java b/src/com/android/settings/wifi/WifiStatusTest.java index 6c1a3fc7865..b06343331f3 100644 --- a/src/com/android/settings/wifi/WifiStatusTest.java +++ b/src/com/android/settings/wifi/WifiStatusTest.java @@ -299,7 +299,7 @@ public class WifiStatusTest extends Activity { WifiInfo info = mWifiManager.getConnectionInfo(); String summary = AccessPoint.getSummary(this, info.getSSID(), networkInfo.getDetailedState(), - info.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID, null); + info.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID, null, null); mNetworkState.setText(summary); } } From bcea263865044cc9a45497a311a792bfeffa2aa9 Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Fri, 25 Jan 2019 12:14:34 -0800 Subject: [PATCH 03/19] Use role for App info default phone shortcut. This change makes the default phone shortcut in App info launch the new default app UI based on roles, since we've migrated default dialer mechanism. Bug: 110557011 Test: atest DefaultAppShortcutPreferenceControllerBaseTest Change-Id: I3c2ac05386b46e574399f453c2869d1aca952332 --- ...aultPhoneShortcutPreferenceController.java | 16 +---- ...PhoneShortcutPreferenceControllerTest.java | 63 ++++--------------- 2 files changed, 14 insertions(+), 65 deletions(-) diff --git a/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceController.java b/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceController.java index c968d5530c0..c19c3676bb6 100644 --- a/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceController.java @@ -14,27 +14,15 @@ package com.android.settings.applications.appinfo; +import android.app.role.RoleManager; import android.content.Context; -import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController; - public class DefaultPhoneShortcutPreferenceController extends DefaultAppShortcutPreferenceControllerBase { private static final String KEY = "default_phone_app"; public DefaultPhoneShortcutPreferenceController(Context context, String packageName) { - super(context, KEY, packageName); + super(context, KEY, RoleManager.ROLE_DIALER, packageName); } - - @Override - protected boolean hasAppCapability() { - return DefaultPhonePreferenceController.hasPhonePreference(mPackageName, mContext); - } - - @Override - protected boolean isDefaultApp() { - return DefaultPhonePreferenceController.isPhoneDefault(mPackageName, mContext); - } - } diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java index bdb7ba338cb..4e7a80028f0 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/DefaultPhoneShortcutPreferenceControllerTest.java @@ -18,13 +18,8 @@ package com.android.settings.applications.appinfo; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - import android.content.Context; -import android.content.pm.PackageManager; - -import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController; +import android.permission.PermissionControllerManager; import org.junit.Before; import org.junit.Test; @@ -33,64 +28,30 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; -import org.robolectric.annotation.Implementation; -import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowApplication; @RunWith(RobolectricTestRunner.class) public class DefaultPhoneShortcutPreferenceControllerTest { - @Mock - private PackageManager mPackageManager; + private static final String TEST_PACKAGE_NAME = "TestPackage"; + private static final String PREFERENCE_KEY = "default_phone_app"; + + @Mock + private PermissionControllerManager mPermissionControllerManager; - private Context mContext; private DefaultPhoneShortcutPreferenceController mController; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); - when(mContext.getPackageManager()).thenReturn(mPackageManager); - mController = new DefaultPhoneShortcutPreferenceController(mContext, "Package1"); + ShadowApplication.getInstance().setSystemService(Context.PERMISSION_CONTROLLER_SERVICE, + mPermissionControllerManager); + mController = new DefaultPhoneShortcutPreferenceController(RuntimeEnvironment.application, + TEST_PACKAGE_NAME); } @Test public void getPreferenceKey_shouldReturnDefaultPhone() { - assertThat(mController.getPreferenceKey()).isEqualTo("default_phone_app"); - } - - @Test - @Config(shadows = ShadowDefaultPhonePreferenceController.class) - public void hasAppCapability_hasPhoneCapability_shouldReturnTrue() { - assertThat(mController.hasAppCapability()).isTrue(); - } - - @Test - public void hasAppCapability_noPhoneCapability_shouldReturnFalse() { - assertThat(mController.hasAppCapability()).isFalse(); - } - - @Test - @Config(shadows = ShadowDefaultPhonePreferenceController.class) - public void isDefaultApp_isDefaultPhone_shouldReturnTrue() { - assertThat(mController.isDefaultApp()).isTrue(); - } - - @Test - public void isDefaultApp_notDefaultPhone_shouldReturnFalse() { - assertThat(mController.isDefaultApp()).isFalse(); - } - - @Implements(DefaultPhonePreferenceController.class) - public static class ShadowDefaultPhonePreferenceController { - @Implementation - protected static boolean hasPhonePreference(String pkg, Context context) { - return true; - } - - @Implementation - protected static boolean isPhoneDefault(String pkg, Context context) { - return true; - } + assertThat(mController.getPreferenceKey()).isEqualTo(PREFERENCE_KEY); } } From 64328862bd6e89b9e30852ed7469b6b6f91d3090 Mon Sep 17 00:00:00 2001 From: Oscar Shu Date: Fri, 25 Jan 2019 01:16:29 +0000 Subject: [PATCH 04/19] Revert "Wifi MAC Randomization: Developer Options" This reverts commit 8c6d8daaf00f80344336ea8181d7e84a38486252. Reason for revert: Bug: 123408542 Test: unit tests Test: Manual test to verify dev option is gone Change-Id: Iae667a331b5d4fb4cb6fe07077eb9f3954f3089e --- res/values/config.xml | 4 - res/xml/development_settings.xml | 5 - .../DevelopmentSettingsDashboardFragment.java | 1 - ...dMacRandomizationPreferenceController.java | 80 ----------- .../wifi/WifiInfoPreferenceController.java | 7 +- tests/robotests/res/values-mcc999/config.xml | 1 - tests/robotests/res/values/config.xml | 1 - ...RandomizationPreferenceControllerTest.java | 124 ------------------ .../WifiInfoPreferenceControllerTest.java | 44 ++++--- 9 files changed, 31 insertions(+), 236 deletions(-) delete mode 100644 src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceController.java delete mode 100644 tests/robotests/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceControllerTest.java diff --git a/res/values/config.xml b/res/values/config.xml index a6e5e1ce332..529332b5559 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -41,10 +41,6 @@ false - - false - com.android.settings.overlay.FeatureFactoryImpl diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml index 6d22a1d1480..2c0a759dbfd 100644 --- a/res/xml/development_settings.xml +++ b/res/xml/development_settings.xml @@ -221,11 +221,6 @@ android:title="@string/wifi_verbose_logging" android:summary="@string/wifi_verbose_logging_summary" /> - - false false false - false false false false diff --git a/tests/robotests/res/values/config.xml b/tests/robotests/res/values/config.xml index 1252ecef048..15ae89927f1 100644 --- a/tests/robotests/res/values/config.xml +++ b/tests/robotests/res/values/config.xml @@ -20,7 +20,6 @@ true true true - true diff --git a/tests/robotests/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceControllerTest.java deleted file mode 100644 index 60e7d47feea..00000000000 --- a/tests/robotests/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceControllerTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2017 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.development; - -import static com.android.settings.development.WifiConnectedMacRandomizationPreferenceController - .SETTING_VALUE_OFF; -import static com.android.settings.development.WifiConnectedMacRandomizationPreferenceController - .SETTING_VALUE_ON; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.provider.Settings; - -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -@RunWith(RobolectricTestRunner.class) -public class WifiConnectedMacRandomizationPreferenceControllerTest { - - @Mock - private PreferenceScreen mPreferenceScreen; - - private Context mContext; - private SwitchPreference mPreference; - private WifiConnectedMacRandomizationPreferenceController mController; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - mController = new WifiConnectedMacRandomizationPreferenceController(mContext); - mPreference = new SwitchPreference(mContext); - when(mPreferenceScreen.findPreference(mController.getPreferenceKey())) - .thenReturn(mPreference); - mController.displayPreference(mPreferenceScreen); - } - - @Test - public void isAvailable_trueSupportFlag_shouldReturnTrue() { - assertThat(mController.isAvailable()).isTrue(); - } - - @Test - @Config(qualifiers = "mcc999") - public void isAvailable_falseSupportFlag_shouldReturnFalse() { - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void onPreferenceChange_settingEnabled_shouldEnableConnectedMacRandomization() { - mController.onPreferenceChange(mPreference, true /* new value */); - - final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */); - - assertThat(mode).isEqualTo(SETTING_VALUE_ON); - } - - @Test - public void onPreferenceChange_settingDisabled_shouldDisableConnectedMacRandomization() { - mController.onPreferenceChange(mPreference, false /* new value */); - - final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */); - - assertThat(mode).isEqualTo(SETTING_VALUE_OFF); - } - - @Test - public void updateState_settingEnabled_shouldEnablePreference() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_ON); - mController.updateState(mPreference); - - assertThat(mPreference.isChecked()).isTrue(); - } - - @Test - public void updateState_settingDisabled_shouldDisablePreference() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_OFF); - mController.updateState(mPreference); - - assertThat(mPreference.isChecked()).isFalse(); - } - - @Test - public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() { - mController.onDeveloperOptionsSwitchDisabled(); - - final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */); - - assertThat(mode).isEqualTo(SETTING_VALUE_OFF); - assertThat(mPreference.isChecked()).isFalse(); - assertThat(mPreference.isEnabled()).isFalse(); - } -} diff --git a/tests/robotests/src/com/android/settings/wifi/WifiInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiInfoPreferenceControllerTest.java index c4a5c787d8f..85d7726ee66 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiInfoPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiInfoPreferenceControllerTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.when; import android.content.BroadcastReceiver; import android.content.Context; import android.content.IntentFilter; +import android.content.res.Resources; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.provider.Settings; @@ -65,6 +66,8 @@ public class WifiInfoPreferenceControllerTest { private Preference mMacPreference; @Mock private WifiInfo mWifiInfo; + @Mock + private Resources mResources; private Lifecycle mLifecycle; private LifecycleOwner mLifecycleOwner; @@ -82,6 +85,7 @@ public class WifiInfoPreferenceControllerTest { .thenReturn(mIpPreference); when(mWifiManager.getConnectionInfo()).thenReturn(mWifiInfo); when(mWifiManager.getCurrentNetwork()).thenReturn(null); + when(mContext.getResources()).thenReturn(mResources); mController = new WifiInfoPreferenceController(mContext, mLifecycle, mWifiManager); } @@ -117,8 +121,9 @@ public class WifiInfoPreferenceControllerTest { @Test public void updateWifiInfo_nullWifiInfoWithMacRandomizationOff_setMacUnavailable() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 0); + when(mResources.getBoolean( + com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) + .thenReturn(false); mController.displayPreference(mScreen); when(mWifiManager.getConnectionInfo()).thenReturn(null); @@ -129,8 +134,9 @@ public class WifiInfoPreferenceControllerTest { @Test public void updateWifiInfo_nullMacWithMacRandomizationOff_setMacUnavailable() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 0); + when(mResources.getBoolean( + com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) + .thenReturn(false); mController.displayPreference(mScreen); when(mWifiInfo.getMacAddress()).thenReturn(null); @@ -141,8 +147,9 @@ public class WifiInfoPreferenceControllerTest { @Test public void updateWifiInfo_defaultMacWithMacRandomizationOff_setMacUnavailable() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 0); + when(mResources.getBoolean( + com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) + .thenReturn(false); mController.displayPreference(mScreen); when(mWifiInfo.getMacAddress()).thenReturn(WifiInfo.DEFAULT_MAC_ADDRESS); @@ -153,8 +160,9 @@ public class WifiInfoPreferenceControllerTest { @Test public void updateWifiInfo_validMacWithMacRandomizationOff_setValidMac() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 0); + when(mResources.getBoolean( + com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) + .thenReturn(false); mController.displayPreference(mScreen); when(mWifiInfo.getMacAddress()).thenReturn(TEST_MAC_ADDRESS); @@ -165,8 +173,9 @@ public class WifiInfoPreferenceControllerTest { @Test public void updateWifiInfo_nullWifiInfoWithMacRandomizationOn_setMacUnavailable() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 1); + when(mResources.getBoolean( + com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) + .thenReturn(true); mController.displayPreference(mScreen); when(mWifiManager.getConnectionInfo()).thenReturn(null); @@ -177,8 +186,9 @@ public class WifiInfoPreferenceControllerTest { @Test public void updateWifiInfo_nullMacWithMacRandomizationOn_setMacUnavailable() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 1); + when(mResources.getBoolean( + com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) + .thenReturn(true); mController.displayPreference(mScreen); when(mWifiInfo.getMacAddress()).thenReturn(null); @@ -189,8 +199,9 @@ public class WifiInfoPreferenceControllerTest { @Test public void updateWifiInfo_defaultMacWithMacRandomizationOn_setMacRandomized() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 1); + when(mResources.getBoolean( + com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) + .thenReturn(true); mController.displayPreference(mScreen); when(mWifiInfo.getMacAddress()).thenReturn(WifiInfo.DEFAULT_MAC_ADDRESS); @@ -201,8 +212,9 @@ public class WifiInfoPreferenceControllerTest { @Test public void updateWifiInfo_validMacWithMacRandomizationOn_setValidMac() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, 1); + when(mResources.getBoolean( + com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) + .thenReturn(true); mController.displayPreference(mScreen); when(mWifiInfo.getMacAddress()).thenReturn(TEST_MAC_ADDRESS); From 0bfef6381211ecc2b42bd6f6be412f9e89cce4cd Mon Sep 17 00:00:00 2001 From: Chandan Nath Date: Mon, 28 Jan 2019 21:15:13 +0000 Subject: [PATCH 05/19] [Multi-user] Change Backup Settings page to support multi-user. With multi-user backup, backup will be available or secondary users and profiles too. 1. When there are profile users, this CL changes UI flow A to B A. Settings Homepage -> System -> Google Backup Settings for primary user to B. Settings Homepage -> System -> Profile Select Dialog -> Google Backup Settings for chosen profile. Change done as per https://g3doc.corp.google.com/company/teams/apps-android-settings/howto/ia.md?cl=head 2. Functionality remains the same when there are no profiles (BackupSettingsHelper, BackupSettingsContentProvider) 3. Also, enabled Backup Settings for secondary users. (Previously, backup settings were only shown for system user).(SettingsGateway) Bug: 121198738 Test: 1) System -> Backup -> shows Profile Select Dialog -> Backup page for selected profile 2) On secondary user without profile, System -> Backup (with summary) -> Backup page for secondary user. Change-Id: I6e21279978a5dfc6eca6f5a34bbfc15a34eac68b --- AndroidManifest.xml | 26 +++-- res/xml/system_dashboard_fragment.xml | 11 -- .../android/settings/SettingsActivity.java | 6 - ...pSettingsActivityPreferenceController.java | 54 --------- .../backup/BackupSettingsContentProvider.java | 78 +++++++++++++ .../backup/BackupSettingsFragment.java | 2 +- .../settings/backup/BackupSettingsHelper.java | 21 +++- ...y.java => UserBackupSettingsActivity.java} | 26 ++--- .../core/gateway/SettingsGateway.java | 2 + ...tingsActivityPreferenceControllerTest.java | 110 ------------------ .../backup/BackupSettingsHelperTest.java | 41 ++++++- ...va => UserBackupSettingsActivityTest.java} | 34 ++---- .../settings/backup/BackupIntentTest.java | 17 +-- 13 files changed, 179 insertions(+), 249 deletions(-) delete mode 100644 src/com/android/settings/backup/BackupSettingsActivityPreferenceController.java create mode 100644 src/com/android/settings/backup/BackupSettingsContentProvider.java rename src/com/android/settings/backup/{BackupSettingsActivity.java => UserBackupSettingsActivity.java} (84%) delete mode 100644 tests/robotests/src/com/android/settings/backup/BackupSettingsActivityPreferenceControllerTest.java rename tests/robotests/src/com/android/settings/backup/{BackupSettingsActivityTest.java => UserBackupSettingsActivityTest.java} (82%) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a12c9825111..ee301519321 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2777,13 +2777,17 @@ android:value="com.android.settings.webview.WebViewAppPicker" /> - + + + + android:icon="@drawable/ic_settings_backup"> - @@ -2791,10 +2795,16 @@ - - + + + + + + + + - - - - - getNonIndexableKeys(Context context) { - final List keys = super.getNonIndexableKeys(context); - - // For non-primary user, no backup is available, so don't show it in search - // TODO: http://b/22388012 - if (UserHandle.myUserId() != UserHandle.USER_SYSTEM) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Not a system user, not indexing the screen"); - } - keys.add(BACKUP_SEARCH_INDEX_KEY); - } - - return keys; - } }; @VisibleForTesting diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index 7ba36887c4d..bb292a154f2 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -49,6 +49,7 @@ import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminSe import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureDetails; import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureSettings; import com.android.settings.applications.specialaccess.vrlistener.VrListenerSettings; +import com.android.settings.backup.UserBackupSettingsActivity; import com.android.settings.backup.PrivacySettings; import com.android.settings.backup.ToggleBackupSettingFragment; import com.android.settings.biometrics.face.FaceSettings; @@ -298,5 +299,6 @@ public class SettingsGateway { Settings.DateTimeSettingsActivity.class.getName(), Settings.EnterprisePrivacySettingsActivity.class.getName(), Settings.MyDeviceInfoActivity.class.getName(), + UserBackupSettingsActivity.class.getName(), }; } diff --git a/tests/robotests/src/com/android/settings/backup/BackupSettingsActivityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/backup/BackupSettingsActivityPreferenceControllerTest.java deleted file mode 100644 index 97ddc4bc1ad..00000000000 --- a/tests/robotests/src/com/android/settings/backup/BackupSettingsActivityPreferenceControllerTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2017 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.backup; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.verify; - -import android.app.backup.BackupManager; -import android.content.Context; -import android.os.UserManager; - -import androidx.preference.Preference; - -import com.android.settings.R; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.shadow.api.Shadow; -import org.robolectric.shadows.ShadowApplication; -import org.robolectric.shadows.ShadowUserManager; - -@RunWith(RobolectricTestRunner.class) -public class BackupSettingsActivityPreferenceControllerTest { - - private static final String KEY_BACKUP_SETTINGS = "backup_settings"; - - private Context mContext; - private BackupManager mBackupManager; - private UserManager mUserManager; - - @Mock - private Preference mBackupPreference; - - private BackupSettingsActivityPreferenceController mController; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mContext = RuntimeEnvironment.application; - mBackupManager = new BackupManager(mContext); - - final ShadowApplication shadowApplication = ShadowApplication.getInstance(); - shadowApplication.grantPermissions(android.Manifest.permission.BACKUP); - shadowApplication.setSystemService(Context.BACKUP_SERVICE, mBackupManager); - - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - - mController = new BackupSettingsActivityPreferenceController(mContext, KEY_BACKUP_SETTINGS); - } - - @Test - public void updateState_backupOn() { - mBackupManager.setBackupEnabled(true); - - mController.updateState(mBackupPreference); - String summaryString = mContext.getString(R.string.backup_summary_state_on); - verify(mBackupPreference).setSummary(summaryString); - } - - @Test - public void updateState_backupOff() { - mBackupManager.setBackupEnabled(false); - - mController.updateState(mBackupPreference); - String summaryString = mContext.getString(R.string.backup_summary_state_off); - verify(mBackupPreference).setSummary(summaryString); - } - - @Test - public void isAvailable_systemUser() { - final ShadowUserManager sum = Shadow.extract(mUserManager); - sum.setIsAdminUser(true); - - assertThat(mController.isAvailable()).isTrue(); - } - - @Test - public void isAvailable_nonSystemUser() { - final ShadowUserManager sum = Shadow.extract(mUserManager); - sum.setIsAdminUser(false); - - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void getPreferenceKey() { - assertThat(mController.getPreferenceKey()).isEqualTo(KEY_BACKUP_SETTINGS); - } -} diff --git a/tests/robotests/src/com/android/settings/backup/BackupSettingsHelperTest.java b/tests/robotests/src/com/android/settings/backup/BackupSettingsHelperTest.java index 9a809cc7ba2..ee8912af56f 100644 --- a/tests/robotests/src/com/android/settings/backup/BackupSettingsHelperTest.java +++ b/tests/robotests/src/com/android/settings/backup/BackupSettingsHelperTest.java @@ -31,12 +31,16 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.content.res.Resources; import android.os.IBinder; import android.os.RemoteException; +import android.os.UserHandle; +import android.os.UserManager; import com.android.settings.R; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -47,11 +51,12 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowUserManager; @RunWith(RobolectricTestRunner.class) @Config(shadows = BackupSettingsHelperTest.ShadowBackupManagerStub.class) public class BackupSettingsHelperTest { - private static final String DEFAULT_SETTINGS_CLASSNAME = "com.android.settings.Settings$PrivacySettingsActivity"; @@ -72,12 +77,46 @@ public class BackupSettingsHelperTest { @Mock private static IBackupManager mBackupManager; + private ShadowUserManager mUserManager; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application.getApplicationContext()); when(mBackupManager.getCurrentTransport()).thenReturn("test_transport"); mBackupSettingsHelper = new BackupSettingsHelper(mContext); + mUserManager = Shadow.extract(mContext.getSystemService(Context.USER_SERVICE)); + } + + @Test + public void testGetSummary_backupEnabledOnlyOneProfile_showsOn() throws Exception { + mUserManager.addUserProfile(new UserHandle(0)); + when(mBackupManager.isBackupEnabled()).thenReturn(true); + + String backupSummary = mBackupSettingsHelper.getSummary(); + + assertThat(backupSummary).isEqualTo(mContext.getString(R.string.backup_summary_state_on)); + } + + @Test + public void testGetSummary_backupDisabledOnlyOneProfile_showsOff() throws Exception { + mUserManager.addUserProfile(new UserHandle(0)); + when(mBackupManager.isBackupEnabled()).thenReturn(false); + + String backupSummary = mBackupSettingsHelper.getSummary(); + + assertThat(backupSummary).isEqualTo(mContext.getString(R.string.backup_summary_state_off)); + } + + @Test + public void testGetSummary_TwoProfiles_returnsNull() throws Exception { + mUserManager.addUserProfile(new UserHandle(0)); + mUserManager.addUserProfile(new UserHandle(10)); + when(mBackupManager.isBackupEnabled()).thenReturn(true); + + String backupSummary = mBackupSettingsHelper.getSummary(); + + assertThat(backupSummary).isNull(); } @Test diff --git a/tests/robotests/src/com/android/settings/backup/BackupSettingsActivityTest.java b/tests/robotests/src/com/android/settings/backup/UserBackupSettingsActivityTest.java similarity index 82% rename from tests/robotests/src/com/android/settings/backup/BackupSettingsActivityTest.java rename to tests/robotests/src/com/android/settings/backup/UserBackupSettingsActivityTest.java index 931bc1e7ee0..19a6051f143 100644 --- a/tests/robotests/src/com/android/settings/backup/BackupSettingsActivityTest.java +++ b/tests/robotests/src/com/android/settings/backup/UserBackupSettingsActivityTest.java @@ -35,8 +35,6 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; -import com.android.settings.search.SearchIndexableRaw; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -54,14 +52,12 @@ import org.robolectric.annotation.Implements; import org.robolectric.annotation.Resetter; import org.robolectric.shadows.ShadowPackageManager; -import java.util.List; - @RunWith(RobolectricTestRunner.class) -@Config(shadows = {BackupSettingsActivityTest.ShadowBackupSettingsHelper.class, - BackupSettingsActivityTest.ShadowUserHandle.class}) -public class BackupSettingsActivityTest { - private ActivityController mActivityController; - private BackupSettingsActivity mActivity; +@Config(shadows = {UserBackupSettingsActivityTest.ShadowBackupSettingsHelper.class, + UserBackupSettingsActivityTest.ShadowUserHandle.class}) +public class UserBackupSettingsActivityTest { + private ActivityController mActivityController; + private UserBackupSettingsActivity mActivity; private Application mApplication; private ShadowPackageManager mPackageManager; private static boolean mIsBackupProvidedByOEM; @@ -81,7 +77,7 @@ public class BackupSettingsActivityTest { MockitoAnnotations.initMocks(this); mApplication = RuntimeEnvironment.application; - mActivityController = Robolectric.buildActivity(BackupSettingsActivity.class); + mActivityController = Robolectric.buildActivity(UserBackupSettingsActivity.class); mActivity = mActivityController.get(); mPackageManager = Shadows.shadowOf(mApplication.getPackageManager()); when(mIntent.getComponent()).thenReturn(mComponent); @@ -130,9 +126,9 @@ public class BackupSettingsActivityTest { @Test public void getNonIndexableKeys_SystemUser() { - assertThat(BackupSettingsActivity.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex( + assertThat(UserBackupSettingsActivity.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex( mApplication, true)).isNotEmpty(); - assertThat(BackupSettingsActivity.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( + assertThat(UserBackupSettingsActivity.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( mApplication)).isEmpty(); } @@ -140,16 +136,10 @@ public class BackupSettingsActivityTest { public void getNonIndexableKeys_NonSystemUser() { ShadowUserHandle.setUid(1); // Non-SYSTEM user. - final List indexableRaws = - BackupSettingsActivity.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex( - mApplication, true); - final List nonIndexableKeys = - BackupSettingsActivity.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( - mApplication); - - assertThat(indexableRaws).isNotNull(); - assertThat(indexableRaws).isNotEmpty(); - assertThat(nonIndexableKeys).isNotEmpty(); + assertThat(UserBackupSettingsActivity.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex( + mApplication, true)).isNotEmpty(); + assertThat(UserBackupSettingsActivity.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys( + mApplication)).isEmpty(); } @Implements(BackupSettingsHelper.class) diff --git a/tests/unit/src/com/android/settings/backup/BackupIntentTest.java b/tests/unit/src/com/android/settings/backup/BackupIntentTest.java index 18fb17a59a0..0115c569aef 100644 --- a/tests/unit/src/com/android/settings/backup/BackupIntentTest.java +++ b/tests/unit/src/com/android/settings/backup/BackupIntentTest.java @@ -37,12 +37,9 @@ import java.util.List; @RunWith(AndroidJUnit4.class) @SmallTest public class BackupIntentTest { - private static final String INTENT_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; - private static final String INTENT_BACKUP_SETTINGS = - "android.settings.BACKUP_AND_RESET_SETTINGS"; private static final String BACKUP_SETTINGS_ACTIVITY = - "com.android.settings.backup.BackupSettingsActivity"; + "com.android.settings.backup.UserBackupSettingsActivity"; private Context mContext; @@ -52,17 +49,6 @@ public class BackupIntentTest { mContext = instrumentation.getTargetContext(); } - @Test - public void testBackupSettingsIntentResolvesToOnlyOneActivity(){ - PackageManager pm = mContext.getPackageManager(); - Intent intent = new Intent(INTENT_BACKUP_SETTINGS); - List activities = pm.queryIntentActivities(intent, 0); - assertThat(activities).isNotNull(); - assertThat(activities.size()).isEqualTo(1); - assertThat(activities.get(0).activityInfo.getComponentName().getClassName()). - isEqualTo(BACKUP_SETTINGS_ACTIVITY); - } - @Test public void testPrivacySettingsIntentResolvesToOnlyOneActivity(){ PackageManager pm = mContext.getPackageManager(); @@ -73,5 +59,4 @@ public class BackupIntentTest { assertThat(activities.get(0).activityInfo.getComponentName().getClassName()). isEqualTo(BACKUP_SETTINGS_ACTIVITY); } - } From 7818363e718f2ab1a4f73e466e3bd0f5969a1238 Mon Sep 17 00:00:00 2001 From: lesl Date: Wed, 2 Jan 2019 18:26:46 +0800 Subject: [PATCH 06/19] Use API to get necessary value when activity init Framework change intent design from sticky to non-sticky due to location sensitive data protect. Use APIs to get information when activity resume. Intents from sticy to non-sticy: WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION WifiP2pManager#WIFI_P2P_THIS_DEVICE_CHANGED_ACTION Bug: 77228252 Test: Manually test Wi-Fi Direct settings Change-Id: I115515d6832c5c5f290ef9f757ca94afa4e9f1bd --- .../settings/wifi/p2p/WifiP2pSettings.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java index d1500e7092e..1c1da38f696 100644 --- a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java +++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java @@ -85,6 +85,7 @@ public class WifiP2pSettings extends DashboardFragment private boolean mWifiP2pSearching; private int mConnectedDevices; private boolean mLastGroupFormed = false; + private boolean mIsIgnoreInitConnectionInfoCallback = false; private P2pPeerCategoryPreferenceController mPeerCategoryController; private P2pPersistentCategoryPreferenceController mPersistentCategoryController; @@ -131,6 +132,7 @@ public class WifiP2pSettings extends DashboardFragment startSearch(); } mLastGroupFormed = wifip2pinfo.groupFormed; + mIsIgnoreInitConnectionInfoCallback = true; } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) { mThisDevice = (WifiP2pDevice) intent.getParcelableExtra( WifiP2pManager.EXTRA_WIFI_P2P_DEVICE); @@ -338,6 +340,29 @@ public class WifiP2pSettings extends DashboardFragment getActivity().registerReceiver(mReceiver, mIntentFilter); if (mWifiP2pManager != null) { mWifiP2pManager.requestPeers(mChannel, WifiP2pSettings.this); + mWifiP2pManager.requestDeviceInfo(mChannel, wifiP2pDevice -> { + if (DBG) { + Log.d(TAG, "Get device info: " + wifiP2pDevice); + } + mThisDevice = wifiP2pDevice; + mThisDevicePreferenceController.updateDeviceName(wifiP2pDevice); + }); + mIsIgnoreInitConnectionInfoCallback = false; + mWifiP2pManager.requestNetworkInfo(mChannel, networkInfo -> { + mWifiP2pManager.requestConnectionInfo(mChannel, wifip2pinfo -> { + if (!mIsIgnoreInitConnectionInfoCallback) { + if (networkInfo.isConnected()) { + if (DBG) { + Log.d(TAG, "Connected"); + } + } else if (!mLastGroupFormed) { + // Find peers when p2p doesn't connected. + startSearch(); + } + mLastGroupFormed = wifip2pinfo.groupFormed; + } + }); + }); } } From 4ab826ac5b68d05ad5a1d495b81822fc1978e6af Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Thu, 24 Jan 2019 15:19:23 +0800 Subject: [PATCH 07/19] Set Wi-Fi DPP fragment icons. 1. set fragment icon for WifiDppChooseSavedWifiNetworkFragment 2. set fragment icon of success for WifiDppAddDeviceFragment All Wi-Fi DPP fragment icons are VectorDrawable of instinct size 24dp draw on a 48dp canvas. Except for ic_devices_check_circle_green, it's a LayerDrawable of different size. I dynamically change ImageView layout width & height between these 2 different kind of drawable. Bug: 122982132 Test: manual test Change-Id: Idab8cd8b0798363e447da00dc6bc68a86498b8be --- .../ic_devices_check_circle_green.xml | 30 +++++++++++++++++++ res/layout/wifi_dpp_fragment_header.xml | 12 ++++++-- res/values/dimens.xml | 3 ++ .../wifi/dpp/WifiDppAddDeviceFragment.java | 4 +-- ...WifiDppChooseSavedWifiNetworkFragment.java | 2 ++ .../wifi/dpp/WifiDppQrCodeBaseFragment.java | 19 +++++++++++- .../dpp/WifiDppQrCodeGeneratorFragment.java | 3 +- .../dpp/WifiDppQrCodeScannerFragment.java | 2 +- 8 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 res/drawable/ic_devices_check_circle_green.xml diff --git a/res/drawable/ic_devices_check_circle_green.xml b/res/drawable/ic_devices_check_circle_green.xml new file mode 100644 index 00000000000..71c683b3021 --- /dev/null +++ b/res/drawable/ic_devices_check_circle_green.xml @@ -0,0 +1,30 @@ + + + + + + + diff --git a/res/layout/wifi_dpp_fragment_header.xml b/res/layout/wifi_dpp_fragment_header.xml index 20bcd7d77c3..e8e71d12b84 100644 --- a/res/layout/wifi_dpp_fragment_header.xml +++ b/res/layout/wifi_dpp_fragment_header.xml @@ -28,8 +28,16 @@ + + + 264dp 360dp + + 48dp + 360dp diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java index 52243d4b7cf..c5b570ff747 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java @@ -55,7 +55,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment { @Override public void onConfiguratorSuccess(int code) { // Update success UI. - mHeaderIcon.setImageResource(R.drawable.ic_check_circle_green); + setHeaderIconImageResource(R.drawable.ic_devices_check_circle_green); mTitle.setText(R.string.wifi_dpp_wifi_shared_with_device); mSummary.setVisibility(View.INVISIBLE); mWifiApPictureView.setImageResource(R.drawable.wifi_dpp_success); @@ -110,7 +110,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment { public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - mHeaderIcon.setImageResource(R.drawable.ic_devices_other_opaque_black); + setHeaderIconImageResource(R.drawable.ic_devices_other_opaque_black); final WifiQrCode wifiQrCode = ((WifiDppConfiguratorActivity) getActivity()) .getWifiDppQrCode(); diff --git a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java index 6a229a14468..682ebd45eb8 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java @@ -82,6 +82,8 @@ public class WifiDppChooseSavedWifiNetworkFragment extends WifiDppQrCodeBaseFrag public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + setHeaderIconImageResource(R.drawable.ic_wifi_signal_4); + mTitle.setText(R.string.wifi_dpp_choose_network); mSummary.setText(R.string.wifi_dpp_choose_network_to_connect_device); diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java index cd0db62e75e..fab495d6e8f 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java @@ -21,6 +21,7 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import com.android.settings.R; import com.android.settings.core.InstrumentedFragment; /** @@ -33,7 +34,8 @@ import com.android.settings.core.InstrumentedFragment; * {@code WifiDppAddDeviceFragment} */ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment { - protected ImageView mHeaderIcon; + private ImageView mHeaderIcon; + private ImageView mDevicesCheckCircleGreenHeaderIcon; protected TextView mTitle; protected TextView mSummary; @@ -42,7 +44,22 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment { super.onViewCreated(view, savedInstanceState); mHeaderIcon = view.findViewById(android.R.id.icon); + mDevicesCheckCircleGreenHeaderIcon = + view.findViewById(R.id.devices_check_circle_green_icon); mTitle = view.findViewById(android.R.id.title); mSummary = view.findViewById(android.R.id.summary); } + + protected void setHeaderIconImageResource(int resId) { + // ic_devices_check_circle_green is a LayerDrawable, + // it has different size from other VectorDrawable icons + if (resId == R.drawable.ic_devices_check_circle_green) { + mHeaderIcon.setVisibility(View.GONE); + mDevicesCheckCircleGreenHeaderIcon.setVisibility(View.VISIBLE); + } else { + mDevicesCheckCircleGreenHeaderIcon.setVisibility(View.GONE); + mHeaderIcon.setImageResource(resId); + mHeaderIcon.setVisibility(View.VISIBLE); + } + } } diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java index d0a96384d7c..2264ba6a1b9 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java @@ -124,7 +124,8 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment { mQrCodeView = view.findViewById(R.id.qrcode_view); - mHeaderIcon.setImageResource(R.drawable.ic_qrcode_24dp); + setHeaderIconImageResource(R.drawable.ic_qrcode_24dp); + final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity(); mTitle.setText(R.string.wifi_dpp_share_wifi); mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_with_another_device, diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java index 7beeeb2c870..9524fee9051 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java @@ -171,7 +171,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view); - mHeaderIcon.setImageResource(R.drawable.ic_scan_24dp); + setHeaderIconImageResource(R.drawable.ic_scan_24dp); if (mIsConfiguratorMode) { mTitle.setText(R.string.wifi_dpp_add_device_to_network); From 8de242ada6df76a6137540addcaa315e9312de35 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Fri, 25 Jan 2019 14:12:03 +0800 Subject: [PATCH 08/19] Wi-Fi DPP code refine 1. call Activity#setResult only for RESULT_OK case 2. refine @VisibleForTesting usage remove redundant assignment otherwise = PRIVATE set all @VisibleForTesting annotated methods package scope 3. rename WifiQrCode#SECURITY_WPA to WifiQrCode#SECURITY_WPA_PSK Bug: 120645817 Test: atest WifiQrCodeTest atest WifiDppConfiguratorActivityTest atest WifiDppEnrolleeActivityTest atest WifiDppQrCodeGeneratorFragmentTest atest WifiDppQrCodeScannerFragmentTest atest WifiNetworkListFragmentTest atest WifiDppChooseSavedWifiNetworkFragmentTest Change-Id: Id5de7eadc73185716422fc0d197f82bdd025ce45 --- .../settings/wifi/dpp/WifiDppAddDeviceFragment.java | 11 ++++++----- .../dpp/WifiDppChooseSavedWifiNetworkFragment.java | 5 +---- .../wifi/dpp/WifiDppConfiguratorActivity.java | 11 ++++------- .../settings/wifi/dpp/WifiDppEnrolleeActivity.java | 2 -- src/com/android/settings/wifi/dpp/WifiDppUtils.java | 2 +- .../android/settings/wifi/dpp/WifiNetworkConfig.java | 10 +++++----- .../settings/wifi/dpp/WifiNetworkListFragment.java | 2 +- src/com/android/settings/wifi/dpp/WifiQrCode.java | 10 +++++----- 8 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java index c5b570ff747..4523defe023 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java @@ -63,7 +63,11 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment { mButtonLeft.setText(R.string.wifi_dpp_add_another_device); mButtonLeft.setOnClickListener(v -> getFragmentManager().popBackStack()); mButtonRight.setText(R.string.done); - mButtonRight.setOnClickListener(v -> getActivity().finish()); + mButtonRight.setOnClickListener(v -> { + final Activity activity = getActivity(); + activity.setResult(Activity.RESULT_OK); + activity.finish(); + }); } @Override @@ -138,10 +142,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment { mButtonLeft = view.findViewById(R.id.button_left); mButtonLeft.setText(R.string.cancel); - mButtonLeft.setOnClickListener(v -> { - getActivity().setResult(Activity.RESULT_CANCELED); - getActivity().finish(); - }); + mButtonLeft.setOnClickListener(v -> getActivity().finish()); mButtonRight = view.findViewById(R.id.button_right); mButtonRight.setText(R.string.wifi_dpp_share_wifi); diff --git a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java index 682ebd45eb8..72e845f561e 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java @@ -17,7 +17,6 @@ package com.android.settings.wifi.dpp; import android.app.ActionBar; -import android.app.Activity; import android.app.settings.SettingsEnums; import android.content.Intent; import android.os.Bundle; @@ -100,9 +99,7 @@ public class WifiDppChooseSavedWifiNetworkFragment extends WifiDppQrCodeBaseFrag .ACTION_CONFIGURATOR_QR_CODE_GENERATOR.equals(action)) { getFragmentManager().popBackStack(); } else { - final Activity activity = getActivity(); - activity.setResult(Activity.RESULT_CANCELED); - activity.finish(); + getActivity().finish(); } }); diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java index e5beea03760..4aac538ec58 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java @@ -17,7 +17,6 @@ package com.android.settings.wifi.dpp; import android.app.ActionBar; -import android.app.Activity; import android.app.settings.SettingsEnums; import android.content.Intent; import android.os.Bundle; @@ -160,7 +159,6 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements } if (cancelActivity) { - setResult(Activity.RESULT_CANCELED); finish(); } } @@ -279,8 +277,8 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements return mWifiDppQrCode; } - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - protected boolean setWifiNetworkConfig(WifiNetworkConfig config) { + @VisibleForTesting + boolean setWifiNetworkConfig(WifiNetworkConfig config) { if(!WifiNetworkConfig.isValidConfig(config)) { return false; } else { @@ -289,8 +287,8 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements } } - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - protected boolean setWifiDppQrCode(WifiQrCode wifiQrCode) { + @VisibleForTesting + boolean setWifiDppQrCode(WifiQrCode wifiQrCode) { if (wifiQrCode == null) { return false; } @@ -307,7 +305,6 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements public boolean onNavigateUp() { Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container); if (fragment instanceof WifiDppQrCodeGeneratorFragment) { - setResult(Activity.RESULT_CANCELED); finish(); return true; } else if (fragment instanceof WifiDppQrCodeScannerFragment) { diff --git a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java index 3dea7a0eec8..df36ae52ce3 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java @@ -117,7 +117,6 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements break; default: Log.e(TAG, "Launch with an invalid action"); - setResult(Activity.RESULT_CANCELED); finish(); } } @@ -141,7 +140,6 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements @Override public boolean onNavigateUp(){ - setResult(Activity.RESULT_CANCELED); finish(); return true; } diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java index b43ee92f9a9..9c69032992d 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java +++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java @@ -139,7 +139,7 @@ public class WifiDppUtils { case AccessPoint.SECURITY_WEP: return WifiQrCode.SECURITY_WEP; case AccessPoint.SECURITY_PSK: - return WifiQrCode.SECURITY_WPA; + return WifiQrCode.SECURITY_WPA_PSK; case AccessPoint.SECURITY_SAE: return WifiQrCode.SECURITY_SAE; default: diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java index 8e95b3e7c0a..979e602bf4a 100644 --- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java +++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java @@ -19,7 +19,7 @@ package com.android.settings.wifi.dpp; import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_NO_PASSWORD; import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_SAE; import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_WEP; -import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_WPA; +import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_WPA_PSK; import android.content.Context; import android.content.Intent; @@ -53,8 +53,8 @@ public class WifiNetworkConfig { private boolean mHiddenSsid; private int mNetworkId; - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - protected WifiNetworkConfig(String security, String ssid, String preSharedKey, + @VisibleForTesting + WifiNetworkConfig(String security, String ssid, String preSharedKey, boolean hiddenSsid, int networkId) { mSecurity = security; mSsid = ssid; @@ -218,7 +218,7 @@ public class WifiNetworkConfig { } // DPP 1.0 only supports SAE and PSK. - if (SECURITY_SAE.equals(mSecurity) || SECURITY_WPA.equals(mSecurity)) { + if (SECURITY_SAE.equals(mSecurity) || SECURITY_WPA_PSK.equals(mSecurity)) { return true; } @@ -256,7 +256,7 @@ public class WifiNetworkConfig { } else { wifiConfiguration.wepKeys[0] = addQuotationIfNeeded(mPreSharedKey); } - } else if (mSecurity.startsWith(SECURITY_WPA)) { + } else if (mSecurity.startsWith(SECURITY_WPA_PSK)) { wifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_PSK); if (mPreSharedKey.matches("[0-9A-Fa-f]{64}")) { diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java index b078b01d083..89efc31d65c 100644 --- a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java @@ -235,7 +235,7 @@ public class WifiNetworkListFragment extends SettingsPreferenceFragment implemen if (mOnChooseNetworkListener != null) { mOnChooseNetworkListener.onChooseNetwork( new WifiNetworkConfig( - WifiQrCode.SECURITY_WPA, + WifiQrCode.SECURITY_WPA_PSK, /* ssid */ WifiNetworkConfig.FAKE_SSID, /* preSharedKey */ WifiNetworkConfig.FAKE_PASSWORD, /* hiddenSsid */ true, diff --git a/src/com/android/settings/wifi/dpp/WifiQrCode.java b/src/com/android/settings/wifi/dpp/WifiQrCode.java index d3f8ebf5aa5..a08fb4460d8 100644 --- a/src/com/android/settings/wifi/dpp/WifiQrCode.java +++ b/src/com/android/settings/wifi/dpp/WifiQrCode.java @@ -66,7 +66,7 @@ public class WifiQrCode { // Ignores password if security is SECURITY_NO_PASSWORD or absent public static final String SECURITY_NO_PASSWORD = "nopass"; public static final String SECURITY_WEP = "WEP"; - public static final String SECURITY_WPA = "WPA"; + public static final String SECURITY_WPA_PSK = "WPA"; public static final String SECURITY_SAE = "WPA3"; private String mQrCode; @@ -169,8 +169,8 @@ public class WifiQrCode { return null; } - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - protected String removeBackSlash(String input) { + @VisibleForTesting + String removeBackSlash(String input) { if (input == null) { return null; } @@ -210,8 +210,8 @@ public class WifiQrCode { } /** Available when {@code getScheme()} returns SCHEME_DPP */ - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - protected String getPublicKey() { + @VisibleForTesting + String getPublicKey() { return mPublicKey; } From 465ffcd48da38550a418e5c37b341d897c201873 Mon Sep 17 00:00:00 2001 From: tmfang Date: Tue, 29 Jan 2019 14:50:46 +0800 Subject: [PATCH 09/19] Remove empty space in Usage access When there is no need to show filter component, we don't need to set an extra padding top. Test: robotest, visual Change-Id: Ieaa65ed9785a06f0737aefaf102d0c857002bbdd Fixes: 123037802 --- res/layout/manage_applications_apps.xml | 4 +- .../ManageApplications.java | 39 +++++++++++++++---- .../ManageApplicationsTest.java | 29 ++++++++++++++ 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/res/layout/manage_applications_apps.xml b/res/layout/manage_applications_apps.xml index c2f58c3394b..021a61ef9a0 100644 --- a/res/layout/manage_applications_apps.xml +++ b/res/layout/manage_applications_apps.xml @@ -28,9 +28,9 @@ settings:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior"> + android:layout_height="match_parent"> 1 ? View.VISIBLE : View.GONE); + updateFilterView(mFilterOptions.size() > 1); notifyDataSetChanged(); if (mFilterOptions.size() == 1) { if (DEBUG) { @@ -826,14 +830,13 @@ public class ManageApplications extends InstrumentedFragment filter.getTitle())); } Collections.sort(mFilterOptions); - mManageApplications.mSpinnerHeader.setVisibility( - mFilterOptions.size() > 1 ? View.VISIBLE : View.GONE); + updateFilterView(mFilterOptions.size() > 1); notifyDataSetChanged(); if (mManageApplications.mFilter == filter) { if (mFilterOptions.size() > 0) { if (DEBUG) { Log.d(TAG, "Auto selecting filter " + mFilterOptions.get(0) - + mContext.getText(mFilterOptions.get(0).getTitle())); + + mContext.getText(mFilterOptions.get(0).getTitle())); } mManageApplications.mFilterSpinner.setSelection(0); mManageApplications.onItemSelected(null, null, 0, 0); @@ -850,6 +853,26 @@ public class ManageApplications extends InstrumentedFragment public CharSequence getItem(int position) { return mContext.getText(mFilterOptions.get(position).getTitle()); } + + @VisibleForTesting + void updateFilterView(boolean hasFilter) { + // If we need to add a floating filter in this screen, we should have an extra top + // padding for putting floating filter view. Otherwise, the content of list will be + // overlapped by floating filter. + if (hasFilter) { + mManageApplications.mSpinnerHeader.setVisibility(View.VISIBLE); + mManageApplications.mContentContainer.setPadding(0 /* left */, + mContext.getResources().getDimensionPixelSize( + R.dimen.app_bar_height) /* top */, + 0 /* right */, + 0 /* bottom */); + } else { + mManageApplications.mSpinnerHeader.setVisibility(View.GONE); + mManageApplications.mContentContainer.setPadding(0 /* left */, 0 /* top */, + 0 /* right */, + 0 /* bottom */); + } + } } static class ApplicationsAdapter extends RecyclerView.Adapter diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java index 3dc0bc453ff..27aeccc933d 100644 --- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java +++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java @@ -91,6 +91,8 @@ public class ManageApplicationsTest { private UserManager mUserManager; @Mock private PackageManager mPackageManager; + + private Context mContext; private MenuItem mAppReset; private MenuItem mSortRecent; private MenuItem mSortFrequent; @@ -99,6 +101,7 @@ public class ManageApplicationsTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; mAppReset = new RoboMenuItem(R.id.reset_app_preferences); mSortRecent = new RoboMenuItem(R.id.sort_order_recent_notification); mSortFrequent = new RoboMenuItem(R.id.sort_order_frequent_notification); @@ -107,6 +110,7 @@ public class ManageApplicationsTest { when(mState.getBackgroundLooper()).thenReturn(Looper.myLooper()); mFragment = spy(new ManageApplications()); + when(mFragment.getContext()).thenReturn(mContext); when(mFragment.getActivity()).thenReturn(mActivity); when(mActivity.getResources()).thenReturn(mResources); when(mActivity.getSystemService(UserManager.class)).thenReturn(mUserManager); @@ -460,6 +464,31 @@ public class ManageApplicationsTest { assertThat(mFragment.mSortOrder).isEqualTo(mSortFrequent.getItemId()); } + @Test + public void updateFilterView_hasFilterSet_shouldShowFilterAndHavePaddingTop() { + mFragment.mContentContainer = new View(mContext); + mFragment.mSpinnerHeader = new View(mContext); + mFragment.mFilterAdapter = new ManageApplications.FilterSpinnerAdapter(mFragment); + + mFragment.mFilterAdapter.updateFilterView(true); + + assertThat(mFragment.mSpinnerHeader.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mFragment.mContentContainer.getPaddingTop()).isEqualTo( + mContext.getResources().getDimensionPixelSize(R.dimen.app_bar_height)); + } + + @Test + public void updateFilterView_noFilterSet_shouldHideFilterAndNoPaddingTop() { + mFragment.mContentContainer = new View(mContext); + mFragment.mSpinnerHeader = new View(mContext); + mFragment.mFilterAdapter = new ManageApplications.FilterSpinnerAdapter(mFragment); + + mFragment.mFilterAdapter.updateFilterView(false); + + assertThat(mFragment.mSpinnerHeader.getVisibility()).isEqualTo(View.GONE); + assertThat(mFragment.mContentContainer.getPaddingTop()).isEqualTo(0); + } + private void setUpOptionMenus() { when(mMenu.findItem(anyInt())).thenAnswer(invocation -> { final Object[] args = invocation.getArguments(); From 8db2d30fabe0bd959709c868ec70a129bdb4d8fc Mon Sep 17 00:00:00 2001 From: Nikita Iashchenko Date: Mon, 28 Jan 2019 21:16:31 +0000 Subject: [PATCH 10/19] Fix crash if timezone is changed and "Don't keep activities" mode is on The issues is that TimeZoneData is being loaded with LoaderManager on every fragment's onCreate(). At the same time this fragment has onActivityResult() handler that accesses TimeZoneData and relies on the fact that it has been already initialized prior this call. So when you enable "Don't keep activities" mode, the TimeZoneSettings fragment [1] that holds TimeZoneData is immediately destroyed after launching time zone picker fragment [2] (which result [1] waits for), and when android calls onActivityResult() for [1] (after time zone has been picked in [2]), Android has to recreate [1] from scratch. So you get onCreate() called and immidiately after that onActivityResult() called, and at this point we get the crash, because the loader hasn't finished yet and onActivityResult() tries to access uninitialized mTimeZoneData. This CL fixes this crash issue by postponing mTimeZoneData.lookupCountryTimeZones call until mTimeZoneData is loaded by loader. It is done through saving data intent in onActivityResult() and calling onZonePickerRequestResult() when time zone data is loaded. Bug: 112351583 Test: m Settings droid successfully builds, manual testing with "Don't keep activities" mode enabled Change-Id: Id30d36dc17a0de96ba871f9d0f4a2686479d0eeb --- .../datetime/timezone/TimeZoneSettings.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/com/android/settings/datetime/timezone/TimeZoneSettings.java b/src/com/android/settings/datetime/timezone/TimeZoneSettings.java index 6f776c984a1..d557bf93e61 100644 --- a/src/com/android/settings/datetime/timezone/TimeZoneSettings.java +++ b/src/com/android/settings/datetime/timezone/TimeZoneSettings.java @@ -69,6 +69,7 @@ public class TimeZoneSettings extends DashboardFragment { private Locale mLocale; private boolean mSelectByRegion; private TimeZoneData mTimeZoneData; + private Intent mPendingZonePickerRequestResult; private String mSelectedTimeZoneId; private TimeZoneInfo.Formatter mTimeZoneInfoFormatter; @@ -136,12 +137,10 @@ public class TimeZoneSettings extends DashboardFragment { switch (requestCode) { case REQUEST_CODE_REGION_PICKER: case REQUEST_CODE_ZONE_PICKER: { - String regionId = data.getStringExtra(RegionSearchPicker.EXTRA_RESULT_REGION_ID); - String tzId = data.getStringExtra(RegionZonePicker.EXTRA_RESULT_TIME_ZONE_ID); - // Ignore the result if user didn't change the region or time zone. - if (!Objects.equals(regionId, use(RegionPreferenceController.class).getRegionId()) - || !Objects.equals(tzId, mSelectedTimeZoneId)) { - onRegionZoneChanged(regionId, tzId); + if (mTimeZoneData == null) { + mPendingZonePickerRequestResult = data; + } else { + onZonePickerRequestResult(mTimeZoneData, data); } break; } @@ -166,8 +165,11 @@ public class TimeZoneSettings extends DashboardFragment { mTimeZoneData = timeZoneData; setupForCurrentTimeZone(); getActivity().invalidateOptionsMenu(); + if (mPendingZonePickerRequestResult != null) { + onZonePickerRequestResult(timeZoneData, mPendingZonePickerRequestResult); + mPendingZonePickerRequestResult = null; + } } - } private void startRegionPicker() { @@ -226,9 +228,17 @@ public class TimeZoneSettings extends DashboardFragment { updatePreferenceStates(); } - private void onRegionZoneChanged(String regionId, String tzId) { + private void onZonePickerRequestResult(TimeZoneData timeZoneData, Intent data) { + String regionId = data.getStringExtra(RegionSearchPicker.EXTRA_RESULT_REGION_ID); + String tzId = data.getStringExtra(RegionZonePicker.EXTRA_RESULT_TIME_ZONE_ID); + // Ignore the result if user didn't change the region or time zone. + if (Objects.equals(regionId, use(RegionPreferenceController.class).getRegionId()) + && Objects.equals(tzId, mSelectedTimeZoneId)) { + return; + } + FilteredCountryTimeZones countryTimeZones = - mTimeZoneData.lookupCountryTimeZones(regionId); + timeZoneData.lookupCountryTimeZones(regionId); if (countryTimeZones == null || !countryTimeZones.getTimeZoneIds().contains(tzId)) { Log.e(TAG, "Unknown time zone id is selected: " + tzId); return; From 3d0078766d63a2050b027c00df59f194ddd9e752 Mon Sep 17 00:00:00 2001 From: Dan Sandler Date: Tue, 29 Jan 2019 14:41:54 -0500 Subject: [PATCH 11/19] Fix dsandler's email address. Test: dsandler can give OWNERS approval again Change-Id: I8a59453ec95b98ce74703bbe003c9039e2a96f22 --- src/com/android/settings/notification/OWNERS | 2 +- tests/robotests/src/com/android/settings/notification/OWNERS | 2 +- tests/unit/src/com/android/settings/notification/OWNERS | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/notification/OWNERS b/src/com/android/settings/notification/OWNERS index 0d73685a875..edf266eebbf 100644 --- a/src/com/android/settings/notification/OWNERS +++ b/src/com/android/settings/notification/OWNERS @@ -1,4 +1,4 @@ # Default reviewers for this and subdirectories. asc@google.com -dsandler@google.com +dsandler@android.com juliacr@google.com \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/notification/OWNERS b/tests/robotests/src/com/android/settings/notification/OWNERS index 0d73685a875..edf266eebbf 100644 --- a/tests/robotests/src/com/android/settings/notification/OWNERS +++ b/tests/robotests/src/com/android/settings/notification/OWNERS @@ -1,4 +1,4 @@ # Default reviewers for this and subdirectories. asc@google.com -dsandler@google.com +dsandler@android.com juliacr@google.com \ No newline at end of file diff --git a/tests/unit/src/com/android/settings/notification/OWNERS b/tests/unit/src/com/android/settings/notification/OWNERS index 0d73685a875..edf266eebbf 100644 --- a/tests/unit/src/com/android/settings/notification/OWNERS +++ b/tests/unit/src/com/android/settings/notification/OWNERS @@ -1,4 +1,4 @@ # Default reviewers for this and subdirectories. asc@google.com -dsandler@google.com +dsandler@android.com juliacr@google.com \ No newline at end of file From beedd3abe50df8f6e17a63b62f61acb1fce742e4 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Tue, 29 Jan 2019 13:52:12 -0800 Subject: [PATCH 12/19] Add referrer when launching search intent. Bug: 123294739 Test: robotests Change-Id: I600abf1d764e828d52f3b8d35ad24cdc94dfba01 --- .../android/settings/SettingsActivity.java | 3 +- .../homepage/SettingsHomepageActivity.java | 3 +- .../search/SearchFeatureProvider.java | 11 ++++---- .../search/SearchFeatureProviderImpl.java | 18 ++++++++++++ .../actionbar/SearchMenuController.java | 24 +++++++++------- .../search/SearchFeatureProviderImplTest.java | 19 ++++++++++--- .../actionbar/SearchMenuControllerTest.java | 28 ++++++++++++++----- 7 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 25ad73d274b..99eb218b0d9 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -18,6 +18,7 @@ package com.android.settings; import android.app.ActionBar; import android.app.ActivityManager; +import android.app.settings.SettingsEnums; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -287,7 +288,7 @@ public class SettingsActivity extends SettingsBaseActivity final Toolbar toolbar = findViewById(R.id.search_action_bar); setActionBar(toolbar); FeatureFactory.getFactory(this).getSearchFeatureProvider() - .initSearchToolbar(this, toolbar); + .initSearchToolbar(this, toolbar, SettingsEnums.SETTINGS_HOMEPAGE); } ActionBar actionBar = getActionBar(); diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index 9acda68d71c..bdf47698d71 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -16,6 +16,7 @@ package com.android.settings.homepage; +import android.app.settings.SettingsEnums; import android.content.Intent; import android.os.Bundle; import android.util.FeatureFlagUtils; @@ -53,7 +54,7 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { final Toolbar toolbar = findViewById(R.id.search_action_bar); FeatureFactory.getFactory(this).getSearchFeatureProvider() - .initSearchToolbar(this /* activity */, toolbar); + .initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE); final ImageView avatarView = findViewById(R.id.account_avatar); final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView); diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java index b98936e796c..dcb4acc5d92 100644 --- a/src/com/android/settings/search/SearchFeatureProvider.java +++ b/src/com/android/settings/search/SearchFeatureProvider.java @@ -25,7 +25,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.provider.Settings; import android.view.View; import android.view.ViewGroup; import android.widget.Toolbar; @@ -40,7 +39,6 @@ import com.android.settingslib.search.SearchIndexableResources; */ public interface SearchFeatureProvider { - Intent SEARCH_UI_INTENT = new Intent(Settings.ACTION_APP_SEARCH_SETTINGS); int REQUEST_CODE = 0; /** @@ -64,7 +62,7 @@ public interface SearchFeatureProvider { /** * Initializes the search toolbar. */ - default void initSearchToolbar(Activity activity, Toolbar toolbar) { + default void initSearchToolbar(Activity activity, Toolbar toolbar, int pageId) { if (activity == null || toolbar == null) { return; } @@ -87,9 +85,8 @@ public interface SearchFeatureProvider { navView.setBackground(null); toolbar.setOnClickListener(tb -> { - final Intent intent = SEARCH_UI_INTENT; - intent.setPackage(getSettingsIntelligencePkgName(activity)); final Context context = activity.getApplicationContext(); + final Intent intent = buildSearchIntent(context, pageId); if (activity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { @@ -97,10 +94,12 @@ public interface SearchFeatureProvider { } FeatureFactory.getFactory(context).getSlicesFeatureProvider() - .indexSliceDataAsync(activity.getApplicationContext()); + .indexSliceDataAsync(context); FeatureFactory.getFactory(context).getMetricsFeatureProvider() .action(context, SettingsEnums.ACTION_SEARCH_RESULTS); activity.startActivityForResult(intent, REQUEST_CODE); }); } + + Intent buildSearchIntent(Context context, int pageId); } diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java index a5a87774ee6..63bf420c027 100644 --- a/src/com/android/settings/search/SearchFeatureProviderImpl.java +++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java @@ -19,6 +19,9 @@ package com.android.settings.search; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.provider.Settings; import android.text.TextUtils; import com.android.settingslib.search.SearchIndexableResources; @@ -59,7 +62,22 @@ public class SearchFeatureProviderImpl implements SearchFeatureProvider { return mSearchIndexableResources; } + @Override + public Intent buildSearchIntent(Context context, int pageId) { + return new Intent(Settings.ACTION_APP_SEARCH_SETTINGS) + .setPackage(getSettingsIntelligencePkgName(context)) + .putExtra(Intent.EXTRA_REFERRER, buildReferrer(context, pageId)); + } + protected boolean isSignatureWhitelisted(Context context, String callerPackage) { return false; } + + private static Uri buildReferrer(Context context, int pageId) { + return new Uri.Builder() + .scheme("android-app") + .authority(context.getPackageName()) + .path(String.valueOf(pageId)) + .build(); + } } diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java index 2f1c27084f8..af7141e54f1 100644 --- a/src/com/android/settings/search/actionbar/SearchMenuController.java +++ b/src/com/android/settings/search/actionbar/SearchMenuController.java @@ -30,11 +30,10 @@ import androidx.fragment.app.Fragment; import com.android.settings.R; import com.android.settings.Utils; +import com.android.settings.core.InstrumentedFragment; +import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.search.SearchFeatureProvider; import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.ObservableFragment; -import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment; import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu; public class SearchMenuController implements LifecycleObserver, OnCreateOptionsMenu { @@ -42,17 +41,21 @@ public class SearchMenuController implements LifecycleObserver, OnCreateOptionsM public static final String NEED_SEARCH_ICON_IN_ACTION_BAR = "need_search_icon_in_action_bar"; private final Fragment mHost; + private final int mPageId; - public static void init(@NonNull ObservablePreferenceFragment host) { - host.getSettingsLifecycle().addObserver(new SearchMenuController(host)); + public static void init(@NonNull InstrumentedPreferenceFragment host) { + host.getSettingsLifecycle().addObserver( + new SearchMenuController(host, host.getMetricsCategory())); } - public static void init(@NonNull ObservableFragment host) { - host.getSettingsLifecycle().addObserver(new SearchMenuController(host)); + public static void init(@NonNull InstrumentedFragment host) { + host.getSettingsLifecycle().addObserver( + new SearchMenuController(host, host.getMetricsCategory())); } - private SearchMenuController(@NonNull Fragment host) { + private SearchMenuController(@NonNull Fragment host, int pageId) { mHost = host; + mPageId = pageId; } @Override @@ -79,8 +82,9 @@ public class SearchMenuController implements LifecycleObserver, OnCreateOptionsM searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); searchItem.setOnMenuItemClickListener(target -> { - final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT; - intent.setPackage(SettingsIntelligencePkgName); + final Intent intent = FeatureFactory.getFactory(context) + .getSearchFeatureProvider() + .buildSearchIntent(context, mPageId); if (context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java index 7f709d6fb9b..444a8137889 100644 --- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java @@ -20,10 +20,12 @@ package com.android.settings.search; import static com.google.common.truth.Truth.assertThat; import android.app.Activity; +import android.app.settings.SettingsEnums; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ResolveInfo; +import android.net.Uri; import android.provider.Settings; import android.widget.Toolbar; @@ -60,19 +62,19 @@ public class SearchFeatureProviderImplTest { @Test @Config(shadows = ShadowUtils.class) public void initSearchToolbar_hasResolvedInfo_shouldStartCorrectIntent() { - final Intent searchIntent = new Intent(SearchFeatureProvider.SEARCH_UI_INTENT) + final Intent searchIntent = new Intent(Settings.ACTION_APP_SEARCH_SETTINGS) .setPackage(mActivity.getString(R.string.config_settingsintelligence_package_name)); final ResolveInfo info = new ResolveInfo(); info.activityInfo = new ActivityInfo(); mPackageManager.addResolveInfoForIntent(searchIntent, info); // Should not crash. - mProvider.initSearchToolbar(mActivity, null); + mProvider.initSearchToolbar(mActivity, null, SettingsEnums.TESTING); final Toolbar toolbar = new Toolbar(mActivity); // This ensures navigationView is created. toolbar.setNavigationContentDescription("test"); - mProvider.initSearchToolbar(mActivity, toolbar); + mProvider.initSearchToolbar(mActivity, toolbar, SettingsEnums.TESTING); toolbar.performClick(); @@ -87,7 +89,7 @@ public class SearchFeatureProviderImplTest { final Toolbar toolbar = new Toolbar(mActivity); // This ensures navigationView is created. toolbar.setNavigationContentDescription("test"); - mProvider.initSearchToolbar(mActivity, toolbar); + mProvider.initSearchToolbar(mActivity, toolbar, SettingsEnums.TESTING); toolbar.performClick(); @@ -108,6 +110,15 @@ public class SearchFeatureProviderImplTest { assertThat(Shadows.shadowOf(mActivity).getNextStartedActivity()).isNull(); } + @Test + public void buildSearchIntent_shouldIncludeReferrer() { + final Intent searchIntent = mProvider.buildSearchIntent(mActivity, SettingsEnums.TESTING); + final Uri referrer = searchIntent.getParcelableExtra(Intent.EXTRA_REFERRER); + + assertThat(referrer.toSafeString()).isEqualTo( + "android-app://" + mActivity.getPackageName() + "/" + SettingsEnums.TESTING); + } + @Test(expected = IllegalArgumentException.class) public void verifyLaunchSearchResultPageCaller_nullCaller_shouldCrash() { mProvider.verifyLaunchSearchResultPageCaller(mActivity, null /* caller */); diff --git a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java index af1a82de905..3063912e0f6 100644 --- a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java +++ b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java @@ -17,11 +17,11 @@ package com.android.settings.search.actionbar; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; +import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; import android.provider.Settings.Global; @@ -29,9 +29,9 @@ import android.view.Menu; import android.view.MenuItem; import com.android.settings.R; +import com.android.settings.core.InstrumentedFragment; +import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.testutils.shadow.ShadowUtils; -import com.android.settingslib.core.lifecycle.ObservableFragment; -import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment; import org.junit.Before; import org.junit.Test; @@ -49,15 +49,24 @@ public class SearchMenuControllerTest { @Mock private Menu mMenu; private TestPreferenceFragment mPreferenceHost; - private ObservableFragment mHost; + private InstrumentedFragment mHost; private Context mContext; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - mHost = spy(new ObservableFragment()); - when(mHost.getContext()).thenReturn(mContext); + mHost = new InstrumentedFragment() { + @Override + public Context getContext() { + return mContext; + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.TESTING; + } + }; mPreferenceHost = new TestPreferenceFragment(); Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1); @@ -101,7 +110,7 @@ public class SearchMenuControllerTest { verifyZeroInteractions(mMenu); } - private static class TestPreferenceFragment extends ObservablePreferenceFragment { + private static class TestPreferenceFragment extends InstrumentedPreferenceFragment { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { } @@ -110,5 +119,10 @@ public class SearchMenuControllerTest { public Context getContext() { return RuntimeEnvironment.application; } + + @Override + public int getMetricsCategory() { + return SettingsEnums.TESTING; + } } } From 1107d310f1cf5f5ef0b50487f9be60060b676e90 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Tue, 29 Jan 2019 15:39:32 -0800 Subject: [PATCH 13/19] Use settingslib ActionBarShadowController Change-Id: Ib70a0ca307bb98e576f2c3deb8f7aea88e59b10e Fixes: 123311100 Test: robotests --- .../widget/ActionBarShadowController.java | 134 ------------------ .../widget/EntityHeaderController.java | 1 + .../widget/ActionBarShadowControllerTest.java | 116 --------------- 3 files changed, 1 insertion(+), 250 deletions(-) delete mode 100644 src/com/android/settings/widget/ActionBarShadowController.java delete mode 100644 tests/robotests/src/com/android/settings/widget/ActionBarShadowControllerTest.java diff --git a/src/com/android/settings/widget/ActionBarShadowController.java b/src/com/android/settings/widget/ActionBarShadowController.java deleted file mode 100644 index 1b8d3192a4a..00000000000 --- a/src/com/android/settings/widget/ActionBarShadowController.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2017 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.widget; - -import android.app.ActionBar; -import android.app.Activity; -import android.view.View; - -import androidx.annotation.VisibleForTesting; -import androidx.recyclerview.widget.RecyclerView; - -import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnStart; -import com.android.settingslib.core.lifecycle.events.OnStop; - -/** - * A controller that adds shadow to actionbar when content view scrolls. - *

- * It also works on custom views acting as an actionbar. - */ -public class ActionBarShadowController implements LifecycleObserver, OnStart, OnStop { - - @VisibleForTesting - static final float ELEVATION_HIGH = 8; - @VisibleForTesting - static final float ELEVATION_LOW = 0; - - @VisibleForTesting - ScrollChangeWatcher mScrollChangeWatcher; - private RecyclerView mRecyclerView; - private boolean isScrollWatcherAttached; - - public static ActionBarShadowController attachToRecyclerView(Activity activity, - Lifecycle lifecycle, RecyclerView recyclerView) { - return new ActionBarShadowController(activity, lifecycle, recyclerView); - } - - public static ActionBarShadowController attachToRecyclerView(View anchorView, - Lifecycle lifecycle, RecyclerView recyclerView) { - return new ActionBarShadowController(anchorView, lifecycle, recyclerView); - } - - private ActionBarShadowController(Activity activity, Lifecycle lifecycle, - RecyclerView recyclerView) { - mScrollChangeWatcher = new ScrollChangeWatcher(activity); - mRecyclerView = recyclerView; - attachScrollWatcher(); - lifecycle.addObserver(this); - } - - private ActionBarShadowController(View anchorView, Lifecycle lifecycle, - RecyclerView recyclerView) { - mScrollChangeWatcher = new ScrollChangeWatcher(anchorView); - mRecyclerView = recyclerView; - attachScrollWatcher(); - lifecycle.addObserver(this); - } - - @Override - public void onStop() { - detachScrollWatcher(); - } - - private void detachScrollWatcher() { - mRecyclerView.removeOnScrollListener(mScrollChangeWatcher); - isScrollWatcherAttached = false; - } - - @Override - public void onStart() { - attachScrollWatcher(); - } - - private void attachScrollWatcher() { - if (!isScrollWatcherAttached) { - isScrollWatcherAttached = true; - mRecyclerView.addOnScrollListener(mScrollChangeWatcher); - mScrollChangeWatcher.updateDropShadow(mRecyclerView); - } - } - - /** - * Update the drop shadow as the scrollable entity is scrolled. - */ - final class ScrollChangeWatcher extends RecyclerView.OnScrollListener { - - private final Activity mActivity; - private final View mAnchorView; - - public ScrollChangeWatcher(Activity activity) { - mActivity = activity; - mAnchorView = null; - } - - public ScrollChangeWatcher(View anchorView) { - mAnchorView = anchorView; - mActivity = null; - } - - // RecyclerView scrolled. - @Override - public void onScrolled(RecyclerView view, int dx, int dy) { - updateDropShadow(view); - } - - public void updateDropShadow(View view) { - final boolean shouldShowShadow = view.canScrollVertically(-1); - if (mAnchorView != null) { - mAnchorView.setElevation(shouldShowShadow ? ELEVATION_HIGH : ELEVATION_LOW); - } else if (mActivity != null) { // activity can become null when running monkey - final ActionBar actionBar = mActivity.getActionBar(); - if (actionBar != null) { - actionBar.setElevation(shouldShowShadow ? ELEVATION_HIGH : ELEVATION_LOW); - } - } - } - } - -} diff --git a/src/com/android/settings/widget/EntityHeaderController.java b/src/com/android/settings/widget/EntityHeaderController.java index c1101079223..351c2bcc00b 100644 --- a/src/com/android/settings/widget/EntityHeaderController.java +++ b/src/com/android/settings/widget/EntityHeaderController.java @@ -49,6 +49,7 @@ import com.android.settings.applications.appinfo.AppInfoDashboardFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.widget.ActionBarShadowController; import com.android.settingslib.widget.LayoutPreference; import java.lang.annotation.Retention; diff --git a/tests/robotests/src/com/android/settings/widget/ActionBarShadowControllerTest.java b/tests/robotests/src/com/android/settings/widget/ActionBarShadowControllerTest.java deleted file mode 100644 index befac3fa2bc..00000000000 --- a/tests/robotests/src/com/android/settings/widget/ActionBarShadowControllerTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2017 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.widget; - -import static androidx.lifecycle.Lifecycle.Event.ON_START; -import static androidx.lifecycle.Lifecycle.Event.ON_STOP; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.ActionBar; -import android.app.Activity; -import android.view.View; - -import androidx.lifecycle.LifecycleOwner; -import androidx.recyclerview.widget.RecyclerView; - -import com.android.settingslib.core.lifecycle.Lifecycle; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@RunWith(RobolectricTestRunner.class) -public class ActionBarShadowControllerTest { - - @Mock - private RecyclerView mRecyclerView; - @Mock - private Activity mActivity; - @Mock - private ActionBar mActionBar; - private Lifecycle mLifecycle; - private LifecycleOwner mLifecycleOwner; - private View mView; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(mActivity.getActionBar()).thenReturn(mActionBar); - mView = new View(RuntimeEnvironment.application); - mLifecycleOwner = () -> mLifecycle; - mLifecycle = new Lifecycle(mLifecycleOwner); - } - - @Test - public void attachToRecyclerView_shouldAddScrollWatcherAndUpdateActionBar() { - when(mRecyclerView.canScrollVertically(-1)).thenReturn(false); - - ActionBarShadowController.attachToRecyclerView(mActivity, mLifecycle, mRecyclerView); - - verify(mActionBar).setElevation(ActionBarShadowController.ELEVATION_LOW); - } - - @Test - public void attachToRecyclerView_customViewAsActionBar_shouldUpdateElevationOnScroll() { - // Setup - mView.setElevation(50); - when(mRecyclerView.canScrollVertically(-1)).thenReturn(false); - final ActionBarShadowController controller = - ActionBarShadowController.attachToRecyclerView(mView, mLifecycle, mRecyclerView); - assertThat(mView.getElevation()).isEqualTo(ActionBarShadowController.ELEVATION_LOW); - - // Scroll - when(mRecyclerView.canScrollVertically(-1)).thenReturn(true); - controller.mScrollChangeWatcher.onScrolled(mRecyclerView, 10 /* dx */, 10 /* dy */); - assertThat(mView.getElevation()).isEqualTo(ActionBarShadowController.ELEVATION_HIGH); - } - - @Test - public void attachToRecyclerView_lifecycleChange_shouldAttachDetach() { - ActionBarShadowController.attachToRecyclerView(mActivity, mLifecycle, mRecyclerView); - - verify(mRecyclerView).addOnScrollListener(any()); - - mLifecycle.handleLifecycleEvent(ON_START); - mLifecycle.handleLifecycleEvent(ON_STOP); - verify(mRecyclerView).removeOnScrollListener(any()); - - mLifecycle.handleLifecycleEvent(ON_START); - verify(mRecyclerView, times(2)).addOnScrollListener(any()); - } - - @Test - public void onScrolled_nullAnchorViewAndActivity_shouldNotCrash() { - final Activity activity = null; - final ActionBarShadowController controller = - ActionBarShadowController.attachToRecyclerView(activity, mLifecycle, mRecyclerView); - - // Scroll - controller.mScrollChangeWatcher.onScrolled(mRecyclerView, 10 /* dx */, 10 /* dy */); - // no crash - } -} From c3fd289969191495e2d24493c4f1665dd9f6dbb3 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Tue, 29 Jan 2019 16:00:19 -0800 Subject: [PATCH 14/19] Remove dead code. Bug: n/a Test: rebuild Change-Id: I71f8d9d99bbff1186e8df518ec8d27db3447ffbe --- .../android/settings/SettingsInitialize.java | 10 +- src/com/android/settings/Utils.java | 11 +- .../RecentAppsPreferenceController.java | 4 +- .../biometrics/BiometricEnrollActivity.java | 9 +- .../biometrics/BiometricEnrollBase.java | 4 +- .../BiometricStatusPreferenceController.java | 4 +- .../fingerprint/FingerprintSettings.java | 6 +- .../settings/fuelgauge/BatteryCellParser.java | 101 ------------------ .../detectors/HighUsageDetector.java | 4 +- .../detectors/RestrictAppDetector.java | 4 +- .../password/ChooseLockSettingsHelper.java | 4 +- .../ConfirmDeviceCredentialActivity.java | 6 +- .../ConfirmDeviceCredentialBaseFragment.java | 17 +-- .../settings/password/PasswordUtils.java | 4 +- tests/robotests/Android.mk | 8 +- .../batterytip/BatteryTipUtilsTest.java | 4 +- 16 files changed, 55 insertions(+), 145 deletions(-) delete mode 100644 src/com/android/settings/fuelgauge/BatteryCellParser.java diff --git a/src/com/android/settings/SettingsInitialize.java b/src/com/android/settings/SettingsInitialize.java index 784617aa39d..515703358e5 100644 --- a/src/com/android/settings/SettingsInitialize.java +++ b/src/com/android/settings/SettingsInitialize.java @@ -21,6 +21,8 @@ import static android.content.pm.PackageManager.GET_META_DATA; import static android.content.pm.PackageManager.GET_RESOLVED_FILTER; import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -51,14 +53,13 @@ public class SettingsInitialize extends BroadcastReceiver { private static final String TAG = "Settings"; private static final String PRIMARY_PROFILE_SETTING = "com.android.settings.PRIMARY_PROFILE_CONTROLLED"; - private static final String SETTINGS_PACKAGE = "com.android.settings"; private static final String WEBVIEW_IMPLEMENTATION_ACTIVITY = ".WebViewImplementation"; @Override public void onReceive(Context context, Intent broadcast) { final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); UserInfo userInfo = um.getUserInfo(UserHandle.myUserId()); - final PackageManager pm = context.getPackageManager(); + final PackageManager pm = context.getPackageManager(); managedProfileSetup(context, pm, broadcast, userInfo); webviewSettingSetup(context, pm, userInfo); refreshExistingShortcuts(context); @@ -91,7 +92,7 @@ public class SettingsInitialize extends BroadcastReceiver { PRIMARY_PROFILE_SETTING); if (shouldForward) { pm.addCrossProfileIntentFilter(info.filter, userInfo.id, - userInfo.profileGroupId, PackageManager.SKIP_CURRENT_PROFILE); + userInfo.profileGroupId, PackageManager.SKIP_CURRENT_PROFILE); } } } @@ -113,7 +114,8 @@ public class SettingsInitialize extends BroadcastReceiver { return; } ComponentName settingsComponentName = - new ComponentName(SETTINGS_PACKAGE, SETTINGS_PACKAGE + WEBVIEW_IMPLEMENTATION_ACTIVITY); + new ComponentName(SETTINGS_PACKAGE_NAME, + SETTINGS_PACKAGE_NAME + WEBVIEW_IMPLEMENTATION_ACTIVITY); pm.setComponentEnabledSetting(settingsComponentName, userInfo.isAdmin() ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 79caefe0fad..93a785f127f 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -111,16 +111,7 @@ public final class Utils extends com.android.settingslib.Utils { */ public static final int UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY = 1; - /** - * Color spectrum to use to indicate badness. 0 is completely transparent (no data), - * 1 is most bad (red), the last value is least bad (green). - */ - public static final int[] BADNESS_COLORS = new int[] { - 0x00000000, 0xffc43828, 0xffe54918, 0xfff47b00, - 0xfffabf2c, 0xff679e37, 0xff0a7f42 - }; - - private static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; + public static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; public static final String OS_PKG = "os"; diff --git a/src/com/android/settings/applications/RecentAppsPreferenceController.java b/src/com/android/settings/applications/RecentAppsPreferenceController.java index c7d310e3adf..364aeffd09b 100644 --- a/src/com/android/settings/applications/RecentAppsPreferenceController.java +++ b/src/com/android/settings/applications/RecentAppsPreferenceController.java @@ -16,6 +16,8 @@ package com.android.settings.applications; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.app.Application; import android.app.settings.SettingsEnums; import android.app.usage.UsageStats; @@ -91,7 +93,7 @@ public class RecentAppsPreferenceController extends AbstractPreferenceController SKIP_SYSTEM_PACKAGES.addAll(Arrays.asList( "android", "com.android.phone", - "com.android.settings", + SETTINGS_PACKAGE_NAME, "com.android.systemui", "com.android.providers.calendar", "com.android.providers.media" diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java index ee359454007..b650c6c46cb 100644 --- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java +++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java @@ -16,6 +16,8 @@ package com.android.settings.biometrics; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.app.settings.SettingsEnums; import android.content.Intent; import android.content.pm.PackageManager; @@ -33,8 +35,6 @@ import com.android.settings.core.InstrumentedActivity; */ public class BiometricEnrollActivity extends InstrumentedActivity { - private static final String SETTINGS_PACKAGE = "com.android.settings"; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -44,9 +44,10 @@ public class BiometricEnrollActivity extends InstrumentedActivity { // This logic may have to be modified on devices with multiple biometrics. if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { - intent.setClassName(SETTINGS_PACKAGE, FingerprintEnrollIntroduction.class.getName()); + intent.setClassName(SETTINGS_PACKAGE_NAME, + FingerprintEnrollIntroduction.class.getName()); } else if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) { - intent.setClassName(SETTINGS_PACKAGE, FaceEnrollIntroduction.class.getName()); + intent.setClassName(SETTINGS_PACKAGE_NAME, FaceEnrollIntroduction.class.getName()); } startActivity(intent); diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java index bca70d7acfa..9c9f4fad030 100644 --- a/src/com/android/settings/biometrics/BiometricEnrollBase.java +++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java @@ -16,6 +16,8 @@ package com.android.settings.biometrics; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.annotation.Nullable; import android.content.Intent; import android.content.res.Resources; @@ -148,7 +150,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { protected Intent getFingerprintEnrollingIntent() { Intent intent = new Intent(); - intent.setClassName("com.android.settings", FingerprintEnrollEnrolling.class.getName()); + intent.setClassName(SETTINGS_PACKAGE_NAME, FingerprintEnrollEnrolling.class.getName()); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); if (mUserId != UserHandle.USER_NULL) { intent.putExtra(Intent.EXTRA_USER_ID, mUserId); diff --git a/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java b/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java index 379a02b7479..156d663dfff 100644 --- a/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java +++ b/src/com/android/settings/biometrics/BiometricStatusPreferenceController.java @@ -16,6 +16,8 @@ package com.android.settings.biometrics; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.content.Context; import android.content.Intent; import android.os.UserHandle; @@ -114,7 +116,7 @@ public abstract class BiometricStatusPreferenceController extends BasePreference return false; } Intent intent = new Intent(); - intent.setClassName("com.android.settings", clazz); + intent.setClassName(SETTINGS_PACKAGE_NAME, clazz); intent.putExtra(Intent.EXTRA_USER_ID, userId); context.startActivity(intent); return true; diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java index 4c7276dac36..d696f2fff75 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java @@ -17,6 +17,8 @@ package com.android.settings.biometrics.fingerprint; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.app.Activity; import android.app.Dialog; import android.app.admin.DevicePolicyManager; @@ -460,7 +462,7 @@ public class FingerprintSettings extends SubSettings { final String key = pref.getKey(); if (KEY_FINGERPRINT_ADD.equals(key)) { Intent intent = new Intent(); - intent.setClassName("com.android.settings", + intent.setClassName(SETTINGS_PACKAGE_NAME, FingerprintEnrollEnrolling.class.getName()); intent.putExtra(Intent.EXTRA_USER_ID, mUserId); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); @@ -613,7 +615,7 @@ public class FingerprintSettings extends SubSettings { if (!helper.launchConfirmationActivity(CONFIRM_REQUEST, getString(R.string.security_settings_fingerprint_preference_title), null, null, challenge, mUserId)) { - intent.setClassName("com.android.settings", ChooseLockGeneric.class.getName()); + intent.setClassName(SETTINGS_PACKAGE_NAME, ChooseLockGeneric.class.getName()); intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, diff --git a/src/com/android/settings/fuelgauge/BatteryCellParser.java b/src/com/android/settings/fuelgauge/BatteryCellParser.java deleted file mode 100644 index 9139084d52e..00000000000 --- a/src/com/android/settings/fuelgauge/BatteryCellParser.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2016 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.fuelgauge; - -import android.os.BatteryStats.HistoryItem; -import android.telephony.ServiceState; -import android.util.SparseIntArray; - -import com.android.settings.Utils; -import com.android.settings.fuelgauge.BatteryActiveView.BatteryActiveProvider; - -public class BatteryCellParser implements BatteryInfo.BatteryDataParser, BatteryActiveProvider { - - private final SparseIntArray mData = new SparseIntArray(); - - private int mLastValue; - private long mLength; - private long mLastTime; - - protected int getValue(HistoryItem rec) { - int bin; - if (((rec.states & HistoryItem.STATE_PHONE_STATE_MASK) - >> HistoryItem.STATE_PHONE_STATE_SHIFT) - == ServiceState.STATE_POWER_OFF) { - bin = 0; - } else if ((rec.states & HistoryItem.STATE_PHONE_SCANNING_FLAG) != 0) { - bin = 1; - } else { - bin = (rec.states & HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK) - >> HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT; - bin += 2; - } - return bin; - } - - @Override - public void onParsingStarted(long startTime, long endTime) { - mLength = endTime - startTime; - } - - @Override - public void onDataPoint(long time, HistoryItem record) { - int value = getValue(record); - if (value != mLastValue) { - mData.put((int) time, value); - mLastValue = value; - } - mLastTime = time; - } - - @Override - public void onDataGap() { - if (mLastValue != 0) { - mData.put((int) mLastTime, 0); - mLastValue = 0; - } - } - - @Override - public void onParsingDone() { - if (mLastValue != 0) { - mData.put((int) mLastTime, 0); - mLastValue = 0; - } - } - - @Override - public long getPeriod() { - return mLength; - } - - @Override - public boolean hasData() { - return mData.size() > 1; - } - - @Override - public SparseIntArray getColorArray() { - SparseIntArray ret = new SparseIntArray(); - for (int i = 0; i < mData.size(); i++) { - ret.put(mData.keyAt(i), getColor(mData.valueAt(i))); - } - return ret; - } - - private int getColor(int i) { - return Utils.BADNESS_COLORS[i]; - } -} diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java index 13ba5f6bcfe..02af00c39a9 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java @@ -16,6 +16,8 @@ package com.android.settings.fuelgauge.batterytip.detectors; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.content.Context; import android.os.BatteryStats; import android.text.format.DateUtils; @@ -91,7 +93,7 @@ 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") + .setPackageName(SETTINGS_PACKAGE_NAME) .setScreenOnTimeMs(TimeUnit.HOURS.toMillis(3)) .build()); } diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java index 63bb97784ce..70ae0ec9eaa 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java @@ -16,6 +16,8 @@ package com.android.settings.fuelgauge.batterytip.detectors; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.content.Context; import androidx.annotation.VisibleForTesting; @@ -87,7 +89,7 @@ public class RestrictAppDetector implements BatteryTipDetector { private BatteryTip getFakeData() { final List highUsageApps = new ArrayList<>(); highUsageApps.add(new AppInfo.Builder() - .setPackageName("com.android.settings") + .setPackageName(SETTINGS_PACKAGE_NAME) .build()); return new RestrictAppTip(BatteryTip.StateType.NEW, highUsageApps); } diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java index 32e8eafa2f6..00e0bcdb658 100644 --- a/src/com/android/settings/password/ChooseLockSettingsHelper.java +++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java @@ -16,6 +16,8 @@ package com.android.settings.password; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.annotation.Nullable; import android.app.Activity; import android.app.KeyguardManager; @@ -408,7 +410,7 @@ public final class ChooseLockSettingsHelper { if (extras != null) { intent.putExtras(extras); } - intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName()); + intent.setClassName(SETTINGS_PACKAGE_NAME, activityClass.getName()); if (external) { intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); if (mFragment != null) { diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java index 3fa2f6ac08b..db0935d08ab 100644 --- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java +++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java @@ -17,6 +17,8 @@ package com.android.settings.password; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.app.Activity; import android.app.KeyguardManager; import android.app.admin.DevicePolicyManager; @@ -62,7 +64,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity { public static Intent createIntent(CharSequence title, CharSequence details) { Intent intent = new Intent(); - intent.setClassName("com.android.settings", + intent.setClassName(SETTINGS_PACKAGE_NAME, ConfirmDeviceCredentialActivity.class.getName()); intent.putExtra(KeyguardManager.EXTRA_TITLE, title); intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION, details); @@ -71,7 +73,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity { public static Intent createIntent(CharSequence title, CharSequence details, long challenge) { Intent intent = new Intent(); - intent.setClassName("com.android.settings", + intent.setClassName(SETTINGS_PACKAGE_NAME, ConfirmDeviceCredentialActivity.class.getName()); intent.putExtra(KeyguardManager.EXTRA_TITLE, title); intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION, details); diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java index e14ec811353..bb953a133a2 100644 --- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java +++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java @@ -17,6 +17,8 @@ // TODO (b/35202196): move this class out of the root of the package. package com.android.settings.password; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.annotation.Nullable; import android.app.Dialog; import android.app.KeyguardManager; @@ -55,17 +57,16 @@ import com.android.settings.core.InstrumentedFragment; */ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment { - public static final String PACKAGE = "com.android.settings"; - public static final String TITLE_TEXT = PACKAGE + ".ConfirmCredentials.title"; - public static final String HEADER_TEXT = PACKAGE + ".ConfirmCredentials.header"; - public static final String DETAILS_TEXT = PACKAGE + ".ConfirmCredentials.details"; - public static final String DARK_THEME = PACKAGE + ".ConfirmCredentials.darkTheme"; + public static final String TITLE_TEXT = SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.title"; + public static final String HEADER_TEXT = SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.header"; + public static final String DETAILS_TEXT = SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.details"; + public static final String DARK_THEME = SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.darkTheme"; public static final String SHOW_CANCEL_BUTTON = - PACKAGE + ".ConfirmCredentials.showCancelButton"; + SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.showCancelButton"; public static final String SHOW_WHEN_LOCKED = - PACKAGE + ".ConfirmCredentials.showWhenLocked"; + SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.showWhenLocked"; public static final String USE_FADE_ANIMATION = - PACKAGE + ".ConfirmCredentials.useFadeAnimation"; + SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.useFadeAnimation"; protected static final int USER_TYPE_PRIMARY = 1; protected static final int USER_TYPE_MANAGED_PROFILE = 2; diff --git a/src/com/android/settings/password/PasswordUtils.java b/src/com/android/settings/password/PasswordUtils.java index 5f118cf0e6c..2300b980a6a 100644 --- a/src/com/android/settings/password/PasswordUtils.java +++ b/src/com/android/settings/password/PasswordUtils.java @@ -16,6 +16,8 @@ package com.android.settings.password; +import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; + import android.annotation.Nullable; import android.app.ActivityManager; import android.app.IActivityManager; @@ -32,8 +34,6 @@ public final class PasswordUtils extends com.android.settingslib.Utils { private static final String TAG = "Settings"; - private static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; - /** * Returns whether the uid which the activity with {@code activityToken} is launched from has * been granted the {@code permission}. diff --git a/tests/robotests/Android.mk b/tests/robotests/Android.mk index 50133d9347c..b0733f4ded7 100644 --- a/tests/robotests/Android.mk +++ b/tests/robotests/Android.mk @@ -3,11 +3,11 @@ LOCAL_PATH := $(call my-dir) SETTINGS_AOSP_PATH := packages/apps/Settings ############################################################# -# Build SettingsTest.apk which includes test-only resources.# +# Build SettingsRoboTestStub.apk which includes test-only resources.# ############################################################# include $(CLEAR_VARS) -LOCAL_PACKAGE_NAME := SettingsTest +LOCAL_PACKAGE_NAME := SettingsRoboTestStub LOCAL_PRIVATE_PLATFORM_APIS := true LOCAL_CERTIFICATE := platform LOCAL_PRIVILEGED_MODULE := true @@ -77,7 +77,7 @@ LOCAL_JAVA_LIBRARIES := \ mockito-robolectric-prebuilt \ truth-prebuilt -LOCAL_INSTRUMENTATION_FOR := SettingsTest +LOCAL_INSTRUMENTATION_FOR := SettingsRoboTestStub LOCAL_MODULE_TAGS := optional @@ -100,7 +100,7 @@ LOCAL_JAVA_LIBRARIES := \ mockito-robolectric-prebuilt \ truth-prebuilt -LOCAL_TEST_PACKAGE := SettingsTest +LOCAL_TEST_PACKAGE := SettingsRoboTestStub LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src \ frameworks/base/packages/SettingsLib/search/src \ diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java index 3b024ebfb72..275bfe02787 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java @@ -18,7 +18,6 @@ package com.android.settings.fuelgauge.batterytip; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -60,7 +59,8 @@ public class BatteryTipUtilsTest { MockitoAnnotations.initMocks(this); FakeFeatureFactory.setupForTest(); - doReturn(RuntimeEnvironment.application).when(mFragment).getContext(); + when(mSettingsActivity.getApplicationContext()).thenReturn(RuntimeEnvironment.application); + when(mFragment.getContext()).thenReturn(RuntimeEnvironment.application); mRestrictAppTip = spy(new RestrictAppTip(BatteryTip.StateType.NEW, new ArrayList<>())); mEarlyWarningTip = spy( new EarlyWarningTip(BatteryTip.StateType.NEW, true /* powerSaveModeOn */)); From 5bf4e1ec4f878e64427ebdcddbd1b00a87ddd7c3 Mon Sep 17 00:00:00 2001 From: Ruchi Kandoi Date: Thu, 17 Jan 2019 15:31:02 -0800 Subject: [PATCH 15/19] Add Secure NFC functionality Secure NFC will permit NFC acitvity only when screen is unlocked. Bug: 117253725 Test: Manual; Toggle switch; check if HCE works with screen off Change-Id: I9977d85065fc7ebca3ed4991ffa52fef0590cf90 --- res/values/strings.xml | 7 +- res/xml/connected_devices_advanced.xml | 8 ++ .../settings/nfc/AndroidBeamEnabler.java | 2 +- .../settings/nfc/SecureNfcEnabler.java | 60 +++++++++++ .../nfc/SecureNfcPreferenceController.java | 99 +++++++++++++++++++ ...dConnectedDeviceDashboardFragmentTest.java | 14 ++- 6 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 src/com/android/settings/nfc/SecureNfcEnabler.java create mode 100644 src/com/android/settings/nfc/SecureNfcPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index f77c10d577c..9576c1482b7 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1859,6 +1859,11 @@ NFC exchanges data between this device and other nearby devices or targets, such as payment terminals, access readers, and interactive ads or tags. + + Secure NFC + + Allow NFC Payment and Transit use only when screen is unlocked + Android Beam @@ -1866,7 +1871,7 @@ Off - Unavailable because NFC is turned off + Unavailable because NFC is turned off Android Beam diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml index b5d2a999e4b..2ceceb384f0 100644 --- a/res/xml/connected_devices_advanced.xml +++ b/res/xml/connected_devices_advanced.xml @@ -44,6 +44,14 @@ android:icon="@drawable/ic_android" android:order="-6"/> + + niks = AdvancedConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER - .getNonIndexableKeys(RuntimeEnvironment.application); + .getNonIndexableKeys(context); assertThat(niks).contains(AdvancedConnectedDeviceDashboardFragment.KEY_BLUETOOTH); } From 1c15a27c1dbab59bfe4fee9d9b56067dec882526 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Tue, 29 Jan 2019 16:33:53 -0800 Subject: [PATCH 16/19] Remove cardview wrapper on condition collapse button. The cardview is adding a strange background color in dark mode Change-Id: Id205fbd5209e15597157d86d225f8c6c97a2ec5a Fixes: 123411225 Test: visual --- res/layout/homepage_condition_footer.xml | 32 ++++++++++-------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/res/layout/homepage_condition_footer.xml b/res/layout/homepage_condition_footer.xml index 0ff7ac61231..56687fe4b04 100644 --- a/res/layout/homepage_condition_footer.xml +++ b/res/layout/homepage_condition_footer.xml @@ -15,26 +15,20 @@ limitations under the License. --> - + android:layout_height="@dimen/homepage_condition_footer_height" + android:contentDescription="@string/homepage_condition_footer_content_description" + android:gravity="end" + android:orientation="horizontal" + android:paddingTop="@dimen/homepage_condition_footer_padding_top" + android:paddingEnd="@dimen/homepage_condition_footer_padding_end"> - + - - - - \ No newline at end of file + \ No newline at end of file From c04425fe38f38d50316d80e6be73563e8e3e796f Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Tue, 29 Jan 2019 12:12:39 -0500 Subject: [PATCH 17/19] Add silent status bar icon setting Test: atest Bug: 123419917 Change-Id: I40fe580b76589c45a70365c09a966a76b5bc882b --- res/values/strings.xml | 6 + res/xml/configure_notification_settings.xml | 6 + .../notification/NotificationBackend.java | 17 +++ .../SilentStatusBarPreferenceController.java | 58 +++++++++ ...lentStatusBarPreferenceControllerTest.java | 110 ++++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 src/com/android/settings/notification/SilentStatusBarPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/notification/SilentStatusBarPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 1a92f7bc1c7..ecb74bbae71 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7590,6 +7590,12 @@ Work notifications + + Hide silent notification status icons + + + Hide icons for silent notifications in the status bar + Allow notification dots diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml index e4d948bef88..ca826095f08 100644 --- a/res/xml/configure_notification_settings.xml +++ b/res/xml/configure_notification_settings.xml @@ -26,6 +26,12 @@ android:summary="@string/summary_placeholder" settings:searchable="false"/> + + Date: Tue, 29 Jan 2019 17:33:57 -0800 Subject: [PATCH 18/19] ConfirmDeviceCredential should default to setRequireConfirmation(true) If the value is unset, we should maintain the same default behavior as BiometricPrompt, which is to dfeault to requiring confirmation. Fixes: 123598496 Test: manual Change-Id: Icaf27d184e0aea5eee077b8ec14bca27fd0ddad3 --- src/com/android/settings/password/BiometricFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/password/BiometricFragment.java b/src/com/android/settings/password/BiometricFragment.java index 3809a4a5b48..7a685ab535a 100644 --- a/src/com/android/settings/password/BiometricFragment.java +++ b/src/com/android/settings/password/BiometricFragment.java @@ -125,7 +125,8 @@ public class BiometricFragment extends InstrumentedFragment { .setUseDefaultTitle() // use default title if title is null/empty .setSubtitle(mBundle.getString(BiometricPrompt.KEY_SUBTITLE)) .setDescription(mBundle.getString(BiometricPrompt.KEY_DESCRIPTION)) - .setRequireConfirmation(mBundle.getBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION)) + .setRequireConfirmation( + mBundle.getBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true)) .setNegativeButton(getResources().getString( R.string.confirm_device_credential_use_alternate_method), mClientExecutor, mNegativeButtonListener) From fa27a88292c974eed478fe6a09c3b8be235441d4 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 30 Jan 2019 18:10:17 +0000 Subject: [PATCH 19/19] Revert "Add live caption preference in accessibility page." This reverts commit d64901494fb4bd2f195d8c6da7258f107207eebf. Reason for revert: b/123636344 Change-Id: If6307935ba3613cb24f5bab2234febef83c6f7d2 --- res/values/strings.xml | 6 -- res/xml/accessibility_settings.xml | 6 -- .../accessibility/AccessibilitySettings.java | 19 ++---- .../LiveCaptionPreferenceController.java | 58 ---------------- .../LiveCaptionPreferenceControllerTest.java | 66 ------------------- 5 files changed, 4 insertions(+), 151 deletions(-) delete mode 100644 src/com/android/settings/accessibility/LiveCaptionPreferenceController.java delete mode 100644 tests/robotests/src/com/android/settings/accessibility/LiveCaptionPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index ea3979f3175..9f5b562c2be 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7355,12 +7355,6 @@ Turn off now - - Live Caption - - - Auto-convert on-device audio to captions - Do Not Disturb is on until %s diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml index b3e1704967c..cc07ce119e9 100644 --- a/res/xml/accessibility_settings.xml +++ b/res/xml/accessibility_settings.xml @@ -124,12 +124,6 @@ android:key="audio_and_captions_category" android:title="@string/audio_and_captions_category_title"> - - resolved = - mPackageManager.queryIntentActivities(LIVE_CAPTION_INTENT, 0 /* flags */); - return resolved != null && !resolved.isEmpty() - ? AVAILABLE - : UNSUPPORTED_ON_DEVICE; - } - - @Override - public void updateState(Preference preference) { - super.updateState(preference); - preference.setIntent(LIVE_CAPTION_INTENT); - } -} diff --git a/tests/robotests/src/com/android/settings/accessibility/LiveCaptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/LiveCaptionPreferenceControllerTest.java deleted file mode 100644 index f6160b285cb..00000000000 --- a/tests/robotests/src/com/android/settings/accessibility/LiveCaptionPreferenceControllerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2019 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.accessibility; - -import static com.android.settings.core.BasePreferenceController.AVAILABLE; -import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; - -import static com.google.common.truth.Truth.assertThat; - -import android.content.pm.ResolveInfo; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.Shadows; -import org.robolectric.shadows.ShadowPackageManager; - -import java.util.Collections; - -@RunWith(RobolectricTestRunner.class) -public class LiveCaptionPreferenceControllerTest { - - private LiveCaptionPreferenceController mController; - - @Before - public void setUp() { - mController = new LiveCaptionPreferenceController(RuntimeEnvironment.application, - "test_key"); - } - - @Test - public void getAvailabilityStatus_canResolveIntent_shouldReturnAvailable() { - final ShadowPackageManager pm = Shadows.shadowOf( - RuntimeEnvironment.application.getPackageManager()); - pm.addResolveInfoForIntent(LiveCaptionPreferenceController.LIVE_CAPTION_INTENT, - new ResolveInfo()); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); - } - - @Test - public void getAvailabilityStatus_noResolveIntent_shouldReturnUnavailable() { - final ShadowPackageManager pm = Shadows.shadowOf( - RuntimeEnvironment.application.getPackageManager()); - pm.setResolveInfosForIntent(LiveCaptionPreferenceController.LIVE_CAPTION_INTENT, - Collections.emptyList()); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); - } -}