public final static int PRESENCE_INTERNAL = 1 << 0;
public final static int PRESENCE_EXTERNAL = 1 << 1;
+ // Navigation bar position values
+ int NAV_BAR_LEFT = 1 << 0;
+ int NAV_BAR_RIGHT = 1 << 1;
+ int NAV_BAR_BOTTOM = 1 << 2;
+
public final static boolean WATCH_POINTER = false;
/**
public boolean isNavBarForcedShownLw(WindowState win);
/**
+ * @return The side of the screen where navigation bar is positioned.
+ * @see #NAV_BAR_LEFT
+ * @see #NAV_BAR_RIGHT
+ * @see #NAV_BAR_BOTTOM
+ */
+ int getNavBarPosition();
+
+ /**
* Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system
* bar or button bar. See {@link #getNonDecorDisplayWidth}.
*
import static android.os.Build.VERSION_CODES.O;
import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.view.WindowManagerPolicy.NAV_BAR_LEFT;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
import android.view.IApplicationToken;
import android.view.WindowManager.LayoutParams;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.util.XmlUtils;
// Compute configuration based on max supported width and height.
outBounds.set(0, 0, maxActivityWidth, maxActivityHeight);
+ // Position the activity frame on the opposite side of the nav bar.
+ final int navBarPosition = service.mWindowManager.getNavBarPosition();
+ final int left = navBarPosition == NAV_BAR_LEFT
+ ? configuration.appBounds.right - outBounds.width() : 0;
+ outBounds.offsetTo(left, 0 /* top */);
+ }
+
+ /** Get bounds of the activity. */
+ @VisibleForTesting
+ Rect getBounds() {
+ return new Rect(mBounds);
}
/**
private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
"com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
- private static final int NAV_BAR_BOTTOM = 0;
- private static final int NAV_BAR_RIGHT = 1;
- private static final int NAV_BAR_LEFT = 2;
-
/**
* Keyguard stuff
*/
}
@Override
+ public int getNavBarPosition() {
+ // TODO(multi-display): Support system decor on secondary displays.
+ return mNavigationBarPosition;
+ }
+
+ @Override
public boolean isDockSideAllowed(int dockSide) {
// We do not allow all dock sides at which the navigation bar touches the docked stack.
}
}
+ /**
+ * Used by ActivityManager to determine where to position an app with aspect ratio shorter then
+ * the screen is.
+ * @see WindowManagerPolicy#getNavBarPosition()
+ */
+ public int getNavBarPosition() {
+ synchronized (mWindowMap) {
+ // Perform layout if it was scheduled before to make sure that we get correct nav bar
+ // position when doing rotations.
+ final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
+ defaultDisplayContent.performLayout(false /* initial */,
+ false /* updateInputWindows */);
+ return mPolicy.getNavBarPosition();
+ }
+ }
+
@Override
public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
InputEventReceiver.Factory inputEventReceiverFactory) {
package com.android.server.am;
+import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM;
+import static android.view.WindowManagerPolicy.NAV_BAR_LEFT;
+import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
return -1;
}
+
+ @Test
+ public void testPositionLimitedAspectRatioNavBarBottom() throws Exception {
+ verifyPositionWithLimitedAspectRatio(NAV_BAR_BOTTOM, new Rect(0, 0, 1000, 2000), 1.5f,
+ new Rect(0, 0, 1000, 1500));
+ }
+
+ @Test
+ public void testPositionLimitedAspectRatioNavBarLeft() throws Exception {
+ verifyPositionWithLimitedAspectRatio(NAV_BAR_LEFT, new Rect(0, 0, 2000, 1000), 1.5f,
+ new Rect(500, 0, 2000, 1000));
+ }
+
+ @Test
+ public void testPositionLimitedAspectRatioNavBarRight() throws Exception {
+ verifyPositionWithLimitedAspectRatio(NAV_BAR_RIGHT, new Rect(0, 0, 2000, 1000), 1.5f,
+ new Rect(0, 0, 1500, 1000));
+ }
+
+ private void verifyPositionWithLimitedAspectRatio(int navBarPosition, Rect taskBounds,
+ float aspectRatio, Rect expectedActivityBounds) {
+ final ActivityManagerService service = createActivityManagerService();
+ final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
+ final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+ // Verify with nav bar on the right.
+ when(service.mWindowManager.getNavBarPosition()).thenReturn(navBarPosition);
+ task.getConfiguration().setAppBounds(taskBounds);
+ record.info.maxAspectRatio = aspectRatio;
+ record.ensureActivityConfigurationLocked(0 /* globalChanges */, false /* preserveWindow */);
+ assertEquals(expectedActivityBounds, record.getBounds());
+ }
}
null /*_taskDescription*/, new ActivityManager.TaskThumbnailInfo());
final ActivityStack stack = service.mStackSupervisor.getStack(stackId,
true /*createStaticStackIfNeeded*/, true /*onTop*/);
+ service.mStackSupervisor.setFocusStackUnchecked("test", stack);
stack.addTask(task, true, "creating test task");
task.setStack(stack);
task.setWindowContainerController(mock(TaskWindowContainerController.class));
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
}
@Override
+ public int getNavBarPosition() {
+ return NAV_BAR_BOTTOM;
+ }
+
+ @Override
public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
Rect outInsets) {