diff options
16 files changed, 523 insertions, 43 deletions
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp index 61dc6e425ddf..2018e76e9bee 100644 --- a/core/jni/android/graphics/SurfaceTexture.cpp +++ b/core/jni/android/graphics/SurfaceTexture.cpp @@ -18,6 +18,8 @@ #include <stdio.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> @@ -34,6 +36,8 @@ // ---------------------------------------------------------------------------- +#define EGL_QCOM_PROTECTED_CONTENT 0x32E0 + namespace android { static const char* const OutOfResourcesException = @@ -55,6 +59,28 @@ static int32_t createProcessUniqueId() { return android_atomic_inc(&globalCounter); } +// Check whether the current EGL context is protected. +static bool isProtectedContext() { + EGLDisplay dpy = eglGetCurrentDisplay(); + EGLContext ctx = eglGetCurrentContext(); + + if (dpy == EGL_NO_DISPLAY) { + ALOGE("isProtectedSurface: invalid current EGLDisplay"); + return false; + } + + if (ctx == EGL_NO_CONTEXT) { + ALOGE("isProtectedSurface: invalid current EGLContext"); + return false; + } + + EGLint isProtected = EGL_FALSE; + // TODO: Change the enum value below when an extension is ratified. + eglQueryContext(dpy, ctx, EGL_QCOM_PROTECTED_CONTENT, &isProtected); + + return isProtected; +} + // ---------------------------------------------------------------------------- static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz, @@ -263,6 +289,11 @@ static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached, getpid(), createProcessUniqueId())); + // If the current context is protected, inform the producer. + if (isProtectedContext()) { + consumer->setConsumerUsageBits(GRALLOC_USAGE_PROTECTED); + } + SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture); SurfaceTexture_setProducer(env, thiz, producer); diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index aedc2c52e05b..4aa4d4272bf5 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -195,6 +195,10 @@ <!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. --> <integer name="recents_svelte_level">0</integer> + <!-- In multi-window, determines whether the stack where recents lives should grow from + the smallest position when being launched. --> + <bool name="recents_grow_in_multiwindow">true</bool> + <!-- Recents: The relative range of visible tasks from the current scroll position while the stack is focused. --> <item name="recents_layout_focused_range_min" format="float" type="integer">-3</item> diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java index 99028a6c403f..001d1f23af62 100644 --- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java @@ -32,7 +32,7 @@ public interface RecentsComponent { /** * Docks the top-most task and opens recents. */ - boolean dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds); + boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds); /** * Called during a drag-from-navbar-in gesture. diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl index b36b95a5442b..37085c77055b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl +++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl @@ -16,6 +16,8 @@ package com.android.systemui.recents; +import android.graphics.Rect; + /** * Due to the fact that RecentsActivity is per-user, we need to establish an * interface (this) for the system user to callback to the secondary users in @@ -29,6 +31,8 @@ oneway interface IRecentsNonSystemUserCallbacks { void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); void toggleRecents(); void onConfigurationChanged(); + void dockTopTask(int topTaskId, int dragMode, int stackCreateMode, + in Rect initialBounds); void onDraggingInRecents(float distanceFromTop); void onDraggingInRecentsEnded(float velocity); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl index 6b491953a45a..cb8f0e7e91de 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl +++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl @@ -26,4 +26,7 @@ oneway interface IRecentsSystemUserCallbacks { void updateRecentsVisibility(boolean visible); void startScreenPinning(); + void sendRecentsDrawnEvent(); + void sendDockingTopTaskEvent(int dragMode); + void sendLaunchRecentsEvent(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index 2baefd57b0cc..b8310f20353a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -16,6 +16,7 @@ package com.android.systemui.recents; +import android.app.ActivityManager; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -36,8 +37,11 @@ import android.view.View; import com.android.systemui.RecentsComponent; import com.android.systemui.SystemUI; import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.events.activity.DockingTopTaskEvent; +import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent; import com.android.systemui.recents.events.component.ScreenPinningRequestEvent; +import com.android.systemui.recents.events.ui.RecentsDrawnEvent; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.model.RecentsTaskLoader; @@ -366,17 +370,38 @@ public class Recents extends SystemUI } @Override - public boolean dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) { + public boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds) { // Ensure the device has been provisioned before allowing the user to interact with // recents if (!isUserSetup()) { return false; } - if (mImpl.dockTopTask(draggingInRecents, stackCreateMode,initialBounds)) { - if (draggingInRecents) { - mDraggingInRecentsCurrentUser = sSystemServicesProxy.getCurrentUser(); + int currentUser = sSystemServicesProxy.getCurrentUser(); + SystemServicesProxy ssp = Recents.getSystemServices(); + ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); + boolean screenPinningActive = ssp.isScreenPinningActive(); + boolean isTopTaskHome = topTask != null && SystemServicesProxy.isHomeStack(topTask.stackId); + if (topTask != null && !isTopTaskHome && !screenPinningActive) { + if (sSystemServicesProxy.isSystemUser(currentUser)) { + mImpl.dockTopTask(topTask.id, dragMode, stackCreateMode, initialBounds); + } else { + if (mSystemUserCallbacks != null) { + IRecentsNonSystemUserCallbacks callbacks = + mSystemUserCallbacks.getNonSystemUserRecentsForUser(currentUser); + if (callbacks != null) { + try { + callbacks.dockTopTask(topTask.id, dragMode, stackCreateMode, + initialBounds); + } catch (RemoteException e) { + Log.e(TAG, "Callback failed", e); + } + } else { + Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser); + } + } } + mDraggingInRecentsCurrentUser = currentUser; return true; } return false; @@ -516,6 +541,54 @@ public class Recents extends SystemUI } } + public final void onBusEvent(final RecentsDrawnEvent event) { + int processUser = sSystemServicesProxy.getProcessUser(); + if (!sSystemServicesProxy.isSystemUser(processUser)) { + postToSystemUser(new Runnable() { + @Override + public void run() { + try { + mCallbacksToSystemUser.sendRecentsDrawnEvent(); + } catch (RemoteException e) { + Log.e(TAG, "Callback failed", e); + } + } + }); + } + } + + public final void onBusEvent(final DockingTopTaskEvent event) { + int processUser = sSystemServicesProxy.getProcessUser(); + if (!sSystemServicesProxy.isSystemUser(processUser)) { + postToSystemUser(new Runnable() { + @Override + public void run() { + try { + mCallbacksToSystemUser.sendDockingTopTaskEvent(event.dragMode); + } catch (RemoteException e) { + Log.e(TAG, "Callback failed", e); + } + } + }); + } + } + + public final void onBusEvent(final RecentsActivityStartingEvent event) { + int processUser = sSystemServicesProxy.getProcessUser(); + if (!sSystemServicesProxy.isSystemUser(processUser)) { + postToSystemUser(new Runnable() { + @Override + public void run() { + try { + mCallbacksToSystemUser.sendLaunchRecentsEvent(); + } catch (RemoteException e) { + Log.e(TAG, "Callback failed", e); + } + } + }); + } + } + /** * Attempts to register with the system user. */ @@ -525,7 +598,8 @@ public class Recents extends SystemUI @Override public void run() { try { - mCallbacksToSystemUser.registerNonSystemUserCallbacks(mImpl, processUser); + mCallbacksToSystemUser.registerNonSystemUserCallbacks( + new RecentsImplProxy(mImpl), processUser); } catch (RemoteException e) { Log.e(TAG, "Failed to register", e); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 3a3b19dc3441..a11c06d76b40 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -59,6 +59,7 @@ import com.android.systemui.recents.events.component.RecentsVisibilityChangedEve import com.android.systemui.recents.events.component.ScreenPinningRequestEvent; import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent; import com.android.systemui.recents.events.ui.DeleteTaskDataEvent; +import com.android.systemui.recents.events.ui.RecentsDrawnEvent; import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent; import com.android.systemui.recents.events.ui.StackViewScrolledEvent; import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent; @@ -400,6 +401,17 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true)); MetricsLogger.visible(this, MetricsLogger.OVERVIEW_ACTIVITY); + + mRecentsView.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + + @Override + public boolean onPreDraw() { + mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this); + EventBus.getDefault().post(new RecentsDrawnEvent()); + return true; + } + }); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 5f11bee9249a..b78fd2282441 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -41,9 +41,11 @@ import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.SystemUIApplication; import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.events.activity.DockingTopTaskEvent; import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent; import com.android.systemui.recents.events.activity.HideRecentsEvent; import com.android.systemui.recents.events.activity.IterateRecentsEvent; +import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; import com.android.systemui.recents.events.activity.ToggleRecentsEvent; import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent; import com.android.systemui.recents.events.component.ScreenPinningRequestEvent; @@ -62,6 +64,7 @@ import com.android.systemui.recents.views.TaskStackView; import com.android.systemui.recents.views.TaskViewHeader; import com.android.systemui.recents.views.TaskViewTransform; import com.android.systemui.statusbar.BaseStatusBar; +import com.android.systemui.statusbar.phone.NavigationBarGestureHelper; import com.android.systemui.statusbar.phone.PhoneStatusBar; import java.util.ArrayList; @@ -72,8 +75,7 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; * An implementation of the Recents component for the current user. For secondary users, this can * be called remotely from the system user. */ -public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub implements - ActivityOptions.OnAnimationFinishedListener { +public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener { private final static String TAG = "RecentsImpl"; // The minimum amount of time between each recents button press that we will handle @@ -532,18 +534,14 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub implements showRelativeAffiliatedTask(false); } - public boolean dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) { + public void dockTopTask(int topTaskId, int dragMode, + int stackCreateMode, Rect initialBounds) { SystemServicesProxy ssp = Recents.getSystemServices(); - ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask(); - boolean screenPinningActive = ssp.isScreenPinningActive(); - boolean isTopTaskHome = SystemServicesProxy.isHomeStack(topTask.stackId); - if (topTask != null && !isTopTaskHome && !screenPinningActive) { - ssp.moveTaskToDockedStack(topTask.id, stackCreateMode, initialBounds); - showRecents(false /* triggeredFromAltTab */, draggingInRecents, false /* animate */, - true /* reloadTasks*/); - return true; - } - return false; + ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds); + showRecents(false /* triggeredFromAltTab */, + dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS, false /* animate */, + true /* reloadTasks*/); + EventBus.getDefault().send(new DockingTopTaskEvent(dragMode)); } /** @@ -918,6 +916,7 @@ public class RecentsImpl extends IRecentsNonSystemUserCallbacks.Stub implements mContext.startActivityAsUser(intent, UserHandle.CURRENT); } mCanReuseTaskStackViews = true; + EventBus.getDefault().send(new RecentsActivityStartingEvent()); } /**** OnAnimationFinishedListener Implementation ****/ diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java new file mode 100644 index 000000000000..86ec98ae3d4f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2016 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.recents; + +import android.graphics.Rect; +import android.os.Handler; +import android.os.Message; +import android.os.RemoteException; + +import com.android.internal.os.SomeArgs; + +/** + * A proxy class which directs all methods from {@link IRecentsNonSystemUserCallbacks} to + * {@link RecentsImpl} and makes sure they are called from the main thread. + */ +public class RecentsImplProxy extends IRecentsNonSystemUserCallbacks.Stub { + + private static final int MSG_PRELOAD_RECENTS = 1; + private static final int MSG_CANCEL_PRELOADING_RECENTS = 2; + private static final int MSG_SHOW_RECENTS = 3; + private static final int MSG_HIDE_RECENTS = 4; + private static final int MSG_TOGGLE_RECENTS = 5; + private static final int MSG_ON_CONFIGURATION_CHANGED = 6; + private static final int MSG_DOCK_TOP_TASK = 7; + private static final int MSG_ON_DRAGGING_IN_RECENTS = 8; + private static final int MSG_ON_DRAGGING_IN_RECENTS_ENDED = 9; + + private RecentsImpl mImpl; + + public RecentsImplProxy(RecentsImpl recentsImpl) { + mImpl = recentsImpl; + } + + @Override + public void preloadRecents() throws RemoteException { + mHandler.sendEmptyMessage(MSG_PRELOAD_RECENTS); + } + + @Override + public void cancelPreloadingRecents() throws RemoteException { + mHandler.sendEmptyMessage(MSG_CANCEL_PRELOADING_RECENTS); + } + + @Override + public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate, + boolean reloadTasks) throws RemoteException { + SomeArgs args = SomeArgs.obtain(); + args.argi1 = triggeredFromAltTab ? 1 : 0; + args.argi2 = draggingInRecents ? 1 : 0; + args.argi3 = animate ? 1 : 0; + args.argi4 = reloadTasks ? 1 : 0; + mHandler.sendMessage(mHandler.obtainMessage(MSG_SHOW_RECENTS, args)); + } + + @Override + public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) + throws RemoteException { + mHandler.sendMessage(mHandler.obtainMessage(MSG_HIDE_RECENTS, triggeredFromAltTab ? 1 :0, + triggeredFromHomeKey ? 1 : 0)); + } + + @Override + public void toggleRecents() throws RemoteException { + mHandler.sendEmptyMessage(MSG_TOGGLE_RECENTS); + } + + @Override + public void onConfigurationChanged() throws RemoteException { + mHandler.sendEmptyMessage(MSG_ON_CONFIGURATION_CHANGED); + } + + @Override + public void dockTopTask(int topTaskId, int dragMode, int stackCreateMode, + Rect initialBounds) throws RemoteException { + SomeArgs args = SomeArgs.obtain(); + args.argi1 = topTaskId; + args.argi2 = dragMode; + args.argi3 = stackCreateMode; + args.arg1 = initialBounds; + mHandler.sendMessage(mHandler.obtainMessage(MSG_DOCK_TOP_TASK, args)); + } + + @Override + public void onDraggingInRecents(float distanceFromTop) throws RemoteException { + mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_DRAGGING_IN_RECENTS, distanceFromTop)); + } + + @Override + public void onDraggingInRecentsEnded(float velocity) throws RemoteException { + mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_DRAGGING_IN_RECENTS_ENDED, velocity)); + } + + private final Handler mHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_PRELOAD_RECENTS: + mImpl.preloadRecents(); + break; + case MSG_CANCEL_PRELOADING_RECENTS: + mImpl.cancelPreloadingRecents(); + break; + case MSG_SHOW_RECENTS: + SomeArgs args = (SomeArgs) msg.obj; + mImpl.showRecents(args.argi1 != 0, args.argi2 != 0, args.argi3 != 0, + args.argi4 != 0); + break; + case MSG_HIDE_RECENTS: + mImpl.hideRecents(msg.arg1 != 0, msg.arg2 != 0); + break; + case MSG_TOGGLE_RECENTS: + mImpl.toggleRecents(); + break; + case MSG_ON_CONFIGURATION_CHANGED: + mImpl.onConfigurationChanged(); + break; + case MSG_DOCK_TOP_TASK: + args = (SomeArgs) msg.obj; + mImpl.dockTopTask(args.argi1, args.argi2, args.argi3 = 0, + (Rect) args.arg1); + break; + case MSG_ON_DRAGGING_IN_RECENTS: + mImpl.onDraggingInRecents((Float) msg.obj); + break; + case MSG_ON_DRAGGING_IN_RECENTS_ENDED: + mImpl.onDraggingInRecentsEnded((Float) msg.obj); + break; + default: + super.handleMessage(msg); + } + super.handleMessage(msg); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java index fb215001f044..ae0051cba04e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java @@ -22,6 +22,11 @@ import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; +import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.events.activity.DockingTopTaskEvent; +import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; +import com.android.systemui.recents.events.ui.RecentsDrawnEvent; + /** * An implementation of the system user's Recents interface to be called remotely by secondary * users. @@ -70,4 +75,19 @@ public class RecentsSystemUser extends IRecentsSystemUserCallbacks.Stub { public void startScreenPinning() { mImpl.onStartScreenPinning(mContext); } + + @Override + public void sendRecentsDrawnEvent() { + EventBus.getDefault().post(new RecentsDrawnEvent()); + } + + @Override + public void sendDockingTopTaskEvent(int dragMode) throws RemoteException { + EventBus.getDefault().post(new DockingTopTaskEvent(dragMode)); + } + + @Override + public void sendLaunchRecentsEvent() throws RemoteException { + EventBus.getDefault().post(new RecentsActivityStartingEvent()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java new file mode 100644 index 000000000000..264c2c43bd2e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockingTopTaskEvent.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 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.recents.events.activity; + +import com.android.systemui.recents.events.EventBus; + +/** + * Fires when the user invoked the gesture to dock the top/left task. + */ +public class DockingTopTaskEvent extends EventBus.Event { + + public int dragMode; + + public DockingTopTaskEvent(int dragMode) { + this.dragMode = dragMode; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java new file mode 100644 index 000000000000..a2ecfe207cf9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 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.recents.events.activity; + +import com.android.systemui.recents.events.EventBus; + +/** + * Called after recents activity is being started, i.e. startActivity has just been called. + */ +public class RecentsActivityStartingEvent extends EventBus.Event{ + +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java new file mode 100644 index 000000000000..548316607133 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 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.recents.events.ui; + +import com.android.systemui.recents.events.EventBus; + +/** + * Fired when recents was launched and has drawn its first frame. + */ +public class RecentsDrawnEvent extends EventBus.Event { + +} diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 08793e8107a4..c0e1e44f6900 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -49,7 +49,12 @@ import com.android.internal.policy.DividerSnapAlgorithm; import com.android.internal.policy.DockedDividerUtils; import com.android.systemui.R; import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; +import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.events.activity.DockingTopTaskEvent; +import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; +import com.android.systemui.recents.events.ui.RecentsDrawnEvent; import com.android.systemui.statusbar.FlingAnimationUtils; +import com.android.systemui.statusbar.phone.NavigationBarGestureHelper; import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW; import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW; @@ -118,6 +123,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, private DividerSnapAlgorithm mSnapAlgorithm; private final Rect mStableInsets = new Rect(); + private boolean mAnimateAfterRecentsDrawn; + private boolean mGrowAfterRecentsDrawn; + private boolean mGrowRecents; + public DividerView(Context context) { super(context); } @@ -148,6 +157,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, mDividerSize = mDividerWindowWidth - 2 * mDividerInsets; mTouchElevation = getResources().getDimensionPixelSize( R.dimen.docked_stack_divider_lift_elevation); + mGrowRecents = getResources().getBoolean(R.bool.recents_grow_in_multiwindow); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(), android.R.interpolator.fast_out_slow_in); mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); @@ -161,6 +171,18 @@ public class DividerView extends FrameLayout implements OnTouchListener, } @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + EventBus.getDefault().register(this); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + EventBus.getDefault().unregister(this); + } + + @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(), insets.getStableInsetRight(), insets.getStableInsetBottom()); @@ -175,15 +197,18 @@ public class DividerView extends FrameLayout implements OnTouchListener, return mWindowManagerProxy; } - public boolean startDragging(boolean animate) { - mHandle.setTouching(true, animate); + public boolean startDragging(boolean animate, boolean touching) { + if (touching) { + mHandle.setTouching(true, animate); + } mDockSide = mWindowManagerProxy.getDockSide(); - mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth, - mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets); + getSnapAlgorithm(); if (mDockSide != WindowManager.DOCKED_INVALID) { mWindowManagerProxy.setResizing(true); mWindowManager.setSlippery(false); - liftBackground(); + if (touching) { + liftBackground(); + } return true; } else { return false; @@ -197,10 +222,31 @@ public class DividerView extends FrameLayout implements OnTouchListener, releaseBackground(); } + public void stopDragging(int position, SnapTarget target, long duration, + Interpolator interpolator) { + mHandle.setTouching(false, true /* animate */); + flingTo(position, target, duration, interpolator); + mWindowManager.setSlippery(true); + releaseBackground(); + } + public DividerSnapAlgorithm getSnapAlgorithm() { + if (mSnapAlgorithm == null) { + mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth, + mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets); + } return mSnapAlgorithm; } + public int getCurrentPosition() { + getLocationOnScreen(mTempInt2); + if (isHorizontalDivision()) { + return mTempInt2[1] + mDividerInsets; + } else { + return mTempInt2[0] + mDividerInsets; + } + } + @Override public boolean onTouch(View v, MotionEvent event) { convertToScreenCoordinates(event); @@ -211,13 +257,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, mVelocityTracker.addMovement(event); mStartX = (int) event.getX(); mStartY = (int) event.getY(); - getLocationOnScreen(mTempInt2); - boolean result = startDragging(true /* animate */); - if (isHorizontalDivision()) { - mStartPosition = mTempInt2[1] + mDividerInsets; - } else { - mStartPosition = mTempInt2[0] + mDividerInsets; - } + boolean result = startDragging(true /* animate */, true /* touching */); + mStartPosition = getCurrentPosition(); mMoving = false; return result; case MotionEvent.ACTION_MOVE: @@ -265,8 +306,20 @@ public class DividerView extends FrameLayout implements OnTouchListener, if (avoidDismissStart && snapTarget == mSnapAlgorithm.getDismissStartTarget()) { snapTarget = mSnapAlgorithm.getFirstSplitTarget(); } - final SnapTarget finalTarget = snapTarget; + ValueAnimator anim = getFlingAnimator(position, snapTarget); + mFlingAnimationUtils.apply(anim, position, snapTarget.position, velocity); + anim.start(); + } + + private void flingTo(int position, SnapTarget target, long duration, + Interpolator interpolator) { + ValueAnimator anim = getFlingAnimator(position, target); + anim.setDuration(duration); + anim.setInterpolator(interpolator); + anim.start(); + } + private ValueAnimator getFlingAnimator(int position, final SnapTarget snapTarget) { ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position); anim.addUpdateListener(new AnimatorUpdateListener() { @Override @@ -274,19 +327,18 @@ public class DividerView extends FrameLayout implements OnTouchListener, resizeStack((Integer) animation.getAnimatedValue(), animation.getAnimatedFraction() == 1f ? TASK_POSITION_SAME - : finalTarget.position, finalTarget); + : snapTarget.position, snapTarget); } }); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - commitSnapFlags(finalTarget); + commitSnapFlags(snapTarget); mWindowManagerProxy.setResizing(false); mDockSide = WindowManager.DOCKED_INVALID; } }); - mFlingAnimationUtils.apply(anim, position, snapTarget.position, velocity); - anim.start(); + return anim; } private void commitSnapFlags(SnapTarget target) { @@ -359,6 +411,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, display.getDisplayInfo(info); mDisplayWidth = info.logicalWidth; mDisplayHeight = info.logicalHeight; + mSnapAlgorithm = null; } private int calculatePosition(int touchX, int touchY) { @@ -607,4 +660,33 @@ public class DividerView extends FrameLayout implements OnTouchListener, inoutInfo.touchableRegion.op(mBackground.getLeft(), mBackground.getTop(), mBackground.getRight(), mBackground.getBottom(), Op.UNION); } + + public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) { + if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP + && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) { + mGrowAfterRecentsDrawn = true; + startDragging(false /* animate */, false /* touching */); + } + } + + public final void onBusEvent(DockingTopTaskEvent dockingEvent) { + if (dockingEvent.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) { + mGrowAfterRecentsDrawn = false; + mAnimateAfterRecentsDrawn = true; + startDragging(false /* animate */, false /* touching */); + } + } + + public final void onBusEvent(RecentsDrawnEvent drawnEvent) { + if (mAnimateAfterRecentsDrawn) { + mAnimateAfterRecentsDrawn = false; + stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 250, + TOUCH_RESPONSE_INTERPOLATOR); + } + if (mGrowAfterRecentsDrawn) { + mGrowAfterRecentsDrawn = false; + stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 250, + TOUCH_RESPONSE_INTERPOLATOR); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java index abe357ae004c..92288a3c12c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java @@ -42,16 +42,20 @@ public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureL implements TunerService.Tunable { private static final String KEY_DOCK_WINDOW_GESTURE = "overview_nav_bar_gesture"; + /** + * When dragging from the navigation bar, we drag in recents. + */ + public static final int DRAG_MODE_NONE = -1; /** * When dragging from the navigation bar, we drag in recents. */ - private static final int DRAG_MODE_RECENTS = 0; + public static final int DRAG_MODE_RECENTS = 0; /** * When dragging from the navigation bar, we drag the divider. */ - private static final int DRAG_MODE_DIVIDER = 1; + public static final int DRAG_MODE_DIVIDER = 1; private RecentsComponent mRecentsComponent; private Divider mDivider; @@ -207,12 +211,11 @@ public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureL < mContext.getResources().getDisplayMetrics().widthPixels / 2) { createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT; } - boolean docked = mRecentsComponent.dockTopTask(dragMode == DRAG_MODE_RECENTS, - createMode, initialBounds); + boolean docked = mRecentsComponent.dockTopTask(dragMode, createMode, initialBounds); if (docked) { mDragMode = dragMode; if (mDragMode == DRAG_MODE_DIVIDER) { - mDivider.getView().startDragging(false /* animate */); + mDivider.getView().startDragging(false /* animate */, true /* touching*/); } mDockWindowTouchSlopExceeded = true; MetricsLogger.action(mContext, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 354d704650f6..6fa1f5df460c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -47,6 +47,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService; import android.media.AudioAttributes; import android.media.MediaMetadata; @@ -112,6 +113,8 @@ import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.qs.QSPanel; import com.android.systemui.recents.ScreenPinningRequest; +import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.events.activity.DockingTopTaskEvent; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.ActivatableNotificationView; import com.android.systemui.statusbar.BackDropView; @@ -1102,9 +1105,22 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public boolean onLongClick(View v) { if (mRecents != null) { - boolean docked = mRecents.dockTopTask(false /* draggingInRecents */, + Point realSize = new Point(); + mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY) + .getRealSize(realSize); + Rect initialBounds; + + // Hack level over 9000: Make it one pixel smaller so activity manager doesn't + // dismiss it immediately again. Remove once b/26777526 is fixed. + if (mContext.getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE) { + initialBounds = new Rect(0, 0, realSize.x - 1, realSize.y); + } else { + initialBounds = new Rect(0, 0, realSize.x, realSize.y - 1); + } + boolean docked = mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, - null /* initialBounds */); + initialBounds); if (docked) { MetricsLogger.action(mContext, MetricsLogger.ACTION_WINDOW_DOCK_LONGPRESS); |