From 413f0685363f83a7c2fbdd1f4c4f7d86237db704 Mon Sep 17 00:00:00 2001 From: Oli Lan Date: Mon, 15 Mar 2021 17:18:37 +0000 Subject: [PATCH 01/12] Use DeviceConfig property for default value of clipboard access notification setting. This uses a new DeviceConfig property for the default value of the setting that controls whether a notification is shown when an app accesses clipboard. Bug: 182349993 Test: manual, "adb shell device_config put clipboard show_access_notifications false" and observe setting changes when not set manually; also check notifications shown when expected. Test: make RunSettingsRoboTests ROBOTEST_FILTER= "com.android.settings.privacy.ShowClipAccessNotificationPreferenceControllerTest" Change-Id: I452b1850ecc5fefb2ca9476d249866b32c885478 --- ...ccessNotificationPreferenceController.java | 53 +++++++++++++++++-- ...sNotificationPreferenceControllerTest.java | 44 ++++++++++++++- 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceController.java b/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceController.java index 46224315992..cf05ff48cc6 100644 --- a/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceController.java +++ b/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceController.java @@ -16,33 +16,47 @@ package com.android.settings.privacy; +import android.content.ClipboardManager; import android.content.Context; +import android.provider.DeviceConfig; import android.provider.Settings; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + import com.android.settings.core.TogglePreferenceController; /** * Controller for preference to toggle whether clipboard access notifications should be shown. */ -public class ShowClipAccessNotificationPreferenceController extends TogglePreferenceController { +public class ShowClipAccessNotificationPreferenceController + extends TogglePreferenceController implements LifecycleObserver { private static final String KEY_SHOW_CLIP_ACCESS_NOTIFICATION = "show_clip_access_notification"; + private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener = + properties -> updateConfig(); + private boolean mDefault; + private Preference mPreference; + public ShowClipAccessNotificationPreferenceController(Context context) { super(context, KEY_SHOW_CLIP_ACCESS_NOTIFICATION); + updateConfig(); } @Override public boolean isChecked() { - // TODO(b/182349993) Retrieve default value from DeviceConfig. return Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, 1) != 0; + Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, (mDefault ? 1 : 0)) != 0; } @Override public boolean setChecked(boolean isChecked) { Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, isChecked ? 1 : 0); + Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, (isChecked ? 1 : 0)); return true; } @@ -51,4 +65,35 @@ public class ShowClipAccessNotificationPreferenceController extends TogglePrefer return AVAILABLE; } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + mPreference = screen.findPreference(getPreferenceKey()); + } + + /** + * Registers a DeviceConfig listener on start. + */ + @OnLifecycleEvent(Lifecycle.Event.ON_START) + public void onStart() { + DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_CLIPBOARD, + mContext.getMainExecutor(), mDeviceConfigListener); + } + + /** + * Removes the DeviceConfig listener on stop. + */ + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + public void onStop() { + DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListener); + } + + private void updateConfig() { + mDefault = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CLIPBOARD, + ClipboardManager.DEVICE_CONFIG_SHOW_ACCESS_NOTIFICATIONS, + ClipboardManager.DEVICE_CONFIG_DEFAULT_SHOW_ACCESS_NOTIFICATIONS); + updateState(mPreference); + } + } diff --git a/tests/robotests/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceControllerTest.java index c707cd600ae..fdf81e733ce 100644 --- a/tests/robotests/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/privacy/ShowClipAccessNotificationPreferenceControllerTest.java @@ -18,8 +18,10 @@ package com.android.settings.privacy; import static com.google.common.truth.Truth.assertThat; +import android.content.ClipboardManager; import android.content.ContentResolver; import android.content.Context; +import android.provider.DeviceConfig; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; @@ -27,14 +29,18 @@ import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.testutils.shadow.ShadowDeviceConfig; + 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.annotation.Config; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowDeviceConfig.class}) public class ShowClipAccessNotificationPreferenceControllerTest { @Mock @@ -54,19 +60,47 @@ public class ShowClipAccessNotificationPreferenceControllerTest { } @Test - public void isChecked_settingIsOff_shouldReturnFalse() throws Exception { + public void isChecked_settingIsOff_shouldReturnFalse() { setProperty(0); assertThat(mController.isChecked()).isFalse(); } @Test - public void isChecked_settingIsOn_shouldReturnTrue() throws Exception { + public void isChecked_settingIsOn_shouldReturnTrue() { setProperty(1); assertThat(mController.isChecked()).isTrue(); } + @Test + public void isChecked_settingIsUnset_deviceConfigProvidesDefaultOfTrue() { + clearProperty(); + + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CLIPBOARD, + ClipboardManager.DEVICE_CONFIG_SHOW_ACCESS_NOTIFICATIONS, + "true", false); + + ShowClipAccessNotificationPreferenceController controller = + new ShowClipAccessNotificationPreferenceController(mContext); + + assertThat(controller.isChecked()).isTrue(); + } + + @Test + public void isChecked_settingIsUnset_deviceConfigProvidesDefaultOfFalse() { + clearProperty(); + + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CLIPBOARD, + ClipboardManager.DEVICE_CONFIG_SHOW_ACCESS_NOTIFICATIONS, + "false", false); + + ShowClipAccessNotificationPreferenceController controller = + new ShowClipAccessNotificationPreferenceController(mContext); + + assertThat(controller.isChecked()).isFalse(); + } + @Test public void onPreferenceChange_turnOn_shouldChangeSettingTo1() throws Exception { setProperty(0); @@ -93,6 +127,12 @@ public class ShowClipAccessNotificationPreferenceControllerTest { contentResolver, Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, newValue); } + private void clearProperty() { + final ContentResolver contentResolver = mContext.getContentResolver(); + Settings.Secure.putString( + contentResolver, Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, null); + } + private void assertProperty(int expectedValue) throws SettingNotFoundException { final ContentResolver contentResolver = mContext.getContentResolver(); assertThat(Settings.Secure.getInt( From a4788bdc819a5f6f45f815bc73bcd67dd19e1aa3 Mon Sep 17 00:00:00 2001 From: Ivan Chiang Date: Thu, 1 Apr 2021 18:03:24 +0800 Subject: [PATCH 02/12] Update the strings for Media Management Apps Bug: 184102095 Test: manual, screenshot Change-Id: I0be92b600bc45fd805c01e6be5db39df40976ead --- res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 25535000e9b..cc64f2ec1be 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10499,9 +10499,9 @@ Media management apps - Allow app to manage media files + Allow app to manage media - If allowed, this app can modify or delete media files on this device or connected storage device without asking you. App must have permission to access files and media. + If allowed, this app can modify or delete media files created with other apps without asking you. App must have permission to access files and media. Media, File, Management, Manager, Manage, Edit, Editor, App, Application, Program From a51780f35d868a8816c635ad717c139c51a2cf65 Mon Sep 17 00:00:00 2001 From: Jeremy Goldman Date: Wed, 7 Apr 2021 16:26:52 +0800 Subject: [PATCH 03/12] Subscription name has whitespace trimmed to determine uniqueness For example, if a subscription has the name "subsc" and another has "subsc " the extra unique information will be added to the subscriptions. Test: atest -c SubscriptionUtilTest Bug: 183664625 Change-Id: Ia137169f6cdd9804ab04126e5045c9fb61556d54 --- .../settings/network/SubscriptionUtil.java | 2 +- .../network/SubscriptionUtilTest.java | 32 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java index be8f2578a64..4ba7fc90617 100644 --- a/src/com/android/settings/network/SubscriptionUtil.java +++ b/src/com/android/settings/network/SubscriptionUtil.java @@ -256,7 +256,7 @@ public class SubscriptionUtil { .map(i -> { DisplayInfo info = new DisplayInfo(); info.subscriptionInfo = i; - info.originalName = i.getDisplayName(); + info.originalName = i.getDisplayName().toString().trim(); return info; }); diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java index c0e5205a77b..3d192cf5456 100644 --- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java +++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java @@ -48,7 +48,8 @@ public class SubscriptionUtilTest { private static final int SUBID_1 = 1; private static final int SUBID_2 = 2; private static final int SUBID_3 = 3; - private static final CharSequence CARRIER_1 = "carrier1111111"; + private static final CharSequence CARRIER_1 = "carrier1"; + private static final CharSequence CARRIER_1_SPACE = " carrier1 "; private static final CharSequence CARRIER_2 = "carrier2"; private Context mContext; @@ -195,6 +196,35 @@ public class SubscriptionUtilTest { assertEquals(CARRIER_1 + " 4444", idNames.get(SUBID_2)); } + @Test + public void getUniqueDisplayNames_identicalCarriersAfterTrim_fourDigitsUsed() { + // Both subscriptoins have the same display name. + final SubscriptionInfo info1 = mock(SubscriptionInfo.class); + final SubscriptionInfo info2 = mock(SubscriptionInfo.class); + when(info1.getSubscriptionId()).thenReturn(SUBID_1); + when(info2.getSubscriptionId()).thenReturn(SUBID_2); + when(info1.getDisplayName()).thenReturn(CARRIER_1); + when(info2.getDisplayName()).thenReturn(CARRIER_1_SPACE); + when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn( + Arrays.asList(info1, info2)); + + // Each subscription has a unique last 4 digits of the phone number. + TelephonyManager sub1Telmgr = mock(TelephonyManager.class); + TelephonyManager sub2Telmgr = mock(TelephonyManager.class); + when(sub1Telmgr.getLine1Number()).thenReturn("1112223333"); + when(sub2Telmgr.getLine1Number()).thenReturn("2223334444"); + when(mTelMgr.createForSubscriptionId(SUBID_1)).thenReturn(sub1Telmgr); + when(mTelMgr.createForSubscriptionId(SUBID_2)).thenReturn(sub2Telmgr); + + final Map idNames = + SubscriptionUtil.getUniqueSubscriptionDisplayNames(mContext); + + assertThat(idNames).isNotNull(); + assertThat(idNames).hasSize(2); + assertEquals(CARRIER_1 + " 3333", idNames.get(SUBID_1)); + assertEquals(CARRIER_1 + " 4444", idNames.get(SUBID_2)); + } + @Test public void getUniqueDisplayNames_phoneNumberBlocked_subscriptoinIdFallback() { // Both subscriptoins have the same display name. From fe885c96c1f071906de3205fc0620406f5b30640 Mon Sep 17 00:00:00 2001 From: Sunny Shao Date: Wed, 7 Apr 2021 16:58:17 +0800 Subject: [PATCH 04/12] Use "Passwords & accounts" instead of "Passwords and accounts" Bug: 184713810 Test: manual test Change-Id: I48a7ae4f89b2a1df76254978173949ba463ed4a7 --- res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index fcf2f45b075..ea06c1f0b80 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7880,7 +7880,7 @@ Notification access is not available for apps in the work profile. - Passwords and accounts + Passwords & accounts Saved passwords, autofill, synced accounts Not supported by this app - Always-on active + Always on - not secure VPN + Not secure Block connections without VPN diff --git a/src/com/android/settings/vpn2/ManageablePreference.java b/src/com/android/settings/vpn2/ManageablePreference.java index c65073f2d60..b7851864da7 100644 --- a/src/com/android/settings/vpn2/ManageablePreference.java +++ b/src/com/android/settings/vpn2/ManageablePreference.java @@ -107,21 +107,20 @@ public abstract class ManageablePreference extends GearPreference { final Resources res = getContext().getResources(); final String[] states = res.getStringArray(R.array.vpn_states); String summary = (mState == STATE_NONE ? "" : states[mState]); - if (mIsAlwaysOn) { - final String alwaysOnString = res.getString(R.string.vpn_always_on_summary_active); - summary = TextUtils.isEmpty(summary) ? alwaysOnString : res.getString( - R.string.join_two_unrelated_items, summary, alwaysOnString); - } if (mIsInsecureVpn) { final String insecureString = res.getString(R.string.vpn_insecure_summary); - summary = TextUtils.isEmpty(summary) ? insecureString : res.getString( - R.string.join_two_unrelated_items, summary, insecureString); + summary = TextUtils.isEmpty(summary) ? insecureString : summary + " / " + + insecureString; SpannableString summarySpan = new SpannableString(summary); final int colorError = Utils.getColorErrorDefaultColor(getContext()); summarySpan.setSpan(new ForegroundColorSpan(colorError), 0, summary.length(), SPAN_EXCLUSIVE_INCLUSIVE); setSummary(summarySpan); + } else if (mIsAlwaysOn) { + final String alwaysOnString = res.getString(R.string.vpn_always_on_summary_active); + summary = TextUtils.isEmpty(summary) ? alwaysOnString : summary + " / " + + alwaysOnString; } else { setSummary(summary); } From 24fe5922de82b30c19f8be036a45d7905897f765 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Wed, 7 Apr 2021 20:13:36 +0800 Subject: [PATCH 06/12] Sets Storage Settings progress bar unselectable Since it does nothing if users click it. Bug: 184712147 Test: manual Change-Id: I7d243ad465a5fa3f23297ac80c82bef4d078e34a --- res/xml/storage_dashboard_fragment.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/res/xml/storage_dashboard_fragment.xml b/res/xml/storage_dashboard_fragment.xml index 9bca65a6556..adc29d33d71 100644 --- a/res/xml/storage_dashboard_fragment.xml +++ b/res/xml/storage_dashboard_fragment.xml @@ -27,6 +27,7 @@ From 741c1e42982e95fa593ba1664482ebaf9dc340d0 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Wed, 7 Apr 2021 20:34:12 +0800 Subject: [PATCH 07/12] Pop up soft keyboard when rename dialog shows Request focus for the EditText. Bug: 184710864 Test: manual At Storage Settings, select USB drive -> option menu -> Rename. Observe if soft keyboard pops up. Change-Id: Ia73829ee505c94a255306bd817d01b6bc1b80e26 --- .../settings/deviceinfo/storage/StorageRenameFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/settings/deviceinfo/storage/StorageRenameFragment.java b/src/com/android/settings/deviceinfo/storage/StorageRenameFragment.java index c67fe338ffa..c6eb0c8ad6f 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageRenameFragment.java +++ b/src/com/android/settings/deviceinfo/storage/StorageRenameFragment.java @@ -68,6 +68,7 @@ public class StorageRenameFragment extends InstrumentedDialogFragment { final View view = dialogInflater.inflate(R.layout.dialog_edittext, null, false); final EditText nickname = (EditText) view.findViewById(R.id.edittext); nickname.setText(rec.getNickname()); + nickname.requestFocus(); return builder.setTitle(R.string.storage_rename_title) .setView(view) From 209f2daeafff7698ab61152d77159bd7b6d18f33 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 7 Apr 2021 19:02:35 +0000 Subject: [PATCH 08/12] Add a divider line in safety settings https: //screenshot.googleplex.com/BmYJmftnAF354GY.png Bug: 184261824 Test: manual Change-Id: I67223f2811c0bf9a738ad3aedcbcff1f00749641 --- res/xml/emergency_settings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/res/xml/emergency_settings.xml b/res/xml/emergency_settings.xml index f8067aa60fd..66c5fd1ef96 100644 --- a/res/xml/emergency_settings.xml +++ b/res/xml/emergency_settings.xml @@ -25,7 +25,6 @@ android:layout="@layout/more_settings_button" android:order="0" android:selectable="false" - settings:allowDividerBelow="true" settings:controller="com.android.settings.emergency.MoreSettingsPreferenceController" /> + Date: Wed, 7 Apr 2021 20:10:33 +0000 Subject: [PATCH 09/12] Add icon to "Open [safety app] button https://screenshot.googleplex.com/AjFhMECtQ4E9QAa.png Bug: 184261824 Test: manual Change-Id: I2b9b74077aec29dee3a34105584c5364fa663a84 --- res/layout/more_settings_button.xml | 4 +- .../MoreSettingsPreferenceController.java | 57 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/res/layout/more_settings_button.xml b/res/layout/more_settings_button.xml index 84ef75a519e..7140d79425e 100644 --- a/res/layout/more_settings_button.xml +++ b/res/layout/more_settings_button.xml @@ -23,11 +23,13 @@