MTK Android T/U (13/14) Version Screen Rotation Disable After Reboot/Shut Down Issue
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.