1 /* 2 * Copyright (C) 2021 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.launcher3.taskbar; 17 18 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 19 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 20 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; 21 22 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN; 23 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; 24 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED; 25 import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT; 26 import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR; 27 28 import android.animation.AnimatorSet; 29 import android.app.ActivityOptions; 30 import android.content.ActivityNotFoundException; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.pm.ActivityInfo.Config; 34 import android.content.pm.LauncherApps; 35 import android.content.res.Resources; 36 import android.graphics.Insets; 37 import android.graphics.PixelFormat; 38 import android.graphics.Rect; 39 import android.os.Process; 40 import android.os.SystemProperties; 41 import android.provider.Settings; 42 import android.util.Log; 43 import android.view.ContextThemeWrapper; 44 import android.view.Display; 45 import android.view.Gravity; 46 import android.view.LayoutInflater; 47 import android.view.RoundedCorner; 48 import android.view.View; 49 import android.view.WindowManager; 50 import android.widget.FrameLayout; 51 import android.widget.Toast; 52 53 import androidx.annotation.NonNull; 54 import androidx.annotation.Nullable; 55 56 import com.android.launcher3.AbstractFloatingView; 57 import com.android.launcher3.DeviceProfile; 58 import com.android.launcher3.LauncherSettings.Favorites; 59 import com.android.launcher3.R; 60 import com.android.launcher3.folder.Folder; 61 import com.android.launcher3.folder.FolderIcon; 62 import com.android.launcher3.logger.LauncherAtom; 63 import com.android.launcher3.model.data.FolderInfo; 64 import com.android.launcher3.model.data.WorkspaceItemInfo; 65 import com.android.launcher3.touch.ItemClickHandler; 66 import com.android.launcher3.util.PackageManagerHelper; 67 import com.android.launcher3.util.SettingsCache; 68 import com.android.launcher3.util.Themes; 69 import com.android.launcher3.util.TraceHelper; 70 import com.android.launcher3.util.ViewCache; 71 import com.android.launcher3.views.ActivityContext; 72 import com.android.quickstep.SysUINavigationMode; 73 import com.android.quickstep.SysUINavigationMode.Mode; 74 import com.android.systemui.shared.recents.model.Task; 75 import com.android.systemui.shared.rotation.RotationButtonController; 76 import com.android.systemui.shared.system.ActivityManagerWrapper; 77 import com.android.systemui.shared.system.WindowManagerWrapper; 78 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider; 79 80 /** 81 * The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements 82 * that are used by both Launcher and Taskbar (such as Folder) to reference a generic 83 * ActivityContext and BaseDragLayer instead of the Launcher activity and its DragLayer. 84 */ 85 public class TaskbarActivityContext extends ContextThemeWrapper implements ActivityContext { 86 87 private static final boolean ENABLE_THREE_BUTTON_TASKBAR = 88 SystemProperties.getBoolean("persist.debug.taskbar_three_button", false); 89 private static final String TAG = "TaskbarActivityContext"; 90 91 private static final String WINDOW_TITLE = "Taskbar"; 92 93 private final DeviceProfile mDeviceProfile; 94 private final LayoutInflater mLayoutInflater; 95 private final TaskbarDragLayer mDragLayer; 96 private final TaskbarControllers mControllers; 97 98 private final WindowManager mWindowManager; 99 private final @Nullable RoundedCorner mLeftCorner, mRightCorner; 100 private final int mTaskbarHeightForIme; 101 private WindowManager.LayoutParams mWindowLayoutParams; 102 private boolean mIsFullscreen; 103 // The size we should return to when we call setTaskbarWindowFullscreen(false) 104 private int mLastRequestedNonFullscreenHeight; 105 106 private final SysUINavigationMode.Mode mNavMode; 107 private final ViewCache mViewCache = new ViewCache(); 108 109 private final boolean mIsSafeModeEnabled; 110 private final boolean mIsUserSetupComplete; 111 private boolean mIsDestroyed = false; 112 // The flag to know if the window is excluded from magnification region computation. 113 private boolean mIsExcludeFromMagnificationRegion = false; 114 TaskbarActivityContext(Context windowContext, DeviceProfile dp, TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider unfoldTransitionProgressProvider)115 public TaskbarActivityContext(Context windowContext, DeviceProfile dp, 116 TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider 117 unfoldTransitionProgressProvider) { 118 super(windowContext, Themes.getActivityThemeRes(windowContext)); 119 mDeviceProfile = dp; 120 121 mNavMode = SysUINavigationMode.getMode(windowContext); 122 mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode", 123 () -> getPackageManager().isSafeMode()); 124 mIsUserSetupComplete = SettingsCache.INSTANCE.get(this).getValue( 125 Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0); 126 127 final Resources resources = getResources(); 128 float taskbarIconSize = resources.getDimension(R.dimen.taskbar_icon_size); 129 mDeviceProfile.updateIconSize(1, resources); 130 float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx; 131 mDeviceProfile.updateIconSize(iconScale, resources); 132 133 mTaskbarHeightForIme = resources.getDimensionPixelSize(R.dimen.taskbar_ime_size); 134 135 mLayoutInflater = LayoutInflater.from(this).cloneInContext(this); 136 137 // Inflate views. 138 mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate( 139 R.layout.taskbar, null, false); 140 TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view); 141 TaskbarScrimView taskbarScrimView = mDragLayer.findViewById(R.id.taskbar_scrim); 142 FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view); 143 StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle); 144 145 Display display = windowContext.getDisplay(); 146 Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY 147 ? windowContext.getApplicationContext() 148 : windowContext.getApplicationContext().createDisplayContext(display); 149 mWindowManager = c.getSystemService(WindowManager.class); 150 mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT); 151 mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT); 152 153 // Construct controllers. 154 mControllers = new TaskbarControllers(this, 155 new TaskbarDragController(this), 156 buttonController, 157 new NavbarButtonsViewController(this, navButtonsView), 158 new RotationButtonController(this, 159 c.getColor(R.color.taskbar_nav_icon_light_color), 160 c.getColor(R.color.taskbar_nav_icon_dark_color), 161 R.drawable.ic_sysbar_rotate_button_ccw_start_0, 162 R.drawable.ic_sysbar_rotate_button_ccw_start_90, 163 R.drawable.ic_sysbar_rotate_button_cw_start_0, 164 R.drawable.ic_sysbar_rotate_button_cw_start_90, 165 () -> getDisplay().getRotation()), 166 new TaskbarDragLayerController(this, mDragLayer), 167 new TaskbarViewController(this, taskbarView), 168 new TaskbarScrimViewController(this, taskbarScrimView), 169 new TaskbarUnfoldAnimationController(unfoldTransitionProgressProvider, 170 mWindowManager), 171 new TaskbarKeyguardController(this), 172 new StashedHandleViewController(this, stashedHandleView), 173 new TaskbarStashController(this), 174 new TaskbarEduController(this), 175 new TaskbarAutohideSuspendController(this), 176 new TaskbarPopupController()); 177 } 178 init(TaskbarSharedState sharedState)179 public void init(TaskbarSharedState sharedState) { 180 mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight(); 181 mWindowLayoutParams = new WindowManager.LayoutParams( 182 MATCH_PARENT, 183 mLastRequestedNonFullscreenHeight, 184 TYPE_NAVIGATION_BAR_PANEL, 185 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 186 | WindowManager.LayoutParams.FLAG_SLIPPERY, 187 PixelFormat.TRANSLUCENT); 188 mWindowLayoutParams.setTitle(WINDOW_TITLE); 189 mWindowLayoutParams.packageName = getPackageName(); 190 mWindowLayoutParams.gravity = Gravity.BOTTOM; 191 mWindowLayoutParams.setFitInsetsTypes(0); 192 mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; 193 mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 194 mWindowLayoutParams.privateFlags = 195 WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; 196 197 WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance(); 198 wmWrapper.setProvidesInsetsTypes( 199 mWindowLayoutParams, 200 new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT } 201 ); 202 // Adjust the frame by the rounded corners (ie. leaving just the bar as the inset) when 203 // the IME is showing 204 mWindowLayoutParams.providedInternalImeInsets = Insets.of(0, 205 getDefaultTaskbarWindowHeight() - mTaskbarHeightForIme, 0, 0); 206 207 // Initialize controllers after all are constructed. 208 mControllers.init(sharedState); 209 updateSysuiStateFlags(sharedState.sysuiStateFlags, true /* fromInit */); 210 211 mWindowManager.addView(mDragLayer, mWindowLayoutParams); 212 } 213 onConfigurationChanged(@onfig int configChanges)214 public void onConfigurationChanged(@Config int configChanges) { 215 mControllers.onConfigurationChanged(configChanges); 216 } 217 isThreeButtonNav()218 public boolean isThreeButtonNav() { 219 return mNavMode == Mode.THREE_BUTTONS; 220 } 221 getLeftCornerRadius()222 public int getLeftCornerRadius() { 223 return mLeftCorner == null ? 0 : mLeftCorner.getRadius(); 224 } 225 getRightCornerRadius()226 public int getRightCornerRadius() { 227 return mRightCorner == null ? 0 : mRightCorner.getRadius(); 228 } 229 230 @Override getLayoutInflater()231 public LayoutInflater getLayoutInflater() { 232 return mLayoutInflater; 233 } 234 235 @Override getDragLayer()236 public TaskbarDragLayer getDragLayer() { 237 return mDragLayer; 238 } 239 240 @Override getDeviceProfile()241 public DeviceProfile getDeviceProfile() { 242 return mDeviceProfile; 243 } 244 245 @Override getFolderBoundingBox()246 public Rect getFolderBoundingBox() { 247 return mControllers.taskbarDragLayerController.getFolderBoundingBox(); 248 } 249 250 @Override getDragController()251 public TaskbarDragController getDragController() { 252 return mControllers.taskbarDragController; 253 } 254 255 @Override getViewCache()256 public ViewCache getViewCache() { 257 return mViewCache; 258 } 259 260 @Override supportsIme()261 public boolean supportsIme() { 262 // Currently we don't support IME because we have FLAG_NOT_FOCUSABLE. We can remove that 263 // flag when opening a floating view that needs IME (such as Folder), but then that means 264 // Taskbar will be below IME and thus users can't click the back button. 265 return false; 266 } 267 268 @Override getItemOnClickListener()269 public View.OnClickListener getItemOnClickListener() { 270 return this::onTaskbarIconClicked; 271 } 272 273 /** 274 * Change from hotseat/predicted hotseat to taskbar container. 275 */ 276 @Override applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder)277 public void applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder) { 278 if (!itemInfoBuilder.hasContainerInfo()) { 279 return; 280 } 281 LauncherAtom.ContainerInfo oldContainer = itemInfoBuilder.getContainerInfo(); 282 283 if (oldContainer.hasPredictedHotseatContainer()) { 284 LauncherAtom.PredictedHotseatContainer predictedHotseat = 285 oldContainer.getPredictedHotseatContainer(); 286 LauncherAtom.TaskBarContainer.Builder taskbarBuilder = 287 LauncherAtom.TaskBarContainer.newBuilder(); 288 289 if (predictedHotseat.hasIndex()) { 290 taskbarBuilder.setIndex(predictedHotseat.getIndex()); 291 } 292 if (predictedHotseat.hasCardinality()) { 293 taskbarBuilder.setCardinality(predictedHotseat.getCardinality()); 294 } 295 296 itemInfoBuilder.setContainerInfo(LauncherAtom.ContainerInfo.newBuilder() 297 .setTaskBarContainer(taskbarBuilder)); 298 } else if (oldContainer.hasHotseat()) { 299 LauncherAtom.HotseatContainer hotseat = oldContainer.getHotseat(); 300 LauncherAtom.TaskBarContainer.Builder taskbarBuilder = 301 LauncherAtom.TaskBarContainer.newBuilder(); 302 303 if (hotseat.hasIndex()) { 304 taskbarBuilder.setIndex(hotseat.getIndex()); 305 } 306 307 itemInfoBuilder.setContainerInfo(LauncherAtom.ContainerInfo.newBuilder() 308 .setTaskBarContainer(taskbarBuilder)); 309 } else if (oldContainer.hasFolder() && oldContainer.getFolder().hasHotseat()) { 310 LauncherAtom.FolderContainer.Builder folderBuilder = oldContainer.getFolder() 311 .toBuilder(); 312 LauncherAtom.HotseatContainer hotseat = folderBuilder.getHotseat(); 313 LauncherAtom.TaskBarContainer.Builder taskbarBuilder = 314 LauncherAtom.TaskBarContainer.newBuilder(); 315 316 if (hotseat.hasIndex()) { 317 taskbarBuilder.setIndex(hotseat.getIndex()); 318 } 319 320 folderBuilder.setTaskbar(taskbarBuilder); 321 folderBuilder.clearHotseat(); 322 itemInfoBuilder.setContainerInfo(LauncherAtom.ContainerInfo.newBuilder() 323 .setFolder(folderBuilder)); 324 } 325 } 326 327 /** 328 * Sets a new data-source for this taskbar instance 329 */ setUIController(@onNull TaskbarUIController uiController)330 public void setUIController(@NonNull TaskbarUIController uiController) { 331 mControllers.uiController.onDestroy(); 332 mControllers.uiController = uiController; 333 mControllers.uiController.init(mControllers); 334 } 335 336 /** 337 * Sets the flag indicating setup UI is visible 338 */ setSetupUIVisible(boolean isVisible)339 public void setSetupUIVisible(boolean isVisible) { 340 mControllers.taskbarStashController.setSetupUIVisible(isVisible); 341 } 342 343 /** 344 * Called when this instance of taskbar is no longer needed 345 */ onDestroy()346 public void onDestroy() { 347 mIsDestroyed = true; 348 setUIController(TaskbarUIController.DEFAULT); 349 mControllers.onDestroy(); 350 mWindowManager.removeViewImmediate(mDragLayer); 351 } 352 updateSysuiStateFlags(int systemUiStateFlags, boolean fromInit)353 public void updateSysuiStateFlags(int systemUiStateFlags, boolean fromInit) { 354 mControllers.navbarButtonsViewController.updateStateForSysuiFlags(systemUiStateFlags, 355 fromInit); 356 mControllers.taskbarViewController.setImeIsVisible( 357 mControllers.navbarButtonsViewController.isImeVisible()); 358 int shadeExpandedFlags = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED 359 | SYSUI_STATE_QUICK_SETTINGS_EXPANDED; 360 onNotificationShadeExpandChanged((systemUiStateFlags & shadeExpandedFlags) != 0, fromInit); 361 mControllers.taskbarViewController.setRecentsButtonDisabled( 362 mControllers.navbarButtonsViewController.isRecentsDisabled()); 363 mControllers.stashedHandleViewController.setIsHomeButtonDisabled( 364 mControllers.navbarButtonsViewController.isHomeDisabled()); 365 mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags); 366 mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags, fromInit); 367 mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags, 368 fromInit); 369 mControllers.navButtonController.updateSysuiFlags(systemUiStateFlags); 370 } 371 372 /** 373 * Hides the taskbar icons and background when the notication shade is expanded. 374 */ onNotificationShadeExpandChanged(boolean isExpanded, boolean skipAnim)375 private void onNotificationShadeExpandChanged(boolean isExpanded, boolean skipAnim) { 376 float alpha = isExpanded ? 0 : 1; 377 AnimatorSet anim = new AnimatorSet(); 378 anim.play(mControllers.taskbarViewController.getTaskbarIconAlpha().getProperty( 379 TaskbarViewController.ALPHA_INDEX_NOTIFICATION_EXPANDED).animateToValue(alpha)); 380 if (!isThreeButtonNav()) { 381 anim.play(mControllers.taskbarDragLayerController.getNotificationShadeBgTaskbar() 382 .animateToValue(alpha)); 383 } 384 anim.start(); 385 if (skipAnim) { 386 anim.end(); 387 } 388 } 389 onRotationProposal(int rotation, boolean isValid)390 public void onRotationProposal(int rotation, boolean isValid) { 391 mControllers.rotationButtonController.onRotationProposal(rotation, isValid); 392 } 393 disableNavBarElements(int displayId, int state1, int state2, boolean animate)394 public void disableNavBarElements(int displayId, int state1, int state2, boolean animate) { 395 if (displayId != getDisplayId()) { 396 return; 397 } 398 mControllers.rotationButtonController.onDisable2FlagChanged(state2); 399 } 400 onSystemBarAttributesChanged(int displayId, int behavior)401 public void onSystemBarAttributesChanged(int displayId, int behavior) { 402 mControllers.rotationButtonController.onBehaviorChanged(displayId, behavior); 403 } 404 onNavButtonsDarkIntensityChanged(float darkIntensity)405 public void onNavButtonsDarkIntensityChanged(float darkIntensity) { 406 if (!isUserSetupComplete()) { 407 return; 408 } 409 mControllers.navbarButtonsViewController.getTaskbarNavButtonDarkIntensity() 410 .updateValue(darkIntensity); 411 } 412 413 /** 414 * Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size. 415 */ setTaskbarWindowFullscreen(boolean fullscreen)416 public void setTaskbarWindowFullscreen(boolean fullscreen) { 417 mControllers.taskbarAutohideSuspendController.updateFlag( 418 TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, fullscreen); 419 mIsFullscreen = fullscreen; 420 setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight); 421 } 422 isTaskbarWindowFullscreen()423 public boolean isTaskbarWindowFullscreen() { 424 return mIsFullscreen; 425 } 426 427 /** 428 * Updates the TaskbarContainer height (pass {@link #getDefaultTaskbarWindowHeight()} to reset). 429 */ setTaskbarWindowHeight(int height)430 public void setTaskbarWindowHeight(int height) { 431 if (mWindowLayoutParams.height == height || mIsDestroyed) { 432 return; 433 } 434 if (height == MATCH_PARENT) { 435 height = mDeviceProfile.heightPx; 436 } else { 437 mLastRequestedNonFullscreenHeight = height; 438 if (mIsFullscreen) { 439 // We still need to be fullscreen, so defer any change to our height until we call 440 // setTaskbarWindowFullscreen(false). For example, this could happen when dragging 441 // from the gesture region, as the drag will cancel the gesture and reset launcher's 442 // state, which in turn normally would reset the taskbar window height as well. 443 return; 444 } 445 } 446 mWindowLayoutParams.height = height; 447 mWindowLayoutParams.providedInternalImeInsets = 448 Insets.of(0, height - mTaskbarHeightForIme, 0, 0); 449 mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); 450 } 451 452 /** 453 * Returns the default height of the window, including the static corner radii above taskbar. 454 */ getDefaultTaskbarWindowHeight()455 public int getDefaultTaskbarWindowHeight() { 456 return mDeviceProfile.taskbarSize + Math.max(getLeftCornerRadius(), getRightCornerRadius()); 457 } 458 459 /** 460 * Returns the bottom insets taskbar provides to the IME when IME is visible. 461 */ getTaskbarHeightForIme()462 public int getTaskbarHeightForIme() { 463 return mTaskbarHeightForIme; 464 } 465 onTaskbarIconClicked(View view)466 protected void onTaskbarIconClicked(View view) { 467 Object tag = view.getTag(); 468 if (tag instanceof Task) { 469 Task task = (Task) tag; 470 ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key, 471 ActivityOptions.makeBasic()); 472 } else if (tag instanceof FolderInfo) { 473 FolderIcon folderIcon = (FolderIcon) view; 474 Folder folder = folderIcon.getFolder(); 475 setTaskbarWindowFullscreen(true); 476 477 getDragLayer().post(() -> { 478 folder.animateOpen(); 479 getStatsLogManager().logger().withItemInfo(folder.mInfo).log(LAUNCHER_FOLDER_OPEN); 480 481 folder.iterateOverItems((itemInfo, itemView) -> { 482 mControllers.taskbarViewController 483 .setClickAndLongClickListenersForIcon(itemView); 484 // To play haptic when dragging, like other Taskbar items do. 485 itemView.setHapticFeedbackEnabled(true); 486 return false; 487 }); 488 }); 489 } else if (tag instanceof WorkspaceItemInfo) { 490 WorkspaceItemInfo info = (WorkspaceItemInfo) tag; 491 if (info.isDisabled()) { 492 ItemClickHandler.handleDisabledItemClicked(info, this); 493 } else { 494 Intent intent = new Intent(info.getIntent()) 495 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 496 try { 497 if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) { 498 Toast.makeText(this, R.string.safemode_shortcut_error, 499 Toast.LENGTH_SHORT).show(); 500 } else if (info.isPromise()) { 501 intent = new PackageManagerHelper(this) 502 .getMarketIntent(info.getTargetPackage()) 503 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 504 startActivity(intent); 505 506 } else if (info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) { 507 String id = info.getDeepShortcutId(); 508 String packageName = intent.getPackage(); 509 getSystemService(LauncherApps.class) 510 .startShortcut(packageName, id, null, null, info.user); 511 } else if (info.user.equals(Process.myUserHandle())) { 512 startActivity(intent); 513 } else { 514 getSystemService(LauncherApps.class).startMainActivity( 515 intent.getComponent(), info.user, intent.getSourceBounds(), null); 516 } 517 518 mControllers.uiController.onTaskbarIconLaunched(info); 519 } catch (NullPointerException | ActivityNotFoundException | SecurityException e) { 520 Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT) 521 .show(); 522 Log.e(TAG, "Unable to launch. tag=" + info + " intent=" + intent, e); 523 } 524 } 525 } else { 526 Log.e(TAG, "Unknown type clicked: " + tag); 527 } 528 529 AbstractFloatingView.closeAllOpenViews(this); 530 } 531 532 /** 533 * Called when we detect a long press in the nav region before passing the gesture slop. 534 * @return Whether taskbar handled the long press, and thus should cancel the gesture. 535 */ onLongPressToUnstashTaskbar()536 public boolean onLongPressToUnstashTaskbar() { 537 return mControllers.taskbarStashController.onLongPressToUnstashTaskbar(); 538 } 539 540 /** 541 * Called when we detect a motion down or up/cancel in the nav region while stashed. 542 * @param animateForward Whether to animate towards the unstashed hint state or back to stashed. 543 */ startTaskbarUnstashHint(boolean animateForward)544 public void startTaskbarUnstashHint(boolean animateForward) { 545 mControllers.taskbarStashController.startUnstashHint(animateForward); 546 } 547 isUserSetupComplete()548 protected boolean isUserSetupComplete() { 549 return mIsUserSetupComplete; 550 } 551 552 /** 553 * Called when we determine the touchable region. 554 * 555 * @param exclude {@code true} then the magnification region computation will omit the window. 556 */ excludeFromMagnificationRegion(boolean exclude)557 public void excludeFromMagnificationRegion(boolean exclude) { 558 if (mIsExcludeFromMagnificationRegion == exclude) { 559 return; 560 } 561 562 mIsExcludeFromMagnificationRegion = exclude; 563 if (exclude) { 564 mWindowLayoutParams.privateFlags |= 565 WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION; 566 } else { 567 mWindowLayoutParams.privateFlags &= 568 ~WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION; 569 } 570 mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); 571 } 572 } 573