void resizeDockedStack(in Rect dockedBounds, in Rect tempDockedTaskBounds,
in Rect tempDockedTaskInsetBounds,
in Rect tempOtherTaskBounds, in Rect tempOtherTaskInsetBounds);
+ /**
+ * Sets whether we are currently in an interactive split screen resize operation where we
+ * are changing the docked stack size.
+ */
+ void setSplitScreenResizing(boolean resizing);
int setVrMode(in IBinder token, boolean enabled, in ComponentName packageName);
// Gets the URI permissions granted to an arbitrary package (or all packages if null)
// NOTE: this is different from getPersistedUriPermissions(), which returns the URIs the package
int getDockedStackSide();
/**
- * Sets whether we are currently in a drag resize operation where we are changing the docked
- * stack size.
- */
- void setDockedStackResizing(boolean resizing);
-
- /**
* Sets the region the user can touch the divider. This region will be excluded from the region
* which is used to cause a focus switch when dispatching touch.
*/
--- /dev/null
+/*
+ * Copyright (C) 2018 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 android.graphics;
+
+import static android.graphics.Rect.copyOrNull;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class RectTest {
+
+ @Test
+ public void copyOrNull_passesThroughNull() {
+ assertNull(copyOrNull(null));
+ }
+
+ @Test
+ public void copyOrNull_copiesNonNull() {
+ final Rect orig = new Rect(1, 2, 3, 4);
+ final Rect copy = copyOrNull(orig);
+
+ assertEquals(orig, copy);
+ assertNotSame(orig, copy);
+ }
+}
package android.graphics;
import android.annotation.CheckResult;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
}
}
+ /**
+ * Returns a copy of {@code r} if {@code r} is not {@code null}, or {@code null} otherwise.
+ *
+ * @hide
+ */
+ @Nullable
+ public static Rect copyOrNull(@Nullable Rect r) {
+ return r == null ? null : new Rect(r);
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@Override
public void run() {
try {
- WindowManagerGlobal.getWindowManagerService().setDockedStackResizing(resizing);
+ ActivityManager.getService().setSplitScreenResizing(resizing);
} catch (RemoteException e) {
Log.w(TAG, "Error calling setDockedStackResizing: " + e);
}
}
@Override
+ public void setSplitScreenResizing(boolean resizing) {
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setSplitScreenResizing()");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ mStackSupervisor.setSplitScreenResizing(resizing);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizePinnedStack()");
final long ident = Binder.clearCallingIdentity();
return getDisplay().isTopStack(this);
}
+ boolean isTopActivityVisible() {
+ final ActivityRecord topActivity = getTopActivity();
+ return topActivity != null && topActivity.visible;
+ }
+
/**
* Returns true if the stack should be visible.
*
import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.graphics.Rect.copyOrNull;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
// the activity callback indicating that it has completed pausing
static final boolean PAUSE_IMMEDIATELY = true;
+ /** True if the docked stack is currently being resized. */
+ private boolean mDockedStackResizing;
+
+ /**
+ * True if there are pending docked bounds that need to be applied after
+ * {@link #mDockedStackResizing} is reset to false.
+ */
+ private boolean mHasPendingDockedBounds;
+ private Rect mPendingDockedBounds;
+ private Rect mPendingTempDockedTaskBounds;
+ private Rect mPendingTempDockedTaskInsetBounds;
+ private Rect mPendingTempOtherTaskBounds;
+ private Rect mPendingTempOtherTaskInsetBounds;
+
/**
* The modes which affect which tasks are returned when calling
* {@link ActivityStackSupervisor#anyTaskForIdLocked(int)}.
moveTasksToFullscreenStackInSurfaceTransaction(fromStack, toDisplayId, onTop));
}
+ void setSplitScreenResizing(boolean resizing) {
+ if (resizing == mDockedStackResizing) {
+ return;
+ }
+
+ mDockedStackResizing = resizing;
+ mWindowManager.setDockedStackResizing(resizing);
+
+ if (!resizing && mHasPendingDockedBounds) {
+ resizeDockedStackLocked(mPendingDockedBounds, mPendingTempDockedTaskBounds,
+ mPendingTempDockedTaskInsetBounds, mPendingTempOtherTaskBounds,
+ mPendingTempOtherTaskInsetBounds, PRESERVE_WINDOWS);
+
+ mHasPendingDockedBounds = false;
+ mPendingDockedBounds = null;
+ mPendingTempDockedTaskBounds = null;
+ mPendingTempDockedTaskInsetBounds = null;
+ mPendingTempOtherTaskBounds = null;
+ mPendingTempOtherTaskInsetBounds = null;
+ }
+ }
+
void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds,
boolean preserveWindows) {
return;
}
+ if (mDockedStackResizing) {
+ mHasPendingDockedBounds = true;
+ mPendingDockedBounds = copyOrNull(dockedBounds);
+ mPendingTempDockedTaskBounds = copyOrNull(tempDockedTaskBounds);
+ mPendingTempDockedTaskInsetBounds = copyOrNull(tempDockedTaskInsetBounds);
+ mPendingTempOtherTaskBounds = copyOrNull(tempOtherTaskBounds);
+ mPendingTempOtherTaskInsetBounds = copyOrNull(tempOtherTaskInsetBounds);
+ }
+
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeDockedStack");
mWindowManager.deferSurfaceLayout();
try {
if (!current.affectedBySplitScreenResize()) {
continue;
}
+ if (mDockedStackResizing && !current.isTopActivityVisible()) {
+ // Non-visible stacks get resized once we're done with the resize
+ // interaction.
+ continue;
+ }
// Need to set windowing mode here before we try to get the dock bounds.
current.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
current.getStackDockedModeBounds(
}
}
- @Override
public void setDockedStackResizing(boolean resizing) {
synchronized (mWindowMap) {
getDefaultDisplayContentLocked().getDockedDividerController().setResizing(resizing);
@Override
public void binderDied() {
try {
+ boolean resetSplitScreenResizing = false;
synchronized(mService.mWindowMap) {
final WindowState win = mService.windowForClientLocked(mSession, mClient, false);
Slog.i(TAG, "WIN DEATH: " + win);
if (stack != null) {
stack.resetDockedStackToMiddle();
}
- mService.setDockedStackResizing(false);
+ resetSplitScreenResizing = true;
}
} else if (mHasSurface) {
Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
WindowState.this.removeIfPossible();
}
}
+ if (resetSplitScreenResizing) {
+ try {
+ // Note: this calls into ActivityManager, so we must *not* hold the window
+ // manager lock while calling this.
+ mService.mActivityManager.setSplitScreenResizing(false);
+ } catch (RemoteException e) {
+ // Local call, shouldn't return RemoteException.
+ throw e.rethrowAsRuntimeException();
+ }
+ }
} catch (IllegalArgumentException ex) {
// This will happen if the window has already been removed.
}