summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManager.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java1
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java6
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java7
-rw-r--r--services/tests/servicestests/AndroidManifest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java66
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java15
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java34
9 files changed, 129 insertions, 9 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 3170d0d97af0..f1f6e7b09767 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -628,6 +628,10 @@ public class ActivityManager {
return stackId >= FIRST_STATIC_STACK_ID && stackId <= LAST_STATIC_STACK_ID;
}
+ public static boolean isDynamicStack(int stackId) {
+ return stackId >= FIRST_DYNAMIC_STACK_ID;
+ }
+
/**
* Returns true if the activities contained in the input stack display a shadow around
* their border.
@@ -825,7 +829,7 @@ public class ActivityManager {
/** Returns true if the input stack and its content can affect the device orientation. */
public static boolean canSpecifyOrientation(int stackId) {
return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID
- || stackId == FULLSCREEN_WORKSPACE_STACK_ID;
+ || stackId == FULLSCREEN_WORKSPACE_STACK_ID || isDynamicStack(stackId);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 527e91830ccf..4fe893979c6f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1984,7 +1984,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (!createStaticStackIfNeeded || !StackId.isStaticStack(stackId)) {
return null;
}
- // TODO(multi-display): Allow creating stacks on secondary displays.
return createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop);
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 81a5d3beefbd..2634385e49dc 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -32,7 +32,7 @@ import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
-import static android.app.ActivityManager.StackId.isStaticStack;
+import static android.app.ActivityManager.StackId.isDynamicStack;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -1926,7 +1926,7 @@ class ActivityStarter {
final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
|| (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
|| (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced())
- || !isStaticStack(focusedStackId);
+ || isDynamicStack(focusedStackId);
if (canUseFocusedStack && (!newTask
|| mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
@@ -1938,7 +1938,7 @@ class ActivityStarter {
final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
stack = homeDisplayStacks.get(stackNdx);
- if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
+ if (isDynamicStack(stack.mStackId)) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting focused stack=" + stack);
return stack;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6ac172b26e24..0cc6c701a93e 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -228,7 +228,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
mService.configureDisplayPolicyLocked(dc);
// TODO(multi-display): Create an input channel for each display with touch capability.
- if (displayId == DEFAULT_DISPLAY) {
+ if (displayId == DEFAULT_DISPLAY && mService.canDispatchPointerEvents()) {
dc.mTapDetector = new TaskTapPointerEventListener(
mService, dc);
mService.registerPointerEventListener(dc.mTapDetector);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 381521d5c81d..0c8c10ba2668 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3404,6 +3404,11 @@ public class WindowManagerService extends IWindowManager.Stub
mPointerEventDispatcher.unregisterInputEventListener(listener);
}
+ /** Check if the service is set to dispatch pointer events. */
+ boolean canDispatchPointerEvents() {
+ return mPointerEventDispatcher != null;
+ }
+
// Called by window manager policy. Not exposed externally.
@Override
public int getLidState() {
@@ -4980,7 +4985,7 @@ public class WindowManagerService extends IWindowManager.Stub
int keyboardPresence = 0;
int navigationPresence = 0;
final InputDevice[] devices = mInputManager.getInputDevices();
- final int len = devices.length;
+ final int len = devices != null ? devices.length : 0;
for (int i = 0; i < len; i++) {
InputDevice device = devices[i];
if (!device.isVirtual()) {
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 1c92e452d03c..1393615b5623 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -46,6 +46,7 @@
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
+ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 06837d38d69c..1d9875f308e9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -22,7 +22,11 @@ import org.junit.runner.RunWith;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.view.Surface;
+import android.view.WindowManager;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -83,4 +87,66 @@ public class AppWindowTokenTests extends WindowTestsBase {
final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token, "window2");
assertEquals(window2, token.findMainWindow());
}
+
+ @Test
+ public void testLandscapeSeascapeRotationByApp() throws Exception {
+ // Some plumbing to get the service ready for rotation updates.
+ sWm.mDisplayReady = true;
+ sWm.mDisplayEnabled = true;
+
+ // Create an app window with token on a display.
+ final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ final TestAppWindowToken appWindowToken = new TestAppWindowToken(sDisplayContent);
+ task.addChild(appWindowToken, 0);
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
+ TYPE_BASE_APPLICATION);
+ attrs.setTitle("AppWindow");
+ final TestWindowState appWindow = new TestWindowState(attrs, appWindowToken);
+ appWindowToken.addWindow(appWindow);
+
+ // Set initial orientation and update.
+ appWindowToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ sWm.updateOrientationFromAppTokens(sDisplayContent.getOverrideConfiguration(), null,
+ sDisplayContent.getDisplayId());
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, sWm.mLastOrientation);
+ appWindow.resizeReported = false;
+
+ // Update the orientation to perform 180 degree rotation and check that resize was reported.
+ appWindowToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+ sWm.updateOrientationFromAppTokens(sDisplayContent.getOverrideConfiguration(), null,
+ sDisplayContent.getDisplayId());
+ sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
+ assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, sWm.mLastOrientation);
+ assertTrue(appWindow.resizeReported);
+ }
+
+ @Test
+ public void testLandscapeSeascapeRotationByPolicy() throws Exception {
+ // Some plumbing to get the service ready for rotation updates.
+ sWm.mDisplayReady = true;
+ sWm.mDisplayEnabled = true;
+
+ // Create an app window with token on a display.
+ final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ final TestAppWindowToken appWindowToken = new TestAppWindowToken(sDisplayContent);
+ task.addChild(appWindowToken, 0);
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
+ TYPE_BASE_APPLICATION);
+ attrs.setTitle("AppWindow");
+ final TestWindowState appWindow = new TestWindowState(attrs, appWindowToken);
+ appWindowToken.addWindow(appWindow);
+
+ // Set initial orientation and update.
+ ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = Surface.ROTATION_90;
+ sWm.updateRotation(false, false);
+ appWindow.resizeReported = false;
+
+ // Update the rotation to perform 180 degree rotation and check that resize was reported.
+ ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = Surface.ROTATION_270;
+ sWm.updateRotation(false, false);
+ sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
+ assertTrue(appWindow.resizeReported);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 12e7a15d2cbb..c0c8fb049415 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -65,6 +65,7 @@ import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.hardware.display.DisplayManagerInternal;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -75,10 +76,12 @@ import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
import android.view.animation.Animation;
+import android.os.PowerManagerInternal;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.server.input.InputManagerService;
+import com.android.server.LocalServices;
import java.io.PrintWriter;
@@ -87,10 +90,20 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
private static WindowManagerService sWm = null;
+ int rotationToReport = 0;
+
static synchronized WindowManagerService getWindowManagerService(Context context) {
if (sWm == null) {
// We only want to do this once for the test process as we don't want WM to try to
// register a bunch of local services again.
+ if (LocalServices.getService(DisplayManagerInternal.class) == null) {
+ LocalServices.addService(DisplayManagerInternal.class,
+ mock(DisplayManagerInternal.class));
+ }
+ if (LocalServices.getService(PowerManagerInternal.class) == null) {
+ LocalServices.addService(PowerManagerInternal.class,
+ mock(PowerManagerInternal.class));
+ }
sWm = WindowManagerService.main(context, mock(InputManagerService.class), true, false,
false, new TestWindowManagerPolicy());
}
@@ -543,7 +556,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
@Override
public int rotationForOrientationLw(int orientation,
int lastRotation) {
- return 0;
+ return rotationToReport;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 53e5a2a5995a..44d5055d5eb6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -182,7 +182,7 @@ class WindowTestsBase {
}
}
- /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
+ /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
class TestAppWindowToken extends AppWindowToken {
TestAppWindowToken(DisplayContent dc) {
@@ -280,4 +280,36 @@ class WindowTestsBase {
return mBinder;
}
}
+
+ /** Used to track resize reports. */
+ class TestWindowState extends WindowState {
+ boolean resizeReported;
+
+ TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
+ super(sWm, mMockSession, mIWindow, token, null, OP_NONE, 0, attrs, 0, 0);
+ }
+
+ @Override
+ void reportResized() {
+ super.reportResized();
+ resizeReported = true;
+ }
+
+ @Override
+ public boolean isGoneForLayoutLw() {
+ return false;
+ }
+
+ @Override
+ void updateResizingWindowIfNeeded() {
+ // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
+ // the system that it can actually update the window.
+ boolean hadSurface = mHasSurface;
+ mHasSurface = true;
+
+ super.updateResizingWindowIfNeeded();
+
+ mHasSurface = hadSurface;
+ }
+ }
}