从 锁屏服务AIDL线程通信案例看Android 底层启动
请确保 你已经阅读过 我的
7篇文章,并且初步理解其核心内容
此处,我们从SystemSever的启动开始说起
目录/android/4.4/frameworks/base/services/java/com/android/server/SystemServer.java
开始继续说起
wm = WindowManagerService.main(context, power, display, inputManager,
wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
<pre>try {
wm.systemReady();
} catch (Throwable e) {
reportWtf("making Window Manager Service ready", e);
}
在这里我们初始化了 WindowManagerService
目录(Android4.4/frameworks/base/services/java/com/android/server/wm/WindowManagerService.java)
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs,
DisplayManagerService.WindowManagerFuncs, DisplayManager.DisplayListener {
......
final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
......
public static WindowManagerService main(final Context context,
final PowerManagerService pm, final DisplayManagerService dm,
final InputManagerService im, final Handler wmHandler,
final boolean haveInputMethods, final boolean showBootMsgs,
final boolean onlyCore) {
final WindowManagerService[] holder = new WindowManagerService[1];
wmHandler.runWithScissors(new Runnable() {
@Override
public void run() {
holder[0] = new WindowManagerService(context, pm, dm, im,
haveInputMethods, showBootMsgs, onlyCore);
}
}, 0);
return holder[0];
}
.......
private WindowManagerService(Context context, PowerManagerService pm,
DisplayManagerService displayManager, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
}
}
这里,我们清楚的看到WindowManagerService也是用AIDL来实现,但是我们这里先不管它
我们先关心
final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
public void systemReady() {
mPolicy.systemReady();
}
如果说你还不理解我们的mPolicy 是什么,你可以在返回去看看
这里,我不做出过多解释。
我们只需要知道mPolicy 最终指向了我们PhoneWindowManager
目录(Android4.4/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java)
public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void systemReady() {
if (!mHeadless) {
mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null);
mKeyguardDelegate.onSystemReady();
}
synchronized (mLock) {
updateOrientationListenerLp();
mSystemReady = true;
mHandler.post(new Runnable() {
@Override
public void run() {
updateSettings();
}
});
}
}
}
启动到了这一步,不用我说,大家都明白是时候初始化
KeyguardServiceDelegate并且告诉锁屏的管理者,我准备好了,该你来控制加载锁屏界面了。接着调用到了KeyguardServiceDelegate.java这个类的onSystemReady()方法
/**
* A local class that keeps a cache of keyguard state that can be restored in the event
* keyguard crashes. It currently also allows runtime-selectable
* local or remote instances of keyguard.
*/
public class KeyguardServiceDelegate {
public KeyguardServiceDelegate(Context context, LockPatternUtils lockPatternUtils) {
Intent intent = new Intent();
intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS);
mScrim = createScrim(context);
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
} 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;
}
};
public void onSystemReady() {
if (mKeyguardService != null) {
mKeyguardService.onSystemReady();
} else {
if (DEBUG) Log.v(TAG, "onSystemReady() called before keyguard service was ready");
mKeyguardState.systemIsReady = true;
}
}
public void onSystemReady() {
if (mKeyguardService != null) {
mKeyguardService.onSystemReady();
} else {
if (DEBUG) Log.v(TAG, "onSystemReady() called before keyguard service was ready");
mKeyguardState.systemIsReady = true;
}
}
}
到了这里我们基本一目了然我们的 KeyguardViewMediator充当了Android AIDL理解中主程的角色
同样 毫无疑问,我们的注意力再次集中到
mKeyguardService = new KeyguardServiceWrapper(
IKeyguardService.Stub.asInterface(service));
在Android4.4/frameworks/base/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java中
public class KeyguardServiceWrapper implements IKeyguardService {
public KeyguardServiceWrapper(IKeyguardService service) {
mService = service;
}
}
这样一来,我们的实现自然就转移到了
Android4.4/frameworks\base\packages\Keyguard\src\com\android\keyguard/KeyguardService.java 中
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
private KeyguardViewMediator mKeyguardViewMediator;
@Override
public void onCreate() {
if (mKeyguardViewMediator == null) {
mKeyguardViewMediator = new KeyguardViewMediator(
KeyguardService.this, new LockPatternUtils(KeyguardService.this));
}
Log.v(TAG, "onCreate()");
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
// TODO
}
void checkPermission() {
if (getBaseContext().checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
Log.w(TAG, "Caller needs permission '" + PERMISSION + "' to call " + Debug.getCaller());
throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
+ ", must have permission " + PERMISSION);
}
}
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();
}
};
}
那么再来看一下我们的
Android4.4/frameworks\base\core\java\com\android\internal\policy/IKeyguardService.aidl
interface IKeyguardService {
boolean isShowing();
boolean isSecure();
boolean isShowingAndNotHidden();
boolean isInputRestricted();
boolean isDismissable();
oneway void verifyUnlock(IKeyguardExitCallback callback);
oneway void keyguardDone(boolean authenticated, boolean wakeup);
oneway void setHidden(boolean isHidden);
oneway void dismiss();
oneway void onDreamingStarted();
oneway void onDreamingStopped();
oneway void onScreenTurnedOff(int reason);
void onScreenTurnedOn(IKeyguardShowCallback callback);
oneway void setKeyguardEnabled(boolean enabled);
oneway void onSystemReady();
oneway void doKeyguardTimeout(in Bundle options);
oneway void setCurrentUser(int userId);
oneway void showAssistant();
oneway void dispatch(in MotionEvent event);
oneway void launchCamera();
oneway void onBootCompleted();
}
那么我们的AIDL框架自然就自动布好
也就是说最终的时间处理交给了我们的
Android4.4/frameworks\base\packages\Keyguard\src\com\android\keyguard/KeyguardViewMediator.java
/**
* 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()
|| mLockPatternUtils.usingVoiceWeak()
&& FeatureOption.MTK_VOICE_UNLOCK_SUPPORT) {
if (DEBUG) Log.d(TAG, "suppressing biometric unlock during boot");
mUpdateMonitor.setAlternateUnlockEnabled(false);
} else {
mUpdateMonitor.setAlternateUnlockEnabled(true);
}
/// M: power-off alarm @{
if (!KeyguardUpdateMonitor.isAlarmBoot()) {
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()这个方法来做启动锁屏界面的预处理,来看看这个方法都做了什么:
- private void doKeyguardLocked() {
- doKeyguardLocked(null);
- }
- /**
- * Enable the keyguard if the settings are appropriate.
- */
- private void doKeyguardLocked(Bundle options) {
- // if another app is disabling us, don't show
- if (!mExternallyEnabled || KeyguardUpdateMonitor.isAlarmBoot()) {
- if (DEBUG) KeyguardUtils.xlogD(TAG, "doKeyguard: not showing because externally disabled");
- // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
- // for an occasional ugly flicker in this situation:
- // 1) receive a call with the screen on (no keyguard) or make a call
- // 2) screen times out
- // 3) user hits key to turn screen back on
- // instead, we reenable the keyguard when we know the screen is off and the call
- // ends (see the broadcast receiver below)
- // TODO: clean this up when we have better support at the window manager level
- // for apps that wish to be on top of the keyguard
- return;
- }
- // if the keyguard is already showing, don't bother
- if (mKeyguardViewManager.isShowing()) {
- if (DEBUG) KeyguardUtils.xlogD(TAG, "doKeyguard: not showing because it is already showing");
- return;
- }
- // if the setup wizard hasn't run yet, don't show
- if (DEBUG) KeyguardUtils.xlogD(TAG, "doKeyguard: get keyguard.no_require_sim property before");
- final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
- false);
- if (DEBUG) KeyguardUtils.xlogD(TAG, "doKeyguard: get keyguard.no_require_sim property after");
- final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
- final IccCardConstants.State state = mUpdateMonitor.getSimState();
- boolean lockedOrMissing = false;
- /// M: Support GeminiPlus
- for (int i = PhoneConstants.GEMINI_SIM_1; i <= KeyguardUtils.getMaxSimId(); i++) {
- lockedOrMissing = (lockedOrMissing || isLockedOrMissingGemini(i, requireSim));
- if (lockedOrMissing) {
- break;
- }
- }
- if (DEBUG) KeyguardUtils.xlogD(TAG, "doKeyguard: get sim state after");
- /// M: MTK MOTA UPDATE when on ics2 keygaurd set none,update to JB,the keyguard will show LockScreen.
- /// MTK MOTA UPDATE when the phone first boot,check the settingDB mirged or not ,because mota update,
- /// the settingdb migrate slow than keygaurd(timing sequence problem) @{
- boolean keyguardDisable = false;