• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 android.app.ActivityManager;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.res.TypedArray;
23 import android.hardware.input.InputManager;
24 import android.view.KeyEvent;
25 import android.view.View;
26 
27 import androidx.annotation.VisibleForTesting;
28 
29 import com.android.systemui.R;
30 import com.android.systemui.shared.system.TaskStackChangeListener;
31 import com.android.systemui.shared.system.TaskStackChangeListeners;
32 import com.android.systemui.statusbar.AlphaOptimizedImageView;
33 
34 import java.util.function.Consumer;
35 
36 /**
37  * Used to add Recents state functionality to a {@link CarSystemBarButton}
38  * Long click functionality is updated to send KeyEvent instead of regular intents when Recents is
39  * inactive.
40  * click functionality is updated to send KeyEvent when Recents is active.
41  * TaskStackChangeListener helps to toggle the local long clicked state which further helps
42  * determine the appropriate icon and alpha to show.
43  */
44 public class RecentsButtonStateProvider {
45     private final InputManager mInputManager;
46     private final ComponentName mRecentsComponentName;
47     private final CarSystemBarButton mCarSystemBarButton;
48     private final boolean mIsRecentsEntryPointEnabled;
49     private TaskStackChangeListener mTaskStackChangeListener;
50     private boolean mIsRecentsActive;
51 
RecentsButtonStateProvider(Context context, CarSystemBarButton carSystemBarButton)52     public RecentsButtonStateProvider(Context context, CarSystemBarButton carSystemBarButton) {
53         mCarSystemBarButton = carSystemBarButton;
54         mInputManager = context.getSystemService(InputManager.class);
55         mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
56                 com.android.internal.R.string.config_recentsComponentName));
57         mIsRecentsEntryPointEnabled = context.getResources()
58                 .getBoolean(R.bool.config_enableRecentsEntryPoint);
59         initialiseListener();
60     }
61 
initialiseListener()62     protected void initialiseListener() {
63         mTaskStackChangeListener = new TaskStackChangeListener() {
64             @Override
65             public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
66                 if (mRecentsComponentName == null) {
67                     return;
68                 }
69                 ComponentName topComponent =
70                         taskInfo.topActivity != null ? taskInfo.topActivity
71                                 : taskInfo.baseIntent.getComponent();
72                 if (topComponent != null && mRecentsComponentName.getClassName().equals(
73                         topComponent.getClassName())) {
74                     mIsRecentsActive = true;
75                     return;
76                 }
77                 mIsRecentsActive = false;
78             }
79         };
80         TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackChangeListener);
81     }
82 
83     /**
84      * Adds OnLongClickListener to the {@link CarSystemBarButton} to toggle Recents.
85      *
86      * @param defaultSetUpIntents default function to be called for non Recents functionality.
87      * @see CarSystemBarButton#setUpIntents(TypedArray)
88      */
setUpIntents(TypedArray typedArray, Consumer<TypedArray> defaultSetUpIntents)89     public void setUpIntents(TypedArray typedArray, Consumer<TypedArray> defaultSetUpIntents) {
90         if (defaultSetUpIntents != null) {
91             defaultSetUpIntents.accept(typedArray);
92         }
93         mCarSystemBarButton.setOnLongClickListener(v -> {
94             if (mIsRecentsActive) {
95                 return false;
96             }
97             return toggleRecents();
98         });
99     }
100 
101     /**
102      * Adds OnClickListener to the {@link CarSystemBarButton} to toggle Recents.
103      *
104      * @param defaultGetButtonClickListener default function to be called for non Recents
105      *                                      functionality.
106      * @see CarSystemBarButton#getButtonClickListener()
107      */
getButtonClickListener( View.OnClickListener defaultGetButtonClickListener)108     public View.OnClickListener getButtonClickListener(
109             View.OnClickListener defaultGetButtonClickListener) {
110         return v -> {
111             if (mIsRecentsActive) {
112                 toggleRecents();
113                 return;
114             }
115             if (defaultGetButtonClickListener != null) {
116                 defaultGetButtonClickListener.onClick(v);
117             }
118         };
119     }
120 
121 
122     /**
123      * Updates the {@code icon}'s drawable to Recents icon when Recents is active.
124      *
125      * @param defaultUpdateImage default function to be called for non Recents functionality.
126      * @see CarSystemBarButton#updateImage(AlphaOptimizedImageView)
127      */
128     public void updateImage(AlphaOptimizedImageView icon,
129             Consumer<AlphaOptimizedImageView> defaultUpdateImage) {
130         if (mIsRecentsActive) {
131             icon.setImageResource(R.drawable.car_ic_recents);
132             return;
133         }
134         if (defaultUpdateImage == null) {
135             return;
136         }
137         defaultUpdateImage.accept(icon);
138     }
139 
140     /**
141      * Updates the {@code icon}'s alpha to selected alpha when Recents is active.
142      *
143      * @param defaultRefreshIconAlpha default function to be called for non Recents functionality.
144      * @see CarSystemBarButton#refreshIconAlpha(AlphaOptimizedImageView)
145      */
146     public void refreshIconAlpha(AlphaOptimizedImageView icon,
147             Consumer<AlphaOptimizedImageView> defaultRefreshIconAlpha) {
148         if (mIsRecentsActive) {
149             icon.setAlpha(mCarSystemBarButton.getSelectedAlpha());
150             return;
151         }
152         if (defaultRefreshIconAlpha == null) {
153             return;
154         }
155         defaultRefreshIconAlpha.accept(icon);
156     }
157 
158     /**
159      * Sets if the Recents activity is in foreground.
160      */
161     public void setIsRecentsActive(boolean isRecentsActive) {
162         mIsRecentsActive = isRecentsActive;
163     }
164 
165     /**
166      * Gets if the Recents activity is in foreground.
167      */
168     public boolean getIsRecentsActive() {
169         return mIsRecentsActive;
170     }
171 
172     /**
173      * Opens/closes the Recents Activity.
174      */
175     protected boolean toggleRecents() {
176         return mIsRecentsEntryPointEnabled && mInputManager.injectInputEvent(
177                 new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_APP_SWITCH),
178                 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
179     }
180 
181     @VisibleForTesting
182     TaskStackChangeListener getTaskStackChangeListener() {
183         return mTaskStackChangeListener;
184     }
185 }
186