1.原生Keyguard简单探究:
IKeyguardStateCallback.java文件是out底下生成的。因为在framework底下有IKeyguardStateCallback.aidl文件。所有编译之后就会由编译系统生成。
stub内部类有onTransact接口,底下还有个Proxy接口
public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub
即KeyguardStateMonitor这个类继承了系统生成的IKeyguardStateCallback类的子类Stub,获得了onTransact接口。KeyguardStateMonitor
是用来响应别人的transact的,是一个服务端。
比如onShowingStateChanged方法。客户端通过调用之后,Proxy会调用mRemote.transact(Stub.TRANSACTION_onShowingStateChanged).然后stub类呢就进行相应onTransact,调用this.onShowingStateChanged(_arg0)。而这个stub是个抽象类
要去寻找他的实现类,调用才能完成。
而前面我们已经找过了KeyguardStateMonitor就是子类。那很明显了
××××××××××××××××××××××××××××
那服务端找到了,我们要去找到客户端啊。肯定是在keyguard里啊,服务端在framework里,keyguard在SystemUI底下。
先说说KeyguarService吧,他是一个Service,后台不断运行的。
从Binder角度来说,他是一个服务端:
private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub()
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(mContext,
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(
mShowListenerWhenConnect));
mShowListenerWhenConnect = null;
}
if (mKeyguardState.bootCompleted) {
mKeyguardService.onBootCompleted();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
mKeyguardService = null;
}
};
public void bindService(Context context) {
Intent intent = new Intent();
intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS);
//bindService的时候,传入的这个参数
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
mKeyguardState.showing = false;
mKeyguardState.showingAndNotOccluded = false;
mKeyguardState.secure = false;
mKeyguardState.deviceHasKeyguard = false;
hideScrim();
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
}
}
public class KeyguardServiceWrapper implements IKeyguardService这又算个啥?
客户端的代理?包装?,总之,它和KeyguardService关联上了。要是没理解错的话,
KeyguardServiceWrapper.mService就是KeyguardService了
客户端(framwork这边)通过KeyguardServiceWrapper调用KeyguardService
PhoneWindowManager.java中
isKeyguardShowingAndNotOccluded()
mKeyguardDelegate.isShowing()
KeyguardServiceWrapper->isShowing()
mKeyguardStateMonitor.isShowing()
看实现
KeyguardStateMonitor
public boolean isShowing() {
return mIsShowing;
}
找赋值:
KeyguardStateMonitor:
@Override // Binder interface
public void onShowingStateChanged(boolean showing) {
mIsShowing = showing;
}
也就是说只有onShowingStateChanged被调用了,取isShowing的时候才能取到
那么谁会调用onShowingStateChanged呢?
这时候我们先回去说下KeyguardStateMonitor,还记得它是IKeyguardStateCallback服务端
看看他的构造函数:
public KeyguardStateMonitor(Context context, IKeyguardService service) {
mLockPatternUtils = new LockPatternUtils(context);
mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
try {
service.addStateMonitorCallback(this);//注意这个函数
} catch (RemoteException e) {
Slog.w(TAG, "Remote Exception", e);
}
}
不用说,最终调用的就是keyguardService,参数callback就是KeyguardStateMonitor类
public void addStateMonitorCallback(IKeyguardStateCallback callback) {
checkPermission();
mKeyguardViewMediator.addStateMonitorCallback(callback);
}
package com.android.systemui.keyguard;
KeyguardViewMediator类里:
public void addStateMonitorCallback(IKeyguardStateCallback callback) {
synchronized (this) {
mKeyguardStateCallbacks.add(callback);//看看这个数组,有add,必有get
try {
callback.onSimSecureStateChanged(mUpdateMonitor.isSimPinSecure());
callback.onShowingStateChanged(mShowing);
///M: added for ALPS01933830
callback.onAntiTheftStateChanged(AntiTheftManager.isAntiTheftLocked()) ;
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged", e);
}
}
}
KeyguardViewMediator.java:
private void setShowingLocked(boolean showing) {
Log.d(TAG, "setShowingLocked() - showing = " + showing + ", mShowing = " + mShowing) ;
if (showing != mShowing) {
mShowing = showing;
Log.d(TAG, "setShowingLocked() - set mShowing = " + mShowing) ;
try {
int size = mKeyguardStateCallbacks.size();
for (int i = 0; i < size; i++) {
mKeyguardStateCallbacks.get(i).onShowingStateChanged(showing);//看着没?
}
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onShowingStateChanged", e);
}
updateInputRestrictedLocked();
mTrustManager.reportKeyguardShowingChanged();
}
}
我擦,终于明白了,也就是说KeyguardService调用setShowingLocked即可通知framework那边,我是isShowing否?
2.AIDL
自己实现的时候,aidl直接把SystemUI底下的aidl包括文件夹结构原封不动拷贝过来就行,因为最终的路径有区别,binder调用的时候根本找不到。binder调用的时候要求两端的类名包名完全一致,原因可以研究下out底下生成的对应java文件。
这边的aidl使用就是那种一个Service,客户端去binder…原生keyguard的研究,能学习到aidl,binder的使用。
3.如何屏蔽Home键的响应?
由于我们的硬件产品类似与小米那种,有实体按键,所以需要考虑这点。原生系统虚拟三键被keyguard完全遮盖了。
//frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
void launchHomeFromHotKey() {
if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
// don't launch home if keyguard showing
} else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
// before launching home
mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
public void onKeyguardExitResult(boolean success) {
if (success) {
try {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
}
}
});
} else {
// no keyguard stuff to worry about, just launch home!
try {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
}
}
只要是第一个if条件那块满足,PhoneWindowsManager会做处理的。好吧。这可能不是大家想要的答案。因为很多人的需求是作为一个锁屏应用。而不是像这样有很高权限的系统应用,framework代码随便改的应用场景。