Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a74bd36 authored by Mike Lockwood's avatar Mike Lockwood Committed by Mike Lockwood
Browse files

Add headless mode for running the framework without the surface flinger



Enabled by setting system property ro.config.headless to 1
This will allow the framework to run without starting activities,
system UI and the keyguard.
Framework can still run services, content providers and broadcast receivers.

Signed-off-by: default avatarMike Lockwood <lockwood@android.com>

Conflicts:

	policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
	services/java/com/android/server/PowerManagerService.java
	services/java/com/android/server/am/ActivityManagerService.java
parent 2395527c
Loading
Loading
Loading
Loading
+25 −4
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/misc.h>
#include <utils/Log.h>
#include <cutils/properties.h>

// ----------------------------------------------------------------------------

@@ -44,6 +45,7 @@ struct offsets_t {
    jfieldID ydpi;
};
static offsets_t offsets;
static bool headless = false;

// ----------------------------------------------------------------------------

@@ -51,11 +53,20 @@ static void android_view_Display_init(
        JNIEnv* env, jobject clazz, jint dpy)
{
    DisplayInfo info;
    if (headless) {
        // initialize dummy display with reasonable values
        info.pixelFormatInfo.format = 1; // RGB_8888
        info.fps = 60;
        info.density = 160;
        info.xdpi = 160;
        info.ydpi = 160;
    } else {
        status_t err = SurfaceComposerClient::getDisplayInfo(DisplayID(dpy), &info);
        if (err < 0) {
            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
            return;
        }
    }
    env->SetIntField(clazz, offsets.pixelFormat,info.pixelFormatInfo.format);
    env->SetFloatField(clazz, offsets.fps,      info.fps);
    env->SetFloatField(clazz, offsets.density,  info.density);
@@ -66,6 +77,7 @@ static void android_view_Display_init(
static jint android_view_Display_getRawWidthNative(
        JNIEnv* env, jobject clazz)
{
    if (headless) return 640;
    DisplayID dpy = env->GetIntField(clazz, offsets.display);
    return SurfaceComposerClient::getDisplayWidth(dpy);
}
@@ -73,6 +85,7 @@ static jint android_view_Display_getRawWidthNative(
static jint android_view_Display_getRawHeightNative(
        JNIEnv* env, jobject clazz)
{
    if (headless) return 480;
    DisplayID dpy = env->GetIntField(clazz, offsets.display);
    return SurfaceComposerClient::getDisplayHeight(dpy);
}
@@ -80,6 +93,7 @@ static jint android_view_Display_getRawHeightNative(
static jint android_view_Display_getOrientation(
        JNIEnv* env, jobject clazz)
{
    if (headless) return 0; // Surface.ROTATION_0
    DisplayID dpy = env->GetIntField(clazz, offsets.display);
    return SurfaceComposerClient::getDisplayOrientation(dpy);
}
@@ -87,6 +101,7 @@ static jint android_view_Display_getOrientation(
static jint android_view_Display_getDisplayCount(
        JNIEnv* env, jclass clazz)
{
    if (headless) return 1;
    return SurfaceComposerClient::getNumberOfDisplays();
}

@@ -113,6 +128,12 @@ static JNINativeMethod gMethods[] = {

void nativeClassInit(JNIEnv* env, jclass clazz)
{
    char value[PROPERTY_VALUE_MAX];

    property_get("ro.config.headless", value, "0");
    if (strcmp(value, "1") == 0)
        headless = true;

    offsets.display     = env->GetFieldID(clazz, "mDisplay", "I");
    offsets.pixelFormat = env->GetFieldID(clazz, "mPixelFormat", "I");
    offsets.fps         = env->GetFieldID(clazz, "mRefreshRate", "F");
+60 −37
Original line number Diff line number Diff line
@@ -686,7 +686,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        if (mGlobalActions == null) {
            mGlobalActions = new GlobalActions(mContext);
        }
        final boolean keyguardShowing = mKeyguardMediator.isShowingAndNotHidden();
        final boolean keyguardShowing = keyguardIsShowingTq();
        mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
        if (keyguardShowing) {
            // since it took two seconds of long press to bring this up,
@@ -783,7 +783,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        mWindowManager = windowManager;
        mWindowManagerFuncs = windowManagerFuncs;
        mPowerManager = powerManager;
        if ("0".equals(SystemProperties.get("ro.config.headless", "0"))) {
            // don't create KeyguardViewMediator if headless
            mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
        }
        mHandler = new Handler();
        mOrientationListener = new MyOrientationListener(mContext);
        try {
@@ -1839,7 +1842,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
     * given the situation with the keyguard.
     */
    void launchHomeFromHotKey() {
        if (mKeyguardMediator.isShowingAndNotHidden()) {
        if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
            // don't launch home if keyguard showing
        } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
            // when in keyguard restricted mode, must first verify unlock
@@ -2580,6 +2583,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    /** {@inheritDoc} */
    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
        // do nothing if headless
        if (mKeyguardMediator == null) return;

        // lid changed state
        mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED;
        updateKeyboardVisibility();
@@ -2776,9 +2782,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        // the same as if it were open and in front.
        // This will prevent any keys other than the power button from waking the screen
        // when the keyguard is hidden by another activity.
        final boolean keyguardActive = (isScreenOn ?
        final boolean keyguardActive = (mKeyguardMediator == null ? false :
                                            (isScreenOn ?
                                                mKeyguardMediator.isShowingAndNotHidden() :
                                        mKeyguardMediator.isShowing());
                                                mKeyguardMediator.isShowing()));

        if (!mSystemBooted) {
            // If we have not yet booted, don't let key events do anything.
@@ -3046,7 +3053,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        final boolean isWakeMotion = (policyFlags
                & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
        if (isWakeMotion) {
            if (mKeyguardMediator.isShowing()) {
            if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) {
                // If the keyguard is showing, let it decide what to do with the wake motion.
                mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
            } else {
@@ -3114,7 +3121,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            mScreenOnEarly = false;
            mScreenOnFully = false;
        }
        if (mKeyguardMediator != null) {
            mKeyguardMediator.onScreenTurnedOff(why);
        }
        synchronized (mLock) {
            updateOrientationListenerLp();
            updateLockScreenTimeout();
@@ -3131,6 +3140,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            Slog.i(TAG, "Screen turning on...", here);
        }
        if (screenOnListener != null) {
            if (mKeyguardMediator != null) {
                mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
                    @Override public void onShown(IBinder windowToken) {
                        if (windowToken != null) {
@@ -3156,6 +3166,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                        }
                    }
                });
            }
        } else {
            synchronized (mLock) {
                mScreenOnFully = true;
@@ -3181,15 +3192,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    
    /** {@inheritDoc} */
    public void enableKeyguard(boolean enabled) {
        if (mKeyguardMediator != null) {
            mKeyguardMediator.setKeyguardEnabled(enabled);
        }
    }

    /** {@inheritDoc} */
    public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
        if (mKeyguardMediator != null) {
            mKeyguardMediator.verifyUnlock(callback);
        }
    }

    private boolean keyguardIsShowingTq() {
        if (mKeyguardMediator == null) return false;
        return mKeyguardMediator.isShowingAndNotHidden();
    }

@@ -3201,11 +3217,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    /** {@inheritDoc} */
    public boolean isKeyguardSecure() {
        if (mKeyguardMediator == null) return false;
        return mKeyguardMediator.isSecure();
    }

    /** {@inheritDoc} */
    public boolean inKeyguardRestrictedKeyInputMode() {
        if (mKeyguardMediator == null) return false;
        return mKeyguardMediator.isInputRestricted();
    }

@@ -3461,8 +3479,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    
    /** {@inheritDoc} */
    public void systemReady() {
        if (mKeyguardMediator != null) {
            // tell the keyguard
            mKeyguardMediator.onSystemReady();
        }
        synchronized (mLock) {
            updateOrientationListenerLp();
            mSystemReady = true;
@@ -3649,7 +3669,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        public void run() {
            synchronized (this) {
                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
                if (mKeyguardMediator != null) {
                    mKeyguardMediator.doKeyguardTimeout();
                }
                mLockScreenTimerActive = false;
            }
        }
@@ -3663,7 +3685,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    private void updateLockScreenTimeout() {
        synchronized (mScreenLockTimeout) {
            boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly && mKeyguardMediator.isSecure());
            boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly &&
                    mKeyguardMediator != null && mKeyguardMediator.isSecure());
            if (mLockScreenTimerActive != enable) {
                if (enable) {
                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
@@ -3863,7 +3886,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    public void screenOnStoppedLw() {
        if (mPowerManager.isScreenOn()) {
            if (!mKeyguardMediator.isShowingAndNotHidden()) {
            if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
                long curTime = SystemClock.uptimeMillis();
                mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
            }
+8 −3
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.WorkSource;
import android.provider.Settings;
import android.util.EventLog;
@@ -176,6 +177,7 @@ public class PowerManagerService extends IPowerManager.Stub

    private boolean mDoneBooting = false;
    private boolean mBootCompleted = false;
    private boolean mHeadless = false;
    private int mStayOnConditions = 0;
    private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
    private final int[] mBroadcastWhy = new int[3];
@@ -530,6 +532,7 @@ public class PowerManagerService extends IPowerManager.Stub
        mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS);
        mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD);
        mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
        mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));

        nativeInit();
        synchronized (mLocks) {
@@ -1894,10 +1897,12 @@ public class PowerManagerService extends IPowerManager.Stub
    }

    private void updateNativePowerStateLocked() {
        if (!mHeadless) {
            nativeSetPowerState(
                    (mPowerState & SCREEN_ON_BIT) != 0,
                    (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
        }
    }

    private int screenOffFinishedAnimatingLocked(int reason) {
        // I don't think we need to check the current state here because all of these
+6 −3
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ class ServerThread extends Thread {
        String factoryTestStr = SystemProperties.get("ro.factorytest");
        int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
                : Integer.parseInt(factoryTestStr);
        final boolean headless = "1".equals(SystemProperties.get("ro.config.headless", "0"));

        LightsService lights = null;
        PowerManagerService power = null;
@@ -462,8 +463,10 @@ class ServerThread extends Thread {

            try {
                Slog.i(TAG, "Wallpaper Service");
                if (!headless) {
                    wallpaper = new WallpaperManagerService(context);
                    ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
                }
            } catch (Throwable e) {
                reportWtf("starting Wallpaper Service", e);
            }
@@ -655,7 +658,7 @@ class ServerThread extends Thread {
            public void run() {
                Slog.i(TAG, "Making services ready");

                startSystemUi(contextF);
                if (!headless) startSystemUi(contextF);
                try {
                    if (batteryF != null) batteryF.systemReady();
                } catch (Throwable e) {
+10 −2
Original line number Diff line number Diff line
@@ -270,6 +270,8 @@ public final class ActivityManagerService extends ActivityManagerNative
    public ActivityStack mMainStack;
    private final boolean mHeadless;
    /**
     * Description of a request to start a new activity, which has been held
     * due to app switches being disabled.
@@ -2311,6 +2313,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        
        mUsageStatsService = new UsageStatsService(new File(
                systemDir, "usagestats").toString());
        mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
        GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
            ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
@@ -4747,7 +4750,9 @@ public final class ActivityManagerService extends ActivityManagerNative
            if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                    && processName.equals(hr.processName)) {
                try {
                    if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                    if (mHeadless) {
                        Slog.e(TAG, "Starting activities not supported on headless device: " + hr);
                    } else if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
@@ -13878,6 +13883,9 @@ public final class ActivityManagerService extends ActivityManagerNative
     */
    boolean updateConfigurationLocked(Configuration values,
            ActivityRecord starting, boolean persistent, boolean initLocale) {
        // do nothing if we are headless
        if (mHeadless) return true;
        int changes = 0;
        
        boolean kept = true;
Loading