From 5a3e02dd38f07c8e7e3c7136ed0b4f17b87f7fd9 Mon Sep 17 00:00:00 2001 From: Phil Weaver Date: Thu, 8 Mar 2018 17:38:46 -0800 Subject: [PATCH 1/8] Don't pre-scale vector drawables in settings The idea of scaling down icons to prevent the system from dealing with large images seems to be catching some VectorDrawables and rescaling them. I don't think VectorDrawables are likely to create a memory issue, and the protection code seemed to be added to protect against large pngs, not vector graphics. Bug: 70562945 Test: Visually verified that all icons in the Accessibility Shortcut list are now the same size with maximum display and font sizes. Change-Id: I9f177d11a614c122d333d4625bf6fa756d1bf4af --- src/com/android/settings/Utils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 2a5582971c1..1091aea755f 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -48,6 +48,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.VectorDrawable; import android.hardware.fingerprint.FingerprintManager; import android.net.ConnectivityManager; import android.net.LinkProperties; @@ -929,7 +930,7 @@ public final class Utils extends com.android.settingslib.Utils { */ public static void setSafeIcon(Preference pref, Drawable icon) { Drawable safeIcon = icon; - if (icon != null) { + if ((icon != null) && !(icon instanceof VectorDrawable)) { safeIcon = getSafeDrawable(icon, 500, 500); } pref.setIcon(safeIcon); From fcfdeb7cb5d4a03e8189b2aa1a999d1af8fe710e Mon Sep 17 00:00:00 2001 From: Phil Weaver Date: Thu, 8 Mar 2018 17:46:49 -0800 Subject: [PATCH 2/8] Show default a11y icon in shortcut menu Making the shortcut menu icons consistent with those in the main accessibility settings. Bug: 74411102 Test: The list of CTS-installed services now have the same default in both pages of settings. Change-Id: I0deedb593e7ef8c8ef2b01ab836bb9f1c4bfd91b --- .../ShortcutServicePickerFragment.java | 62 +++++++++++++++---- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java index 5b45cfa3caa..a8a960f7671 100644 --- a/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java +++ b/src/com/android/settings/accessibility/ShortcutServicePickerFragment.java @@ -26,7 +26,9 @@ import android.app.Fragment; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.os.Binder; import android.os.Bundle; @@ -34,7 +36,6 @@ import android.os.IBinder; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; -import android.util.IconDrawableFactory; import android.view.accessibility.AccessibilityManager; import com.android.internal.accessibility.AccessibilityShortcutController; @@ -45,7 +46,6 @@ import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settings.widget.RadioButtonPreference; import com.android.settingslib.accessibility.AccessibilityUtils; -import com.android.settingslib.applications.DefaultAppInfo; import com.android.settingslib.widget.CandidateInfo; import com.android.settingslib.wrapper.PackageManagerWrapper; @@ -71,13 +71,11 @@ public class ShortcutServicePickerFragment extends RadioButtonPickerFragment { @Override protected List getCandidates() { final Context context = getContext(); - final PackageManager pm = context.getPackageManager(); final AccessibilityManager accessibilityManager = context .getSystemService(AccessibilityManager.class); final List installedServices = accessibilityManager.getInstalledAccessibilityServiceList(); final int numInstalledServices = installedServices.size(); - final PackageManagerWrapper pmw = new PackageManagerWrapper(context.getPackageManager()); final List candidates = new ArrayList<>(numInstalledServices); Map frameworkFeatureInfoMap = @@ -95,10 +93,7 @@ public class ShortcutServicePickerFragment extends RadioButtonPickerFragment { iconId, componentName.flattenToString())); } for (int i = 0; i < numInstalledServices; i++) { - final AccessibilityServiceInfo installedServiceInfo = installedServices.get(i); - candidates.add(new DefaultAppInfo(context, pmw, UserHandle.myUserId(), - installedServiceInfo.getComponentName(), - (String) installedServiceInfo.loadSummary(pm), true /* enabled */)); + candidates.add(new ServiceCandidateInfo(installedServices.get(i))); } return candidates; @@ -196,9 +191,9 @@ public class ShortcutServicePickerFragment extends RadioButtonPickerFragment { } private class FrameworkCandidateInfo extends CandidateInfo { - ToggleableFrameworkFeatureInfo mToggleableFrameworkFeatureInfo; - int mIconResId; - String mKey; + final ToggleableFrameworkFeatureInfo mToggleableFrameworkFeatureInfo; + final int mIconResId; + final String mKey; public FrameworkCandidateInfo( ToggleableFrameworkFeatureInfo frameworkFeatureInfo, int iconResId, String key) { @@ -223,4 +218,49 @@ public class ShortcutServicePickerFragment extends RadioButtonPickerFragment { return mKey; } } + + private class ServiceCandidateInfo extends CandidateInfo { + final AccessibilityServiceInfo mServiceInfo; + + public ServiceCandidateInfo(AccessibilityServiceInfo serviceInfo) { + super(true /* enabled */); + mServiceInfo = serviceInfo; + } + + @Override + public CharSequence loadLabel() { + final PackageManagerWrapper pmw = + new PackageManagerWrapper(getContext().getPackageManager()); + final CharSequence label = + mServiceInfo.getResolveInfo().serviceInfo.loadLabel(pmw.getPackageManager()); + if (label != null) { + return label; + } + + final ComponentName componentName = mServiceInfo.getComponentName(); + if (componentName != null) { + try { + final ApplicationInfo appInfo = pmw.getApplicationInfoAsUser( + componentName.getPackageName(), 0, UserHandle.myUserId()); + return appInfo.loadLabel(pmw.getPackageManager()); + } catch (PackageManager.NameNotFoundException e) { + return null; + } + } + return null; + } + + @Override + public Drawable loadIcon() { + final ResolveInfo resolveInfo = mServiceInfo.getResolveInfo(); + return (resolveInfo.getIconResource() == 0) + ? getContext().getDrawable(R.mipmap.ic_accessibility_generic) + : resolveInfo.loadIcon(getContext().getPackageManager()); + } + + @Override + public String getKey() { + return mServiceInfo.getComponentName().flattenToString(); + } + } } From f4318f613d846b8f825865d9ba552fd6167c3e2c Mon Sep 17 00:00:00 2001 From: Lei Yu Date: Mon, 12 Mar 2018 13:32:59 -0700 Subject: [PATCH 3/8] update the whitelist for anomaly detection Add "allow-in-power-save-except-idle" to whitelist. Also ignore all the system uids Bug: 74241534 Test: RunSettingsRoboTests Change-Id: I593e558168db339f6f38c7f78ab4fd63f99b16ab --- .../AnomalyDetectionJobService.java | 13 +++++++--- .../AnomalyDetectionJobServiceTest.java | 25 ++++++++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java b/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java index 83a79bcee1b..5d0e71d150d 100644 --- a/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java +++ b/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobService.java @@ -31,8 +31,9 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.Process; import android.os.StatsDimensionsValue; -import android.os.SystemPropertiesProto; +import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.support.annotation.VisibleForTesting; @@ -122,7 +123,8 @@ public class AnomalyDetectionJobService extends JobService { final boolean smartBatteryOn = Settings.Global.getInt(contentResolver, Settings.Global.APP_STANDBY_ENABLED, ON) == ON; final String packageName = batteryUtils.getPackageName(uid); - if (!powerWhitelistBackend.isSysWhitelisted(packageName)) { + if (!powerWhitelistBackend.isSysWhitelistedExceptIdle(packageName) + && !isSystemUid(uid)) { if (anomalyType == StatsManagerConfig.AnomalyType.EXCESSIVE_BG) { // TODO(b/72385333): check battery percentage draining in batterystats if (batteryUtils.isLegacyApp(packageName) && batteryUtils.isAppHeavilyUsed( @@ -156,7 +158,7 @@ public class AnomalyDetectionJobService extends JobService { * 3. Bluetooth anomaly: 3:{1:{1:{1:10140|}|}|} */ @VisibleForTesting - final int extractUidFromStatsDimensionsValue(StatsDimensionsValue statsDimensionsValue) { + int extractUidFromStatsDimensionsValue(StatsDimensionsValue statsDimensionsValue) { //TODO(b/73172999): Add robo test for this method if (statsDimensionsValue == null) { return UID_NULL; @@ -178,4 +180,9 @@ public class AnomalyDetectionJobService extends JobService { return UID_NULL; } + + private boolean isSystemUid(int uid) { + final int appUid = UserHandle.getAppId(uid); + return appUid >= Process.ROOT_UID && appUid < Process.FIRST_APPLICATION_UID; + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java index aa3d5a86b90..499ab9dc199 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AnomalyDetectionJobServiceTest.java @@ -18,11 +18,13 @@ package com.android.settings.fuelgauge.batterytip; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.robolectric.RuntimeEnvironment.application; @@ -32,6 +34,7 @@ import android.app.job.JobScheduler; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.Process; import android.os.StatsDimensionsValue; import android.os.UserManager; @@ -84,7 +87,7 @@ public class AnomalyDetectionJobServiceTest { mBundle = new Bundle(); mBundle.putParcelable(StatsManager.EXTRA_STATS_DIMENSIONS_VALUE, mStatsDimensionsValue); - mAnomalyDetectionJobService = new AnomalyDetectionJobService(); + mAnomalyDetectionJobService = spy(new AnomalyDetectionJobService()); } @Test @@ -92,13 +95,14 @@ public class AnomalyDetectionJobServiceTest { AnomalyDetectionJobService.scheduleAnomalyDetection(application, new Intent()); ShadowJobScheduler shadowJobScheduler = - Shadows.shadowOf(application.getSystemService(JobScheduler.class)); + Shadows.shadowOf(application.getSystemService(JobScheduler.class)); List pendingJobs = shadowJobScheduler.getAllPendingJobs(); assertThat(pendingJobs).hasSize(1); + JobInfo pendingJob = pendingJobs.get(0); assertThat(pendingJob.getId()).isEqualTo(R.id.job_anomaly_detection); assertThat(pendingJob.getMaxExecutionDelayMillis()) - .isEqualTo(TimeUnit.MINUTES.toMillis(30)); + .isEqualTo(TimeUnit.MINUTES.toMillis(30)); } @Test @@ -114,10 +118,25 @@ public class AnomalyDetectionJobServiceTest { anyInt(), anyLong()); } + @Test + public void testSaveAnomalyToDatabase_systemUid_doNotSave() { + doReturn(Process.SYSTEM_UID).when( + mAnomalyDetectionJobService).extractUidFromStatsDimensionsValue(any()); + + mAnomalyDetectionJobService.saveAnomalyToDatabase(mBatteryStatsHelper, mUserManager, + mBatteryDatabaseManager, mBatteryUtils, mPolicy, mPowerWhitelistBackend, + mContext.getContentResolver(), mBundle); + + verify(mBatteryDatabaseManager, never()).insertAnomaly(anyInt(), anyString(), anyInt(), + anyInt(), anyLong()); + } + @Test public void testSaveAnomalyToDatabase_normalApp_save() { doReturn(SYSTEM_PACKAGE).when(mBatteryUtils).getPackageName(anyInt()); doReturn(false).when(mPowerWhitelistBackend).isSysWhitelisted(SYSTEM_PACKAGE); + doReturn(Process.FIRST_APPLICATION_UID).when( + mAnomalyDetectionJobService).extractUidFromStatsDimensionsValue(any()); mAnomalyDetectionJobService.saveAnomalyToDatabase(mBatteryStatsHelper, mUserManager, mBatteryDatabaseManager, mBatteryUtils, mPolicy, mPowerWhitelistBackend, From bffd531aa3b2053c57c73a1c87f866295f6b6b27 Mon Sep 17 00:00:00 2001 From: Ecco Park Date: Mon, 12 Mar 2018 11:37:51 -0700 Subject: [PATCH 4/8] Fix the system crash issue when secondary user clicks any 802.1x AP on Wifi Picker. Catch the exception when keystore failed to list the certs Bug: 73794111 Test: test it with clicking the Google-A on Wifi Picker. Test: make ROBOTEST_FILTER="(WifiConfigControllerTest)" RunSettingsRoboTests -j32 RunSettingsRoboTests: OK (12 tests) Change-Id: I0db66730261c72ef35d1b299bacd2aed7710d247 --- .../settings/wifi/WifiConfigController.java | 13 +++++++++-- .../wifi/WifiConfigControllerTest.java | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index d7b42996308..4bdc0a478b3 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -1216,6 +1216,11 @@ public class WifiConfigController implements TextWatcher, } } + @VisibleForTesting + KeyStore getKeyStore() { + return KeyStore.getInstance(); + } + private void loadCertificates( Spinner spinner, String prefix, @@ -1232,8 +1237,12 @@ public class WifiConfigController implements TextWatcher, if (showUsePreinstalledCertOption) { certs.add(mUseSystemCertsString); } - certs.addAll( - Arrays.asList(KeyStore.getInstance().list(prefix, android.os.Process.WIFI_UID))); + try { + certs.addAll( + Arrays.asList(getKeyStore().list(prefix, android.os.Process.WIFI_UID))); + } catch (Exception e) { + Log.e(TAG, "can't get the certificate list from KeyStore"); + } certs.add(noCertificateString); final ArrayAdapter adapter = new ArrayAdapter( diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java index bbe104c1641..1654d6d8a20 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java @@ -20,11 +20,14 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; +import android.os.ServiceSpecificException; +import android.security.KeyStore; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -56,6 +59,8 @@ public class WifiConfigControllerTest { private View mView; @Mock private AccessPoint mAccessPoint; + @Mock + private KeyStore mKeyStore; public WifiConfigController mController; private static final String HEX_PSK = "01234567012345670123456701234567012345670123456701234567" @@ -210,6 +215,21 @@ public class WifiConfigControllerTest { assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.GONE); } + @Test + public void loadCertificates_keyStoreListFail_shouldNotCrash() { + // Set up + when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_EAP); + when(mKeyStore.list(anyString())) + .thenThrow(new ServiceSpecificException(-1, "permission error")); + + mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint, + WifiConfigUiBase.MODE_CONNECT); + + // Verify that the EAP method menu is visible. + assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); + // No Crash + } + public class TestWifiConfigController extends WifiConfigController { private TestWifiConfigController( @@ -221,5 +241,8 @@ public class WifiConfigControllerTest { boolean isSplitSystemUser() { return false; } + + @Override + KeyStore getKeyStore() { return mKeyStore; } } } From 101c1d09e1b2dc72038900775a11b46f34b63abd Mon Sep 17 00:00:00 2001 From: Sundeep Ghuman Date: Mon, 12 Mar 2018 20:28:09 -0700 Subject: [PATCH 5/8] Fix new DataUsageSummary page line spacing. There are still some unspecified items pending UX. Have left comments on ag/3702541 to avoid regressions. Bug: 70950124 Test: UI change only, no code to test. Change-Id: I7fa96134af750d71786d031652162aed6bffbeb5 --- res/layout/data_usage_summary_preference.xml | 25 ++++++++------------ 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/res/layout/data_usage_summary_preference.xml b/res/layout/data_usage_summary_preference.xml index 445e7cdd468..c2cb8413b9d 100644 --- a/res/layout/data_usage_summary_preference.xml +++ b/res/layout/data_usage_summary_preference.xml @@ -18,6 +18,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" + android:paddingTop="24dp" + android:paddingBottom="32dp" android:paddingStart="@dimen/preference_no_icon_padding_start" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:orientation="vertical" @@ -31,26 +33,18 @@ android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textColor="?android:attr/textColorSecondary" - android:paddingBottom="5dp" android:text="@string/data_usage_title" /> - - + android:layout_height="wrap_content" /> + android:layout_height="wrap_content" />