笨人,大到浏览了android4.2 锁屏代码的流程,以及关键的几个类,及布局文件,用于备忘。
写得有点乱,等有时间再整理下。
//1 java层核心第一个类:(famework/base/service/java/com/android/server/)
SystemServer.javaà
//2 系统调用第一个类的入口init1():
native public static voidinit1(String[] args);à
//3 接着init1()通过jni回调init2()
public static final voidinit2() {
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
//4 init2()开启自已的线程
thr.start();
} à
//5 线程开启调用run()
public void run()à
//run()中,启动一系列service
//6其中之一是:wm = WindowManagerService.main(context, power, display, inputManager,uiHandler, wmHandler, factoryTest !=SystemServer.FACTORY_TEST_LOW_LEVEL,!firstBoot, onlyCore);à
// 7 在main方法中,调用了WindowManagerService构造方法,构造方法中又在initPolicy中调用了(PhoneWindowManager)mPolicy.init(),该方法对PhoneWindowManager里面的重要变量,进行初始化。
//7 继续第5步中的run方法中,调用如下代码。
try {
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
}à
try {
//通知WindowManagerService.displayReady()系统已启动好:
wm.systemReady();
Configuration config =wm.computeNewConfiguration();
à
---------------------------------------------------------
/*以下代码是WindowManagerService如何获取PhoneWindowManager(mPolicy)引用的。
1 Frameworks/base/service/java/com/android/server/wm/WindowManagerService.javaà
//通过PolicyManager获取PhoneWindowManager对象。
final WindowManagerPolicy (PhoneWindowManager)mPolicy = PolicyManager.makeNewWindowManager();à
PolicyManager.javaà
Class policyClass = Class.forName(“com.android.internal.policy.impl.Policy”);
sPolicy =(IPolicy)policyClass.newInstance();
publicstatic WindowManagerPolicy makeNewWindowManager() {
return sPolicy.makeNewWindowManager();
}à
Policy.javaà
publicWindowManagerPolicy makeNewWindowManager() {
return new PhoneWindowManager();
}
-------------------------------------------------------
//8 WindowManagerService.javaà
public void systemReady() {
//通知PhoneWindowManager系统启动好:
(PhoneWindowManager)mPolicy.systemReady();à
}
//9 PhoneWindowManager.java(implementsWindowManagerPolicy)
在PhoneWindowManager的init方法中,初始化了成员变量,
mWindowManager
mOrientationListener new
mKeyguardMediator = new KeyguardViewMediator(context, null);
mSettingsObserver new
mShortcutManager new
public void systemReady() {
if (mKeyguardMediator != null) {
// tell the keyguard 告知锁屏系统已好,可以开始工作了
mKeyguardMediator.onSystemReady();
}
synchronized (mLock) {
updateOrientationListenerLp(); //???????
mSystemReady = true;
mHandler.post(new Runnable() {
public void run() {
updateSettings();//?????
}
});
}
}
// 10 mKeyguardMediator.onSystemReady():
KeyguardViewMediator.java
1 成员
private AlarmManager mAlarmManager;
private AudioManager mAudioManager;
private PowerManager mPM;
private UserManager mUserManager;
private PowerManager.WakeLock mShowKeyguardWakeLock;
private LockPatternUtils mLockPatternUtils;
* mViewMediatorCallback—〉这个接口会给多view回调
* mUpdateCallback—〉
* mUpdateMonitor。
* mKeyguardViewManager= new KeyguardViewManager(context, wm,mViewMediatorCallback,mLockPatternUtils);//这个类就是创建锁屏界面的类。
* private StatusBarManager mStatusBarManager;
2 构造函数:
mKeyguardViewManage <- mViewMediatorCallback
mUpdateMonitor= KeyguardUpdateMonitor.getInstance(context);
3
onSystemReady():{
mUpdateMonitor.registerCallback(mUpdateCallback);
/// M:power-off alarm @{
if (!KeyguardUpdateMonitor.isAlarmBoot()){
doKeyguardLocked();//调用锁屏
}
/// @}
}
doKeyguardLocked():{
// 如果有第三方锁屏应用,就不显示锁屏
if (!mExternallyEnabled || KeyguardUpdateMonitor.isAlarmBoot()){
if (DEBUG) KeyguardUtils.xlogD(TAG,"doKeyguard:not showing because externally disabled");
return;
}
}
4 showLocked(Bundle options){
5 handleShow(Bundle options){
mKeyguardViewManager.show(options);
}
// 11 KeyguardViewManager:
----------------------------- 注 begin----------------------------
maybeCreateKeyguardLocked()本类中有三处调用:
a reset()方法,由mediator监听到系统某状态变化调用。
B onScreenturnon():由phonemanageràmediator调用。
C ViewManagerHost.onConfigchannged调用。(这个ViewManagerHost就是锁屏的根view)
----------------------------- 注 end----------------------------
mKeyguardViewManager.show(options){
//创建锁屏界面
maybeCreateKeyguardLocked(enableScreenRotation,false, options); ---》
maybeEnableScreenRotation(enableScreenRotation);
mKeyguardHost.setSystemUiVisibility(visFlags);
mViewManager.updateViewLayout(mKeyguardHost,mWindowLayoutParams);
mKeyguardHost.setVisibility(View.VISIBLE); //锁屏界面可见
mKeyguardView.show();//锁屏界面可见
mKeyguardView.requestFocus();//取得焦点
}
--》maybeCreateKeyguardLocked(){
if (mKeyguardHost ==null) {
mKeyguardHost = new ViewManagerHost(mContext);
mViewManager.addView(mKeyguardHost,lp);//将锁屏界面加入到framelayout中
}
if (force && mKeyguardView != null) {
mKeyguardView.cleanUp();//释放旧锁屏占用的空间。
}
if (force ||mKeyguardView == null) {
inflateKeyguardView(options);//创建新的锁屏界面
}
updateUserActivityTimeoutInWindowLayoutParams();
mViewManager.updateViewLayout(mKeyguardHost,mWindowLayoutParams);
mKeyguardHost.restoreHierarchyState(mStateContainer);
--》inflateKeyguardView—这个方法将锁屏界面解析出view放到容器里。{
1 判断是否是闹钟启动-- KeyguardUpdateMonitor.isAlarmBoot()
2 移除之前的view.-- mKeyguardHost.removeView(v);
3//解析layout锁屏布局,放到父容器中。
int layoutId = R.layout.keyguard_host_view;
mKeyguardView = (KeyguardHostView)view.findViewById(resId);
mKeyguardView.setLockPatternUtils(mLockPatternUtils);
mKeyguardView.setViewMediatorCallback(mViewMediatorCallback);
}
// 12 KeyguardHostView.java
一、先画一下布局:
1最外层是KeyguardHostView(间接继承自framelayout)+Id/keyguard_host_view
2 第二层SlidingChallengeLayout(继承自viewgroup)@+id/sliding_layout
3 再里面有七个东东:
依次是:1) mediatekLayerBackground 背景
2) +id/keyguard_widget_pager_delete_target:(TextView)删除目的地
3) <includelayout="@layout/keyguard_widget_pager"
android:id="@+id/app_widget_container"> (ViewGroup)widget容器。
注:显示时间,日期的keyguard_status_view由方法addDefaultStatusWidget(intindex)中add 进来。
4) 麻布
5)前景
6)KeyguardSecurityContainer(FrameLayout):@+id/keyguard_security_container
KeyguardSecurityViewFlipper(ViewFlipper):@+id/view_flipper
7)一个锁。
具体布局如下图所示:
----à -------à xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/glow_pad_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="horizontal" android:gravity="@integer/kg_selector_gravity" android:contentDescription="@string/keyguard_accessibility_slide_area" prvandroid:targetDrawables="@array/lockscreen_targets_unlock_only" prvandroid:targetDescriptions="@array/lockscreen_target_descriptions_unlock_only" prvandroid:directionDescriptions="@*android:array/lockscreen_direction_descriptions" prvandroid:handleDrawable="@*android:drawable/ic_lockscreen_handle" prvandroid:outerRingDrawable="@*android:drawable/ic_lockscreen_outerring" prvandroid:outerRadius="@*android:dimen/glowpadview_target_placement_radius" prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius" prvandroid:snapMargin="@*android:dimen/glowpadview_snap_margin" prvandroid:firstItemOffset="@integer/kg_glowpad_rotation_offset" prvandroid:magneticTargets="true" prvandroid:feedbackCount="1" prvandroid:vibrationDuration="20" prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius" prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot" prvandroid:allowScaling="true" /> 二、接下来看看:onFinishInflate()方法里做了什么。 1)mAppWidgetContainer.setCallbacks(mWidgetCallbacks);这个callback中,会控制锁屏界面的widget快捷界面最多为5个,方法是让+不可点击。 2)mAppWidgetContainer.setDeleteDropTarget(deleteDropTarget);删除的目的地。 3)addDefaultWidgets(): 添加加号,和相机widget.这里只有“滑动解锁”界面才会有相机界面。 其它解锁界面不会有,原因是进相机后就已解锁了。这对于其它解锁方式是不合适的。 4)addWidgetsFromSettings();//添加用户自定的widget以及默认界面。 5) mSwitchPageRunnable.run();//显示默认页。 6) showPrimarySecurityScreen(false);//根据安全模式显示界面。 updateSecurityViews();设置回调参数等 // 13 KeyguardSelectorView.java 成员变量: private KeyguardSecurityCallbackmCallback;//回调 privateMediatekGlowPadViewmGlowPadView;//动画pannal private ObjectAnimator mAnim; mOnTriggerListener:解锁回调监听器 成员方法: onFinishInflate(){ mGlowPadView =(MediatekGlowPadView) findViewById(R.id.glow_pad_view);//解锁动画panel. mGlowPadView.setOnTriggerListener(mOnTriggerListener); updateTargets();//ic_lockscreen_camera,ic_action_assist_generic inflater.inflate(com.mediatek.internal.R.layout.keyguard_unread_event_view,unLockPanel, true);//未读事件的view读入并可见。 } //14UnReadEventView.java:未读事件视图。 ViewGroup drawableView =(ViewGroup)layouterInfalter.inflate(R.layout.keyguard_new_event_view, this,false); newEventView.setViewVisibility(View.VISIBLE); addView(drawableView); //15 MediatekGlowPadView.java 构造函数:MediatekGlowPadView(){ mInnerRadius = 15dip 内圈半径 mOuterRadius = 135dip外圈半径 mSnapMargin = 40dip mFirstItemOffset = 0 mVibrationDuration = 0 mFeedbackCount = mAllowScaling mHandleDrawable =中间拖拽的锁图 mOuterRing =外圈白色 mAlwaysTrackFinger mMagneticTargets mGlowRadius白点增长半径 // Read array of target drawables //下面这段,用于初始化解锁界面的圆环上有几种快捷解锁方式。mTargetDrawables if (a.getValue(R.styleable.GlowPadView_targetDrawables,outValue)) { //上面一行代码是,将targetDrawables属性值对应的drawble数组资源里的图片全部读入,默认是一张解锁的//图片,如果想改成有多种快捷解锁方式,可以改这个drawble数组即可。 internalSetTargetResources(outValue.resourceId);//计算每个targetDrawables的//元素的中心坐标以及与中心的相对坐标,用于在滑动解锁时判断是何快捷方式。 } if (mTargetDrawables ==null || mTargetDrawables.size() == 0) { throw new IllegalStateException("Must specify at least one target drawable"); } } //滑动解锁面板的onDraw()方法 @Override protected void onDraw(Canvas canvas) { mPointCloud.draw(canvas); mOuterRing.draw(canvas); final int ntargets =mTargetDrawables.size(); for (int i = 0; i < ntargets; i++) { TargetDrawable target =mTargetDrawables.get(i); if (target != null) { target.draw(canvas); } } mHandleDrawable.draw(canvas); if (mFakeHandleDrawable != null) { mFakeHandleDrawable.draw(canvas); updateHandleDrawablePositions(false); } } // onTouchEvent方法: handleDown(event);//置状态,背景动画,动画,未读事件动画,画云。 handleMove(event);//更改云的配置。在这个方法中,不断的根据当前的触点位置,计算该点到中心的距离,以及相对中心的角度,然后根据这距离与角度看是否与某个快捷图标角度匹配,并记住匹配项,赋值给mActiveTarget变量。 if (activeTarget!= -1) { switchToState(STATE_SNAP, x,y); updateGlowPosition(x, y); } else { switchToState(STATE_TRACKING, x, y); updateGlowPosition(x, y); } 上面代码:是如果匹配到就隐藏handledrawable(就是中间的手柄)并置状态为STATE_SNAP否则就状态为STATE_TRACKING。 updateTargetPosition()这个方法好像只是放中心坐标,位置坐标。 //下面分析dofinish()方法: boolean targetHit = activeTarget != -1;//这个变量表示是否有目标被匹配。 highlightSelected(activeTarget);//高亮被选中的,隐藏没有选中的。 hideGlow//动画隐藏什么。 dispatchTriggerEvent(activeTarget);//调用解锁方法。 _pin_view; //case SimPuk: return R.layout.keyguard_sim_puk_view; case SimPinPuk1: returncom.mediatek.internal.R.layout.keyguard_sim_pin_puk_view; case SimPinPuk2: returncom.mediatek.internal.R.layout.keyguard_sim_pin_puk_view; /// @} /// M: power-off alarm @{ case AlarmBoot: returncom.mediatek.internal.R.layout.power_off_alarm_view; /// @} ///M: add voice unlock view layout case Voice: return R.layout.zz_keyguard_voice_unlock_view; default: return 0; }