1 /* 2 * Copyright (C) 2019 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 package com.android.quickstep; 17 18 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; 19 20 import android.content.Context; 21 import android.graphics.Bitmap; 22 import android.graphics.Insets; 23 import android.graphics.Rect; 24 import android.os.Bundle; 25 import android.os.IBinder; 26 import android.os.IBinder.DeathRecipient; 27 import android.os.RemoteException; 28 import android.util.Log; 29 import android.view.MotionEvent; 30 31 import com.android.launcher3.util.MainThreadInitializedObject; 32 import com.android.systemui.shared.recents.IPinnedStackAnimationListener; 33 import com.android.systemui.shared.recents.ISystemUiProxy; 34 import com.android.systemui.shared.recents.model.Task; 35 36 /** 37 * Holds the reference to SystemUI. 38 */ 39 public class SystemUiProxy implements ISystemUiProxy { 40 private static final String TAG = SystemUiProxy.class.getSimpleName(); 41 42 public static final MainThreadInitializedObject<SystemUiProxy> INSTANCE = 43 new MainThreadInitializedObject<>(SystemUiProxy::new); 44 45 private ISystemUiProxy mSystemUiProxy; 46 private final DeathRecipient mSystemUiProxyDeathRecipient = () -> { 47 MAIN_EXECUTOR.execute(() -> setProxy(null)); 48 }; 49 50 // Used to dedupe calls to SystemUI 51 private int mLastShelfHeight; 52 private boolean mLastShelfVisible; 53 private float mLastBackButtonAlpha; 54 private boolean mLastBackButtonAnimate; 55 56 // TODO(141886704): Find a way to remove this 57 private int mLastSystemUiStateFlags; 58 SystemUiProxy(Context context)59 public SystemUiProxy(Context context) { 60 // Do nothing 61 } 62 63 @Override asBinder()64 public IBinder asBinder() { 65 // Do nothing 66 return null; 67 } 68 setProxy(ISystemUiProxy proxy)69 public void setProxy(ISystemUiProxy proxy) { 70 unlinkToDeath(); 71 mSystemUiProxy = proxy; 72 linkToDeath(); 73 } 74 75 // TODO(141886704): Find a way to remove this setLastSystemUiStateFlags(int stateFlags)76 public void setLastSystemUiStateFlags(int stateFlags) { 77 mLastSystemUiStateFlags = stateFlags; 78 } 79 80 // TODO(141886704): Find a way to remove this getLastSystemUiStateFlags()81 public int getLastSystemUiStateFlags() { 82 return mLastSystemUiStateFlags; 83 } 84 isActive()85 public boolean isActive() { 86 return mSystemUiProxy != null; 87 } 88 linkToDeath()89 private void linkToDeath() { 90 if (mSystemUiProxy != null) { 91 try { 92 mSystemUiProxy.asBinder().linkToDeath(mSystemUiProxyDeathRecipient, 0 /* flags */); 93 } catch (RemoteException e) { 94 Log.e(TAG, "Failed to link sysui proxy death recipient"); 95 } 96 } 97 } 98 unlinkToDeath()99 private void unlinkToDeath() { 100 if (mSystemUiProxy != null) { 101 mSystemUiProxy.asBinder().unlinkToDeath(mSystemUiProxyDeathRecipient, 0 /* flags */); 102 } 103 } 104 105 @Override startScreenPinning(int taskId)106 public void startScreenPinning(int taskId) { 107 if (mSystemUiProxy != null) { 108 try { 109 mSystemUiProxy.startScreenPinning(taskId); 110 } catch (RemoteException e) { 111 Log.w(TAG, "Failed call startScreenPinning", e); 112 } 113 } 114 } 115 116 @Override onSplitScreenInvoked()117 public void onSplitScreenInvoked() { 118 if (mSystemUiProxy != null) { 119 try { 120 mSystemUiProxy.onSplitScreenInvoked(); 121 } catch (RemoteException e) { 122 Log.w(TAG, "Failed call onSplitScreenInvoked", e); 123 } 124 } 125 } 126 127 @Override onOverviewShown(boolean fromHome)128 public void onOverviewShown(boolean fromHome) { 129 onOverviewShown(fromHome, TAG); 130 } 131 onOverviewShown(boolean fromHome, String tag)132 public void onOverviewShown(boolean fromHome, String tag) { 133 if (mSystemUiProxy != null) { 134 try { 135 mSystemUiProxy.onOverviewShown(fromHome); 136 } catch (RemoteException e) { 137 Log.w(tag, "Failed call onOverviewShown from: " + (fromHome ? "home" : "app"), e); 138 } 139 } 140 } 141 142 @Override getNonMinimizedSplitScreenSecondaryBounds()143 public Rect getNonMinimizedSplitScreenSecondaryBounds() { 144 if (mSystemUiProxy != null) { 145 try { 146 return mSystemUiProxy.getNonMinimizedSplitScreenSecondaryBounds(); 147 } catch (RemoteException e) { 148 Log.w(TAG, "Failed call getNonMinimizedSplitScreenSecondaryBounds", e); 149 } 150 } 151 return null; 152 } 153 154 @Override setBackButtonAlpha(float alpha, boolean animate)155 public void setBackButtonAlpha(float alpha, boolean animate) { 156 boolean changed = Float.compare(alpha, mLastBackButtonAlpha) != 0 157 || animate != mLastBackButtonAnimate; 158 if (mSystemUiProxy != null && changed) { 159 mLastBackButtonAlpha = alpha; 160 mLastBackButtonAnimate = animate; 161 try { 162 mSystemUiProxy.setBackButtonAlpha(alpha, animate); 163 } catch (RemoteException e) { 164 Log.w(TAG, "Failed call setBackButtonAlpha", e); 165 } 166 } 167 } 168 getLastBackButtonAlpha()169 public float getLastBackButtonAlpha() { 170 return mLastBackButtonAlpha; 171 } 172 173 @Override setNavBarButtonAlpha(float alpha, boolean animate)174 public void setNavBarButtonAlpha(float alpha, boolean animate) { 175 if (mSystemUiProxy != null) { 176 try { 177 mSystemUiProxy.setNavBarButtonAlpha(alpha, animate); 178 } catch (RemoteException e) { 179 Log.w(TAG, "Failed call setNavBarButtonAlpha", e); 180 } 181 } 182 } 183 184 @Override onStatusBarMotionEvent(MotionEvent event)185 public void onStatusBarMotionEvent(MotionEvent event) { 186 if (mSystemUiProxy != null) { 187 try { 188 mSystemUiProxy.onStatusBarMotionEvent(event); 189 } catch (RemoteException e) { 190 Log.w(TAG, "Failed call onStatusBarMotionEvent", e); 191 } 192 } 193 } 194 195 @Override onAssistantProgress(float progress)196 public void onAssistantProgress(float progress) { 197 if (mSystemUiProxy != null) { 198 try { 199 mSystemUiProxy.onAssistantProgress(progress); 200 } catch (RemoteException e) { 201 Log.w(TAG, "Failed call onAssistantProgress with progress: " + progress, e); 202 } 203 } 204 } 205 206 @Override onAssistantGestureCompletion(float velocity)207 public void onAssistantGestureCompletion(float velocity) { 208 if (mSystemUiProxy != null) { 209 try { 210 mSystemUiProxy.onAssistantGestureCompletion(velocity); 211 } catch (RemoteException e) { 212 Log.w(TAG, "Failed call onAssistantGestureCompletion", e); 213 } 214 } 215 } 216 217 @Override startAssistant(Bundle args)218 public void startAssistant(Bundle args) { 219 if (mSystemUiProxy != null) { 220 try { 221 mSystemUiProxy.startAssistant(args); 222 } catch (RemoteException e) { 223 Log.w(TAG, "Failed call startAssistant", e); 224 } 225 } 226 } 227 228 @Override monitorGestureInput(String name, int displayId)229 public Bundle monitorGestureInput(String name, int displayId) { 230 if (mSystemUiProxy != null) { 231 try { 232 return mSystemUiProxy.monitorGestureInput(name, displayId); 233 } catch (RemoteException e) { 234 Log.w(TAG, "Failed call monitorGestureInput: " + name, e); 235 } 236 } 237 return null; 238 } 239 240 @Override notifyAccessibilityButtonClicked(int displayId)241 public void notifyAccessibilityButtonClicked(int displayId) { 242 if (mSystemUiProxy != null) { 243 try { 244 mSystemUiProxy.notifyAccessibilityButtonClicked(displayId); 245 } catch (RemoteException e) { 246 Log.w(TAG, "Failed call notifyAccessibilityButtonClicked", e); 247 } 248 } 249 } 250 251 @Override notifyAccessibilityButtonLongClicked()252 public void notifyAccessibilityButtonLongClicked() { 253 if (mSystemUiProxy != null) { 254 try { 255 mSystemUiProxy.notifyAccessibilityButtonLongClicked(); 256 } catch (RemoteException e) { 257 Log.w(TAG, "Failed call notifyAccessibilityButtonLongClicked", e); 258 } 259 } 260 } 261 262 @Override stopScreenPinning()263 public void stopScreenPinning() { 264 if (mSystemUiProxy != null) { 265 try { 266 mSystemUiProxy.stopScreenPinning(); 267 } catch (RemoteException e) { 268 Log.w(TAG, "Failed call stopScreenPinning", e); 269 } 270 } 271 } 272 273 @Override setShelfHeight(boolean visible, int shelfHeight)274 public void setShelfHeight(boolean visible, int shelfHeight) { 275 boolean changed = visible != mLastShelfVisible || shelfHeight != mLastShelfHeight; 276 if (mSystemUiProxy != null && changed) { 277 mLastShelfVisible = visible; 278 mLastShelfHeight = shelfHeight; 279 try { 280 mSystemUiProxy.setShelfHeight(visible, shelfHeight); 281 } catch (RemoteException e) { 282 Log.w(TAG, "Failed call setShelfHeight visible: " + visible 283 + " height: " + shelfHeight, e); 284 } 285 } 286 } 287 288 @Override handleImageAsScreenshot(Bitmap bitmap, Rect rect, Insets insets, int i)289 public void handleImageAsScreenshot(Bitmap bitmap, Rect rect, Insets insets, int i) { 290 if (mSystemUiProxy != null) { 291 try { 292 mSystemUiProxy.handleImageAsScreenshot(bitmap, rect, insets, i); 293 } catch (RemoteException e) { 294 Log.w(TAG, "Failed call handleImageAsScreenshot", e); 295 } 296 } 297 } 298 299 @Override setSplitScreenMinimized(boolean minimized)300 public void setSplitScreenMinimized(boolean minimized) { 301 if (mSystemUiProxy != null) { 302 try { 303 mSystemUiProxy.setSplitScreenMinimized(minimized); 304 } catch (RemoteException e) { 305 Log.w(TAG, "Failed call stopScreenPinning", e); 306 } 307 } 308 } 309 310 /** 311 * Notifies that swipe-to-home action is finished. 312 */ 313 @Override notifySwipeToHomeFinished()314 public void notifySwipeToHomeFinished() { 315 if (mSystemUiProxy != null) { 316 try { 317 mSystemUiProxy.notifySwipeToHomeFinished(); 318 } catch (RemoteException e) { 319 Log.w(TAG, "Failed call setPinnedStackAnimationType", e); 320 } 321 } 322 } 323 324 /** 325 * Sets listener to get pinned stack animation callbacks. 326 */ 327 @Override setPinnedStackAnimationListener(IPinnedStackAnimationListener listener)328 public void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) { 329 if (mSystemUiProxy != null) { 330 try { 331 mSystemUiProxy.setPinnedStackAnimationListener(listener); 332 } catch (RemoteException e) { 333 Log.w(TAG, "Failed call setPinnedStackAnimationListener", e); 334 } 335 } 336 } 337 338 @Override onQuickSwitchToNewTask(int rotation)339 public void onQuickSwitchToNewTask(int rotation) { 340 if (mSystemUiProxy != null) { 341 try { 342 mSystemUiProxy.onQuickSwitchToNewTask(rotation); 343 } catch (RemoteException e) { 344 Log.w(TAG, "Failed call onQuickSwitchToNewTask with arg: " + rotation, e); 345 } 346 } 347 } 348 349 @Override handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen, Insets visibleInsets, Task.TaskKey task)350 public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen, 351 Insets visibleInsets, Task.TaskKey task) { 352 if (mSystemUiProxy != null) { 353 try { 354 mSystemUiProxy.handleImageBundleAsScreenshot(screenImageBundle, locationInScreen, 355 visibleInsets, task); 356 } catch (RemoteException e) { 357 Log.w(TAG, "Failed call handleImageBundleAsScreenshot"); 358 } 359 } 360 } 361 } 362