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

Commit 9a419cda authored by Joshua Duong's avatar Joshua Duong Committed by Android (Google) Code Review
Browse files

Merge "Fix PendingIntent hijacking for adb notifications." into rvc-dev

parents 2bac1596 ec1980f8
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;