Merge "Prevent HTML Injection on the Device Admin request screen" into sc-dev
diff --git a/res/layout/accessibility_edit_magnification_shortcut.xml b/res/layout/accessibility_edit_magnification_shortcut.xml
index bed1255..5f885b9 100644
--- a/res/layout/accessibility_edit_magnification_shortcut.xml
+++ b/res/layout/accessibility_edit_magnification_shortcut.xml
@@ -25,13 +25,21 @@
android:orientation="vertical"
android:padding="24dp">
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="@dimen/accessibility_imageview_size"
+ android:layout_height="@dimen/accessibility_imageview_size"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="@dimen/accessibility_textview_layout_margin_bottom"
+ android:scaleType="fitCenter"/>
+
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accessibility_magnification_switch_shortcut_message"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
- android:layout_marginBottom="24dp"/>
+ android:layout_marginBottom="@dimen/accessibility_textview_layout_margin_bottom"/>
<LinearLayout
android:layout_width="match_parent"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index aca3322..e56b2c8 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -292,6 +292,8 @@
<dimen name="accessibility_layout_margin_start_end">16dp</dimen>
<dimen name="accessibility_button_preference_padding_top_bottom">18dp</dimen>
<dimen name="accessibility_imageview_size">176dp</dimen>
+ <!-- The margin between two Textviews-->
+ <dimen name="accessibility_textview_layout_margin_bottom">24dp</dimen>
<!-- Restricted icon in switch bar -->
<dimen name="restricted_icon_margin_end">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2a05a4d..c1c165e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6565,8 +6565,10 @@
<string name="vpn_settings_title">VPN</string>
<!-- Title of preference to enter the VPN settings activity [CHAR LIMIT=30] -->
<string name="vpn_settings_insecure_single">Not secure</string>
- <!-- Title of preference to enter the VPN settings activity [CHAR LIMIT=30] -->
- <string name="vpn_settings_insecure_multiple"><xliff:g id="vpn_count" example="1">%d</xliff:g> not secure</string>
+ <!-- Title of preference to enter the VPN settings activity, if there are multiple vpns but only 1 insecure vpn [CHAR LIMIT=60] -->
+ <string name="vpn_settings_single_insecure_multiple_total"><xliff:g id="vpn_count" example="1">%d</xliff:g> not secure</string>
+ <!-- Title of preference to enter the VPN settings activity, if there are multiple vpns and multiple insecure vpns [CHAR LIMIT=60] -->
+ <string name="vpn_settings_multiple_insecure_multiple_total"><xliff:g id="vpn_count" example="1">%d</xliff:g> not secure</string>
<!-- Title of Adaptive connectivity. Adaptive connectivity is a feature which automatically manages network connections for better battery life and performance. [CHAR LIMIT=60] -->
<string name="adaptive_connectivity_title">Adaptive connectivity</string>
@@ -13135,13 +13137,13 @@
<!-- Brightness category name in Display Settings [CHAR LIMIT=none] -->
<string name="category_name_brightness">Brightness</string>
<!-- Lock screen category name in Display Settings [CHAR LIMIT=none] -->
- <string name="category_name_lock_display">Lock Display</string>
+ <string name="category_name_lock_display">Lock display</string>
<!-- Appearance category name in Display Settings [CHAR LIMIT=none] -->
<string name="category_name_appearance">Appearance</string>
<!-- Color category name in Display Settings [CHAR LIMIT=none] -->
<string name="category_name_color">Color</string>
<!-- Name of Other display controls category in Display Settings [CHAR LIMIT=none] -->
- <string name="category_name_display_controls">Other Display Controls</string>
+ <string name="category_name_display_controls">Other display controls</string>
<!-- Others category name [CHAR LIMIT=none] -->
<string name="category_name_others">Others</string>
<!-- General category name [CHAR LIMIT=none] -->
diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
index 5d2a3fa..da3b479 100644
--- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
@@ -168,6 +168,7 @@
View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM,
View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM);
}
+
private static void setEditShortcutButtonsListener(AlertDialog dialog,
View.OnClickListener listener) {
final View contentView = dialog.findViewById(R.id.container_layout);
@@ -215,6 +216,8 @@
case DialogType.EDIT_MAGNIFICATION_SWITCH_SHORTCUT:
contentView = inflater.inflate(
R.layout.accessibility_edit_magnification_shortcut, null);
+ final ImageView image = contentView.findViewById(R.id.image);
+ image.setImageResource(retrieveSoftwareShortcutImageResId(context));
break;
default:
throw new IllegalArgumentException();
@@ -247,7 +250,7 @@
final int lineHeight = summary.getLineHeight();
setupShortcutWidget(dialogView, title, retrieveSummary(context, lineHeight),
- retrieveImageResId(context));
+ retrieveSoftwareShortcutImageResId(context));
}
private static void initHardwareShortcut(Context context, View view) {
@@ -286,7 +289,7 @@
? getSummaryStringWithLink(context) : getSummaryStringWithIcon(context, lineHeight);
}
- private static int retrieveImageResId(Context context) {
+ private static int retrieveSoftwareShortcutImageResId(Context context) {
return AccessibilityUtil.isFloatingMenuEnabled(context)
? R.drawable.accessibility_shortcut_type_software_floating
: R.drawable.accessibility_shortcut_type_software;
diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
index e502d65..cc14586 100644
--- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
@@ -85,6 +85,7 @@
private static final int RIGHT_DEVICE_ID = 2;
private static final int CASE_DEVICE_ID = 3;
private static final int MAIN_DEVICE_ID = 4;
+ private static final float HALF_ALPHA = 0.5f;
@VisibleForTesting
LayoutPreference mLayoutPreference;
@@ -430,10 +431,12 @@
@VisibleForTesting
void updateIcon(ImageView imageView, String iconUri) {
if (mIconCache.containsKey(iconUri)) {
+ imageView.setAlpha(1f);
imageView.setImageBitmap(mIconCache.get(iconUri));
return;
}
+ imageView.setAlpha(HALF_ALPHA);
ThreadUtils.postOnBackgroundThread(() -> {
final Uri uri = Uri.parse(iconUri);
try {
@@ -444,6 +447,7 @@
mContext.getContentResolver(), uri);
ThreadUtils.postOnMainThread(() -> {
mIconCache.put(iconUri, bitmap);
+ imageView.setAlpha(1f);
imageView.setImageBitmap(bitmap);
});
} catch (IOException e) {
diff --git a/src/com/android/settings/development/BluetoothGabeldorschePreferenceController.java b/src/com/android/settings/development/BluetoothGabeldorschePreferenceController.java
index 48a3e95..f5c30f5 100644
--- a/src/com/android/settings/development/BluetoothGabeldorschePreferenceController.java
+++ b/src/com/android/settings/development/BluetoothGabeldorschePreferenceController.java
@@ -17,7 +17,7 @@
package com.android.settings.development;
import android.content.Context;
-import android.os.SystemProperties;
+import android.provider.DeviceConfig;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -35,9 +35,9 @@
private static final String BLUETOOTH_GABELDORSCHE_KEY =
"bluetooth_gabeldorsche_enable";
+
@VisibleForTesting
- static final String BLUETOOTH_GABELDORSCHE_PROPERTY =
- "bluetooth.gd.enabled";
+ static final String CURRENT_GD_FLAG = "INIT_gd_scanning";
public BluetoothGabeldorschePreferenceController(Context context) {
super(context);
@@ -51,22 +51,23 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean isEnabled = (Boolean) newValue;
- SystemProperties.set(BLUETOOTH_GABELDORSCHE_PROPERTY,
- isEnabled ? "true" : "false");
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH,
+ CURRENT_GD_FLAG, isEnabled ? "true" : "false", false /* makeDefault */);
return true;
}
@Override
public void updateState(Preference preference) {
- final boolean isEnabled = SystemProperties.getBoolean(
- BLUETOOTH_GABELDORSCHE_PROPERTY, false /* default */);
+ final boolean isEnabled = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_BLUETOOTH, CURRENT_GD_FLAG, false /* default */);
((SwitchPreference) mPreference).setChecked(isEnabled);
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
super.onDeveloperOptionsSwitchDisabled();
- SystemProperties.set(BLUETOOTH_GABELDORSCHE_PROPERTY, "false");
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH,
+ CURRENT_GD_FLAG, null, false /* makeDefault */);
((SwitchPreference) mPreference).setChecked(false);
}
}
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index ed52f48..309551b 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -55,13 +55,20 @@
public static final class NameAndIcon {
public final String name;
+ public final String packageName;
public final Drawable icon;
public final int iconId;
public NameAndIcon(String name, Drawable icon, int iconId) {
+ this(name, /*packageName=*/ null, icon, iconId);
+ }
+
+ public NameAndIcon(
+ String name, String packageName, Drawable icon, int iconId) {
this.name = name;
this.icon = icon;
this.iconId = iconId;
+ this.packageName = packageName;
}
}
@@ -102,7 +109,15 @@
}
be = sRequestQueue.remove(0);
}
- be.loadNameAndIcon();
+ final NameAndIcon nameAndIcon =
+ BatteryEntry.loadNameAndIcon(
+ be.mContext, be.getUid(), sHandler, be, be.mDefaultPackageName);
+ if (nameAndIcon != null) {
+ be.icon = getNonNull(be.icon, nameAndIcon.icon);
+ be.name = getNonNull(be.name, nameAndIcon.name);
+ be.mDefaultPackageName = getNonNull(
+ be.mDefaultPackageName, nameAndIcon.packageName);
+ }
}
}
}
@@ -262,27 +277,33 @@
/**
* Loads the app label and icon image and stores into the cache.
*/
- public void loadNameAndIcon() {
+ public static NameAndIcon loadNameAndIcon(
+ Context context,
+ int uid,
+ Handler handler,
+ BatteryEntry batteryEntry,
+ String defaultPackageName) {
+ String name = null;
+ Drawable icon = null;
// Bail out if the current sipper is not an App sipper.
- final int uid = getUid();
if (uid == 0 || uid == Process.INVALID_UID) {
- return;
+ return null;
}
- final PackageManager pm = mContext.getPackageManager();
+ final PackageManager pm = context.getPackageManager();
final String[] packages;
if (uid == Process.SYSTEM_UID) {
- packages = new String[]{PACKAGE_SYSTEM};
+ packages = new String[] {PACKAGE_SYSTEM};
} else {
packages = pm.getPackagesForUid(uid);
}
if (packages != null) {
- String[] packageLabels = new String[packages.length];
+ final String[] packageLabels = new String[packages.length];
System.arraycopy(packages, 0, packageLabels, 0, packages.length);
// Convert package names to user-facing labels where possible
- IPackageManager ipm = AppGlobals.getPackageManager();
+ final IPackageManager ipm = AppGlobals.getPackageManager();
final int userId = UserHandle.getUserId(uid);
for (int i = 0; i < packageLabels.length; i++) {
try {
@@ -293,12 +314,12 @@
+ packageLabels[i] + ", user " + userId);
continue;
}
- CharSequence label = ai.loadLabel(pm);
+ final CharSequence label = ai.loadLabel(pm);
if (label != null) {
packageLabels[i] = label.toString();
}
if (ai.icon != 0) {
- mDefaultPackageName = packages[i];
+ defaultPackageName = packages[i];
icon = ai.loadIcon(pm);
break;
}
@@ -326,7 +347,7 @@
if (nm != null) {
name = nm.toString();
if (pi.applicationInfo.icon != 0) {
- mDefaultPackageName = pkgName;
+ defaultPackageName = pkgName;
icon = pi.applicationInfo.loadIcon(pm);
}
break;
@@ -352,12 +373,13 @@
UidToDetail utd = new UidToDetail();
utd.name = name;
utd.icon = icon;
- utd.packageName = mDefaultPackageName;
+ utd.packageName = defaultPackageName;
sUidCache.put(uidString, utd);
- if (sHandler != null) {
- sHandler.sendMessage(sHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this));
+ if (handler != null) {
+ handler.sendMessage(sHandler.obtainMessage(MSG_UPDATE_NAME_ICON, batteryEntry));
}
+ return new NameAndIcon(name, defaultPackageName, icon, /*iconId=*/ 0);
}
/**
@@ -557,4 +579,8 @@
}
return new NameAndIcon(name, null /* icon */, iconId);
}
+
+ private static <T> T getNonNull(T originalObj, T newObj) {
+ return newObj != null ? newObj : originalObj;
+ }
}
diff --git a/src/com/android/settings/network/VpnPreferenceController.java b/src/com/android/settings/network/VpnPreferenceController.java
index 0bec7ac..4944f43 100644
--- a/src/com/android/settings/network/VpnPreferenceController.java
+++ b/src/com/android/settings/network/VpnPreferenceController.java
@@ -169,9 +169,14 @@
- connectedLegacyVpnCount;
if (vpnCount == 1) {
summary = mContext.getString(R.string.vpn_settings_insecure_single);
+ } else if (insecureVpnCount == 1) {
+ summary = mContext.getString(
+ R.string.vpn_settings_single_insecure_multiple_total,
+ insecureVpnCount);
} else {
summary = mContext.getString(
- R.string.vpn_settings_insecure_multiple, insecureVpnCount);
+ R.string.vpn_settings_multiple_insecure_multiple_total,
+ insecureVpnCount);
}
}
}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothGabeldorschePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothGabeldorschePreferenceControllerTest.java
new file mode 100644
index 0000000..472a960
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothGabeldorschePreferenceControllerTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 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.BluetoothGabeldorschePreferenceController
+ .CURRENT_GD_FLAG;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothGabeldorschePreferenceControllerTest {
+
+ @Mock
+ private SwitchPreference mPreference;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private BluetoothGabeldorschePreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ Context context = RuntimeEnvironment.application;
+ mController = new BluetoothGabeldorschePreferenceController(context);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void onPreferenceChanged_settingEnabled_shouldTurnOnBluetoothGabeldorsche() {
+ mController.onPreferenceChange(mPreference, true /* new value */);
+
+ boolean enabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH,
+ CURRENT_GD_FLAG, false /* defaultValue */);
+
+ assertThat(enabled).isTrue();
+ }
+
+ @Test
+ public void onPreferenceChanged_settingDisabled_shouldTurnOffBluetoothGabeldorsche() {
+ mController.onPreferenceChange(mPreference, false /* new value */);
+
+ boolean enabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH,
+ CURRENT_GD_FLAG, false /* defaultValue */);
+
+ assertThat(enabled).isFalse();
+ }
+
+ @Test
+ public void updateState_settingEnabled_preferenceShouldBeChecked() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH,
+ CURRENT_GD_FLAG, "true", false /* makeDefault */);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(true);
+ }
+
+ @Test
+ public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH,
+ CURRENT_GD_FLAG, "false", false /* makeDefault */);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(false);
+ }
+
+ @Test
+ public void onDeveloperOptionsDisabled_shouldDisablePreference() {
+ mController.onDeveloperOptionsDisabled();
+
+ String configStr = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_BLUETOOTH,
+ CURRENT_GD_FLAG);
+
+ assertThat(configStr).isNull();
+ verify(mPreference).setEnabled(false);
+ verify(mPreference).setChecked(false);
+ }
+}