Android4.2上内置第三方锁屏(一)、锁屏开机加载流程

最近在研究将第三方锁屏内置到android系统的问题,现在有时间来梳理下最近的工作;
首先列举下当前的外部条件:
1、基于CM修改的android4.2,4.4进行内置,这里以android4.4来讲解;
2、第三方锁屏是一个单独的apk,不对rom厂商进行源码开放,rom厂商源码也不对我们进行开放;
3、第三方锁屏使用了GLSurfaceView作为显示。!!!!

现在来具体的记录下各个细节;

以我们的当前的情况,首先我们要进行调试编码,必须要有一套可用的源码,而rom厂商是不会给你源码的(LOL),所以就只能自己想办法了;
首先我想到的自然是CM了,接下来就是拿取相应版本的CM android源码了,从百度百科摘录了一段,来说明CM和Android之间的版本对应关系:
CM4( Android 1.6
CM5( Android 2.1
CM6( Android 2.2
CM7( Android 2.3
CM8(Android 3.X【因为Google并没有开放这一代系统的源代码,所以跳过了开发】)
CM9 Android 4.0
CM10 Android 4.1
CM10.1( Android 4.2
CM10.2( Android 4.3
CM11 ( Android 4.4 )
后续版本,敬请期待......


根据上面我说的条件一,我拿取CM10.1的源码,具体我就不多说了,可以参考老罗的博客: http://blog.csdn.net/luoshengyang/article/details/29688041 ;
具体CM支持哪些机器,可以查看: http://download.cyanogenmod.org/

拿到了CM10.1对应机器源码并进行编译后,就可以进行后续工作了;

要想内置锁屏,首先得大体的了解系统的锁屏;所有我就首先来看看系统锁屏的加载过程;

首先,在开机时,SystemServer的initAndLoop方法中会通知WindowManagerService我系统已经Ready了,
SystemServer.java
try {
            wm.systemReady();
        } catch (Throwable e) {
            reportWtf("making Window Manager Service ready", e);
        }
WindowManagerService.java
public void systemReady() {
        mPolicy.systemReady();
    }
而这个mPolicy对象是在 WindowManagerService初始化的时初始化的,
final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();

跟踪这个方法,就会发现它返回的是一个PhoneWindowManager对象,而 PhoneWindowManager正是实现了WindowManagerPolicy接口;那么就会进入到 PhoneWindowManager的systemReady()方法中了;

@Override
    public void systemReady() {
        if (!mHeadless) {
            mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null);
            mKeyguardDelegate.onSystemReady();
        }
        mEdgeGestureManager = EdgeGestureManager.getInstance();
        mEdgeGestureManager.setEdgeGestureActivationListener(mEdgeGestureActivationListener);
        synchronized (mLock) {
            updateOrientationListenerLp();
            mSystemReady = true;
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    updateSettings();
                }
            });
        }
    }

这个 KeyguardServiceDelegate做什么的呢?进入它的构造方法中看看;

public KeyguardServiceDelegate(Context context, LockPatternUtils lockPatternUtils) {
        final String keyguardPackage = context.getString(
                com.android.internal.R.string.config_keyguardPackage);
        final String keyguardClass = context.getString(
                com.android.internal.R.string.config_keyguardService);

        Intent intent = new Intent();
        intent.setClassName(keyguardPackage, keyguardClass);
        mScrim = createScrim(context);
        if (!context.bindServiceAsUser(intent, mKeyguardConnection,
                Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
            if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + keyguardClass);
        } else {
            if (DEBUG) Log.v(TAG, "*** Keyguard started");
        }
    }

    private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
            mKeyguardService = new KeyguardServiceWrapper(
                    IKeyguardService.Stub.asInterface(service));
            if (mKeyguardState.systemIsReady) {
                // If the system is ready, it means keyguard crashed and restarted.
                mKeyguardService.onSystemReady();
                // This is used to hide the scrim once keyguard displays.
                mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null));
            }
            if (mKeyguardState.bootCompleted) {
                mKeyguardService.onBootCompleted();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
            mKeyguardService = null;
        }

    };

首先它会去bind一个Service,这个Service的包名。类名分别是:
<string name="config_keyguardPackage">com.android.keyguard</string>
<string name="config_keyguardService">com.android.keyguard.KeyguardService</string>
下面在ServiceConnection中,可以看到其获取了这个Service代理对象,叫KeyguardServiceWrapper,这个Service就是IKeyguardService,它是在
framework/base/core/java/android/internal/policy下;并且定义了一个IKeyguardService.aidl来放出接口,它的具体实现是在真正的Keyguard App中,framework/base/packages/Keyguard

mKeyguardService = new KeyguardServiceWrapper(
                    IKeyguardService.Stub.asInterface(service));

获取到这个Service代理对象之后,就可以和Keyguard进行交互动作了;那么真正第一次的交互应该就是 KeyguardServiceDelegate的mKeyguardConnection.onServiceConnected这个方法这里了:
if (mKeyguardState.systemIsReady) {
                // If the system is ready, it means keyguard crashed and restarted.
                // This is used to hide the scrim once keyguard displays.
            	mKeyguardService.onSystemReady();
                mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null));
            }
            if (mKeyguardState.bootCompleted) {
                mKeyguardService.onBootCompleted();
            }

进入Keyguard App之前,首先了解下几个类:
KeyguardViewMediator:用于控制锁屏的动作逻辑,上与PhoneWindowManager交互,下与KeyguardViewManager交互;
KeyguardViewManager:具体的锁屏View动作;
LockPatternUtils:与加密相关的工具类;

下面进入到KeyguardService中了;在KeyguardService的onCreate方法中初始化了;
@Override
    public void onCreate() {
        if (mKeyguardViewMediator == null) {
            mKeyguardViewMediator = new KeyguardViewMediator(
                    KeyguardService.this, new LockPatternUtils(KeyguardService.this));
        }
        Log.v(TAG, "onCreate()");
    }

下面就是具体的调用到Keyguard App的所有方法了;
private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {

        public boolean isShowing() {
            return mKeyguardViewMediator.isShowing();
        }
        public boolean isSecure() {
            return mKeyguardViewMediator.isSecure();
        }
        public boolean isShowingAndNotHidden() {
            return mKeyguardViewMediator.isShowingAndNotHidden();
        }
        public boolean isInputRestricted() {
            return mKeyguardViewMediator.isInputRestricted();
        }
        public void verifyUnlock(IKeyguardExitCallback callback) {
            mKeyguardViewMediator.verifyUnlock(callback);
        }
        public void keyguardDone(boolean authenticated, boolean wakeup) {
            checkPermission();
            mKeyguardViewMediator.keyguardDone(authenticated, wakeup);
        }
        public void setHidden(boolean isHidden) {
            checkPermission();
            mKeyguardViewMediator.setHidden(isHidden);
        }
        public void dismiss() {
            mKeyguardViewMediator.dismiss();
        }
        public void onDreamingStarted() {
            checkPermission();
            mKeyguardViewMediator.onDreamingStarted();
        }
        public void onDreamingStopped() {
            checkPermission();
            mKeyguardViewMediator.onDreamingStopped();
        }
        public void onScreenTurnedOff(int reason) {
            checkPermission();
            mKeyguardViewMediator.onScreenTurnedOff(reason);
        }
        public void onScreenTurnedOn(IKeyguardShowCallback callback) {
            checkPermission();
            mKeyguardViewMediator.onScreenTurnedOn(callback);
        }
        public void setKeyguardEnabled(boolean enabled) {
            checkPermission();
            mKeyguardViewMediator.setKeyguardEnabled(enabled);
        }
        public boolean isDismissable() {
            return mKeyguardViewMediator.isDismissable();
        }
        public void onSystemReady() {
            checkPermission();
            mKeyguardViewMediator.onSystemReady();
        }
        public void doKeyguardTimeout(Bundle options) {
            checkPermission();
            mKeyguardViewMediator.doKeyguardTimeout(options);
        }
        public void setCurrentUser(int userId) {
            checkPermission();
            mKeyguardViewMediator.setCurrentUser(userId);
        }
        public void showAssistant() {
            checkPermission();
            mKeyguardViewMediator.showAssistant();
        }
        public void dispatch(MotionEvent event) {
            checkPermission();
            mKeyguardViewMediator.dispatch(event);
        }
        public void launchCamera() {
            checkPermission();
            mKeyguardViewMediator.launchCamera();
        }
        public void onBootCompleted() {
            checkPermission();
            mKeyguardViewMediator.onBootCompleted();
        }
    };

mKeyguardService.onSystemReady();
告诉Keyguard App系统已经Ready,你要显示锁屏了;
/**
     * Let us know that the system is ready after startup.
     */
    public void onSystemReady() {
        mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            mUpdateMonitor.registerCallback(mUpdateCallback);

            // Suppress biometric unlock right after boot until things have settled if it is the
            // selected security method, otherwise unsuppress it.  It must be unsuppressed if it is
            // not the selected security method for the following reason:  if the user starts
            // without a screen lock selected, the biometric unlock would be suppressed the first
            // time they try to use it.
            //
            // Note that the biometric unlock will still not show if it is not the selected method.
            // Calling setAlternateUnlockEnabled(true) simply says don't suppress it if it is the
            // selected method.
            if (mLockPatternUtils.usingBiometricWeak()
                    && mLockPatternUtils.isBiometricWeakInstalled()) {
                if (DEBUG) Log.d(TAG, "suppressing biometric unlock during boot");
                mUpdateMonitor.setAlternateUnlockEnabled(false);
            } else {
                mUpdateMonitor.setAlternateUnlockEnabled(true);
            }

            doKeyguardLocked(null); //显示锁屏View
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }

相应的,
mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null));
告诉keyguard App屏幕点亮;
/**
     * Let's us know the screen was turned on.
     */
    public void onScreenTurnedOn(IKeyguardShowCallback callback) {
        synchronized (this) {
            mScreenOn = true;
            cancelDoKeyguardLaterLocked();
            if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
            if (callback != null) {
                notifyScreenOnLocked(callback);
            }
        }
        KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurnedOn();
        maybeSendUserPresentBroadcast();
    }

首先我们跟踪onSystemReady()方法,对其它调用无视,看最重要的一句,doKeyguardLocked(null);中间简单调用略过,它会来到:
 /**
     * Handle message sent by {@link #showLocked}.
     * @see #SHOW
     */
    private void handleShow(Bundle options) {
        synchronized (KeyguardViewMediator.this) {
            if (!mSystemReady) {
                if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
                return;
            } else {
                if (DEBUG) Log.d(TAG, "handleShow");
            }

            new Thread(new Runnable() { 
                public void run() {
                    playSounds(true);  <span style="font-family: 微软雅黑;">//播放锁屏声音</span>
                }
            }).start();

            mKeyguardViewManager.show(options); //大头,锁屏显示
            mShowing = true;
            mKeyguardDonePending = false;
            updateActivityLockScreenState();//告诉ActivityManagerService当前锁屏是showing还是hidden;
            adjustStatusBarLocked();  //控制StatusBar的状态,下拉或者不能下拉
            userActivity();  //告诉PowerManager当前有用户操作
            try {
                ActivityManagerNative.getDefault().closeSystemDialogs("lock");//关闭系统dialog????
            } catch (RemoteException e) {
            }

            mShowKeyguardWakeLock.release();
        }
        mKeyguardDisplayManager.show(); //无视
    }

进入到下面这个方法以后,进入到KeyguardViewManager中,就是具体的View的操作了;
mKeyguardViewManager.show(options);

/**
     * Show the keyguard.  Will handle creating and attaching to the view manager
     * lazily.
     */
    public synchronized void show(Bundle options) {
        if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);

        boolean enableScreenRotation = shouldEnableScreenRotation(); //锁屏下的横竖屏

        maybeCreateKeyguardLocked(enableScreenRotation, false, options);  //大头,创建锁屏View
        maybeEnableScreenRotation(enableScreenRotation);  <span style="font-family: 微软雅黑;">//锁屏下的横竖屏</span>
        updateShowWallpaper(mKeyguardHost.shouldShowWallpaper());  //WALLPAPER显示

        // Disable common aspects of the system/status/navigation bars that are not appropriate or
        // useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED
        // activities. Other disabled bits are handled by the KeyguardViewMediator talking
        // directly to the status bar service.
        int visFlags = View.STATUS_BAR_DISABLE_HOME;
        if (shouldEnableTranslucentDecor()) {  //控制状态栏和navigation bar的透明
            mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                                       | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
        }
        if (DEBUG) Log.v(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");
        mKeyguardHost.setSystemUiVisibility(visFlags);

        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
        mKeyguardHost.setVisibility(View.VISIBLE);
        mKeyguardView.show();  //显示密码View,各种不同的加密view
        mKeyguardView.requestFocus();
    }

通过方法中的注释了解了具体的每一个调用的方法的作用;其中有个重要的对象就是ViewManagerHost,它代表的是整个锁屏的View,控制它就等于控制这个锁屏;


private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
            Bundle options) {
        if (mKeyguardHost != null) {
            mKeyguardHost.saveHierarchyState(mStateContainer);
        }

        if (mKeyguardHost == null) {
            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");

            mKeyguardHost = new ViewManagerHost(mContext); //初始化<span style="font-family: 微软雅黑;">ViewManagerHost</span>

            int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
                    | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
                    | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;

            if (!mNeedsInput) {
                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
            }

            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
            final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                    stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
            lp.windowAnimations = R.style.Animation_LockScreen;
            lp.screenOrientation = enableScreenRotation ?
                    ActivityInfo.SCREEN_ORIENTATION_USER : ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;

            if (ActivityManager.isHighEndGfx()) {
                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
                lp.privateFlags |=
                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
            }
            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
            lp.setTitle("Keyguard");
            mWindowLayoutParams = lp;
            mViewManager.addView(mKeyguardHost, lp); //将这个根View添加到WindowManager

            KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
            mKeyguardHost.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mKeyguardHost.cacheUserImage();
                }
            }, 100);
        }

        if (force || mKeyguardView == null) {
            mKeyguardHost.setCustomBackground(null);
            mKeyguardHost.removeAllViews();
            inflateKeyguardView(options);   //加载具体的View layout
            mKeyguardView.requestFocus();
        }
        updateUserActivityTimeoutInWindowLayoutParams();
        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);

        mKeyguardHost.restoreHierarchyState(mStateContainer);
    }

至此,我也不往下再继续深究了,网络上也有不少资料,我这篇只起一个抛砖引玉的作用吧。附一张简单的View布局;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值