1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.car.systembar;
18 
19 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE;
20 
21 import android.app.role.RoleManager;
22 import android.content.Context;
23 import android.content.res.TypedArray;
24 import android.os.Bundle;
25 import android.os.RemoteException;
26 import android.util.AttributeSet;
27 import android.util.Log;
28 
29 import com.android.internal.app.AssistUtils;
30 import com.android.internal.app.IVoiceInteractionSessionListener;
31 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
32 
33 /**
34  * AssitantButton is a ui component that will trigger the Voice Interaction Service.
35  */
36 public class AssitantButton extends CarSystemBarButton {
37     private static final String TAG = "AssistantButton";
38     private final AssistUtils mAssistUtils;
39     private final IVoiceInteractionSessionShowCallback mShowCallback =
40             new IVoiceInteractionSessionShowCallback.Stub() {
41                 @Override
42                 public void onFailed() {
43                     Log.w(TAG, "Failed to show VoiceInteractionSession");
44                 }
45 
46                 @Override
47                 public void onShown() {
48                     Log.d(TAG, "IVoiceInteractionSessionShowCallback onShown()");
49                 }
50             };
51 
AssitantButton(Context context, AttributeSet attrs)52     public AssitantButton(Context context, AttributeSet attrs) {
53         super(context, attrs);
54         mAssistUtils = new AssistUtils(context);
55         setOnClickListener(v -> showAssistant());
56         mAssistUtils.registerVoiceInteractionSessionListener(
57                 new IVoiceInteractionSessionListener.Stub() {
58                     @Override
59                     public void onVoiceSessionShown() throws RemoteException {
60                         assistantSetSelected(/* selected= */ true);
61                     }
62 
63                     @Override
64                     public void onVoiceSessionHidden() throws RemoteException {
65                         assistantSetSelected(/* selected= */ false);
66                     }
67 
68                     @Override
69                     public void onSetUiHints(Bundle hints) {
70                     }
71                 }
72         );
73     }
74 
showAssistant()75     private void showAssistant() {
76         final Bundle args = new Bundle();
77         mAssistUtils.showSessionForActiveService(args,
78                 SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, /*activityToken=*/ null);
79     }
80 
81     @Override
setUpIntents(TypedArray typedArray)82     protected void setUpIntents(TypedArray typedArray) {
83         // left blank because for the assistant button Intent will not be passed from the layout.
84     }
85 
86     @Override
getRoleName()87     protected String getRoleName() {
88         return RoleManager.ROLE_ASSISTANT;
89     }
90 
91     @Override
setSelected(boolean selected)92     public void setSelected(boolean selected) {
93         // override to no-op as AssistantButton will maintain its own selected state by listening to
94         // the actual voice interaction session.
95     }
96 
assistantSetSelected(boolean selected)97     private void assistantSetSelected(boolean selected) {
98         if (hasSelectionState()) {
99             getContext().getMainExecutor().execute(
100                     () -> AssitantButton.super.setSelected(selected));
101         }
102     }
103 }
104