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

Commit b0f55e99 authored by Milo Sredkov's avatar Milo Sredkov
Browse files

Require screen to be unlocked for smart replies

Currently tapping on a smart reply works even when the screen is
locked. To make it consistent with inline replies, require the screen
to be unlocked before sending the reply.

Bug: 76217177
Test: atest SmartReplyViewTest
Change-Id: I3af8a0411537503650fb9f83cd99f65900e700e0
parent 4d289593
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
@@ -142,5 +143,6 @@ public class SystemUIFactory {
        providers.put(NotificationViewHierarchyManager.class,
                () -> new NotificationViewHierarchyManager(context));
        providers.put(NotificationEntryManager.class, () -> new NotificationEntryManager(context));
        providers.put(KeyguardDismissUtil.class, KeyguardDismissUtil::new);
    }
}
+29 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.phone;

import android.annotation.Nullable;

import com.android.keyguard.KeyguardHostView.OnDismissAction;


/** Executes actions that require the screen to be unlocked. */
public interface KeyguardDismissHandler {
    /** Executes an action that requres the screen to be unlocked. */
    void dismissKeyguardThenExecute(
            OnDismissAction action, @Nullable Runnable cancelAction, boolean afterKeyguardGone);
}
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.phone;

import android.util.Log;

import com.android.keyguard.KeyguardHostView.OnDismissAction;

/**
 * Executes actions that require the screen to be unlocked. Delegates the actual handling to an
 * implementation passed via {@link #setDismissHandler}.
 */
public class KeyguardDismissUtil implements KeyguardDismissHandler {
    private static final String TAG = "KeyguardDismissUtil";

    private volatile KeyguardDismissHandler mDismissHandler;

    /** Sets the actual {@link DismissHandler} implementation. */
    public void setDismissHandler(KeyguardDismissHandler dismissHandler) {
        mDismissHandler = dismissHandler;
    }

    /**
     * Executes an action that requres the screen to be unlocked.
     *
     * <p>Must be called after {@link #setDismissHandler}.
     */
    @Override
    public void dismissKeyguardThenExecute(
            OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone) {
        KeyguardDismissHandler dismissHandler = mDismissHandler;
        if (dismissHandler == null) {
            Log.wtf(TAG, "KeyguardDismissHandler not set.");
            action.onDismiss();
            return;
        }
        dismissHandler.dismissKeyguardThenExecute(action, cancelAction, afterKeyguardGone);
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -213,6 +213,7 @@ import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -1300,6 +1301,8 @@ public class StatusBar extends SystemUI implements DemoMode,

        mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
        mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController);
        Dependency.get(KeyguardDismissUtil.class).setDismissHandler(
                this::dismissKeyguardThenExecute);
        Trace.endSection();
    }

+13 −2
Original line number Diff line number Diff line
@@ -20,8 +20,10 @@ import android.view.ViewGroup;
import android.widget.Button;

import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;

import java.text.BreakIterator;
import java.util.Comparator;
@@ -42,6 +44,7 @@ public class SmartReplyView extends ViewGroup {
    private static final int SQUEEZE_FAILED = -1;

    private final SmartReplyConstants mConstants;
    private final KeyguardDismissUtil mKeyguardDismissUtil;

    /** Spacing to be applied between views. */
    private final int mSpacing;
@@ -62,6 +65,7 @@ public class SmartReplyView extends ViewGroup {
    public SmartReplyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mConstants = Dependency.get(SmartReplyConstants.class);
        mKeyguardDismissUtil = Dependency.get(KeyguardDismissUtil.class);

        int spacing = 0;
        int singleLineButtonPaddingHorizontal = 0;
@@ -126,12 +130,13 @@ public class SmartReplyView extends ViewGroup {
    }

    @VisibleForTesting
    static Button inflateReplyButton(Context context, ViewGroup root, CharSequence choice,
    Button inflateReplyButton(Context context, ViewGroup root, CharSequence choice,
            RemoteInput remoteInput, PendingIntent pendingIntent) {
        Button b = (Button) LayoutInflater.from(context).inflate(
                R.layout.smart_reply_button, root, false);
        b.setText(choice);
        b.setOnClickListener(view -> {

        OnDismissAction action = () -> {
            Bundle results = new Bundle();
            results.putString(remoteInput.getResultKey(), choice.toString());
            Intent intent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -142,6 +147,12 @@ public class SmartReplyView extends ViewGroup {
            } catch (PendingIntent.CanceledException e) {
                Log.w(TAG, "Unable to send smart reply", e);
            }
            return false; // do not defer
        };

        b.setOnClickListener(view -> {
            mKeyguardDismissUtil.dismissKeyguardThenExecute(
                    action, null /* cancelAction */, false /* afterKeyguardGone */);
        });
        return b;
    }
Loading