From 538accf058366cabc002da8216c46d52633570c5 Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Wed, 9 Jan 2019 14:54:19 -0800 Subject: [PATCH 01/37] Hide mainline module apps in settings. - check whether an app is system hidden module and do not show them in recent apps list and battery usage list. Bug: 120546598 Test: make RunSettingsRoboTests Change-Id: I9080c9d39095890f3a3ebc7fce839dcf984a92d6 --- .../RecentAppsPreferenceController.java | 3 + .../BatteryAppListPreferenceController.java | 7 +++ .../RecentAppsPreferenceControllerTest.java | 55 +++++++++++++++++++ ...cialAppAccessPreferenceControllerTest.java | 12 +++- ...atteryAppListPreferenceControllerTest.java | 33 +++++++++++ 5 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/applications/RecentAppsPreferenceController.java b/src/com/android/settings/applications/RecentAppsPreferenceController.java index b6e8f4c6071..5d5229080c7 100644 --- a/src/com/android/settings/applications/RecentAppsPreferenceController.java +++ b/src/com/android/settings/applications/RecentAppsPreferenceController.java @@ -316,6 +316,9 @@ public class RecentAppsPreferenceController extends AbstractPreferenceController Log.d(TAG, "System package, skipping " + pkgName); return false; } + if (AppUtils.isHiddenSystemModule(mContext, pkgName)) { + return false; + } final Intent launchIntent = new Intent().addCategory(Intent.CATEGORY_LAUNCHER) .setPackage(pkgName); diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java index 65181c4a6c0..e2d1c53eb3e 100644 --- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java @@ -46,6 +46,7 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.applications.AppUtils; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; @@ -351,6 +352,12 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro @VisibleForTesting boolean shouldHideSipper(BatterySipper sipper) { + // Don't show hidden system module + final String packageName = mBatteryUtils.getPackageName(sipper.getUid()); + if (!TextUtils.isEmpty(packageName) + && AppUtils.isHiddenSystemModule(mContext, packageName)) { + return true; + } // Don't show over-counted and unaccounted in any condition return sipper.drainType == BatterySipper.DrainType.OVERCOUNTED || sipper.drainType == BatterySipper.DrainType.UNACCOUNTED; diff --git a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java index aab2156de08..3fd43695396 100644 --- a/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/RecentAppsPreferenceControllerTest.java @@ -38,6 +38,7 @@ import android.app.usage.UsageStatsManager; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; +import android.content.pm.ModuleInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.PowerManager; @@ -102,10 +103,13 @@ public class RecentAppsPreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); + when(mContext.getApplicationContext()).thenReturn(mContext); + ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mAppState); doReturn(mUsageStatsManager).when(mContext).getSystemService(Context.USAGE_STATS_SERVICE); doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE); doReturn(mPackageManager).when(mContext).getPackageManager(); doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class); + when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {}); mController = new RecentAppsPreferenceController(mContext, mAppState, null); when(mScreen.findPreference(anyString())).thenReturn(mCategory); @@ -350,6 +354,57 @@ public class RecentAppsPreferenceControllerTest { verify(mCategory).addPreference(argThat(summaryMatches("0 minutes ago"))); } + @Test + public void displayPreference_shouldNotShowHiddenSystemModule() { + final List stats = new ArrayList<>(); + // Regular app. + final UsageStats stat1 = new UsageStats(); + stat1.mLastTimeUsed = System.currentTimeMillis(); + stat1.mPackageName = "com.foo.bar"; + stats.add(stat1); + + // Hidden system module. + final UsageStats stat2 = new UsageStats(); + stat2.mLastTimeUsed = System.currentTimeMillis() + 200; + stat2.mPackageName = "com.foo.hidden"; + stats.add(stat2); + + ApplicationsState.AppEntry stat1Entry = mock(ApplicationsState.AppEntry.class); + ApplicationsState.AppEntry stat2Entry = mock(ApplicationsState.AppEntry.class); + stat1Entry.info = mApplicationInfo; + stat2Entry.info = mApplicationInfo; + + when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())).thenReturn(stat1Entry); + when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())).thenReturn(stat2Entry); + + final ModuleInfo moduleInfo1 = new ModuleInfo(); + moduleInfo1.setPackageName(stat1.mPackageName); + moduleInfo1.setHidden(false); + + final ModuleInfo moduleInfo2 = new ModuleInfo(); + moduleInfo2.setPackageName(stat2.mPackageName); + moduleInfo2.setHidden(true); + + ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null); + final List modules = new ArrayList<>(); + modules.add(moduleInfo2); + when(mPackageManager.getInstalledModules(anyInt() /* flags */)) + .thenReturn(modules); + + when(mPackageManager.resolveActivity(any(Intent.class), anyInt())) + .thenReturn(new ResolveInfo()); + when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) + .thenReturn(stats); + + mController.displayPreference(mScreen); + + // Only add stat1. stat2 is skipped because it is hidden module. + final ArgumentCaptor prefCaptor = ArgumentCaptor.forClass(Preference.class); + verify(mCategory).addPreference(prefCaptor.capture()); + final Preference pref = prefCaptor.getValue(); + assertThat(pref.getKey()).isEqualTo(stat1.mPackageName); + } + private static ArgumentMatcher summaryMatches(String expected) { return preference -> TextUtils.equals(expected, preference.getSummary()); } diff --git a/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java index e2035e33c42..75302d837c3 100644 --- a/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/SpecialAppAccessPreferenceControllerTest.java @@ -20,11 +20,16 @@ import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEA import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.ModuleInfo; +import android.content.pm.PackageManager; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; @@ -55,6 +60,8 @@ public class SpecialAppAccessPreferenceControllerTest { private ApplicationsState.Session mSession; @Mock private PreferenceScreen mScreen; + @Mock + private PackageManager mPackageManager; private SpecialAppAccessPreferenceController mController; private Preference mPreference; @@ -62,8 +69,11 @@ public class SpecialAppAccessPreferenceControllerTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; + mContext = spy(RuntimeEnvironment.application); + when(mContext.getApplicationContext()).thenReturn(mContext); ShadowUserManager.getShadow().setProfileIdsWithDisabled(new int[]{0}); + doReturn(mPackageManager).when(mContext).getPackageManager(); + doReturn(new ArrayList()).when(mPackageManager).getInstalledModules(anyInt()); mController = new SpecialAppAccessPreferenceController(mContext, "test_key"); mPreference = new Preference(mContext); when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java index e1913a2d304..32829755a62 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java @@ -18,11 +18,15 @@ package com.android.settings.fuelgauge; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.pm.ModuleInfo; +import android.content.pm.PackageManager; +import android.os.UserManager; import android.text.TextUtils; import android.text.format.DateUtils; @@ -34,6 +38,7 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settingslib.applications.ApplicationsState; import org.junit.Before; import org.junit.Test; @@ -42,6 +47,10 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.util.ReflectionHelpers; + +import java.util.ArrayList; +import java.util.List; @RunWith(RobolectricTestRunner.class) public class BatteryAppListPreferenceControllerTest { @@ -60,6 +69,10 @@ public class BatteryAppListPreferenceControllerTest { private InstrumentedPreferenceFragment mFragment; @Mock private BatteryUtils mBatteryUtils; + @Mock + private PackageManager mPackageManager; + @Mock + private UserManager mUserManager; private Context mContext; private PowerGaugePreference mPreference; @@ -70,6 +83,11 @@ public class BatteryAppListPreferenceControllerTest { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mContext.getApplicationContext()).thenReturn(mContext); + when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); + when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[] {}); + FakeFeatureFactory.setupForTest(); mPreference = new PowerGaugePreference(mContext); @@ -183,6 +201,21 @@ public class BatteryAppListPreferenceControllerTest { assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isFalse(); } + @Test + public void testShouldHideSipper_hiddenSystemModule_returnTrue() { + ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null); + final String packageName = "test.hidden.module"; + final ModuleInfo moduleInfo = new ModuleInfo(); + moduleInfo.setPackageName(packageName); + moduleInfo.setHidden(true); + final List modules = new ArrayList<>(); + modules.add(moduleInfo); + when(mBatteryUtils.getPackageName(anyInt() /* uid */)).thenReturn(packageName); + when(mPackageManager.getInstalledModules(anyInt() /* flags */)).thenReturn(modules); + + assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isTrue(); + } + @Test public void testNeverUseFakeData() { assertThat(BatteryAppListPreferenceController.USE_FAKE_DATA).isFalse(); From 380e92c54c5ed42e664a898b245706de31f30cab Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Wed, 16 Jan 2019 12:39:57 -0800 Subject: [PATCH 02/37] Add module version in About settings. Change-Id: I2474d05ee96e3dd29fe012fe77450c91775fdf1d Fixes: 122615240 Test: make RunSettingsRoboTests --- res/layout/dialog_firmware_version.xml | 12 +++ res/values/strings.xml | 2 + .../FirmwareVersionDialogFragment.java | 1 + .../ModuleVersionDialogController.java | 65 +++++++++++ .../ModuleVersionDialogControllerTest.java | 101 ++++++++++++++++++ 5 files changed, 181 insertions(+) create mode 100644 src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogController.java create mode 100644 tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogControllerTest.java diff --git a/res/layout/dialog_firmware_version.xml b/res/layout/dialog_firmware_version.xml index 874d7af0063..1d5f531dfaa 100644 --- a/res/layout/dialog_firmware_version.xml +++ b/res/layout/dialog_firmware_version.xml @@ -51,6 +51,18 @@ android:background="?android:attr/selectableItemBackground" android:textColor="?android:attr/colorAccent"/> + + + Kernel version Build number + + Mainline module versions Not available diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogFragment.java b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogFragment.java index 5dbc5ac5744..36302cca0db 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogFragment.java +++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogFragment.java @@ -90,5 +90,6 @@ public class FirmwareVersionDialogFragment extends InstrumentedDialogFragment { new BasebandVersionDialogController(this).initialize(); new KernelVersionDialogController(this).initialize(); new BuildNumberDialogController(this).initialize(); + new ModuleVersionDialogController(this).initialize(); } } diff --git a/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogController.java b/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogController.java new file mode 100644 index 00000000000..d6fcc38bf7f --- /dev/null +++ b/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogController.java @@ -0,0 +1,65 @@ +/* + * 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.deviceinfo.firmwareversion; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.settings.R; + +import androidx.annotation.VisibleForTesting; + +public class ModuleVersionDialogController { + + private static final String TAG = "MainlineModuleControl"; + + @VisibleForTesting + static final int MODULE_VERSION_LABEL_ID = R.id.module_version_label; + @VisibleForTesting + static final int MODULE_VERSION_VALUE_ID = R.id.module_version_value; + + private final FirmwareVersionDialogFragment mDialog; + private final Context mContext; + private final PackageManager mPackageManager; + + public ModuleVersionDialogController(FirmwareVersionDialogFragment dialog) { + mDialog = dialog; + mContext = mDialog.getContext(); + mPackageManager = mContext.getPackageManager(); + } + + /** + * Updates the mainline module version field of the dialog. + */ + public void initialize() { + final String moduleProvider = mContext.getString( + com.android.internal.R.string.config_defaultModuleMetadataProvider); + if (!TextUtils.isEmpty(moduleProvider)) { + try { + mDialog.setText(MODULE_VERSION_VALUE_ID, + mPackageManager.getPackageInfo(moduleProvider, 0 /* flags */).versionName); + return; + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Failed to get mainline version.", e); + } + } + mDialog.removeSettingFromScreen(MODULE_VERSION_LABEL_ID); + mDialog.removeSettingFromScreen(MODULE_VERSION_VALUE_ID); + } +} diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogControllerTest.java new file mode 100644 index 00000000000..e5958aab550 --- /dev/null +++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/ModuleVersionDialogControllerTest.java @@ -0,0 +1,101 @@ +/* + * 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.deviceinfo.firmwareversion; + +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; + +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 ModuleVersionDialogControllerTest { + + @Mock + private FirmwareVersionDialogFragment mDialog; + @Mock + private PackageManager mPackageManager; + + private Context mContext; + private ModuleVersionDialogController mController; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + when(mDialog.getContext()).thenReturn(mContext); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + mController = new ModuleVersionDialogController(mDialog); + } + + @Test + public void initialize_noMainlineModuleProvider_shouldRemoveSettingFromDialog() { + when(mContext.getString( + com.android.internal.R.string.config_defaultModuleMetadataProvider)).thenReturn(null); + + mController.initialize(); + + verify(mDialog).removeSettingFromScreen(mController.MODULE_VERSION_LABEL_ID); + verify(mDialog).removeSettingFromScreen(mController.MODULE_VERSION_VALUE_ID); + } + + @Test + public void initialize_noMainlineModulePackageInfo_shouldRemoveSettingFromDialog() + throws PackageManager.NameNotFoundException { + final String provider = "test.provider"; + when(mContext.getString( + com.android.internal.R.string.config_defaultModuleMetadataProvider)) + .thenReturn(provider); + when(mPackageManager.getPackageInfo(eq(provider), anyInt())) + .thenThrow(new PackageManager.NameNotFoundException()); + + mController.initialize(); + + verify(mDialog).removeSettingFromScreen(mController.MODULE_VERSION_LABEL_ID); + verify(mDialog).removeSettingFromScreen(mController.MODULE_VERSION_VALUE_ID); + } + + @Test + public void initialize_hasMainlineModulePackageInfo_shouldshouldSetDialogTextToMainlineVersion() + throws PackageManager.NameNotFoundException { + final String provider = "test.provider"; + final String version = "test version 123"; + final PackageInfo info = new PackageInfo(); + info.versionName = version; + when(mContext.getString( + com.android.internal.R.string.config_defaultModuleMetadataProvider)) + .thenReturn(provider); + when(mPackageManager.getPackageInfo(eq(provider), anyInt())).thenReturn(info); + + mController.initialize(); + + verify(mDialog).setText(mController.MODULE_VERSION_VALUE_ID, version); + } + +} From 2ef995b71269a6f6d62e728d18c4af44acf2e9e9 Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Sat, 19 Jan 2019 11:43:25 +0800 Subject: [PATCH 03/37] Adjust contextual card dismissal view - Increase the height of button clicking area - Decrease top margin and some other corresponding adjustments. Bug: 113783548 Test: visual Change-Id: Iba1cea6c82036ebb9fe2e08d32eb663e0ad026ac --- res/layout/homepage_dismissal_view.xml | 5 ++--- res/values/dimens.xml | 6 +++--- res/values/styles.xml | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/res/layout/homepage_dismissal_view.xml b/res/layout/homepage_dismissal_view.xml index 6d8f7116b40..4295ff6899c 100644 --- a/res/layout/homepage_dismissal_view.xml +++ b/res/layout/homepage_dismissal_view.xml @@ -34,7 +34,6 @@