Android 自己实现Keyguard的一些问题

来源:互联网 发布:单片机8个流水灯程序 编辑:程序博客网 时间:2024/05/22 08:03

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()

看实现

KeyguardStateMonitorpublic 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.javavoid 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代码随便改的应用场景。

0 0
原创粉丝点击