Set Android default orientation to portrait mode

Published on April 19, 2011

Archived Notice

This article has been archived and may contain broken links, photos and out-of-date information. If you have any questions, please Contact Us.

The default screen orientation for the Android-ready Nitrogen and Nitrogen53 is landscape. That's fine for most people, but say you want it in portrait. Or upside down, or whatever. That's a problem, since Android usually takes rotation instructions from code that expects motion sensor input, and since most Nitrogen use cases don't need the board to move during normal operation (sorry, retail kiosks, no 'shake' function for you), there's no sensor to read from.

Well, on an app-by-app basis, you could always update the manifest file. There's a tag in there that defines the activity's requested orientation. This isn't really the best way to go about this, though, especially if you're planning on using lots of apps this way.

Credit goes to android-porting group for establishing the right direction for people in our situation. The answer is in frameworks/base/policy/src/com/internal/policy/impl/PhoneWindowManager.java (whew). Among other things, this file provides rotation settings to the rest of the system. Check out rotationForOrientationLw():

    public int rotationForOrientationLw(int orientation, int lastRotation,
            boolean displayEnabled) {
        if (mPortraitRotation < 0) {             // Initialize the rotation angles for each orientation once.
            Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
            if (d.getWidth() > d.getHeight()) {
                mPortraitRotation = Surface.ROTATION_90;
                mLandscapeRotation = Surface.ROTATION_0;
                mUpsideDownRotation = Surface.ROTATION_270;
                mSeascapeRotation = Surface.ROTATION_180;
            } else {
                mPortraitRotation = Surface.ROTATION_0;
                mLandscapeRotation = Surface.ROTATION_90;
                mUpsideDownRotation = Surface.ROTATION_180;
                mSeascapeRotation = Surface.ROTATION_270;
            }
        }
        synchronized (mLock) {
            switch (orientation) {
                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
                    //always return portrait if orientation set to portrait
                    return mPortraitRotation;
                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
                    //always return landscape if orientation set to landscape
                    return mLandscapeRotation;
                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
                    //always return portrait if orientation set to portrait
                    return mUpsideDownRotation;
                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
                    //always return seascape if orientation set to reverse landscape
                    return mSeascapeRotation;
                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
                    //return either landscape rotation based on the sensor
                    mOrientationListener.setAllow180Rotation(false);
                    return getCurrentLandscapeRotation(lastRotation);
                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
                    mOrientationListener.setAllow180Rotation(true);
                    return getCurrentPortraitRotation(lastRotation);
            }
            mOrientationListener.setAllow180Rotation(
                    orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
            // case for nosensor meaning ignore sensor and consider only lid
            // or orientation sensor disabled
            //or case.unspecified
            if (mLidOpen) {
                return mLidOpenRotation;
            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
                return mCarDockRotation;
            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
                return mDeskDockRotation;
            } else {
                if (useSensorForOrientationLp(orientation)) {
                    return mOrientationListener.getCurrentRotation(lastRotation);
                }
                return Surface.ROTATION_0;
            }
        }
    }

The first block defines the rotation angles, and then the rest administrates them on request. Most utility apps don't request a particular rotation, however; instead, they leave it up to the motion sensor. So, look in the last block, which dictates behavior when the orientation sensor is disabled. Since we aren't worried about dock mode, car mode, or open lid, the last line is what gets called. That last line (line 59 in the snippet) is what ends up determining the rotation that gets dictated to most apps in our situation. Try changing ROTATION_0 to ROTATION_270, rebuild and see what happens.

Portrait mode!

EDIT: One thing I found out while working on an upcoming post... The screen orientation defined in Launcher2's manifest file is "nosensor", which is why the process I described above works.  This sets the behavior for activities opened on top of Launcher -- most of the default apps don't even have a defined orientation.  If you are set up to open an app other than Launcher on boot, you will need to define the screenOrientation in their manifest, otherwise you'll get the default landscape orientation. If you made the above changes, "nosensor" should work fine.