Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt +20 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.systemui.statusbar.notification.collection import android.app.Notification import android.content.Context import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.service.notification.StatusBarNotification import android.util.Log Loading @@ -39,16 +41,27 @@ class TargetSdkResolver @Inject constructor( } private fun resolveNotificationSdk(sbn: StatusBarNotification): Int { val applicationInfo = getApplicationInfoFromExtras(sbn.notification) ?: getApplicationInfoFromPackageManager(sbn) return applicationInfo?.targetSdkVersion ?: 0 } private fun getApplicationInfoFromExtras(notification: Notification): ApplicationInfo? = notification.extras.getParcelable( Notification.EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo::class.java ) private fun getApplicationInfoFromPackageManager(sbn: StatusBarNotification): ApplicationInfo? { val pmUser = CentralSurfaces.getPackageManagerForUser(context, sbn.user.identifier) var targetSdk = 0 // Extract target SDK version. try { val info = pmUser.getApplicationInfo(sbn.packageName, 0) targetSdk = info.targetSdkVersion return try { pmUser.getApplicationInfo(sbn.packageName, 0) } catch (ex: PackageManager.NameNotFoundException) { Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.packageName, ex) null } return targetSdk } private val TAG = "TargetSdkResolver" Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.systemui.statusbar.notification.collection import android.app.Notification import android.app.NotificationManager import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.os.Bundle import android.os.UserHandle import android.service.notification.NotificationListenerService.Ranking import android.service.notification.StatusBarNotification import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.withArgCaptor import junit.framework.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyString import org.mockito.Mockito.eq import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions import org.mockito.Mockito.`when` as whenever private const val SDK_VERSION = 33 private const val PACKAGE = "pkg" private const val USER_ID = -1 @SmallTest @RunWith(AndroidTestingRunner::class) class TargetSdkResolverTest : SysuiTestCase() { private val packageManager: PackageManager = mock() private val applicationInfo = ApplicationInfo().apply { targetSdkVersion = SDK_VERSION } private lateinit var targetSdkResolver: TargetSdkResolver private lateinit var notifListener: NotifCollectionListener @Before fun setUp() { targetSdkResolver = TargetSdkResolver(mContext) mContext.setMockPackageManager(packageManager) val notifCollection: CommonNotifCollection = mock() targetSdkResolver.initialize(notifCollection) notifListener = withArgCaptor { verify(notifCollection).addCollectionListener(capture()) } } @Test fun resolveFromNotificationExtras() { val extras = Bundle().apply { putParcelable(Notification.EXTRA_BUILDER_APPLICATION_INFO, applicationInfo) } val notification = Notification().apply { this.extras = extras } val sbn = createSbn(notification) val entry = createNotificationEntry(sbn) notifListener.onEntryBind(entry, sbn) assertEquals(SDK_VERSION, entry.targetSdk) verifyZeroInteractions(packageManager) } @Test fun resolveFromPackageManager() { val sbn = createSbn(Notification()) val entry = createNotificationEntry(sbn) whenever(packageManager.getApplicationInfo(anyString(), anyInt())) .thenReturn(applicationInfo) notifListener.onEntryBind(entry, sbn) assertEquals(SDK_VERSION, entry.targetSdk) verify(packageManager).getApplicationInfo(eq(PACKAGE), anyInt()) } @Test fun resolveFromPackageManager_andPackageManagerCrashes() { val sbn = createSbn(Notification()) val entry = createNotificationEntry(sbn) whenever(packageManager.getApplicationInfo(anyString(), anyInt())) .thenThrow(PackageManager.NameNotFoundException()) notifListener.onEntryBind(entry, sbn) assertEquals(0, entry.targetSdk) verify(packageManager).getApplicationInfo(eq(PACKAGE), anyInt()) } private fun createSbn(notification: Notification) = StatusBarNotification( PACKAGE, "opPkg", 0, "tag", 0, 0, notification, UserHandle(USER_ID), "", 0 ) private fun createNotificationEntry(sbn: StatusBarNotification) = NotificationEntry(sbn, createRanking(sbn.key), 0) private fun createRanking(key: String) = Ranking().apply { populate( key, 0, false, 0, 0, NotificationManager.IMPORTANCE_DEFAULT, null, null, null, null, null, true, 0, false, -1, false, null, null, false, false, false, null, 0, false) } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt +20 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.systemui.statusbar.notification.collection import android.app.Notification import android.content.Context import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.service.notification.StatusBarNotification import android.util.Log Loading @@ -39,16 +41,27 @@ class TargetSdkResolver @Inject constructor( } private fun resolveNotificationSdk(sbn: StatusBarNotification): Int { val applicationInfo = getApplicationInfoFromExtras(sbn.notification) ?: getApplicationInfoFromPackageManager(sbn) return applicationInfo?.targetSdkVersion ?: 0 } private fun getApplicationInfoFromExtras(notification: Notification): ApplicationInfo? = notification.extras.getParcelable( Notification.EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo::class.java ) private fun getApplicationInfoFromPackageManager(sbn: StatusBarNotification): ApplicationInfo? { val pmUser = CentralSurfaces.getPackageManagerForUser(context, sbn.user.identifier) var targetSdk = 0 // Extract target SDK version. try { val info = pmUser.getApplicationInfo(sbn.packageName, 0) targetSdk = info.targetSdkVersion return try { pmUser.getApplicationInfo(sbn.packageName, 0) } catch (ex: PackageManager.NameNotFoundException) { Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.packageName, ex) null } return targetSdk } private val TAG = "TargetSdkResolver" Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt 0 → 100644 +132 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.systemui.statusbar.notification.collection import android.app.Notification import android.app.NotificationManager import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.os.Bundle import android.os.UserHandle import android.service.notification.NotificationListenerService.Ranking import android.service.notification.StatusBarNotification import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.withArgCaptor import junit.framework.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyString import org.mockito.Mockito.eq import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions import org.mockito.Mockito.`when` as whenever private const val SDK_VERSION = 33 private const val PACKAGE = "pkg" private const val USER_ID = -1 @SmallTest @RunWith(AndroidTestingRunner::class) class TargetSdkResolverTest : SysuiTestCase() { private val packageManager: PackageManager = mock() private val applicationInfo = ApplicationInfo().apply { targetSdkVersion = SDK_VERSION } private lateinit var targetSdkResolver: TargetSdkResolver private lateinit var notifListener: NotifCollectionListener @Before fun setUp() { targetSdkResolver = TargetSdkResolver(mContext) mContext.setMockPackageManager(packageManager) val notifCollection: CommonNotifCollection = mock() targetSdkResolver.initialize(notifCollection) notifListener = withArgCaptor { verify(notifCollection).addCollectionListener(capture()) } } @Test fun resolveFromNotificationExtras() { val extras = Bundle().apply { putParcelable(Notification.EXTRA_BUILDER_APPLICATION_INFO, applicationInfo) } val notification = Notification().apply { this.extras = extras } val sbn = createSbn(notification) val entry = createNotificationEntry(sbn) notifListener.onEntryBind(entry, sbn) assertEquals(SDK_VERSION, entry.targetSdk) verifyZeroInteractions(packageManager) } @Test fun resolveFromPackageManager() { val sbn = createSbn(Notification()) val entry = createNotificationEntry(sbn) whenever(packageManager.getApplicationInfo(anyString(), anyInt())) .thenReturn(applicationInfo) notifListener.onEntryBind(entry, sbn) assertEquals(SDK_VERSION, entry.targetSdk) verify(packageManager).getApplicationInfo(eq(PACKAGE), anyInt()) } @Test fun resolveFromPackageManager_andPackageManagerCrashes() { val sbn = createSbn(Notification()) val entry = createNotificationEntry(sbn) whenever(packageManager.getApplicationInfo(anyString(), anyInt())) .thenThrow(PackageManager.NameNotFoundException()) notifListener.onEntryBind(entry, sbn) assertEquals(0, entry.targetSdk) verify(packageManager).getApplicationInfo(eq(PACKAGE), anyInt()) } private fun createSbn(notification: Notification) = StatusBarNotification( PACKAGE, "opPkg", 0, "tag", 0, 0, notification, UserHandle(USER_ID), "", 0 ) private fun createNotificationEntry(sbn: StatusBarNotification) = NotificationEntry(sbn, createRanking(sbn.key), 0) private fun createRanking(key: String) = Ranking().apply { populate( key, 0, false, 0, 0, NotificationManager.IMPORTANCE_DEFAULT, null, null, null, null, null, true, 0, false, -1, false, null, null, false, false, false, null, 0, false) } }