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

Commit a509832d authored by Jeff DeCew's avatar Jeff DeCew Committed by Android (Google) Code Review
Browse files

Merge changes from topic "b204127880_pipeline_backport_3" into sc-v2-dev

* changes:
  New Pipeline: Remote Input 4/4: Add RemoteInputCoordinator
  New Pipeline: Remote Input 3/4: Extract notification rebuilder methods to a utility
  New Pipeline: Remote Input 2/4: Add ability to internally update notifications
  New Pipeline: Remote Input 1/4: Extract legacy pipeline logic within NotificationRemoteInputManager
  Make SmartReplyController a Dumpable
parents 0f4943a7 34c62de5
Loading
Loading
Loading
Loading
+328 −269

File changed.

Preview size limit exceeded, changes collapsed.

+3 −0
Original line number Diff line number Diff line
@@ -299,6 +299,9 @@ public class RemoteInputController {
        default void onRemoteInputSent(NotificationEntry entry) {}
    }

    /**
     * This is a delegate which implements some view controller pieces of the remote input process
     */
    public interface Delegate {
        /**
         * Activate remote input if necessary.
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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;

import android.annotation.NonNull;
import android.app.Notification;
import android.app.RemoteInputHistoryItem;
import android.content.Context;
import android.net.Uri;
import android.os.Parcelable;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;

import java.util.Arrays;
import java.util.stream.Stream;

import javax.inject.Inject;

/**
 * A helper class which will augment the notifications using arguments and other information
 * accessible to the entry in order to provide intermediate remote input states.
 */
@SysUISingleton
public class RemoteInputNotificationRebuilder {

    private final Context mContext;

    @Inject
    RemoteInputNotificationRebuilder(Context context) {
        mContext = context;
    }

    /**
     * When a smart reply is sent off to the app, we insert the text into the remote input history,
     * and show a spinner to indicate that the app has yet to respond.
     */
    @NonNull
    public StatusBarNotification rebuildForSendingSmartReply(NotificationEntry entry,
            CharSequence reply) {
        return rebuildWithRemoteInputInserted(entry, reply,
                true /* showSpinner */,
                null /* mimeType */, null /* uri */);
    }

    /**
     * When the app cancels a notification in response to a smart reply, we remove the spinner
     * and leave the previously-added reply.  This is the lifetime-extended appearance of the
     * notification.
     */
    @NonNull
    public StatusBarNotification rebuildForCanceledSmartReplies(
            NotificationEntry entry) {
        return rebuildWithRemoteInputInserted(entry, null /* remoteInputTest */,
                false /* showSpinner */, null /* mimeType */, null /* uri */);
    }

    /**
     * When the app cancels a notification in response to a remote input reply, we update the
     * notification with the reply text and/or attachment. This is the lifetime-extended
     * appearance of the notification.
     */
    @NonNull
    public StatusBarNotification rebuildForRemoteInputReply(NotificationEntry entry) {
        CharSequence remoteInputText = entry.remoteInputText;
        if (TextUtils.isEmpty(remoteInputText)) {
            remoteInputText = entry.remoteInputTextWhenReset;
        }
        String remoteInputMimeType = entry.remoteInputMimeType;
        Uri remoteInputUri = entry.remoteInputUri;
        StatusBarNotification newSbn = rebuildWithRemoteInputInserted(entry,
                remoteInputText, false /* showSpinner */, remoteInputMimeType,
                remoteInputUri);
        return newSbn;
    }

    /** Inner method for generating the SBN */
    @VisibleForTesting
    @NonNull
    StatusBarNotification rebuildWithRemoteInputInserted(NotificationEntry entry,
            CharSequence remoteInputText, boolean showSpinner, String mimeType, Uri uri) {
        StatusBarNotification sbn = entry.getSbn();

        Notification.Builder b = Notification.Builder
                .recoverBuilder(mContext, sbn.getNotification().clone());
        if (remoteInputText != null || uri != null) {
            RemoteInputHistoryItem newItem = uri != null
                    ? new RemoteInputHistoryItem(mimeType, uri, remoteInputText)
                    : new RemoteInputHistoryItem(remoteInputText);
            Parcelable[] oldHistoryItems = sbn.getNotification().extras
                    .getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
            RemoteInputHistoryItem[] newHistoryItems = oldHistoryItems != null
                    ? Stream.concat(
                    Stream.of(newItem),
                    Arrays.stream(oldHistoryItems).map(p -> (RemoteInputHistoryItem) p))
                    .toArray(RemoteInputHistoryItem[]::new)
                    : new RemoteInputHistoryItem[] { newItem };
            b.setRemoteInputHistory(newHistoryItems);
        }
        b.setShowRemoteInputSpinner(showSpinner);
        b.setHideSmartReplies(true);

        Notification newNotification = b.build();

        // Undo any compatibility view inflation
        newNotification.contentView = sbn.getNotification().contentView;
        newNotification.bigContentView = sbn.getNotification().bigContentView;
        newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;

        return new StatusBarNotification(
                sbn.getPackageName(),
                sbn.getOpPkg(),
                sbn.getId(),
                sbn.getTag(),
                sbn.getUid(),
                sbn.getInitialPid(),
                newNotification,
                sbn.getUser(),
                sbn.getOverrideGroupKey(),
                sbn.getPostTime());
    }


}
+21 −3
Original line number Diff line number Diff line
@@ -19,35 +19,44 @@ import android.app.Notification;
import android.os.RemoteException;
import android.util.ArraySet;

import androidx.annotation.NonNull;

import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Set;

/**
 * Handles when smart replies are added to a notification
 * and clicked upon.
 */
public class SmartReplyController {
public class SmartReplyController implements Dumpable {
    private final IStatusBarService mBarService;
    private final NotificationEntryManager mEntryManager;
    private final NotificationClickNotifier mClickNotifier;
    private Set<String> mSendingKeys = new ArraySet<>();
    private final Set<String> mSendingKeys = new ArraySet<>();
    private Callback mCallback;

    /**
     * Injected constructor. See {@link StatusBarModule}.
     */
    public SmartReplyController(NotificationEntryManager entryManager,
    public SmartReplyController(
            DumpManager dumpManager,
            NotificationEntryManager entryManager,
            IStatusBarService statusBarService,
            NotificationClickNotifier clickNotifier) {
        mBarService = statusBarService;
        mEntryManager = entryManager;
        mClickNotifier = clickNotifier;
        dumpManager.registerDumpable(this);
    }

    public void setCallback(Callback callback) {
@@ -75,6 +84,7 @@ public class SmartReplyController {
    public void smartActionClicked(
            NotificationEntry entry, int actionIndex, Notification.Action action,
            boolean generatedByAssistant) {
        // TODO(b/204183781): get this from the current pipeline
        final int count = mEntryManager.getActiveNotificationsCount();
        final int rank = entry.getRanking().getRank();
        NotificationVisibility.NotificationLocation location =
@@ -112,6 +122,14 @@ public class SmartReplyController {
        }
    }

    @Override
    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
        pw.println("mSendingKeys: " + mSendingKeys.size());
        for (String key : mSendingKeys) {
            pw.println(" * " + key);
        }
    }

    /**
     * Callback for any class that needs to do something in response to a smart reply being sent.
     */
+7 −1
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.RemoteInputNotificationRebuilder;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -96,9 +97,11 @@ public interface StatusBarDependenciesModule {
    @Provides
    static NotificationRemoteInputManager provideNotificationRemoteInputManager(
            Context context,
            FeatureFlags featureFlags,
            NotificationLockscreenUserManager lockscreenUserManager,
            SmartReplyController smartReplyController,
            NotificationEntryManager notificationEntryManager,
            RemoteInputNotificationRebuilder rebuilder,
            Lazy<Optional<StatusBar>> statusBarOptionalLazy,
            StatusBarStateController statusBarStateController,
            Handler mainHandler,
@@ -108,9 +111,11 @@ public interface StatusBarDependenciesModule {
            DumpManager dumpManager) {
        return new NotificationRemoteInputManager(
                context,
                featureFlags,
                lockscreenUserManager,
                smartReplyController,
                notificationEntryManager,
                rebuilder,
                statusBarOptionalLazy,
                statusBarStateController,
                mainHandler,
@@ -166,10 +171,11 @@ public interface StatusBarDependenciesModule {
    @SysUISingleton
    @Provides
    static SmartReplyController provideSmartReplyController(
            DumpManager dumpManager,
            NotificationEntryManager entryManager,
            IStatusBarService statusBarService,
            NotificationClickNotifier clickNotifier) {
        return new SmartReplyController(entryManager, statusBarService, clickNotifier);
        return new SmartReplyController(dumpManager, entryManager, statusBarService, clickNotifier);
    }


Loading