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