Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +3 −98 Original line number Diff line number Diff line Loading @@ -44,19 +44,13 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.UserIdInt; import android.app.ActivityManager.RunningTaskInfo; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.RemoteInput; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ShortcutManager; import android.content.res.Configuration; import android.graphics.Rect; import android.net.Uri; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.service.notification.NotificationListenerService.RankingMap; Loading @@ -75,7 +69,6 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ScreenshotHelper; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading @@ -93,7 +86,6 @@ import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.RemoteInputUriController; import com.android.systemui.statusbar.policy.ZenModeController; import java.io.FileDescriptor; Loading @@ -101,10 +93,8 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Singleton; Loading Loading @@ -146,8 +136,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer; private final NotificationGroupManager mNotificationGroupManager; private final ShadeController mShadeController; private final RemoteInputUriController mRemoteInputUriController; private Handler mHandler = new Handler() {}; private BubbleData mBubbleData; @Nullable private BubbleStackView mStackView; Loading @@ -171,7 +159,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final NotificationShadeWindowController mNotificationShadeWindowController; private final ZenModeController mZenModeController; private StatusBarStateListener mStatusBarStateListener; private final ScreenshotHelper mScreenshotHelper; // Callback that updates BubbleOverflowActivity on data change. @Nullable private Runnable mOverflowCallback = null; Loading Loading @@ -216,16 +203,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi void onBubbleExpandChanged(boolean isExpanding, String key); } /** * Listener for handling bubble screenshot events. */ public interface BubbleScreenshotListener { /** * Called to trigger taking a screenshot and sending the result to a bubble. */ void onBubbleScreenshot(Bubble bubble); } /** * Listener to be notified when a bubbles' notification suppression state changes. */ Loading Loading @@ -300,12 +277,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, NotificationGroupManager groupManager, NotificationEntryManager entryManager, RemoteInputUriController remoteInputUriController) { NotificationEntryManager entryManager) { this(context, notificationShadeWindowController, statusBarStateController, shadeController, data, null /* synchronizer */, configurationController, interruptionStateProvider, zenModeController, notifUserManager, groupManager, entryManager, remoteInputUriController); zenModeController, notifUserManager, groupManager, entryManager); } public BubbleController(Context context, Loading @@ -319,14 +294,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, NotificationGroupManager groupManager, NotificationEntryManager entryManager, RemoteInputUriController remoteInputUriController) { NotificationEntryManager entryManager) { mContext = context; mShadeController = shadeController; mNotificationInterruptionStateProvider = interruptionStateProvider; mNotifUserManager = notifUserManager; mZenModeController = zenModeController; mRemoteInputUriController = remoteInputUriController; mZenModeController.addCallback(new ZenModeController.Callback() { @Override public void onZenChanged(int zen) { Loading Loading @@ -399,7 +372,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mUserCreatedBubbles = new HashSet<>(); mUserBlockedBubbles = new HashSet<>(); mScreenshotHelper = new ScreenshotHelper(context); mBubbleIconFactory = new BubbleIconFactory(context); } Loading Loading @@ -536,9 +508,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (mExpandListener != null) { mStackView.setExpandListener(mExpandListener); } if (mBubbleScreenshotListener != null) { mStackView.setBubbleScreenshotListener(mBubbleScreenshotListener); } } } Loading Loading @@ -1267,68 +1236,4 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } } // TODO: Copied from RemoteInputView. Consolidate RemoteInput intent logic. private Intent prepareRemoteInputFromData(String contentType, Uri data, RemoteInput remoteInput, NotificationEntry entry) { HashMap<String, Uri> results = new HashMap<>(); results.put(contentType, data); mRemoteInputUriController.grantInlineReplyUriPermission(entry.getSbn(), data); Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); RemoteInput.addDataResultToIntent(remoteInput, fillInIntent, results); return fillInIntent; } // TODO: Copied from RemoteInputView. Consolidate RemoteInput intent logic. private void sendRemoteInput(Intent intent, NotificationEntry entry, PendingIntent pendingIntent) { // Tell ShortcutManager that this package has been "activated". ShortcutManager // will reset the throttling for this package. // Strictly speaking, the intent receiver may be different from the notification publisher, // but that's an edge case, and also because we can't always know which package will receive // an intent, so we just reset for the publisher. mContext.getSystemService(ShortcutManager.class).onApplicationActive( entry.getSbn().getPackageName(), entry.getSbn().getUser().getIdentifier()); try { pendingIntent.send(mContext, 0, intent); } catch (PendingIntent.CanceledException e) { Log.i(TAG, "Unable to send remote input result", e); } } private void sendScreenshotToBubble(Bubble bubble) { mScreenshotHelper.takeScreenshot( android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN, true /* hasStatus */, true /* hasNav */, mHandler, new Consumer<Uri>() { @Override public void accept(Uri uri) { if (uri != null) { NotificationEntry entry = bubble.getEntry(); Pair<RemoteInput, Notification.Action> pair = entry.getSbn() .getNotification().findRemoteInputActionPair(false); if (pair != null) { RemoteInput remoteInput = pair.first; Notification.Action action = pair.second; Intent dataIntent = prepareRemoteInputFromData("image/png", uri, remoteInput, entry); sendRemoteInput(dataIntent, entry, action.actionIntent); mBubbleData.setSelectedBubble(bubble); mBubbleData.setExpanded(true); } else { Log.w(TAG, "No RemoteInput found for notification: " + entry.getSbn().getKey()); } } } }); } private final BubbleScreenshotListener mBubbleScreenshotListener = bubble -> sendScreenshotToBubble(bubble); } packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java +0 −13 Original line number Diff line number Diff line Loading @@ -73,9 +73,6 @@ public class BubbleExperimentConfig { private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps"; private static final String ALLOW_BUBBLE_MENU = "allow_bubble_screenshot_menu"; private static final boolean ALLOW_BUBBLE_MENU_DEFAULT = false; private static final String ALLOW_BUBBLE_OVERFLOW = "allow_bubble_overflow"; private static final boolean ALLOW_BUBBLE_OVERFLOW_DEFAULT = false; Loading Loading @@ -133,16 +130,6 @@ public class BubbleExperimentConfig { return false; } /** * When true, show a menu when a bubble is long-pressed, which will allow the user to take * actions on that bubble. */ static boolean allowBubbleScreenshotMenu(Context context) { return Settings.Secure.getInt(context.getContentResolver(), ALLOW_BUBBLE_MENU, ALLOW_BUBBLE_MENU_DEFAULT ? 1 : 0) != 0; } /** * When true, show a menu when a bubble is long-pressed, which will allow the user to take * actions on that bubble. Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.javadeleted 100644 → 0 +0 −84 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.bubbles; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import com.android.systemui.R; /** * Menu which allows users to take actions on bubbles, ex. screenshots. */ public class BubbleMenuView extends FrameLayout { private FrameLayout mMenu; private boolean mShowing = false; /** Delay before taking a screenshot once the button is tapped to allow the menu time to hide.*/ public static final long SCREENSHOT_DELAY = 200; public BubbleMenuView(Context context, AttributeSet attrs) { super(context, attrs); } public BubbleMenuView(Context context) { super(context); } @Override protected void onFinishInflate() { super.onFinishInflate(); mMenu = findViewById(R.id.bubble_menu_view); ImageView icon = findViewById(com.android.internal.R.id.icon); icon.setImageDrawable(mContext.getDrawable(com.android.internal.R.drawable.ic_screenshot)); } /** * Get the bubble menu view. */ public View getMenuView() { return mMenu; } /** * Checks whether the bubble menu is currently displayed. */ public boolean isShowing() { return mShowing; } /** * Show the bubble menu at the specified position on the screen. */ public void show(float x, float y) { mShowing = true; this.setVisibility(VISIBLE); mMenu.setTranslationX(x); mMenu.setTranslationY(y); } /** * Hide the bubble menu. */ public void hide() { mShowing = false; this.setVisibility(GONE); } } packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +0 −69 Original line number Diff line number Diff line Loading @@ -115,7 +115,6 @@ public class BubbleStackView extends FrameLayout { /** How long to wait, in milliseconds, before hiding the flyout. */ @VisibleForTesting static final int FLYOUT_HIDE_AFTER = 5000; private BubbleController.BubbleScreenshotListener mBubbleScreenshotListener; /** * Interface to synchronize {@link View} state and the screen. Loading Loading @@ -169,7 +168,6 @@ public class BubbleStackView extends FrameLayout { private ExpandedAnimationController mExpandedAnimationController; private FrameLayout mExpandedViewContainer; @Nullable private BubbleMenuView mBubbleMenuView; private BubbleFlyoutView mFlyout; /** Runnable that fades out the flyout and then sets it to GONE. */ Loading Loading @@ -516,9 +514,6 @@ public class BubbleStackView extends FrameLayout { mDesaturateAndDarkenPaint.setColorFilter(new ColorMatrixColorFilter(animatedMatrix)); mDesaturateAndDarkenTargetView.setLayerPaint(mDesaturateAndDarkenPaint); }); mInflater.inflate(R.layout.bubble_menu_view, this); mBubbleMenuView = findViewById(R.id.bubble_menu_container); } private void setUpOverflow() { Loading Loading @@ -737,13 +732,6 @@ public class BubbleStackView extends FrameLayout { mExpandListener = listener; } /** * Sets the screenshot listener. */ public void setBubbleScreenshotListener(BubbleController.BubbleScreenshotListener listener) { mBubbleScreenshotListener = listener; } /** * Whether the stack of bubbles is expanded or not. */ Loading Loading @@ -942,12 +930,6 @@ public class BubbleStackView extends FrameLayout { public View getTargetView(MotionEvent event) { float x = event.getRawX(); float y = event.getRawY(); if (mBubbleMenuView.isShowing()) { if (isIntersecting(mBubbleMenuView.getMenuView(), x, y)) { return mBubbleMenuView; } return null; } if (mIsExpanded) { if (isIntersecting(mBubbleContainer, x, y)) { if (BubbleExperimentConfig.allowBubbleOverflow(mContext) Loading Loading @@ -1168,7 +1150,6 @@ public class BubbleStackView extends FrameLayout { } return; } hideBubbleMenu(); mStackAnimationController.cancelStackPositionAnimations(); mBubbleContainer.setActiveController(mStackAnimationController); hideFlyoutImmediate(); Loading Loading @@ -1570,10 +1551,6 @@ public class BubbleStackView extends FrameLayout { @Override public void getBoundsOnScreen(Rect outRect) { // If the bubble menu is open, the entire screen should capture touch events. if (mBubbleMenuView.isShowing()) { outRect.set(0, 0, getWidth(), getHeight()); return; } if (!mIsExpanded) { if (getBubbleCount() > 0) { mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect); Loading Loading @@ -1808,50 +1785,4 @@ public class BubbleStackView extends FrameLayout { } return bubbles; } /** * Show the bubble menu, positioned relative to the stack. */ public void showBubbleMenu() { PointF currentPos = mStackAnimationController.getStackPosition(); mBubbleMenuView.setVisibility(View.INVISIBLE); post(() -> { float yPos = currentPos.y; float xPos = currentPos.x; if (mStackAnimationController.isStackOnLeftSide()) { xPos += mBubbleSize; } else { xPos -= mBubbleMenuView.getMenuView().getWidth(); } mBubbleMenuView.show(xPos, yPos); }); } /** * Hide the bubble menu. */ public void hideBubbleMenu() { mBubbleMenuView.hide(); } /** * Determines whether the bubble menu is currently showing. */ public boolean isShowingBubbleMenu() { return mBubbleMenuView.isShowing(); } /** * Take a screenshot and send it to the specified bubble. */ public void sendScreenshotToBubble(Bubble bubble) { hideBubbleMenu(); // delay allows the bubble menu to disappear before the screenshot // done here because we already have a Handler to delay with. // TODO: Hide bubble + menu UI from screenshots entirely instead of just delaying. postDelayed(() -> { mBubbleScreenshotListener.onBubbleScreenshot(bubble); }, BubbleMenuView.SCREENSHOT_DELAY); } } packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java +0 −29 Original line number Diff line number Diff line Loading @@ -58,14 +58,12 @@ class BubbleTouchHandler implements View.OnTouchListener { private final PointF mViewPositionOnTouchDown = new PointF(); private final BubbleStackView mStack; private final BubbleData mBubbleData; private final Context mContext; private BubbleController mController = Dependency.get(BubbleController.class); private boolean mMovedEnough; private int mTouchSlopSquared; private VelocityTracker mVelocityTracker; private Runnable mShowBubbleMenuRunnable; /** View that was initially touched, when we received the first ACTION_DOWN event. */ private View mTouchedView; Loading @@ -78,7 +76,6 @@ class BubbleTouchHandler implements View.OnTouchListener { mTouchSlopSquared = touchSlop * touchSlop; mBubbleData = bubbleData; mStack = stackView; mContext = context; } @Override Loading @@ -95,18 +92,10 @@ class BubbleTouchHandler implements View.OnTouchListener { // anything, collapse the stack. if (action == MotionEvent.ACTION_OUTSIDE || mTouchedView == null) { mBubbleData.setExpanded(false); mStack.hideBubbleMenu(); resetForNextGesture(); return false; } if (mTouchedView instanceof BubbleMenuView) { mStack.hideBubbleMenu(); resetForNextGesture(); mStack.sendScreenshotToBubble(mBubbleData.getSelectedBubble()); return false; } if (!(mTouchedView instanceof BadgedImageView) && !(mTouchedView instanceof BubbleStackView) && !(mTouchedView instanceof BubbleFlyoutView)) { Loading @@ -116,7 +105,6 @@ class BubbleTouchHandler implements View.OnTouchListener { } // Not touching anything touchable, but we shouldn't collapse (e.g. touching edge // of expanded view). mStack.hideBubbleMenu(); resetForNextGesture(); return false; } Loading @@ -139,12 +127,6 @@ class BubbleTouchHandler implements View.OnTouchListener { if (isStack) { mViewPositionOnTouchDown.set(mStack.getStackPosition()); mStack.onDragStart(); if (!mStack.isShowingBubbleMenu() && !mStack.isExpanded() && BubbleExperimentConfig.allowBubbleScreenshotMenu(mContext)) { mShowBubbleMenuRunnable = mStack::showBubbleMenu; mStack.postDelayed(mShowBubbleMenuRunnable, ViewConfiguration.getLongPressTimeout()); } } else if (isFlyout) { mStack.onFlyoutDragStart(); } else { Loading @@ -155,10 +137,6 @@ class BubbleTouchHandler implements View.OnTouchListener { break; case MotionEvent.ACTION_MOVE: // block all further touch inputs once the menu is open if (mStack.isShowingBubbleMenu()) { return true; } trackMovement(event); final float deltaX = rawX - mTouchDown.x; final float deltaY = rawY - mTouchDown.y; Loading @@ -168,7 +146,6 @@ class BubbleTouchHandler implements View.OnTouchListener { } if (mMovedEnough) { mStack.removeCallbacks(mShowBubbleMenuRunnable); if (isStack) { mStack.onDragged(viewX, viewY); } else if (isFlyout) { Loading Loading @@ -199,12 +176,6 @@ class BubbleTouchHandler implements View.OnTouchListener { break; case MotionEvent.ACTION_UP: if (mStack.isShowingBubbleMenu()) { resetForNextGesture(); return true; } else { mStack.removeCallbacks(mShowBubbleMenuRunnable); } trackMovement(event); mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000); final float velX = mVelocityTracker.getXVelocity(); Loading Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +3 −98 Original line number Diff line number Diff line Loading @@ -44,19 +44,13 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.UserIdInt; import android.app.ActivityManager.RunningTaskInfo; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.RemoteInput; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ShortcutManager; import android.content.res.Configuration; import android.graphics.Rect; import android.net.Uri; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.service.notification.NotificationListenerService.RankingMap; Loading @@ -75,7 +69,6 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ScreenshotHelper; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading @@ -93,7 +86,6 @@ import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.RemoteInputUriController; import com.android.systemui.statusbar.policy.ZenModeController; import java.io.FileDescriptor; Loading @@ -101,10 +93,8 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Singleton; Loading Loading @@ -146,8 +136,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer; private final NotificationGroupManager mNotificationGroupManager; private final ShadeController mShadeController; private final RemoteInputUriController mRemoteInputUriController; private Handler mHandler = new Handler() {}; private BubbleData mBubbleData; @Nullable private BubbleStackView mStackView; Loading @@ -171,7 +159,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final NotificationShadeWindowController mNotificationShadeWindowController; private final ZenModeController mZenModeController; private StatusBarStateListener mStatusBarStateListener; private final ScreenshotHelper mScreenshotHelper; // Callback that updates BubbleOverflowActivity on data change. @Nullable private Runnable mOverflowCallback = null; Loading Loading @@ -216,16 +203,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi void onBubbleExpandChanged(boolean isExpanding, String key); } /** * Listener for handling bubble screenshot events. */ public interface BubbleScreenshotListener { /** * Called to trigger taking a screenshot and sending the result to a bubble. */ void onBubbleScreenshot(Bubble bubble); } /** * Listener to be notified when a bubbles' notification suppression state changes. */ Loading Loading @@ -300,12 +277,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, NotificationGroupManager groupManager, NotificationEntryManager entryManager, RemoteInputUriController remoteInputUriController) { NotificationEntryManager entryManager) { this(context, notificationShadeWindowController, statusBarStateController, shadeController, data, null /* synchronizer */, configurationController, interruptionStateProvider, zenModeController, notifUserManager, groupManager, entryManager, remoteInputUriController); zenModeController, notifUserManager, groupManager, entryManager); } public BubbleController(Context context, Loading @@ -319,14 +294,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, NotificationGroupManager groupManager, NotificationEntryManager entryManager, RemoteInputUriController remoteInputUriController) { NotificationEntryManager entryManager) { mContext = context; mShadeController = shadeController; mNotificationInterruptionStateProvider = interruptionStateProvider; mNotifUserManager = notifUserManager; mZenModeController = zenModeController; mRemoteInputUriController = remoteInputUriController; mZenModeController.addCallback(new ZenModeController.Callback() { @Override public void onZenChanged(int zen) { Loading Loading @@ -399,7 +372,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mUserCreatedBubbles = new HashSet<>(); mUserBlockedBubbles = new HashSet<>(); mScreenshotHelper = new ScreenshotHelper(context); mBubbleIconFactory = new BubbleIconFactory(context); } Loading Loading @@ -536,9 +508,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (mExpandListener != null) { mStackView.setExpandListener(mExpandListener); } if (mBubbleScreenshotListener != null) { mStackView.setBubbleScreenshotListener(mBubbleScreenshotListener); } } } Loading Loading @@ -1267,68 +1236,4 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } } // TODO: Copied from RemoteInputView. Consolidate RemoteInput intent logic. private Intent prepareRemoteInputFromData(String contentType, Uri data, RemoteInput remoteInput, NotificationEntry entry) { HashMap<String, Uri> results = new HashMap<>(); results.put(contentType, data); mRemoteInputUriController.grantInlineReplyUriPermission(entry.getSbn(), data); Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); RemoteInput.addDataResultToIntent(remoteInput, fillInIntent, results); return fillInIntent; } // TODO: Copied from RemoteInputView. Consolidate RemoteInput intent logic. private void sendRemoteInput(Intent intent, NotificationEntry entry, PendingIntent pendingIntent) { // Tell ShortcutManager that this package has been "activated". ShortcutManager // will reset the throttling for this package. // Strictly speaking, the intent receiver may be different from the notification publisher, // but that's an edge case, and also because we can't always know which package will receive // an intent, so we just reset for the publisher. mContext.getSystemService(ShortcutManager.class).onApplicationActive( entry.getSbn().getPackageName(), entry.getSbn().getUser().getIdentifier()); try { pendingIntent.send(mContext, 0, intent); } catch (PendingIntent.CanceledException e) { Log.i(TAG, "Unable to send remote input result", e); } } private void sendScreenshotToBubble(Bubble bubble) { mScreenshotHelper.takeScreenshot( android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN, true /* hasStatus */, true /* hasNav */, mHandler, new Consumer<Uri>() { @Override public void accept(Uri uri) { if (uri != null) { NotificationEntry entry = bubble.getEntry(); Pair<RemoteInput, Notification.Action> pair = entry.getSbn() .getNotification().findRemoteInputActionPair(false); if (pair != null) { RemoteInput remoteInput = pair.first; Notification.Action action = pair.second; Intent dataIntent = prepareRemoteInputFromData("image/png", uri, remoteInput, entry); sendRemoteInput(dataIntent, entry, action.actionIntent); mBubbleData.setSelectedBubble(bubble); mBubbleData.setExpanded(true); } else { Log.w(TAG, "No RemoteInput found for notification: " + entry.getSbn().getKey()); } } } }); } private final BubbleScreenshotListener mBubbleScreenshotListener = bubble -> sendScreenshotToBubble(bubble); }
packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java +0 −13 Original line number Diff line number Diff line Loading @@ -73,9 +73,6 @@ public class BubbleExperimentConfig { private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps"; private static final String ALLOW_BUBBLE_MENU = "allow_bubble_screenshot_menu"; private static final boolean ALLOW_BUBBLE_MENU_DEFAULT = false; private static final String ALLOW_BUBBLE_OVERFLOW = "allow_bubble_overflow"; private static final boolean ALLOW_BUBBLE_OVERFLOW_DEFAULT = false; Loading Loading @@ -133,16 +130,6 @@ public class BubbleExperimentConfig { return false; } /** * When true, show a menu when a bubble is long-pressed, which will allow the user to take * actions on that bubble. */ static boolean allowBubbleScreenshotMenu(Context context) { return Settings.Secure.getInt(context.getContentResolver(), ALLOW_BUBBLE_MENU, ALLOW_BUBBLE_MENU_DEFAULT ? 1 : 0) != 0; } /** * When true, show a menu when a bubble is long-pressed, which will allow the user to take * actions on that bubble. Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.javadeleted 100644 → 0 +0 −84 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.bubbles; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import com.android.systemui.R; /** * Menu which allows users to take actions on bubbles, ex. screenshots. */ public class BubbleMenuView extends FrameLayout { private FrameLayout mMenu; private boolean mShowing = false; /** Delay before taking a screenshot once the button is tapped to allow the menu time to hide.*/ public static final long SCREENSHOT_DELAY = 200; public BubbleMenuView(Context context, AttributeSet attrs) { super(context, attrs); } public BubbleMenuView(Context context) { super(context); } @Override protected void onFinishInflate() { super.onFinishInflate(); mMenu = findViewById(R.id.bubble_menu_view); ImageView icon = findViewById(com.android.internal.R.id.icon); icon.setImageDrawable(mContext.getDrawable(com.android.internal.R.drawable.ic_screenshot)); } /** * Get the bubble menu view. */ public View getMenuView() { return mMenu; } /** * Checks whether the bubble menu is currently displayed. */ public boolean isShowing() { return mShowing; } /** * Show the bubble menu at the specified position on the screen. */ public void show(float x, float y) { mShowing = true; this.setVisibility(VISIBLE); mMenu.setTranslationX(x); mMenu.setTranslationY(y); } /** * Hide the bubble menu. */ public void hide() { mShowing = false; this.setVisibility(GONE); } }
packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +0 −69 Original line number Diff line number Diff line Loading @@ -115,7 +115,6 @@ public class BubbleStackView extends FrameLayout { /** How long to wait, in milliseconds, before hiding the flyout. */ @VisibleForTesting static final int FLYOUT_HIDE_AFTER = 5000; private BubbleController.BubbleScreenshotListener mBubbleScreenshotListener; /** * Interface to synchronize {@link View} state and the screen. Loading Loading @@ -169,7 +168,6 @@ public class BubbleStackView extends FrameLayout { private ExpandedAnimationController mExpandedAnimationController; private FrameLayout mExpandedViewContainer; @Nullable private BubbleMenuView mBubbleMenuView; private BubbleFlyoutView mFlyout; /** Runnable that fades out the flyout and then sets it to GONE. */ Loading Loading @@ -516,9 +514,6 @@ public class BubbleStackView extends FrameLayout { mDesaturateAndDarkenPaint.setColorFilter(new ColorMatrixColorFilter(animatedMatrix)); mDesaturateAndDarkenTargetView.setLayerPaint(mDesaturateAndDarkenPaint); }); mInflater.inflate(R.layout.bubble_menu_view, this); mBubbleMenuView = findViewById(R.id.bubble_menu_container); } private void setUpOverflow() { Loading Loading @@ -737,13 +732,6 @@ public class BubbleStackView extends FrameLayout { mExpandListener = listener; } /** * Sets the screenshot listener. */ public void setBubbleScreenshotListener(BubbleController.BubbleScreenshotListener listener) { mBubbleScreenshotListener = listener; } /** * Whether the stack of bubbles is expanded or not. */ Loading Loading @@ -942,12 +930,6 @@ public class BubbleStackView extends FrameLayout { public View getTargetView(MotionEvent event) { float x = event.getRawX(); float y = event.getRawY(); if (mBubbleMenuView.isShowing()) { if (isIntersecting(mBubbleMenuView.getMenuView(), x, y)) { return mBubbleMenuView; } return null; } if (mIsExpanded) { if (isIntersecting(mBubbleContainer, x, y)) { if (BubbleExperimentConfig.allowBubbleOverflow(mContext) Loading Loading @@ -1168,7 +1150,6 @@ public class BubbleStackView extends FrameLayout { } return; } hideBubbleMenu(); mStackAnimationController.cancelStackPositionAnimations(); mBubbleContainer.setActiveController(mStackAnimationController); hideFlyoutImmediate(); Loading Loading @@ -1570,10 +1551,6 @@ public class BubbleStackView extends FrameLayout { @Override public void getBoundsOnScreen(Rect outRect) { // If the bubble menu is open, the entire screen should capture touch events. if (mBubbleMenuView.isShowing()) { outRect.set(0, 0, getWidth(), getHeight()); return; } if (!mIsExpanded) { if (getBubbleCount() > 0) { mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect); Loading Loading @@ -1808,50 +1785,4 @@ public class BubbleStackView extends FrameLayout { } return bubbles; } /** * Show the bubble menu, positioned relative to the stack. */ public void showBubbleMenu() { PointF currentPos = mStackAnimationController.getStackPosition(); mBubbleMenuView.setVisibility(View.INVISIBLE); post(() -> { float yPos = currentPos.y; float xPos = currentPos.x; if (mStackAnimationController.isStackOnLeftSide()) { xPos += mBubbleSize; } else { xPos -= mBubbleMenuView.getMenuView().getWidth(); } mBubbleMenuView.show(xPos, yPos); }); } /** * Hide the bubble menu. */ public void hideBubbleMenu() { mBubbleMenuView.hide(); } /** * Determines whether the bubble menu is currently showing. */ public boolean isShowingBubbleMenu() { return mBubbleMenuView.isShowing(); } /** * Take a screenshot and send it to the specified bubble. */ public void sendScreenshotToBubble(Bubble bubble) { hideBubbleMenu(); // delay allows the bubble menu to disappear before the screenshot // done here because we already have a Handler to delay with. // TODO: Hide bubble + menu UI from screenshots entirely instead of just delaying. postDelayed(() -> { mBubbleScreenshotListener.onBubbleScreenshot(bubble); }, BubbleMenuView.SCREENSHOT_DELAY); } }
packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java +0 −29 Original line number Diff line number Diff line Loading @@ -58,14 +58,12 @@ class BubbleTouchHandler implements View.OnTouchListener { private final PointF mViewPositionOnTouchDown = new PointF(); private final BubbleStackView mStack; private final BubbleData mBubbleData; private final Context mContext; private BubbleController mController = Dependency.get(BubbleController.class); private boolean mMovedEnough; private int mTouchSlopSquared; private VelocityTracker mVelocityTracker; private Runnable mShowBubbleMenuRunnable; /** View that was initially touched, when we received the first ACTION_DOWN event. */ private View mTouchedView; Loading @@ -78,7 +76,6 @@ class BubbleTouchHandler implements View.OnTouchListener { mTouchSlopSquared = touchSlop * touchSlop; mBubbleData = bubbleData; mStack = stackView; mContext = context; } @Override Loading @@ -95,18 +92,10 @@ class BubbleTouchHandler implements View.OnTouchListener { // anything, collapse the stack. if (action == MotionEvent.ACTION_OUTSIDE || mTouchedView == null) { mBubbleData.setExpanded(false); mStack.hideBubbleMenu(); resetForNextGesture(); return false; } if (mTouchedView instanceof BubbleMenuView) { mStack.hideBubbleMenu(); resetForNextGesture(); mStack.sendScreenshotToBubble(mBubbleData.getSelectedBubble()); return false; } if (!(mTouchedView instanceof BadgedImageView) && !(mTouchedView instanceof BubbleStackView) && !(mTouchedView instanceof BubbleFlyoutView)) { Loading @@ -116,7 +105,6 @@ class BubbleTouchHandler implements View.OnTouchListener { } // Not touching anything touchable, but we shouldn't collapse (e.g. touching edge // of expanded view). mStack.hideBubbleMenu(); resetForNextGesture(); return false; } Loading @@ -139,12 +127,6 @@ class BubbleTouchHandler implements View.OnTouchListener { if (isStack) { mViewPositionOnTouchDown.set(mStack.getStackPosition()); mStack.onDragStart(); if (!mStack.isShowingBubbleMenu() && !mStack.isExpanded() && BubbleExperimentConfig.allowBubbleScreenshotMenu(mContext)) { mShowBubbleMenuRunnable = mStack::showBubbleMenu; mStack.postDelayed(mShowBubbleMenuRunnable, ViewConfiguration.getLongPressTimeout()); } } else if (isFlyout) { mStack.onFlyoutDragStart(); } else { Loading @@ -155,10 +137,6 @@ class BubbleTouchHandler implements View.OnTouchListener { break; case MotionEvent.ACTION_MOVE: // block all further touch inputs once the menu is open if (mStack.isShowingBubbleMenu()) { return true; } trackMovement(event); final float deltaX = rawX - mTouchDown.x; final float deltaY = rawY - mTouchDown.y; Loading @@ -168,7 +146,6 @@ class BubbleTouchHandler implements View.OnTouchListener { } if (mMovedEnough) { mStack.removeCallbacks(mShowBubbleMenuRunnable); if (isStack) { mStack.onDragged(viewX, viewY); } else if (isFlyout) { Loading Loading @@ -199,12 +176,6 @@ class BubbleTouchHandler implements View.OnTouchListener { break; case MotionEvent.ACTION_UP: if (mStack.isShowingBubbleMenu()) { resetForNextGesture(); return true; } else { mStack.removeCallbacks(mShowBubbleMenuRunnable); } trackMovement(event); mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000); final float velX = mVelocityTracker.getXVelocity(); Loading