Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4611ad6 authored by Beth Thibodeau's avatar Beth Thibodeau Committed by Android (Google) Code Review
Browse files

Merge "Improve app name handling" into tm-qpr-dev

parents 4fd8012b df14df34
Loading
Loading
Loading
Loading
+34 −11
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.media

import android.app.Notification
import android.app.Notification.EXTRA_SUBSTITUTE_APP_NAME
import android.app.PendingIntent
import android.app.smartspace.SmartspaceConfig
import android.app.smartspace.SmartspaceManager
@@ -27,6 +28,7 @@ import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.ImageDecoder
@@ -57,8 +59,8 @@ import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
import com.android.systemui.statusbar.NotificationMediaManager.isConnectingState
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
import com.android.systemui.statusbar.notification.row.HybridGroupManager
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.Assert
@@ -633,9 +635,14 @@ class MediaDataManager(
        }
        val mediaController = mediaControllerFactory.create(token)
        val metadata = mediaController.metadata
        val notif: Notification = sbn.notification

        val appInfo = notif.extras.getParcelable(
            Notification.EXTRA_BUILDER_APPLICATION_INFO,
            ApplicationInfo::class.java
        ) ?: getAppInfoFromPackage(sbn.packageName)

        // Album art
        val notif: Notification = sbn.notification
        var artworkBitmap = metadata?.let { loadBitmapFromUri(it) }
        if (artworkBitmap == null) {
            artworkBitmap = metadata?.getBitmap(MediaMetadata.METADATA_KEY_ART)
@@ -650,8 +657,7 @@ class MediaDataManager(
        }

        // App name
        val builder = Notification.Builder.recoverBuilder(context, notif)
        val app = builder.loadHeaderAppName()
        val appName = getAppName(sbn, appInfo)

        // App Icon
        val smallIcon = sbn.notification.smallIcon
@@ -712,12 +718,7 @@ class MediaDataManager(

        val currentEntry = mediaEntries.get(key)
        val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
        val appUid = try {
            context.packageManager.getApplicationInfo(sbn.packageName, 0)?.uid!!
        } catch (e: PackageManager.NameNotFoundException) {
            Log.w(TAG, "Could not get app UID for ${sbn.packageName}", e)
            Process.INVALID_UID
        }
        val appUid = appInfo?.uid ?: Process.INVALID_UID

        if (logEvent) {
            logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation)
@@ -730,7 +731,7 @@ class MediaDataManager(
            val resumeAction: Runnable? = mediaEntries[key]?.resumeAction
            val hasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true
            val active = mediaEntries[key]?.active ?: true
            onMediaDataLoaded(key, oldKey, MediaData(sbn.normalizedUserId, true, app,
            onMediaDataLoaded(key, oldKey, MediaData(sbn.normalizedUserId, true, appName,
                    smallIcon, artist, song, artWorkIcon, actionIcons, actionsToShowCollapsed,
                    semanticActions, sbn.packageName, token, notif.contentIntent, device,
                    active, resumeAction = resumeAction, playbackLocation = playbackLocation,
@@ -740,6 +741,28 @@ class MediaDataManager(
        }
    }

    private fun getAppInfoFromPackage(packageName: String): ApplicationInfo? {
        try {
            return context.packageManager.getApplicationInfo(packageName, 0)
        } catch (e: PackageManager.NameNotFoundException) {
            Log.w(TAG, "Could not get app info for $packageName", e)
        }
        return null
    }

    private fun getAppName(sbn: StatusBarNotification, appInfo: ApplicationInfo?): String {
        val name = sbn.notification.extras.getString(EXTRA_SUBSTITUTE_APP_NAME)
        if (name != null) {
            return name
        }

        return if (appInfo != null) {
            context.packageManager.getApplicationLabel(appInfo).toString()
        } else {
            sbn.packageName
        }
    }

    /**
     * Generate action buttons based on notification actions
     */
+25 −2
Original line number Diff line number Diff line
@@ -50,11 +50,10 @@ import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit

private const val KEY = "KEY"
private const val KEY_2 = "KEY_2"
@@ -286,6 +285,30 @@ class MediaDataManagerTest : SysuiTestCase() {
            eq(mediaDataCaptor.value.instanceId), eq(MediaData.PLAYBACK_CAST_REMOTE))
    }

    @Test
    fun testOnNotificationAdded_hasSubstituteName_isUsed() {
        val subName = "Substitute Name"
        val notif = SbnBuilder().run {
            modifyNotification(context).also {
                it.extras = Bundle().apply {
                    putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, subName)
                }
                it.setStyle(MediaStyle().apply {
                    setMediaSession(session.sessionToken)
                })
            }
            build()
        }

        mediaDataManager.onNotificationAdded(KEY, notif)
        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
        verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true),
            eq(0), eq(false))

        assertThat(mediaDataCaptor.value!!.app).isEqualTo(subName)
    }

    @Test
    fun testLoadMediaDataInBg_invalidTokenNoCrash() {
        val bundle = Bundle()
+14 −0
Original line number Diff line number Diff line
@@ -6685,6 +6685,20 @@ public class NotificationManagerService extends SystemService {
            }
        }
        // Ensure only allowed packages have a substitute app name
        if (notification.extras.containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)) {
            int hasSubstituteAppNamePermission = mPackageManager.checkPermission(
                    permission.SUBSTITUTE_NOTIFICATION_APP_NAME, pkg, userId);
            if (hasSubstituteAppNamePermission != PERMISSION_GRANTED) {
                notification.extras.remove(Notification.EXTRA_SUBSTITUTE_APP_NAME);
                if (DBG) {
                    Slog.w(TAG, "warning: pkg " + pkg + " attempting to substitute app name"
                            + " without holding perm "
                            + Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME);
                }
            }
        }
        // Remote views? Are they too big?
        checkRemoteViews(pkg, tag, id, notification);
    }
+53 −0
Original line number Diff line number Diff line
@@ -4238,6 +4238,59 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                .containsKey(Notification.EXTRA_MEDIA_REMOTE_DEVICE));
    }

    @Test
    public void testSubstituteAppName_hasPermission() throws RemoteException {
        String subName = "Substitute Name";
        when(mPackageManager.checkPermission(
                eq(android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME), any(), anyInt()))
                .thenReturn(PERMISSION_GRANTED);
        Bundle extras = new Bundle();
        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, subName);
        Notification.Builder nb = new Notification.Builder(mContext,
                mTestNotificationChannel.getId())
                .addExtras(extras);
        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
                "testSubstituteAppNamePermission", mUid, 0,
                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);

        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
        waitForIdle();
        NotificationRecord posted = mService.findNotificationLocked(
                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());

        assertTrue(posted.getNotification().extras
                .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME));
        assertEquals(posted.getNotification().extras
                .getString(Notification.EXTRA_SUBSTITUTE_APP_NAME), subName);
    }

    @Test
    public void testSubstituteAppName_noPermission() throws RemoteException {
        when(mPackageManager.checkPermission(
                eq(android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME), any(), anyInt()))
                .thenReturn(PERMISSION_DENIED);
        Bundle extras = new Bundle();
        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, "Substitute Name");
        Notification.Builder nb = new Notification.Builder(mContext,
                mTestNotificationChannel.getId())
                .addExtras(extras);
        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1,
                "testSubstituteAppNamePermission", mUid, 0,
                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
        NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);

        mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(),
                nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
        waitForIdle();
        NotificationRecord posted = mService.findNotificationLocked(
                PKG, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getUserId());

        assertFalse(posted.getNotification().extras
                .containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME));
    }

    @Test
    public void testGetNotificationCountLocked() {
        String sampleTagToExclude = null;