Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

MTK Android T/U (13/14) Version Screen Rotation Disable After Reboot/Shut Down Issue

Tech 1

Problem Description

This issue occurs in MTK Android T version and later. When screen auto-rotation is manually enabled, it gets disabled after system reboot or shut down.

Initial Enalysis

The problem occurs specifically during shutdown or reboot processes. The invsetigation focuses on whether system settings are being modified during these operations. The shutdown flow in Android provides a good starting point for analysis.

Detailed Shutdown Flow

Framework Components Involved

\frameworks\base\core\res\res\values\config.xml
\frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
\frameworks\base\services\core\java\com\android\server\policy\GlobalActions.java
\frameworks\base\services\core\java\com\android\server\policy\LegacyGlobalActions.java
\frameworks\base\services\core\java\com\android\server\policy\PowerAction.java
\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
\frameworks\base\services\core\java\com\android\server\power\ShutdownThread.java
\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java

Power Key Handling

When the power key is pressed:

private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
    final boolean handledByPowerManager = mPowerManagerInternal.interceptPowerKeyDown(event);
    
    if (!mPowerKeyHandled) {
        if (!interactive) {
            wakeUpFromPowerKey(event.getDownTime());
        }
    }
}

private void powerLongPress(long eventTime) {
    final int behavior = getResolvedLongPressOnPowerBehavior();
    
    switch (behavior) {
        case LONG_PRESS_POWER_GLOBAL_ACTIONS:
            mPowerKeyHandled = true;
            showGlobalActions();
            break;
    }
}

Global Actions Display

void showGlobalActionsInternal() {
    if (mGlobalActions == null) {
        mGlobalActions = mGlobalActionsFactory.get();
    }
    mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
}

public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {
    if (mGlobalActionsAvailable) {
        mGlobalActionsProvider.showGlobalActions();
    } else {
        ensureLegacyCreated();
        mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
    }
}

Legacy Shutdown Dialog

private void handleShow() {
    mDialog = createDialog();
    prepareDialog();
    
    if (mAdapter.getCount() == 1 && mAdapter.getItem(0) instanceof SinglePressAction) {
        ((SinglePressAction) mAdapter.getItem(0)).onPress();
    } else {
        mDialog.show();
    }
}

private ActionsDialog createDialog() {
    mItems.add(new PowerAction(mContext, mWindowManagerFuncs));
    return dialog;
}

Power Action Implementation

@Override
public boolean onLongPress() {
    UserManager um = mContext.getSystemService(UserManager.class);
    if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
        mWindowManagerFuncs.rebootSafeMode(true);
        return true;
    }
    return false;
}

@Override
public void rebootSafeMode(boolean confirm) {
    ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(), confirm);
}

Shutdown Thread Execution

private static void beginShutdownSequence(Context context) {
    sInstance.mProgressDialog = showShutdownDialog(context);
    sInstance.start();
}

public void run() {
    final IActivityManager am = IActivityManager.Stub.asInterface(ServiceManager.checkService("activity"));
    try {
        am.shutdown(MAX_BROADCAST_TIME);
    } catch (RemoteException e) {}
    
    shutdownTimingLog.traceEnd();
    final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
    if (pm != null) {
        pm.shutdown();
    }
    
    rebootOrShutdown(mContext, mReboot, mReason);
}

public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
    PowerManagerService.lowLevelShutdown(reason);
}

public static void lowLevelShutdown(String reason) {
    if (reason == null) reason = "";
    SystemProperties.set("sys.powerctl", "shutdown," + reason);
}

Root Cause Analysis

In the MTK vendor implementation, the MtkShutdownThread.java component disables screen rotation during shutdown for animation purposes:

private static void bootanimCust(Context context) {
    boolean isRotaionEnabled = false;
    
    try {
        isRotaionEnabled = Settings.System.getInt(context.getContentResolver(),
                Settings.System.ACCELEROMETER_ROTATION, 1) != 0;
        
        if (isRotaionEnabled) {
            final IWindowManager wm = IWindowManager.Stub.asInterface(
                    ServiceManager.getService(Context.WINDOW_SERVICE));
            if (wm != null) {
                wm.freezeRotation(Surface.ROTATION_0);
            }
            Settings.System.putInt(context.getContentResolver(),
                    Settings.System.ACCELEROMETER_ROTATION, 0);
            isRestore = true;
        }
    } catch (Exception ex) {
        Log.e(TAG, "check Rotation: context object is null when get Rotation");
    }
    
    startBootAnimation();
}

protected void mShutdownSeqFinish(Context context) {
    if (isRestore) {
        isRestore = false;
        Settings.System.putInt(context.getContentResolver(),
                    MtkSettingsExt.System.ACCELEROMETER_ROTATION_RESTORE, 1);
    }
}

The code sets the rotation to disabled but fails to restore it to the original state in the mShutdownSeqFinish method.

Solution

Add the missing restoration logic to re-enable screen rotation after shutdown:

protected void mShutdownSeqFinish(Context context) {
    if (isRestore) {
        isRestore = false;
        Settings.System.putInt(context.getContentResolver(),
                    Settings.System.ACCELEROMETER_ROTATION, 1);
        Settings.System.putInt(context.getContentResolver(),
                    MtkSettingsExt.System.ACCELEROMETER_ROTATION_RESTORE, 1);
    }
}

This ensures that the screen rotation setting is properly restored to its previous state after the shutdown process.

Tags: Androidmtk

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.