From a37d5233ecc3845f8ed3f4d5cbfe9536c0f16f55 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Fri, 1 Feb 2019 10:14:26 -0500 Subject: [PATCH] Reduce number of calls to getApplicationInfo Converted PrivacyApplication calls to PackageManager#getApplicationInfo to lazy and removed sort by app name in PrivacyDialogBuilder (only the actual dialog needs that sort). This makes it so the calls to getApplicationInfo are only realized when needed. Test: manual using trace-ipc. In one minute of usage, calls are reduced from ~6000 to 7. Test: atest Test: manual, no change in observed behavior Bug: 122878595 Change-Id: Iff4d2b27b8210687079cb12d1bbae83ba33f8392 --- .../systemui/privacy/OngoingPrivacyDialog.kt | 8 ++++-- .../systemui/privacy/PrivacyDialogBuilder.kt | 3 +-- .../android/systemui/privacy/PrivacyItem.kt | 25 +++++++++++-------- .../privacy/PrivacyDialogBuilderTest.kt | 5 ++-- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt index e2688f13134ca..ac3ba6bfd12a0 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt @@ -51,6 +51,10 @@ class OngoingPrivacyDialog constructor( private val MAX_ITEMS = context.resources.getInteger(R.integer.ongoing_appops_dialog_max_apps) private val iconFactory = IconDrawableFactory.newInstance(context, true) private var dismissDialog: (() -> Unit)? = null + private val appsAndTypes = dialogBuilder.appsAndTypes + .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps + { it.second.min() }, + { it.first })) init { val a = context.theme.obtainStyledAttributes( @@ -89,10 +93,10 @@ class OngoingPrivacyDialog constructor( title.setText(dialogBuilder.getDialogTitle()) - val numItems = dialogBuilder.appsAndTypes.size + val numItems = appsAndTypes.size for (i in 0..(numItems - 1)) { if (i >= MAX_ITEMS) break - val item = dialogBuilder.appsAndTypes[i] + val item = appsAndTypes[i] addAppItem(appsList, item.first, item.second, dialogBuilder.types.size > 1) } diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt index 2894621e7775f..9c1076af9ede4 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt @@ -30,8 +30,7 @@ class PrivacyDialogBuilder(val context: Context, itemsList: List) { appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType }) .toList() .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps - { it.second.min() }, // Sort by "smallest" AppOpp (Location is largest) - { it.first })) // Sort alphabetically bt App Name + { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest) types = itemsList.map { it.privacyType }.distinct().sorted() val singleApp = appsAndTypes.size == 1 app = if (singleApp) appsAndTypes[0].first else null diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt index dbe87d1d53c68..f7ca51d6f840e 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt @@ -44,17 +44,22 @@ data class PrivacyApplication(val packageName: String, val uid: Int, val context return applicationName.compareTo(other.applicationName) } - var icon: Drawable = context.getDrawable(android.R.drawable.sym_def_app_icon) - var applicationName: String - - init { + private val applicationInfo: ApplicationInfo? by lazy { try { - val app: ApplicationInfo = context.packageManager - .getApplicationInfo(packageName, 0) - icon = context.packageManager.getApplicationIcon(app) - applicationName = context.packageManager.getApplicationLabel(app) as String - } catch (e: PackageManager.NameNotFoundException) { - applicationName = packageName + context.packageManager.getApplicationInfo(packageName, 0) + } catch (_: PackageManager.NameNotFoundException) { + null } } + val icon: Drawable by lazy { + applicationInfo?.let { + context.packageManager.getApplicationIcon(it) + } ?: context.getDrawable(android.R.drawable.sym_def_app_icon) + } + + val applicationName: String by lazy { + applicationInfo?.let { + context.packageManager.getApplicationLabel(it) as String + } ?: packageName + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt index f163b88357cfa..b6e0d905f4736 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt @@ -37,7 +37,7 @@ class PrivacyDialogBuilderTest : SysuiTestCase() { "Bar", TEST_UID, context)) val bar3 = PrivacyItem(Privacy.TYPE_LOCATION, PrivacyApplication( "Bar", TEST_UID, context)) - val foo0 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication( + val foo0 = PrivacyItem(Privacy.TYPE_MICROPHONE, PrivacyApplication( "Foo", TEST_UID, context)) val baz1 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication( "Baz", TEST_UID, context)) @@ -50,10 +50,11 @@ class PrivacyDialogBuilderTest : SysuiTestCase() { assertEquals(3, list.size) val appsList = list.map { it.first } val typesList = list.map { it.second } + // List is sorted by number of types and then by types assertEquals(listOf("Bar", "Baz", "Foo"), appsList.map { it.packageName }) assertEquals(listOf(Privacy.TYPE_CAMERA, Privacy.TYPE_LOCATION), typesList[0]) assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[1]) - assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[2]) + assertEquals(listOf(Privacy.TYPE_MICROPHONE), typesList[2]) } @Test