Merge "Fix build breakage"
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 61dc6e4..2018e76 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 @@
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 @@
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 aedc2c5..4aa4d42 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 99028a6c..001d1f2 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -32,7 +32,7 @@
/**
* 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 b36b95a..37085c7 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 @@
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 6b49195..cb8f0e7 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 @@
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 2baefd5..b8310f2 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 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 @@
}
@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 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 @@
@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 3a3b19d..a11c06d7 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.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 @@
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 5f11bee..b78fd22 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.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.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 @@
* 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 @@
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 @@
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 0000000..86ec98a
--- /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 fb21500..ae0051c 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.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 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 0000000..264c2c4
--- /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 0000000..a2ecfe2
--- /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 0000000..5483166
--- /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 08793e8..c0e1e44 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.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 @@
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 @@
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 @@
}
@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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
display.getDisplayInfo(info);
mDisplayWidth = info.logicalWidth;
mDisplayHeight = info.logicalHeight;
+ mSnapAlgorithm = null;
}
private int calculatePosition(int touchX, int touchY) {
@@ -607,4 +660,33 @@
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 abe357a..92288a3 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 @@
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 @@
< 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 354d704..6fa1f5df 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.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.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 @@
@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);