Android 实现KeyguardView 锁屏界面横屏显示

问题描述:设备要横屏显示所有界面,但是Keyguard锁屏界面没有横屏显示,前提条件是设备没有Gsensor重力感应。

android版本:8.1

解决过程:从其他资料里学习和查看了keyguard的流程,找到了控制绘制方向的地方,问题随之解决。


系统在启动只会加载很多服务,SystemServer是所有服务的管家,他控制了系统服务的启动,在一切准备结束的时候,会调用各个服务的回调systemReady。

/**

* The main entry point from zygote.

*/

public static void main(String[] args) {

    new SystemServer().run();

}

run开始后会调用很多很多服务的启动

try {

    startBootstrapServices();

    /// M: For mtk systemserver

    sMtkSystemServerIns.startMtkBootstrapServices();

    startCoreServices();

    /// M: for mtk other service.

    sMtkSystemServerIns.startMtkCoreServices();

    startOtherServices();

    SystemServerInitThreadPool.shutdown();

} catch (Throwable ex) {

    throw ex;

} finally {}

最后很多服务启动后开始执行systemready

try {

    wm.systemReady();

} catch (Throwable e) {

    reportWtf("making Window Manager Service ready", e);

}

其中 windowmanager service的systemready会慢慢走到Phonewindowmanagerservice

// windowmanagerservice.java

public void systemReady() {

    mPolicy.systemReady();

    mTaskSnapshotController.systemReady();

    mHasWideColorGamutSupport = queryWideColorGamutSupport();

}

policy是个接口对象,

final WindowManagerPolicy mPolicy;
public interface WindowManagerPolicy{...}

实现这个接口的就是Phonewindowmanager

public class PhoneWindowManager implements WindowManagerPolicy

 

PhoneWindowManager 的systemready里

@Override

public void systemReady() {

// In normal flow, systemReady is called before other system services are ready.

// So it is better not to bind keyguard here.

mKeyguardDelegate.onSystemReady();

....

}

第一句话就是进入keyguard的systemready

public void onSystemReady() {

    if (mKeyguardService != null) {

        mKeyguardService.onSystemReady();

    } else {
    
        mKeyguardState.systemIsReady = true;

    }

}

mKeyguardService的ready,走到了IKeyguardService,

oneway interface IKeyguardService

这里使用了AIDL 的IPC机制,最后的远程服务就是

KeyguardService extends Service

KeyguardService的mbinder就是在binder

private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {

在KeyguardService里有个KeyguardViewMediator

@Override

public void onCreate() {

    ((SystemUIApplication) getApplication()).startServicesIfNeeded();

    mKeyguardViewMediator =

    ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);

    mKeyguardLifecyclesDispatcher = new KeyguardLifecyclesDispatcher(

    Dependency.get(ScreenLifecycle.class),

    Dependency.get(WakefulnessLifecycle.class));


}

在binder的接口里很多方法的实现都是靠这个KeyguardViewMediator,

public class KeyguardViewMediator extends SystemUI

在这里,IKeyguardService的onsystemready

@Override // Binder interface

public void onSystemReady() {

    Trace.beginSection("KeyguardService.mBinder#onSystemReady");

    checkPermission();

    mKeyguardViewMediator.onSystemReady();

    Trace.endSection();

}

接着去看看mKeyguardViewMediator的onsystemready

public void onSystemReady() {

synchronized (this) {

    if (DEBUG) Log.d(TAG, "onSystemReady");

        mSystemReady = true;

        doKeyguardLocked(null);

        mUpdateMonitor.registerCallback(mUpdateCallback);

        mPowerOffAlarmManager.onSystemReady();
    
    }

    // Most services aren't available until the system reaches the ready state, so we

    // send it here when the device first boots.

    maybeSendUserPresentBroadcast();

}

进入doKeyguardLocked(null);

private void doKeyguardLocked(Bundle options) {

    //....省略上百行 方法的最后
    
    if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");

    showLocked(options);

}

方法的最后是showLocked()

private void showLocked(Bundle options) {

    Trace.beginSection("KeyguardViewMediator#showLocked aqcuiring mShowKeyguardWakeLock");

    if (DEBUG) Log.d(TAG, "showLocked");

    // ensure we stay awake until we are finished displaying the keyguard

    mShowKeyguardWakeLock.acquire();

    Message msg = mHandler.obtainMessage(SHOW, options);

    mHandler.sendMessage(msg);
    
    Trace.endSection();

}

发送了message给handler去show

public void handleMessage(Message msg) {

    switch (msg.what) {

        case SHOW:

            handleShow((Bundle) msg.obj);

        break;

看看handleShow

private void handleShow(Bundle options) {

    synchronized (KeyguardViewMediator.this) {

        setShowingLocked(true);

        mStatusBarKeyguardViewManager.show(options);

        mHiding = false;

        mWakeAndUnlocking = false;

        resetKeyguardDonePendingLocked();

        mHideAnimationRun = false;

        adjustStatusBarLocked();

        userActivity();



    if (mKeyguardDisplayManager != null) {

    Log.d(TAG, "handle show call mKeyguardDisplayManager.show()") ;

    mKeyguardDisplayManager.show();

    } else {

    Log.d(TAG, "handle show mKeyguardDisplayManager is null") ;

    }


}

这里调用了两个show,第一个是mStatusBarKeyguardViewManager的show,里面带有bundle参数,

另一个调用了mKeyguardDisplayManager的show,执行了绘画的更新等操作

public void show() {

    if (!mShowing) {

        if (DEBUG) Slog.v(TAG, "show");

        mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,

        mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);

        updateDisplays(true);

    }

    mShowing = true;

}

这里只是绘画相关,但是在绘画之前,那些参数的设置,一定产生了作用

去看看mStatusBarKeyguardViewManager的show

/**

* Show the keyguard. Will handle creating and attaching to the view manager

* lazily.

*/

public void show(Bundle options) {

    if (DEBUG) Log.d(TAG, "show() is called.") ;

    mShowing = true;

    mStatusBarWindowManager.setKeyguardShowing(true);

    mScrimController.abortKeyguardFadingOut();

    reset(true /* hideBouncerWhenShowing */);

}

注释已经说明了,会去创建view

public void setKeyguardShowing(boolean showing) {

    mCurrentState.keyguardShowing = showing;

    apply(mCurrentState);

}

 

这里的apply就是去更新状态,

private void apply(State state) {

    applyKeyguardFlags(state);

    applyForceStatusBarVisibleFlag(state);

    applyFocusableFlag(state);

    adjustScreenOrientation(state);

    applyHeight(state);

    applyUserActivityTimeout(state);

    applyInputFeatures(state);

    applyFitsSystemWindows(state);

    applyModalFlag(state);

    applyBrightness(state);

    applyHasTopUi(state);

    applySleepToken(state);

    。。。。

}

刚好,看到了orientation,

private void adjustScreenOrientation(State state) {

    if (state.isKeyguardShowingAndNotOccluded() || state.dozing) {

        if (mKeyguardScreenRotation) {

            mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;

        } else {

            mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;

        }

    } else {

        mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;

    }

}

在这里,会去判断屏幕方向,如果是nosensor,那么结果就是,默认竖屏了,如果是user或者未指定,那么就是指定方向了,由于开机的时候系统给指定了user_rotate方向,那么在没有gsensor且方向不是nosensor的时候,就会去跟随user_rotate了,改了这里,只返回unspecified,锁屏的横屏问题就解决了,整个过程没有深度分析锁屏界面的各种细节,但是也经过了一个主线流程,这对以后的问题有了一个指导。

 

在这里看到了一个变量,mKeyguardScreenRotation

mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();

走进去看,

private boolean shouldEnableKeyguardScreenRotation() {

    Resources res = mContext.getResources();

    return SystemProperties.getBoolean("lockscreen.rot_override", false)

        || res.getBoolean(R.bool.config_enableLockScreenRotation);

}

原来这里设置了属性开关,决定是否开启锁屏旋转

frameworks\base\core\res\res\values\config.xml

<!-- Disable lockscreen rotation by default -->

<bool name="config_enableLockScreenRotation">false</bool>

所以,改了这里的enable就可以设置锁屏界面的方向了

 

关于user_rotation这个,需要去了解一下相关知识,这里不做解释。

 

 

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值