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

Commit c249f77f authored by Joshua Duong's avatar Joshua Duong Committed by Automerger Merge Worker
Browse files

Merge "Fix PendingIntent hijacking for adb notifications." into rvc-dev am: 9a419cda

Change-Id: Ica79fad48f82380977f9f5c4783a65590669336f
parents 5c64d4f2 9a419cda
Loading
Loading
Loading
Loading
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 android.debug;

import android.annotation.NonNull;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.UserHandle;
import android.provider.Settings;

import com.android.internal.notification.SystemNotificationChannels;

/**
 * Utility class for building adb notifications.
 * @hide
 */
public final class AdbNotifications {
    /**
     * Notification channel for tv types.
     */
    private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";

    /**
     * Builds a notification to show connected state for adb over a transport type.
     * @param context the context
     * @param transportType the adb transport type.
     * @return a newly created Notification for the transport type.
     */
    public static Notification createNotification(@NonNull Context context,
            byte transportType) {
        Resources resources = context.getResources();
        int titleId;
        int messageId;

        if (transportType == AdbTransportType.USB) {
            titleId = com.android.internal.R.string.adb_active_notification_title;
            messageId = com.android.internal.R.string.adb_active_notification_message;
        } else if (transportType == AdbTransportType.WIFI) {
            titleId = com.android.internal.R.string.adbwifi_active_notification_title;
            messageId = com.android.internal.R.string.adbwifi_active_notification_message;
        } else {
            throw new IllegalArgumentException(
                    "createNotification called with unknown transport type=" + transportType);
        }

        CharSequence title = resources.getText(titleId);
        CharSequence message = resources.getText(messageId);

        Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.setPackage(context.getPackageManager().resolveActivity(intent,
                PackageManager.MATCH_SYSTEM_ONLY).activityInfo.packageName);
        PendingIntent pIntent = PendingIntent.getActivityAsUser(context, 0, intent,
                PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);

        return new Notification.Builder(context, SystemNotificationChannels.DEVELOPER_IMPORTANT)
                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                .setWhen(0)
                .setOngoing(true)
                .setTicker(title)
                .setDefaults(0)  // please be quiet
                .setColor(context.getColor(
                            com.android.internal.R.color.system_notification_accent_color))
                .setContentTitle(title)
                .setContentText(message)
                .setContentIntent(pIntent)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .extend(new Notification.TvExtender()
                        .setChannelId(ADB_NOTIFICATION_CHANNEL_ID_TV))
                .build();
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -142,6 +142,9 @@
    <!-- WindowMetricsTest permissions -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <!-- Allow use of PendingIntent.getIntent() -->
    <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />

    <application android:theme="@style/Theme" android:supportsRtl="true">
        <uses-library android:name="android.test.runner" />
        <uses-library android:name="org.apache.http.legacy" android:required="false" />
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 android.debug;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import android.app.Notification;
import android.content.Context;
import android.platform.test.annotations.Presubmit;
import android.text.TextUtils;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
public final class AdbNotificationsTest {
    private Context mContext;

    @Before
    public void setUp() throws Exception {
        mContext = InstrumentationRegistry.getContext();
    }

    @Test
    public void testCreateNotification_UsbTransportType() throws Exception {
        CharSequence title = mContext.getResources().getText(
                com.android.internal.R.string.adb_active_notification_title);
        CharSequence message = mContext.getResources().getText(
                com.android.internal.R.string.adb_active_notification_message);

        Notification notification = AdbNotifications.createNotification(mContext,
                AdbTransportType.USB);

        // Verify that the adb notification for usb connections has the correct text.
        assertEquals(title, notification.extras.getCharSequence(Notification.EXTRA_TITLE, ""));
        assertEquals(message, notification.extras.getCharSequence(Notification.EXTRA_TEXT, ""));
        // Verify the PendingIntent has an explicit intent (b/153356209).
        assertFalse(TextUtils.isEmpty(notification.contentIntent.getIntent().getPackage()));
    }

    @Test
    public void testCreateNotification_WifiTransportType() throws Exception {
        CharSequence title = mContext.getResources().getText(
                com.android.internal.R.string.adbwifi_active_notification_title);
        CharSequence message = mContext.getResources().getText(
                com.android.internal.R.string.adbwifi_active_notification_message);

        Notification notification = AdbNotifications.createNotification(mContext,
                AdbTransportType.WIFI);

        // Verify that the adb notification for usb connections has the correct text.
        assertEquals(title, notification.extras.getCharSequence(Notification.EXTRA_TITLE, ""));
        assertEquals(message, notification.extras.getCharSequence(Notification.EXTRA_TEXT, ""));
        // Verify the PendingIntent has an explicit intent (b/153356209).
        assertFalse(TextUtils.isEmpty(notification.contentIntent.getIntent().getPackage()));
    }
}
+3 −31
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -36,6 +35,7 @@ import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.debug.AdbManager;
import android.debug.AdbNotifications;
import android.debug.AdbProtoEnums;
import android.debug.AdbTransportType;
import android.debug.PairDevice;
@@ -69,7 +69,6 @@ import android.util.Xml;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.XmlUtils;
@@ -760,40 +759,13 @@ public class AdbDebuggingManager {
        // Show when at least one device is connected.
        public void showAdbConnectedNotification(boolean show) {
            final int id = SystemMessage.NOTE_ADB_WIFI_ACTIVE;
            final int titleRes = com.android.internal.R.string.adbwifi_active_notification_title;
            if (show == mAdbNotificationShown) {
                return;
            }
            setupNotifications();
            if (!mAdbNotificationShown) {
                Resources r = mContext.getResources();
                CharSequence title = r.getText(titleRes);
                CharSequence message = r.getText(
                        com.android.internal.R.string.adbwifi_active_notification_message);

                Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
                        intent, 0, null, UserHandle.CURRENT);

                Notification notification =
                        new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER)
                                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                                .setWhen(0)
                                .setOngoing(true)
                                .setTicker(title)
                                .setDefaults(0)  // please be quiet
                                .setColor(mContext.getColor(
                                        com.android.internal.R.color
                                                .system_notification_accent_color))
                                .setContentTitle(title)
                                .setContentText(message)
                                .setContentIntent(pi)
                                .setVisibility(Notification.VISIBILITY_PUBLIC)
                                .extend(new Notification.TvExtender()
                                        .setChannelId(ADB_NOTIFICATION_CHANNEL_ID_TV))
                                .build();
                Notification notification = AdbNotifications.createNotification(mContext,
                        AdbTransportType.WIFI);
                mAdbNotificationShown = true;
                mNotificationManager.notifyAsUser(null, id, notification,
                        UserHandle.ALL);
+4 −32
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.debug.AdbManagerInternal;
import android.debug.AdbNotifications;
import android.debug.AdbTransportType;
import android.debug.IAdbTransport;
import android.hardware.usb.ParcelableUsbPort;
@@ -1180,7 +1181,6 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
        protected void updateAdbNotification(boolean force) {
            if (mNotificationManager == null) return;
            final int id = SystemMessage.NOTE_ADB_ACTIVE;
            final int titleRes = com.android.internal.R.string.adb_active_notification_title;

            if (isAdbEnabled() && mConnected) {
                if ("0".equals(getSystemProperty("persist.adb.notify", ""))) return;
@@ -1191,38 +1191,10 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
                }

                if (!mAdbNotificationShown) {
                    Resources r = mContext.getResources();
                    CharSequence title = r.getText(titleRes);
                    CharSequence message = r.getText(
                            com.android.internal.R.string.adb_active_notification_message);

                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                            | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
                            intent, 0, null, UserHandle.CURRENT);

                    Notification notification =
                            new Notification.Builder(mContext,
                                    SystemNotificationChannels.DEVELOPER_IMPORTANT)
                                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                                    .setWhen(0)
                                    .setOngoing(true)
                                    .setTicker(title)
                                    .setDefaults(0)  // please be quiet
                                    .setColor(mContext.getColor(
                                            com.android.internal.R.color
                                                    .system_notification_accent_color))
                                    .setContentTitle(title)
                                    .setContentText(message)
                                    .setContentIntent(pi)
                                    .setVisibility(Notification.VISIBILITY_PUBLIC)
                                    .extend(new Notification.TvExtender()
                                            .setChannelId(ADB_NOTIFICATION_CHANNEL_ID_TV))
                                    .build();
                    Notification notification = AdbNotifications.createNotification(mContext,
                            AdbTransportType.USB);
                    mAdbNotificationShown = true;
                    mNotificationManager.notifyAsUser(null, id, notification,
                            UserHandle.ALL);
                    mNotificationManager.notifyAsUser(null, id, notification, UserHandle.ALL);
                }
            } else if (mAdbNotificationShown) {
                mAdbNotificationShown = false;