PS:源码目录以Frameworks为基准 , 源码android4.2。
首先我们定位到Android虚拟机启动之后java层的第一个类:./base/services/java/com/android/server/SystemServer.java
在main中通过JNI调用./base/cmds/system_server/System_main.cpp,代码如下:
System.loadLibrary("android_servers");
init1(args);
./base/cmds/System_main.cpp的main中 system_init(); 又跳转至./base/cmds/system_server/library/System_init.cpp中,在system_init中有如下代码:
JNIEnv* env = runtime->getJNIEnv();
if (env == NULL) {
return UNKNOWN_ERROR;
}
jclass clazz = env->FindClass("com/android/server/SystemServer");
if (clazz == NULL) {
return UNKNOWN_ERROR;
}
jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
if (methodId == NULL) {
return UNKNOWN_ERROR;
}
env->CallStaticVoidMethod(clazz, methodId);
由上可知:我们又回到了./base/services/java/com/android/server/SystemServer.java中。在init2中启动所有相关的东东。代码:
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
PS:其中ServerThread类也在SystemServer.java中。
我们继续跟踪ServerThread.run() 方法,在run方法中主要是启动一系列的服务,根据主题的需要我们定位到
wm = WindowManagerService.main(context, power, display, inputManager,
uiHandler, wmHandler,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
而在./base/services/java/com/android/server/wm/WindowManagerService.java 的main 中调用了WindowManagerService构造方法,构造方法中又在initPolicy中调用了(./base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java)mPolicy.init(),该方法对PhoneWindowManager里面的重要变量,进行初始化。
/** {@inheritDoc} */
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs;
mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
if (!mHeadless) {
// don't create KeyguardViewMediator if headless
mKeyguardMediator = new KeyguardViewMediator(context, null);
}
mHandler = new PolicyHandler();
mOrientationListener = new MyOrientationListener(mContext);
try {
mOrientationListener.setCurrentRotation(windowManager.getRotation());
} catch (RemoteException ex) { }
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
mShortcutManager = new ShortcutManager(context, mHandler);
mShortcutManager.observe();
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"PhoneWindowManager.mBroadcastWakeLock");
mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
mLidOpenRotation = readRotation(
com.android.internal.R.integer.config_lidOpenRotation);
mCarDockRotation = readRotation(
com.android.internal.R.integer.config_carDockRotation);
mDeskDockRotation = readRotation(
com.android.internal.R.integer.config_deskDockRotation);
mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_carDockEnablesAccelerometer);
mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
mLidKeyboardAccessibility = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lidKeyboardAccessibility);
mLidNavigationAccessibility = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lidNavigationAccessibility);
mLidControlsSleep = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_lidControlsSleep);
// register for dock events
IntentFilter filter = new IntentFilter();
filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
filter.addAction(Intent.ACTION_DOCK_EVENT);
Intent intent = context.registerReceiver(mDockReceiver, filter);
if (intent != null) {
// Retrieve current sticky dock event broadcast.
mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
// register for dream-related broadcasts
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DREAMING_STARTED);
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
context.registerReceiver(mDreamReceiver, filter);
// register for multiuser-relevant broadcasts
filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
context.registerReceiver(mMultiuserReceiver, filter);
mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
mLongPressVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_longPressVibePattern);
mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_virtualKeyVibePattern);
mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_keyboardTapVibePattern);
mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_safeModeDisabledVibePattern);
mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_safeModeEnabledVibePattern);
mScreenshotChordEnabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableScreenshotChord);
// Controls rotation and the like.
initializeHdmiState();
// Match current screen state.
if (mPowerManager.isScreenOn()) {
screenTurningOn(null);
} else {
screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
}
}
我们回到ServerThread.run中,继续查看wm:
try {
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
}
public void systemReady() {
mPolicy.systemReady();
}
在./base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java中的systemReady有:
/** {@inheritDoc} */
public void systemReady() {
if (mKeyguardMediator != null) {
// tell the keyguard
mKeyguardMediator.onSystemReady();
}
synchronized (mLock) {
updateOrientationListenerLp();
mSystemReady = true;
mHandler.post(new Runnable() {
public void run() {
updateSettings();
}
});
}
}
而在mKeyguardMediator.onSystemReady();--------------------------./base/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java ,有:
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();
}
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
maybeSendUserPresentBroadcast();
}
而 doKeyguardLocked(); 中就是调用锁屏相关: 其中有
mSuppressNextLockSound = true;
doKeyguardLocked(); 即进行正式锁屏
KeyguardViewMediator实现这部分调度是通过持有一个KeyguardViewManager来实现的。总之KeyguardUpdateMonitor是所有会影响整个待机解/锁屏业务的事件的监控器。(除了作为监控器,它还发挥着类似上下文的作用,也许我们应该把这个类命名为(KeyguardContext)。它监控诸如时间改变、电池状态改变、时区改变、SIM卡状态变化、电话状态变化、电话信号变化等事件。它是一个观察者模式的被观察对象。观察者通过调用KeyguardUpdateMonitor的以下方法进行注册,观察自己感兴趣的变化。
KeyguardUpdateMonitor的观察者包括KeyguardViewMediator、LockScreen、PatternUnlockScreen、AccountUnlockScreen、PasswordUnlockScreen、SimUnlockScreen等。观察者通过调用KeyguardUpdateMonitor的removeCallback(Object)取消观察。
KeyguardViewManager负责管理待机屏UI界面的创建、显示、隐藏、重置以及通过一个回调KeyguardViewCallback通知调度器KeyguardViewMediator进行相关的调度。
LockPatternKeyguardView(KeyguardViewBase)是所有锁屏和解锁UI界面的宿主。它有2个模式Mode. LockScreen和Mode. UnlockScreen。它负责根据当前上下文环境切换当前应该显示的待机屏。
它提供一个回调给当前显示的待机屏并处理其回调,如果回调动作是自己处理不了的,则继续报告给KeyguardViewMediator进行处理。
锁屏界面就是LockScreen;解锁界面包括SIM卡解锁SimUnlockScreen、图案解锁PatternUnlockScreen、密码解锁PasswordUnlockScreen、帐号解锁AccountUnlockScreen
解锁成功后,锁屏流程转到KeyguardViewMediator的keyguardDone(boolean, boolean) 进行后续的流程(如转到Launcher桌面)。
在锁屏宿主LockPatternKeyguardView中有updateScreen(Mode mode, boolean force) ,他根据锁屏模式进行相关的屏幕重建,在此过程一般调用recreateLockScreen()或者是recreateUnlockScreen(UnlockMode unlockMode)方法,在recreateLockScreen()会跳转至LockScreen构造函数;而recreateUnlockScreen(UnlockMode unlockMode)方法会根据unlockMode的具体值:
enum UnlockMode {
/**
* Unlock by drawing a pattern.
*/
Pattern,
/**
* Unlock by entering a sim pin.
*/
SimPin,
/**
* Unlock by entering a sim puk.
*/
SimPuk,
/**
* Unlock by entering an account's login and password.
*/
Account,
/**
* Unlock by entering a password or PIN
*/
Password,
/**
* Unknown (uninitialized) value
*/
Unknown
}
进入到相关的锁屏类中,包括:PatternUnlockScreen , SimPukUnlockScreen ,SimUnlockScreen , AccountUnlockScreen , PasswordUnlockScreen 。然后就是在相关的类的构造函数中加载相关的布局文件。
下面以PasswordUnlockScreen为例进行跟踪:
在其构造函数中有:
if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
Log.d(TAG, "portrait mode");
inflater.inflate(R.layout.keyguard_screen_unlock_portrait, this, true);
} else {
Log.d(TAG, "landscape mode");
inflater.inflate(R.layout.keyguard_screen_unlock_landscape, this, true);
}
通过查找我们找到相关布局文件,如图:
而我现在所定制的平板为800*480,所以我以 ../base/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml 为例:布局如下:
基本上锁屏界面出现的先关视图都在里面有所体现。下面查看上图中所引用的 com.android.internal.widget中的LockPatternView类,在它的构造函数中有如下相关设置:
mPathPaint.setAntiAlias(true);
mPathPaint.setDither(true);
mPathPaint.setColor(Color.WHITE); // TODO this should be from the style
mPathPaint.setAlpha(mStrokeAlpha);
mPathPaint.setStyle(Paint.Style.STROKE);
mPathPaint.setStrokeJoin(Paint.Join.ROUND);
mPathPaint.setStrokeCap(Paint.Cap.ROUND);
// lot's of bitmaps!
mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default_holo);
mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched_holo);
mBitmapCircleDefault = getBitmapFor(R.drawable.indicator_code_lock_point_area_default_holo);
mBitmapCircleGreen = getBitmapFor(R.drawable.indicator_code_lock_point_area_green_holo);
mBitmapCircleRed = getBitmapFor(R.drawable.indicator_code_lock_point_area_red_holo);
mBitmapArrowGreenUp = getBitmapFor(R.drawable.indicator_code_lock_drag_direction_green_up);
mBitmapArrowRedUp = getBitmapFor(R.drawable.indicator_code_lock_drag_direction_red_up);
// bitmaps have the size of the largest bitmap in this group
final Bitmap bitmaps[] = { mBitmapBtnDefault, mBitmapBtnTouched, mBitmapCircleDefault,
mBitmapCircleGreen, mBitmapCircleRed };
通过查找匹配,我们可以印证是否相关的位图是在锁屏界面中出现的:
....................................................................................................................................待