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

Commit 2c5642f9 authored by Ricardo Cerqueira's avatar Ricardo Cerqueira
Browse files

Add support for HW Rotation Lock

Forward ported from jellybean

Change-Id: I75fb9fa33541eb6acedd62a67e74977b36768390

Conflicts:
	core/res/res/values/symbols.xml
	services/java/com/android/server/SystemServer.java
parent 81179145
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -75,7 +75,9 @@ public final class RotationPolicy {
        return isRotationLockToggleSupported(context) &&
                Settings.System.getIntForUser(context.getContentResolver(),
                        Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
                        UserHandle.USER_CURRENT) == 0;
                        UserHandle.USER_CURRENT) == 0 &&
                !context.getResources().getBoolean(com.android
                        .internal.R.bool.config_hasRotationLockSwitch);
    }

    /**
+3 −0
Original line number Diff line number Diff line
@@ -4546,4 +4546,7 @@
    <!-- label for item that opens the profile choosing dialog -->
    <string name="global_action_choose_profile">Profile</string>

    <!-- Hardware Rotation lock string -->
    <string name="toast_rotation_unlocked">Display rotation unlocked</string>
    <string name="toast_rotation_locked">Display rotation locked</string>
</resources>
+4 −0
Original line number Diff line number Diff line
@@ -1799,4 +1799,8 @@
  <!-- Developer settings - Kill app back press -->
  <java-symbol type="string" name="app_killed_message" />

  <!-- HW rotation lock -->
  <java-symbol type="string" name="toast_rotation_unlocked" />
  <java-symbol type="string" name="toast_rotation_locked" />

</resources>
+163 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 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 com.android.server;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.os.UEventObserver;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;

import android.widget.Toast;
import android.view.IWindowManager;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.os.AsyncTask;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * <p>RotationLockObserver monitors for rotation lock switch state
 */
class RotationSwitchObserver extends UEventObserver {
    private static final String TAG = RotationSwitchObserver.class
        .getSimpleName();
    private static final boolean LOG = true;

    private static final String LOCK_UEVENT_MATCH =
        "DEVPATH=/devices/virtual/switch/rotationlock";
    private static final String LOCK_STATE_PATH =
        "/sys/class/switch/rotationlock/state";

    private static final int MSG_LOCK_STATE = 0;

    private int mLockState;
    private int mPreviousLockState;

    private boolean mSystemReady;

    private final Context mContext;

    private boolean mAutoRotation;

    public RotationSwitchObserver(Context context) {
        mContext = context;
        init();  // set initial status

        startObserving(LOCK_UEVENT_MATCH);
    }

    @Override
    public void onUEvent(UEventObserver.UEvent event) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Slog.v(TAG, "Switch UEVENT: " + event.toString());
        }

        synchronized (this) {
            try {
                int newState = Integer.parseInt(event.get("SWITCH_STATE"));
                if (newState != mLockState) {
                    mPreviousLockState = mLockState;
                    mLockState = newState;
                    if (mSystemReady) {
                        update();
                    }
                }
            } catch (NumberFormatException e) {
                Slog.e(TAG, "Could not parse switch state from event "
                        + event);
            }
        }
    }

    private final void init() {
        char[] buffer = new char[1024];

        try {
            FileReader file = new FileReader(LOCK_STATE_PATH);
            int len = file.read(buffer, 0, 1024);
            file.close();
            mPreviousLockState = mLockState =
                Integer.valueOf((new String(buffer, 0, len)).trim());
        } catch (FileNotFoundException e) {
            Slog.w(TAG, "This kernel does not have rotation switch support");
        } catch (NumberFormatException e) {
            Slog.e(TAG, "" , e);
        } catch (IOException e) {
            Slog.e(TAG, "" , e);
        }
    }

    void systemReady() {
        synchronized (this) {
            mSystemReady = true;
        }
    }

    private final void update() {
        mHandler.sendEmptyMessage(MSG_LOCK_STATE);
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_LOCK_STATE:
                    synchronized (this) {
                        boolean autoRotate = mLockState == 0;
                        int toastId = autoRotate
                            ? com.android.internal.R.string.toast_rotation_unlocked
                            : com.android.internal.R.string.toast_rotation_locked;

                        setAutoRotation(autoRotate);

                        Toast.makeText(mContext, mContext.getString(toastId),
                            Toast.LENGTH_SHORT).show();
                    break;
                }
            }
        }
    };

    private void setAutoRotation(final boolean autorotate) {
        mAutoRotation = autorotate;
        AsyncTask.execute(new Runnable() {
                public void run() {
                    try {
                        IWindowManager wm = IWindowManager.Stub.asInterface(
                                ServiceManager
                                        .getService(Context.WINDOW_SERVICE));
                        if (autorotate) {
                            wm.thawRotation();
                        } else {
                            wm.freezeRotation(-1);
                        }
                    } catch (RemoteException exc) {
                        Log.w(TAG, "Unable to save auto-rotate setting");
                    }
                }
            });
    }
}
+20 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ class ServerThread {
        WindowManagerService wm = null;
        BluetoothManagerService bluetooth = null;
        DockObserver dock = null;
        RotationSwitchObserver rotateSwitch = null;
        UsbService usb = null;
        SerialService serial = null;
        TwilightService twilight = null;
@@ -361,6 +362,9 @@ class ServerThread {
            Slog.e("System", "************ Failure starting core service", e);
        }

        boolean hasRotationLock = context.getResources().getBoolean(com.android
                .internal.R.bool.config_hasRotationLockSwitch);

        DevicePolicyManagerService devicePolicy = null;
        StatusBarManagerService statusBar = null;
        InputMethodManagerService imm = null;
@@ -688,6 +692,16 @@ class ServerThread {
                }
            }

            try {
                if (hasRotationLock) {
                    Slog.i(TAG, "Rotation Switch Observer");
                    // Listen for switch changes
                    rotateSwitch = new RotationSwitchObserver(context);
                }
            } catch (Throwable e) {
                reportWtf("starting RotationSwitchObserver", e);
            }

            if (!disableNonCoreServices) {
                try {
                    Slog.i(TAG, "USB Service");
@@ -950,6 +964,7 @@ class ServerThread {
        final NetworkPolicyManagerService networkPolicyF = networkPolicy;
        final ConnectivityService connectivityF = connectivity;
        final DockObserver dockF = dock;
        final RotationSwitchObserver rotateSwitchF = rotateSwitch;
        final UsbService usbF = usb;
        final TwilightService twilightF = twilight;
        final UiModeManagerService uiModeF = uiMode;
@@ -1021,6 +1036,11 @@ class ServerThread {
                } catch (Throwable e) {
                    reportWtf("making Dock Service ready", e);
                }
                try {
                    if (rotateSwitchF != null) rotateSwitchF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Rotation Switch Service ready", e);
                }
                try {
                    if (usbF != null) usbF.systemReady();
                } catch (Throwable e) {