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

Commit 8775b659 authored by Julia Reynolds's avatar Julia Reynolds Committed by Android (Google) Code Review
Browse files

Merge "Proxy notification improvments"

parents 0b4e17be ac98aea2
Loading
Loading
Loading
Loading
+36 −10
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@
            android:layout_centerVertical="true"
            android:layout_toEndOf="@id/pkgicon" />
        <TextView
            android:id="@+id/pkg_group_divider"
            android:id="@+id/pkg_divider"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
@@ -61,7 +61,7 @@
            android:layout_centerVertical="true"
            android:layout_toEndOf="@id/pkgname" />
        <TextView
            android:id="@+id/group_name"
            android:id="@+id/delegate_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
@@ -70,7 +70,7 @@
            android:ellipsize="end"
            android:maxLines="1"
            android:layout_centerVertical="true"
            android:layout_toEndOf="@id/pkg_group_divider" />
            android:layout_toEndOf="@id/pkg_divider" />
        <!-- 24 dp icon with 16 dp padding all around to mirror notification content margins -->
        <ImageButton
            android:id="@+id/info"
@@ -101,13 +101,39 @@
            android:layout_marginStart="@*android:dimen/notification_content_margin_start"
            android:layout_marginEnd="@*android:dimen/notification_content_margin_start"
            android:orientation="vertical">
            <RelativeLayout
                android:id="@+id/names"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
                <TextView
                    android:id="@+id/group_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Title"
                    android:layout_marginStart="2dp"
                    android:layout_marginEnd="2dp"
                    android:ellipsize="end"
                    android:maxLines="1"
                    android:layout_centerVertical="true" />
                <TextView
                    android:id="@+id/pkg_group_divider"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Title"
                    android:layout_marginStart="2dp"
                    android:layout_marginEnd="2dp"
                    android:text="@*android:string/notification_header_divider_symbol"
                    android:layout_centerVertical="true"
                    android:layout_toEndOf="@id/group_name" />
                <!-- Channel Name -->
                <TextView
                    android:id="@+id/channel_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                style="@android:style/TextAppearance.Material.Notification.Title" />
                    style="@android:style/TextAppearance.Material.Notification.Title"
                    android:layout_toEndOf="@id/pkg_group_divider"/>
            </RelativeLayout>
            <!-- Question prompt -->
            <TextView
                android:id="@+id/block_prompt"
+3 −0
Original line number Diff line number Diff line
@@ -1529,6 +1529,9 @@
    <!-- Notification: Control panel: Label that displays when the app's notifications cannot be blocked. -->
    <string name="notification_unblockable_desc">These notifications can\'t be turned off</string>

    <!-- Notification: Control panel: Label for the app that posted this notification, if it's not the package that the notification was posted for -->
    <string name="notification_delegate_header">via <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>

    <!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
    <string name="appops_camera">This app is using the camera.</string>
    <!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
+60 −21
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
    private String mPackageName;
    private String mAppName;
    private int mAppUid;
    private String mDelegatePkg;
    private int mNumUniqueChannelsInRow;
    private NotificationChannel mSingleNotificationChannel;
    private int mStartingUserImportance;
@@ -193,6 +194,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
                (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
        mIsForBlockingHelper = isForBlockingHelper;
        mAppUid = mSbn.getUid();
        mDelegatePkg = mSbn.getOpPkg();
        mIsDeviceProvisioned = isDeviceProvisioned;

        int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
@@ -234,26 +236,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
        ((TextView) findViewById(R.id.pkgname)).setText(mAppName);

        // Set group information if this channel has an associated group.
        CharSequence groupName = null;
        if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
            final NotificationChannelGroup notificationChannelGroup =
                    mINotificationManager.getNotificationChannelGroupForPackage(
                            mSingleNotificationChannel.getGroup(), mPackageName, mAppUid);
            if (notificationChannelGroup != null) {
                groupName = notificationChannelGroup.getName();
            }
        }
        TextView groupNameView = findViewById(R.id.group_name);
        TextView groupDividerView = findViewById(R.id.pkg_group_divider);
        if (groupName != null) {
            groupNameView.setText(groupName);
            groupNameView.setVisibility(View.VISIBLE);
            groupDividerView.setVisibility(View.VISIBLE);
        } else {
            groupNameView.setVisibility(View.GONE);
            groupDividerView.setVisibility(View.GONE);
        }
        // Delegate
        bindDelegate();

        // Settings button.
        final View settingsButton = findViewById(R.id.info);
@@ -273,9 +257,10 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        }
    }

    private void bindPrompt() {
    private void bindPrompt() throws RemoteException {
        final TextView blockPrompt = findViewById(R.id.block_prompt);
        bindName();
        bindGroup();
        if (mIsNonblockable) {
            blockPrompt.setText(R.string.notification_unblockable_desc);
        } else {
@@ -298,6 +283,60 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
        }
    }

    private void bindDelegate() {
        TextView delegateView = findViewById(R.id.delegate_name);
        TextView dividerView = findViewById(R.id.pkg_divider);

        CharSequence delegatePkg = null;
        if (!TextUtils.equals(mPackageName, mDelegatePkg)) {
            // this notification was posted by a delegate!
            ApplicationInfo info;
            try {
                info = mPm.getApplicationInfo(
                        mDelegatePkg,
                        PackageManager.MATCH_UNINSTALLED_PACKAGES
                                | PackageManager.MATCH_DISABLED_COMPONENTS
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                                | PackageManager.MATCH_DIRECT_BOOT_AWARE);
                if (info != null) {
                    delegatePkg = String.valueOf(mPm.getApplicationLabel(info));
                }
            } catch (PackageManager.NameNotFoundException e) {}
        }
        if (delegatePkg != null) {
            delegateView.setText(mContext.getResources().getString(
                    R.string.notification_delegate_header, delegatePkg));
            delegateView.setVisibility(View.VISIBLE);
            dividerView.setVisibility(View.VISIBLE);
        } else {
            delegateView.setVisibility(View.GONE);
            dividerView.setVisibility(View.GONE);
        }
    }

    private void bindGroup() throws RemoteException {
        // Set group information if this channel has an associated group.
        CharSequence groupName = null;
        if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
            final NotificationChannelGroup notificationChannelGroup =
                    mINotificationManager.getNotificationChannelGroupForPackage(
                            mSingleNotificationChannel.getGroup(), mPackageName, mAppUid);
            if (notificationChannelGroup != null) {
                groupName = notificationChannelGroup.getName();
            }
        }
        TextView groupNameView = findViewById(R.id.group_name);
        TextView groupDividerView = findViewById(R.id.pkg_group_divider);
        if (groupName != null) {
            groupNameView.setText(groupName);
            groupNameView.setVisibility(View.VISIBLE);
            groupDividerView.setVisibility(View.VISIBLE);
        } else {
            groupNameView.setVisibility(View.GONE);
            groupDividerView.setVisibility(View.GONE);
        }
    }

    @VisibleForTesting
    void logBlockingHelperCounter(String counterTag) {
        if (mIsForBlockingHelper) {
+30 −1
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ public class NotificationInfoTest extends SysuiTestCase {
                .thenReturn(packageInfo);
        final ApplicationInfo applicationInfo = new ApplicationInfo();
        applicationInfo.uid = TEST_UID;  // non-zero
        when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
        when(mMockPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME), anyInt())).thenReturn(
                applicationInfo);
        final PackageInfo systemPackageInfo = new PackageInfo();
        systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME;
@@ -189,6 +189,35 @@ public class NotificationInfoTest extends SysuiTestCase {
        assertEquals(iconDrawable, iconView.getDrawable());
    }

    @Test
    public void testBindNotification_noDelegate() throws Exception {
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
        final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
        assertEquals(GONE, nameView.getVisibility());
        final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider);
        assertEquals(GONE, dividerView.getVisibility());
    }

    @Test
    public void testBindNotification_delegate() throws Exception {
        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, "other", 0, null, TEST_UID, 0,
                new Notification(), UserHandle.CURRENT, null, 0);
        final ApplicationInfo applicationInfo = new ApplicationInfo();
        applicationInfo.uid = 7;  // non-zero
        when(mMockPackageManager.getApplicationInfo(eq("other"), anyInt())).thenReturn(
                applicationInfo);
        when(mMockPackageManager.getApplicationLabel(any())).thenReturn("Other");

        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
        final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
        assertEquals(VISIBLE, nameView.getVisibility());
        assertTrue(nameView.getText().toString().contains("Other"));
        final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider);
        assertEquals(VISIBLE, dividerView.getVisibility());
    }

    @Test
    public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+14 −13
Original line number Diff line number Diff line
@@ -4332,19 +4332,20 @@ public class NotificationManagerService extends SystemService {
     *
     * Has side effects.
     */
    private boolean checkDisqualifyingFeatures(int userId, int callingUid, int id, String tag,
    private boolean checkDisqualifyingFeatures(int userId, int uid, int id, String tag,
            NotificationRecord r, boolean isAutogroup) {
        final String pkg = r.sbn.getPackageName();
        final boolean isSystemNotification =
                isUidSystemOrPhone(callingUid) || ("android".equals(pkg));
                isUidSystemOrPhone(uid) || ("android".equals(pkg));
        final boolean isNotificationFromListener = mListeners.isListenerPackage(pkg);

        // Limit the number of notifications that any given package except the android
        // package or a registered listener can enqueue.  Prevents DOS attacks and deals with leaks.
        if (!isSystemNotification && !isNotificationFromListener) {
            synchronized (mNotificationLock) {
                final int callingUid = Binder.getCallingUid();
                if (mNotificationsByKey.get(r.sbn.getKey()) == null
                        && isCallerInstantApp(pkg, Binder.getCallingUid(), userId)) {
                        && isCallerInstantApp(callingUid, userId)) {
                    // Ephemeral apps have some special constraints for notifications.
                    // They are not allowed to create new notifications however they are allowed to
                    // update notifications created by the system (e.g. a foreground service
@@ -6452,24 +6453,24 @@ public class NotificationManagerService extends SystemService {
    }

    @VisibleForTesting
    boolean isCallerInstantApp(String pkg, int callingUid, int userId) {
    boolean isCallerInstantApp(int callingUid, int userId) {
        // System is always allowed to act for ephemeral apps.
        if (isUidSystemOrPhone(callingUid)) {
            return false;
        }

        try {
            final String pkg = mPackageManager.getNameForUid(callingUid);
            mAppOps.checkPackage(callingUid, pkg);

        try {
           ApplicationInfo ai = mPackageManager.getApplicationInfo(pkg, 0, userId);
           if (ai == null) {
               throw new SecurityException("Unknown package " + pkg);
           }
           return ai.isInstantApp();
        } catch (RemoteException re) {
            throw new SecurityException("Unknown package " + pkg, re);
            throw new SecurityException("Unknown uid " + callingUid, re);
        }

    }

    private void checkCallerIsSameApp(String pkg) {
Loading