Binder驱动之我见
一.介绍接种常见的跨进程通信机制
1. 共享内存(share memory)
2. socket
3. 命名管道(named pipe)
4. 消息队列(message queue)
5. binder
(查看这几种之间的特性与联系)
二.binder的特性
三.Binder的设计原理
四.Binder的设计实现
五.Binder的设计总结
以sensorservice服务为例来进行简要介绍。
首先介绍其大致流程:
将封闭的循环结构建立起来后,就开始服务的最核心的操作了,开始通过binder驱动与客户端进行交互了。
下面来分析binder驱动的服务与客户端实现原理
主要涉及的类:
1. refbase类
功能:引用计数,用于实现垃圾回收
2. Parcel 类
功能:定义了binder IPC通信传输数据的格式
3. IInterface 类
功能:为一个抽象类,用于服务继承,定义属于自己的属性接口
与之相关联的模版类:BnInterface,BpInterface用对应服务的接口来实例化
4. IBinder, BBinder,BpBinder,BpRefBase
功能:IBinder是模型的基类
BBinder代表服务的基类
BpBinder代表客户端的基类
BpRefBase记录对服务的引用(猜测是用于控制服务的生命周期)
5. ProcessState
功能:记录服务进程相关的信息
6. IPCThreadState:
功能:一个线程类,用于与设备文件进行信息交互
几种类之间的关系如下:
下面开始分析这几个类:
/*
**此类是所有服务都需要继承的接口基类。服务继承它实现数据自己的属性接口。
**提供了几个公共的接口。
**sp<IBinder> asBinder();
**sp<const IBinder> asBinder() const;
**这两个接口最终都是调用虚函数virtual IBinder* onAsBinder() = 0;
**此函数设置成虚函数,可供派生类来重新实现。
*/
class IInterface : public virtual RefBase
{
public:
IInterface();
sp<IBinder> asBinder();
sp<const IBinder> asBinder() const;
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
下面来看两个重要的模版类
// ----------------------------------
/*
**此模版类用于BINDER C/S模型的服务端的基类。
**此基类公有继承了INTERFACE类和BBinder类
**此处用来实例化的INTERFACE类都是服务对应的接口类
*/
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
/*
**此虚函数的模版类,用于返回此描述符对应的接口类的对象。
**此函数的实现形式是内联函数
*/
template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor) return this;
return NULL;
}
/*
**此虚函数的模版类是获取对应接口的描述符
**此函数的实现形式是内联函数
*/
template<typename INTERFACE>
inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const
{
return INTERFACE::getInterfaceDescriptor();
}
/*
**获取接口的对象
*/
template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
return this;
}
// ----------------------------------
/*
**此模版类用于BINDER C/S模型的客户端的基类。
**此基类公有继承了INTERFACE类和BpRefBase类
**此处用来实例化的INTERFACE类都是服务对应的接口类
**BpRefBase类用于统筹管理服务被引用的次数,控制服务的生命周期
*/
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
/*
**此内联接口函数就是调用基类BpRefBase的构造函数
*/
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
/*
**此内联函数返回一个Ibinder类型的类对象指针
*/
template<typename INTERFACE>
inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
return remote();
}
下面的两个宏是在定义服务接口的时候定义和实现的。是用于C/S模型中的客户端侧的。
所有的服务都要定义此类型的接口
/*
**1.定义描述符变量
**2.定义接口asInterface()
**3.实现虚函数getInterfaceDescriptor()
**4.定义对应的构造函数和析构函数
*/
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
/*
**上面宏定义接口的实现
*/
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
//初始化描述符变量
const android::String16 I##INTERFACE::descriptor(NAME); \
//获取此接口的描述符变量值
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
}
\
//返回当前接口描述符的对象
//1.首先查询本地接口的对象
//2.如果不是本地接口描述符,则创建对应的远程接口对象
android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
这个本质上就是一个类型转换
调用它的时候就是返回此Ibinder对象,至于NEW Bpxxx不会走!此流程一定成功
一般情况下都是获取服务之后调用的,所有的服务对应服务管理程序而言都是客户端.但是服务本身继承的是BnInterface类。故返回的是此类型。
//通过interface_cast模版函数进行类型转换:
如果是服务调用服务管理程序,返回的是指向服务的binder对象,故
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
直接转换成服务类型的对象返回。
否则则是一般的客户端调用服务的用法,则返回服务代理。
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj);
}
Java层与之相对应的是:举例实现:
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
综述来说下面的操作取决于存进来的Ibinder派生类继承的模版类是BnInterface还是BpInterface,也即此binder是远程代理对象,还是本地服务对象。
现在进入binder模型的几个核心的类
IBinder,BBinder,BpBinder
class IBinder : public virtual RefBase
{
public:
IBinder();
virtual const String16& getInterfaceDescriptor() const = 0;
virtual bool isBinderAlive() const = 0;
virtual status_t pingBinder() = 0;
virtual status_t dump(int fd, const Vector<String16>& args) = 0;
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) = 0;
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0) = 0;
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL) = 0;
virtual bool checkSubclass(const void* subclassID) const;
typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func) = 0;
virtual void* findObject(const void* objectID) const = 0;
virtual void detachObject(const void* objectID) = 0;
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
protected:
virtual ~IBinder();
private:
};
此类是一个抽象类,里面有大量的纯虚函数,其中有一下的函数只是一般的虚函数。
//构造函数不能实现能纯虚函数形式
IBinder::IBinder()
: RefBase()
{
}
IBinder::~IBinder()
{
}
// ---------------------------------------
//查询本地接口函数,这样的接口是本地服务端binder需要继承实现的
sp<IInterface> IBinder::queryLocalInterface(const String16& descriptor)
{
return NULL;
}
//此接口是本地服务端需要继承实现的
BBinder* IBinder::localBinder()
{
return NULL;
}
//此接口是远程服务代理端(即客户端)需要继承实现的
BpBinder* IBinder::remoteBinder()
{
return NULL;
}
//此类目前还不了解其用途,待日后分析
bool IBinder::checkSubclass(const void* /*subclassID*/) const
{
return false;
}
其他的纯虚函数都得在派生类中完全实现,否则不能实例化
class BBinder : public IBinder
{
public:
//类的构造函数
BBinder();
//获取接口描述符
virtual const String16& getInterfaceDescriptor() const;
//判断binder是否活着
virtual bool isBinderAlive() const;
//PING binder 具体作用目前还不清楚
virtual status_t pingBinder();
//用于输出dump LOG
virtual status_t dump(int fd, const Vector<String16>& args);
//此函数是扩进程传输的核心,用binder设备文件进行交互
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
//将此binder加入到死亡容器中(目前姑且这么理解,对其了解目前还不深入)
//当binder死掉的时候,调用DeathRecipient类的binderDied给远程代码对象发送//一个死亡消息通知,如果是本地服务对象对用此接口,则返回无效的操作
//当binder死亡的时候会调用死亡容器recipient中的binderDied函数
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
//卸载掉之前注册的死亡通知,这样当binder死掉的时候不会产生死亡通知
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL);
//此处是管理本服务对应的所有客户端对应的服务代理对象
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func);
//根据对象ID查询对应的远程服务代理对象
virtual void* findObject(const void* objectID) const;
virtual void detachObject(const void* objectID);
//返回此本地服务的对象指针
virtual BBinder* localBinder();
protected:
//类的析构函数
virtual ~BBinder();
//核心的数据传输函数
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
private:
//构造函数私有,其实用的就是单例模型
BBinder(const BBinder& o);
BBinder& operator=(const BBinder& o);
class Extras;
Extras* mExtras;
void* mReserved0;
};
/*通过此类来管理本地服务对应的所有远程代理服务对象
** class BBinder::Extras
**{
**public:
** Mutex mLock;
** BpBinder::ObjectManager mObjects;//此处就是对服务代理的管理
};
*/
下面进入BpBinder类
class BpBinder : public IBinder
{
public:
//构造函数
BpBinder(int32_t handle);
//获得类对象的进程句柄
inline int32_t handle() const { return mHandle; }
//获取接口描述符
virtual const String16& getInterfaceDescriptor() const;
//判断此时binder是否继续活着
virtual bool isBinderAlive() const;
//ping binder
virtual status_t pingBinder();
//输出dump log
virtual status_t dump(int fd, const Vector<String16>& args);
//核心的数据传输函数
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
//注册死亡通知接口
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
//注销死亡通知接口
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL);
//我目前的理解,所有的服务都是servicemanager的客户端,而这些服务又有自己的//客户端,故客户端和服务都有自己的关联OBJECT的管理。
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func);
//根据objectID查询OBJECT
virtual void* findObject(const void* objectID) const;
//取消绑定OBJECT
virtual void detachObject(const void* objectID);
//返回远程的代理对象指针
virtual BpBinder* remoteBinder();
//此函数应该是用来设置常量的,但是一直没有找到函数的实现
status_t setConstantData(const void* data, size_t size);
void sendObituary();
//此类事BBinder端管理远程代理类的类
class ObjectManager
{
public:
ObjectManager();
~ObjectManager();
//对象管理的附加函数
void attach( const void* objectID,
void* object,
void* cleanupCookie,
IBinder::object_cleanup_func func);
//对象管理的查询函数
void* find(const void* objectID) const;
//对象管理的分离函数
void detach(const void* objectID);
//分离所有的对象
void kill();
private:
ObjectManager(const ObjectManager&);
ObjectManager& operator=(const ObjectManager&);
//一个结构体,将一下三种属相集中管理
struct entry_t
{
void* object;
void* cleanupCookie;
IBinder::object_cleanup_func func;
};
//结构体entry类型的对象矢量容器
KeyedVector<const void*, entry_t> mObjects;
};
protected:
//析构函数
virtual ~BpBinder();
//对服务对象进行强引用(目前的理解)
virtual void onFirstRef();
//取消对服务对象的强引用
virtual void onLastStrongRef(const void* id);
//尝试对服务对象进行强引用
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
private:
const int32_t mHandle;
//此结构体集中管理死亡通知
struct Obituary {
wp<DeathRecipient> recipient;
void* cookie;
uint32_t flags;
};
//报告binder对象的死亡消息
void reportOneDeath(const Obituary& obit);
//判断描述符是否被储存起来
bool isDescriptorCached() const;
//互斥锁
mutable Mutex mLock;
volatile int32_t mAlive;
volatile int32_t mObitsSent;
Vector<Obituary>* mObituaries;
ObjectManager mObjects;
//此变量是一个常量数据,但是和函数一样,没有找到什么地方对其进行应用了
Parcel* mConstantData;
mutable String16 mDescriptorCache;
};
下面进入ProcessState类
class ProcessState : public virtual RefBase
{
public:
//静态的成员函数,所有的类对象共享同一个函数,这样做是为了实现单例模型
//类对象调用构造函数的方法,(C++类。如果没有显示可调用的构造函数,会调用一//个默认的构造函数,此构造函数不做任何事情,仅负责对象创建)
static sp<ProcessState> self();
//添加一个进程上下文的对象,类似于添加一个服务,(此函数针对服务管理服务)
void setContextObject(const sp<IBinder>& object);
//获取一个上下文对象,就是获取服务对象(此函数针对服务管理程序)
sp<IBinder> getContextObject(const sp<IBinder>& caller);
//此函数针对一般的服务管理程序,添加服务
void setContextObject(const sp<IBinder>& object,
const String16& name);
//获取服务,针对一般的服务程序
sp<IBinder> getContextObject(const String16& name,
const sp<IBinder>& caller);
//开启线程池
void startThreadPool();
//定义了一个指针函数
typedef bool (*context_check_func)(const String16& name,
const sp<IBinder>& caller,
void* userData);
//判断是否是服务的管理者
bool isContextManager(void) const;
//成为服务的管理者
bool becomeContextManager(
context_check_func checkFunc,
void* userData);
//获取代理的对象,根据handler,此代理对象与服务是强引用关系
sp<IBinder> getStrongProxyForHandle(int32_t handle);
//获取代理的对象,根据handler,此代理对象与服务是弱引用关系
wp<IBinder> getWeakProxyForHandle(int32_t handle);
//擦出此handler关联的binder对象
void expungeHandle(int32_t handle, IBinder* binder);
//设置进程的命令行参数
void setArgs(int argc, const char* const argv[]);
//获取命令行参数的个数
int getArgC() const;
//获取命令行参数
const char* const* getArgV() const;
//设置命令行的第一个参数,即程序运行的全路劲名
void setArgV0(const char* txt);
//创建一个新的线程池
void spawnPooledThread(bool isMain);
private:
friend class IPCThreadState;//友元类
//无参构造函数
ProcessState();
//析构函数
~ProcessState();
//有参构造函数
ProcessState(const ProcessState& o);
//操作符重载
ProcessState& operator=(const ProcessState& o);
//结构体统一管理对象的引用
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
//查找handler对应的对象,如果没有则创建一个新的对象
handle_entry* lookupHandleLocked(int32_t handle);
//binder设备文件的文件句柄
int mDriverFD;
//设备文件map进进程的虚拟地址的起始地址
void* mVMStart;
mutable Mutex mLock; // protects everything below.
Vector<handle_entry>mHandleToObject;
bool mManagesContexts;
context_check_func mBinderContextCheckFunc;
void* mBinderContextUserData;
KeyedVector<String16, sp<IBinder> >
mContexts;
String8 mRootDir;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
};
}; // namespace android
Binder模型有两套协议:
一个是command,另一个是reply协议。
enum BinderDriverReturnProtocol {
BR_ERROR = _IOR_BAD('r', 0, int),
BR_OK = _IO('r', 1),
BR_TRANSACTION = _IOR_BAD('r', 2, struct binder_transaction_data),
BR_REPLY = _IOR_BAD('r', 3, struct binder_transaction_data),
BR_ACQUIRE_RESULT = _IOR_BAD('r', 4, int),
BR_DEAD_REPLY = _IO('r', 5),
BR_TRANSACTION_COMPLETE = _IO('r', 6),
BR_INCREFS = _IOR_BAD('r', 7, struct binder_ptr_cookie),
BR_ACQUIRE = _IOR_BAD('r', 8, struct binder_ptr_cookie),
BR_RELEASE = _IOR_BAD('r', 9, struct binder_ptr_cookie),
BR_DECREFS = _IOR_BAD('r', 10, struct binder_ptr_cookie),
BR_ATTEMPT_ACQUIRE = _IOR_BAD('r', 11, struct binder_pri_ptr_cookie),
BR_NOOP = _IO('r', 12),
BR_SPAWN_LOOPER = _IO('r', 13),
BR_FINISHED = _IO('r', 14),
BR_DEAD_BINDER = _IOR_BAD('r', 15, void *),
BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR_BAD('r', 16, void *),
BR_FAILED_REPLY = _IO('r', 17),
};
enum BinderDriverCommandProtocol {
BC_TRANSACTION = _IOW_BAD('c', 0, struct binder_transaction_data),
BC_REPLY = _IOW_BAD('c', 1, struct binder_transaction_data),
BC_ACQUIRE_RESULT = _IOW_BAD('c', 2, int),
BC_FREE_BUFFER = _IOW_BAD('c', 3, int),
BC_INCREFS = _IOW_BAD('c', 4, int),
BC_ACQUIRE = _IOW_BAD('c', 5, int),
BC_RELEASE = _IOW_BAD('c', 6, int),
BC_DECREFS = _IOW_BAD('c', 7, int),
BC_INCREFS_DONE = _IOW_BAD('c', 8, struct binder_ptr_cookie),
BC_ACQUIRE_DONE = _IOW_BAD('c', 9, struct binder_ptr_cookie),
BC_ATTEMPT_ACQUIRE = _IOW_BAD('c', 10, struct binder_pri_desc),
BC_REGISTER_LOOPER = _IO('c', 11),
BC_ENTER_LOOPER = _IO('c', 12),
BC_EXIT_LOOPER = _IO('c', 13),
BC_REQUEST_DEATH_NOTIFICATION = _IOW_BAD('c', 14, struct binder_ptr_cookie),
BC_CLEAR_DEATH_NOTIFICATION = _IOW_BAD('c', 15, struct binder_ptr_cookie),
BC_DEAD_BINDER_DONE = _IOW_BAD('c', 16, void *),
};
下面进入IPCThreadState类进行浅析
/*
**此类事单例模型
**此类与binder设备驱动进行通信,轮询通信
*/
class IPCThreadState
{
public:
//单例模型,构造函数的对外接口
/*
**1.首先pthread_key_create(&gTLS, threadDestructor) != 0)创建并获取一个线程相关的**key
**2.然后判断IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);区域是否为NULL
**3.如果为NULL,则return new IPCThreadState;
**4.在此类的构造函数中调用pthread_setspecific(gTLS, this);将此类对象存放进线程的私**有数据区域
*/
static IPCThreadState* self();
//直接到线程的私有数据区域去驱动类对象的实例
static IPCThreadState* selfOrNull(); // self(), but won't instantiate
//获取此线程相关的进程实例对象
sp<ProcessState> process();
//清理最后产生的错误
status_t clearLastError();
//获取进程的PID
int getCallingPid();
//获取用户的UID
int getCallingUid();
//设置严格的线程方针模式
/*
**常见的strictMode为:
// Thread-policy:
public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy
public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy
public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy
public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy
// Process-policy://线程方针在此举例列举
static final int DETECT_VM_CURSOR_LEAKS = 0x200; // for VmPolicy
public static final int DETECT_VM_CLOSABLE_LEAKS = 0x400; // for VmPolicy
public static final int DETECT_VM_ACTIVITY_LEAKS = 0x800; // for VmPolicy
private static final int DETECT_VM_INSTANCE_LEAKS = 0x1000; // for VmPolicy
*/
void setStrictModePolicy(int32_t policy);
//获取线程policy mode
int32_t getStrictModePolicy() const;
//设置最后处理binder的状态
void setLastTransactionBinderFlags(int32_t flags);
//获取最后处理的binder的状态
int32_t getLastTransactionBinderFlags() const;
//清理调用的标识,也就是PID和UID
int64_t clearCallingIdentity();
//重新存储PID和UID
void restoreCallingIdentity(int64_t token);
//调用talkWithDriver(false)函数将READ和write存储命令的存储区域清理干净
void flushCommands();
//将此线程加入进程的线程池,开始与binder设备驱动进行交互
void joinThreadPool(bool isMain = true);
// Stop the local process.
void stopProcess(bool immediate = true);
//进程数据传输的函数
status_t transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
//增加对务对象进程强引用
void incStrongHandle(int32_t handle);
//取消对服务的强引用
void decStrongHandle(int32_t handle);
//增加对服务对象的弱引用
void incWeakHandle(int32_t handle);
//取消对服务进程进行强引用
void decWeakHandle(int32_t handle);
//尝试对服务进程进行强引用
status_t attemptIncStrongHandle(int32_t handle);
//调用进程相关函数,擦出此handle对应的binder对象
static void expungeHandle(int32_t handle, IBinder* binder);
//申请注册死亡消息通知
status_t requestDeathNotification( int32_t handle,
BpBinder* proxy);
//注销死亡消息通知
status_t clearDeathNotification( int32_t handle,
BpBinder* proxy);
//退出此线程,并清理此线程私有的数据
static void shutdown();
// Call this to disable switching threads to background scheduling when
// receiving incoming IPC calls. This is specifically here for the
// Android system process, since it expects to have background apps calling
// in to it but doesn't want to acquire locks in its services while in
// the background.
//disable后台进程的调度
static void disableBackgroundScheduling(bool disable);
private:
//构造函数
IPCThreadState();
//析构函数
~IPCThreadState();
//将请求的结果发送回去
status_t sendReply(const Parcel& reply, uint32_t flags);
//等待反馈
status_t waitForResponse(Parcel *reply,
status_t *acquireResult=NULL);
//与驱动进行交互
status_t talkWithDriver(bool doReceive=true);
//通过paracl类,初始化传输数据
status_t writeTransactionData(int32_t cmd,
uint32_t binderFlags,
int32_t handle,
uint32_t code,
const Parcel& data,
status_t* statusBuffer);
//根据命令执行相关操作
status_t executeCommand(int32_t command);
//重新获取PID和UID值
void clearCaller();
//线程的销毁函数,下命令到binder通知此线程退出
static void threadDestructor(void *st);
//通知binder进行相关的存储空间的释放
static void freeBuffer(Parcel* parcel,
const uint8_t* data, size_t dataSize,
const size_t* objects, size_t objectsSize,
void* cookie);
//标识此线程的类对象
const sp<ProcessState> mProcess;
const pid_t mMyThreadId;
Vector<BBinder*> mPendingStrongDerefs;
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
Parcel mIn;
Parcel mOut;
status_t mLastError;
pid_t mCallingPid;
uid_t mCallingUid;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
};
Input子系统内核
重要结构体解析:
struct input_dev {
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
unsigned int hint_events_per_packet;
//这个函数接口是用于计算每个数据包的大小。好准备好大小合适的数据包buffer.
unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;
int (*setkeycode)(struct input_dev *dev,
const struct input_keymap_entry *ke,
unsigned int *old_keycode);
int (*getkeycode)(struct input_dev *dev,
struct input_keymap_entry *ke);
struct ff_device *ff;
unsigned int repeat_key;
struct timer_list timer;
int rep[REP_CNT];
struct input_mt_slot *mt;
int mtsize;
int slot;
int trkid;
struct input_absinfo *absinfo;
unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
unsigned long sw[BITS_TO_LONGS(SW_CNT)];
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
struct input_handle __rcu *grab;
spinlock_t event_lock;
struct mutex mutex;
unsigned int users;
bool going_away;
bool sync;
struct device dev;
struct list_head h_list;
struct list_head node;
};
struct input_handler {
//存放的是此handler的私有变量
void *private;
//进行时间传递的函数接口,此时中断disable,获取dev->event_lock spinlock锁,因
此此时不进入睡眠
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
//对某些时间进行特殊处理
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
//device和handler的匹配函数
bool (*match)(struct input_handler *handler, struct input_dev *dev);
//device和handler匹配成功后的connect函数,在此产生对应的次设备号和注册handle
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
//取消device和handler的链接
void (*disconnect)(struct input_handle *handle);
//通过给定的handle来启用对用的handler
void (*start)(struct input_handle *handle);
const struct file_operations *fops;//此handler的文件操作接口
int minor;//handler的次设备号基地址
//handler的名字,通常显示在/proc/bus/input/handlers路径下
const char *name;
//指向此handler能够处理的属性
/*通常属性包含以下几种:
struct input_device_id {
kernel_ulong_t flags;
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
kernel_ulong_t driver_info;
};
*/
const struct input_device_id *id_table;
//这是handler自己的handle链表管理
struct list_head h_list;
//代表此handler挂在在input_handler_list链表上面
struct list_head node;
};
struct input_handle {
//handle的私有数据
void *private;
//标识此handle是否被打开
int open;
//handle的名字
const char *name;
//与handle相关连的device
struct input_dev *dev;
//与handle相关连的handler
struct input_handler *handler;
//将此handle挂载到device对应的管理handle的链表中
struct list_head d_node;
//将此handle挂载到handler对应的管理handle的链表中
struct list_head h_node;
};
Input子系统解析
属性文件和设备文件的创建。
相关的属性文件
首先类文件夹创建:
路劲:/sys/class/input/里面有所有的设备文件和所有的handle文件。
设备文件:就是调用input_register_device()函数注册的设备
这样的文件一般命名方式为:"input%ld"
最终调用device_add函数注册,并生成一些相关的属性文件
Handle文件:就是device与相对应的handler相匹配后,调用handler的connect函数,创建的文件
这样的文件一般命名方式为:以eventhandler为例:"event%d"对应的handler名称加ID
最终调用device_add函数注册,并生成一些相关的属性文件
NOTE:在创建一些对应的属性文件的同时,也会创建一系列的软link和硬link
调用input_proc_init()函数在proc文件系统中生成一些必备的文件
路劲:/proc/bus/input/
下面有devices和handlers两个文件
Devices文件记录所有的input设备
Handlers记录input中所有的handler
Input子系统与hander:
设备文件:分主设备号和此设备号:
路劲:
/sys/dev/char 主设备号为13
次设备号对应各个handerl的设备
一共有256个次设备号,设计上每个handler占用32个次设备号。故最多有8个handler,
1.由EventHub.h中的
// Epoll FD list size hint.
static const int EPOLL_SIZE_HINT = 8;
也可以推得此信息。
2.由input_register_handler()函数中input_table[handler->minor >> 5] = handler;
也可以推得此信息
3.由static struct input_handler *input_table[8];数组也可以推得此信息
常见的几种handler:
Joydev
#define JOYDEV_MINOR_BASE 0
#define JOYDEV_MINORS 16
Evdev
#define EVDEV_MINOR_BASE 64
#define EVDEV_MINORS 32
Mousedev
#define MOUSEDEV_MINOR_BASE 32
#define MOUSEDEV_MINORS 32
一般内核中形形色色的handler有很多,但是上层看到到一般最多只有八种,那么那些特征的handler上层可见呢?
Input子系统管理上层可见的handler是通过一个8个 handler容量的数组
static struct input_handler *input_table[8];此数组是全局变量
此时我们看看hander的注册函数,什么条件的handler才会存进此数组中。
int input_register_handler(struct input_handler *handler)
{
if (handler->fops != NULL) {
if (input_table[handler->minor >> 5]) {
retval = -EBUSY;
goto out;
}
input_table[handler->minor >> 5] = handler;
}
}
由此可知:只有满足带有文件操作接口的hander才会存进此全局数组中。
其他情况的handler只在内核里面进行链表似的管理。
Hander与devices:
在注册设备的时候会从链表中与handler进行匹配,匹配成功后会调用对应handler的connect函数。在此函数中产生对应段的次设备号。和注册一个关联devices和handler的handle.
通常情况下:每一个handler也有一个全局的数组用来存放此handler关联成功的devices
通常都是调用xxxdev_install_chrdev()函数
Evdev:static struct evdev *evdev_table[EVDEV_MINORS];
Mousedev:static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
Joydev:static struct joydev *joydev_table[JOYDEV_MINORS];
Handler特性:
每一个handler都对应着多个client。也就是说上层可以有多个实例同时关注此handler,此handler对应的设备有时间产生的时候,会通报相关的所有client.
Client通常都是通过链表来管理的,机制是RCU
Client都是在对应handler的open函数中调用对应的XXXdev_attach_client函数进行注册。
Handler结构体通常需要填充的属性:
以eventhandler为例:
static struct input_handler evdev_handler = {
.event = evdev_event,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};
几种术语:
Device:input设备
Handler:处理设备时间的handler
Handle:关联device和handler
下面从几个方面来了解input子系统。
注册流程
注销流程
消息上报流程
Handler和device匹配流程
生成handle流程
Device
device注册流程
/*
**1.device必须是函数input_allocate_device()申请的结构体
**2.device的capabilities必须在注册之前就设置好
**3.如果注册device失败必须调用函数input_free_device()释放之前申请的device
** 的空间
**4.如果注册成功,需要注销的时候必须调用函数input_unregister_device()
**5.
**
**
*/
int input_register_device(struct input_dev *dev)
{
//首先是填充input_dev结构体的相关属性
//所有的device都得支持EV_SYN事件
__set_bit(EV_SYN, dev->evbit);
//所有的device都不支持KEY_RESERVED事件
__clear_bit(KEY_RESERVED, dev->keybit);
//将不支持的事件占有位都清零
input_cleanse_bitmasks(dev);
//计算每个数据包的事件数目
if (!dev->hint_events_per_packet)
dev->hint_events_per_packet =
input_estimate_events_per_packet(dev);
//此处是处理重复按键的
//如果在驱动中设置了延迟事件和周期,在inputcore中就不进行处理了,由驱动//自己控制
init_timer(&dev->timer);
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.data = (long) dev;
dev->timer.function = input_repeat_key;//处理重复按键的函数,上报事件
dev->rep[REP_DELAY] = 250;
dev->rep[REP_PERIOD] = 33;
}
//填充设置和获取keycode的函数
if (!dev->getkeycode)
dev->getkeycode = input_default_getkeycode;
if (!dev->setkeycode)
dev->setkeycode = input_default_setkeycode;
//该函数对原子类型的变量V原子的增加1并且返回指向V的指针
//给device以input+number的方式进行命名
dev_set_name(&dev->dev, "input%ld",
(unsigned long)atomic_inc_return(&input_no) - 1);
//将此device添加进经典模型中,在sys文件系统下面生成对应的文件
error = device_add(&dev->dev);
if (error)
return error;
//将注册成功后产生的路劲获取打印出来
path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
pr_info("%s as %s\n",
dev->name ? dev->name : "Unspecified device",
path ? path : "N/A");
kfree(path);
//加锁互斥变量,但是可被中断打断(这是我个人的了解,不一定正确)
error = mutex_lock_interruptible(&input_mutex);
if (error) {
device_del(&dev->dev);
return error;
}
//将此device添加进input-core全局的dev链表中
list_add_tail(&dev->node, &input_dev_list);
//遍历handler链表,调用input_attach_handler函数与handler进行匹配
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);
//
//这个函数就是唤醒poll的等待队列,poll函数会返回return POLLIN | //POLLRDNORM;
//标识此设备有消息可读,这样就可以对此device进行读操作获取相关的信息了。
//此处就是一个poll模型的应用不多说,需要详细了解的关注下此模型
input_wakeup_procfs_readers();
//去锁互斥变量
mutex_unlock(&input_mutex);
Device注销流程
/*
**注销掉先前注册的设备
**
**
**
**
*/
void input_unregister_device(struct input_dev *dev)
{
//注销前的准备工作,详细信息见下面函数单独分析
input_disconnect_device(dev);
//互斥变量上锁
mutex_lock(&input_mutex);
//在注册的时候,会和handler匹配,如果匹配成功就会调用handler的connect
//函数,在这里与前面相对应的是,注销的时候就会调用相应的disconnect函//数
list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
handle->handler->disconnect(handle);
WARN_ON(!list_empty(&dev->h_list));
//将设备的timer删除
del_timer_sync(&dev->timer);
//将设备从全局设备链表中删除
list_del_init(&dev->node);
//此函数的功能已经在注册函数中描述清楚,这里就不再重复了
input_wakeup_procfs_readers();
//互斥变量解锁
mutex_unlock(&input_mutex);
//之前的注册的时候有调用device_add()函数,这里就调用对应的device注销//函数,具体细节不描述,如果有兴趣,可详细研究设备驱动模型
device_unregister(&dev->dev);
}
static void input_disconnect_device(struct input_dev *dev)
{
//添加此标识,标识设备已经离开
mutex_lock(&dev->mutex);
dev->going_away = true;
mutex_unlock(&dev->mutex);
//加锁
spin_lock_irq(&dev->event_lock);
//在将设备移除之前模拟一个keyup消息,防止出现某些那件一直处于按下状//态,
input_dev_release_keys(dev);
//遍历与device匹配成功的handler链表,将生成的handle,open属性置为0,
//标识此handle没有被引用,引用计数为0,device产生的事件不再传送到//handler中了,进行处理之后或许设备还有有事件产生,但是此时的事件已经//不传递到//handler中去了
list_for_each_entry(handle, &dev->h_list, d_node)
handle->open = 0;
//解锁
spin_unlock_irq(&dev->event_lock);
}
二.Handler
1.handler注册流程
/*
**1.注册一个新的handler,且与所有的devices进行适配
*/
int input_register_handler(struct input_handler *handler)
{
//加锁互斥变量,但是可被中断打断(这是我个人的了解,不一定正确)
retval = mutex_lock_interruptible(&input_mutex);
if (retval)
return retval;
//初始化handle链表,与此handler相关联的handle,都挂载在此链表上面
INIT_LIST_HEAD(&handler->h_list);
//前面已经提到过,handler分为带文件操作接口和不带文件操作接口,而且带文
//件操作接口的handler,最多只能有8个。
//input_table数组是全局的,大小为8,存放贷文件接口的handler.索引为次设备号//偏移5位,这里与每个带文件操作接口handler,最多关联32个设备相对应,对应//着32个次设备号
if (handler->fops != NULL) {
if (input_table[handler->minor >> 5]) {
retval = -EBUSY;
goto out;
}
input_table[handler->minor >> 5] = handler;
}
//将此handler挂载进全局的handler管理链表中去
list_add_tail(&handler->node, &input_handler_list);
//遍历device全局链表,调用input_attach_handler进行匹配
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);
//此函数在之前已经详细描述过,这里面不重复
input_wakeup_procfs_readers();
}
2.handler注销流程
/*
**1.将之前注册的handler进行撤销
*/
void input_unregister_handler(struct input_handler *handler)
{
//互斥变量加锁
mutex_lock(&input_mutex);
//在注册的时候会和所有的device进行适配,如果适配成功就会调用对应//handler的connect函数,这里面要调用对应的disconnect函数
list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
handler->disconnect(handle);
WARN_ON(!list_empty(&handler->h_list));
//将此handler从handler的全局链表中删除
list_del_init(&handler->node);
//前面注册的时候会填充input_table对应索引,此处应该将对应索引值赋为空
if (handler->fops != NULL)
input_table[handler->minor >> 5] = NULL;
//此函数不多解释,前面已经进行过详细的描述
input_wakeup_procfs_readers();
//互斥变量解锁
mutex_unlock(&input_mutex);
}
三.Handle
综述:handle的注册于注销都是在对应handler的connect和disconnect函数中进行
的
1.handle注册流程
/*
**注册一个handle进入对应handler和device链表中,用于关联二者
**所以只要handle的open属性不为0,对应设备产生的事件就会通过它被传送到**上层去,此函数被handler的connect函数调用
*/
int input_register_handle(struct input_handle *handle)
{
//首先提取出与此handle相关联的handler和device
struct input_handler *handler = handle->handler;
struct input_dev *dev = handle->dev;
//给互斥变量上锁(可被中断打断),主要为了防止input_release_device().在此期间//被调用
error = mutex_lock_interruptible(&dev->mutex);
//如果此handler带有filter功能则将handle加到设备链表头,否则加到设备链表//尾
if (handler->filter)
list_add_rcu(&handle->d_node, &dev->h_list);
else
list_add_tail_rcu(&handle->d_node, &dev->h_list);
//互斥变量解锁
mutex_unlock(&dev->mutex);
//由于此函数是被connect函数调用,与disconnect函数式互斥的,不可能同时调//用input_unregister_handle()函数,所以不需要独立的互斥变量
//将handle添加到handler链表的尾
list_add_tail_rcu(&handle->h_node, &handler->h_list);
//通过给定的handle,开始handler,(此处目前我也不怎么理解)
//此函数通常被调用刚好在connect函数之后,也可以在一个进程grabbed一个设备然后释放他的时候调用例如函数:__input_release_device
if (handler->start)
handler->start(handle);
}
2.handle注销流程
/*
**注销函数主要就是将handle的节点从handler和device的链表中删除
*/
void input_unregister_handle(struct input_handle *handle)
{
//将handle从handler的链表中删除
list_del_rcu(&handle->h_node);
/*
* Take dev->mutex to prevent race with input_release_device().
*/
mutex_lock(&dev->mutex);
//将handle从device的链表中删除
list_del_rcu(&handle->d_node);
mutex_unlock(&dev->mutex);
//同步RCU,RCU小解:
//RCU机制是Linux2.6之后提供的一种数据一致性访问的机制,从RCU//(read-copy-update)的名称上看,我们就能对他的实现机制有一个大//概的了解,在修改数据的时候,首先需要读取数据,然后生成一个副本,//对副本进行修改,修改完成之后再将老数据update成新的数据,此所
//谓RCU
synchronize_rcu();
}
Handler的connect和disconnect函数
这里面evdev这个handler进行举例分析
五:消息上报流程
首先从驱动中的上报消息函数开始开流程
input_report_key()àinput_event()àinput_handle_event()àdev->event()
【设备要监听消息】
input_pass_event()
【handler监听消息】
下面主要看handler的消息流程:
input_pass_event()àhandler->event()会调用相应handler的event函数
下面来显示看看这些函数流程
/*
**根据支持的事件传递事件类型,调用input-core的事件传递函数
*/
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
//事件类型是EV_KEY,,其他的类似
input_event(dev, EV_KEY, code, !!value);
}
/*
**首先判断此device是否支持此事件,然后调用对应的handle的event传递函数
*/
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
unsigned long flags;
if (is_event_supported(type, dev->evbit, EV_MAX)) {
//调用函数将事件锁锁住
spin_lock_irqsave(&dev->event_lock, flags);
//此处之前我也不明白啥意思,从网上查阅了下,有人说此处没啥用处,就是//为系统提供一个随机的熵值,因为按键消息是一个随机的事件
add_input_randomness(type, code, value);
//调用事件传递函数,继续input事件的传递
input_handle_event(dev, type, code, value);
//解锁事件锁
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
Note:
//每一个数据包的结束都会调用此函数进行同步标识
input_mt_sync()
//多点事件的结束时调用此函数进行标识同步(一整个事件中会有多个数据包)
input_sync()
/*
**1.根据事件类型进行判断事件disposition类型
** a. #define INPUT_IGNORE_EVENT 0
** b.#define INPUT_PASS_TO_HANDLERS 1
** c.#define INPUT_PASS_TO_DEVICE 2
**d.#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
**2.根据事件处置的三种类型分别:
** a.忽略事件
** b.将事件传递到device的event的处置函数中
** c.将事件传递到handler的event的处置函数中
*/
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
//标识以何种方式处理事件,默认处理方法是忽略
int disposition = INPUT_IGNORE_EVENT;
switch (type) {
case EV_SYN:
switch (code) {
case SYN_CONFIG:
//标识此种事件处置等级是TOALL
disposition = INPUT_PASS_TO_ALL;
break;
case SYN_REPORT:
if (!dev->sync) {
//此处将设备的事件同步信号设置成true,完整事件的同步
dev->sync = true;
//标识此事件的处置等级是只传递给handlers
disposition = INPUT_PASS_TO_HANDLERS;
}
break;
case SYN_MT_REPORT:
//此处将设备的事件同步信号设置成true,数据包的同步
dev->sync = false;
//标识此事件的处置等级是只传递给handlers
disposition = INPUT_PASS_TO_HANDLERS;
break;
}
break;
case EV_KEY:
//判断此设备是否支持此事件
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
!!test_bit(code, dev->key) != value) {//测试按键状态是否改变
if (value != 2) {
__change_bit(code, dev->key);//改变按键的状态
if (value)
//如果是重复按键,则自动调用重复按键的函数
input_start_autorepeat(dev, code);
else
//停止自动报重复按键消息
input_stop_autorepeat(dev);
}
disposition = INPUT_PASS_TO_HANDLERS;
}
break;
case EV_SW:
//与上面类似
if (is_event_supported(code, dev->swbit, SW_MAX) &&
!!test_bit(code, dev->sw) != value) {
__change_bit(code, dev->sw);
disposition = INPUT_PASS_TO_HANDLERS;
}
break;
case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX))
//其实就是根据此种事件的特性,判断处理方式
disposition = input_handle_abs_event(dev, code, &value);
break;
case EV_REL:
if (is_event_supported(code, dev->relbit, REL_MAX) && value)
disposition = INPUT_PASS_TO_HANDLERS;
break;
case EV_MSC:
if (is_event_supported(code, dev->mscbit, MSC_MAX))
disposition = INPUT_PASS_TO_ALL;
break;
case EV_LED:
if (is_event_supported(code, dev->ledbit, LED_MAX) &&
!!test_bit(code, dev->led) != value) {
__change_bit(code, dev->led);
disposition = INPUT_PASS_TO_ALL;
}
break;
case EV_SND:
if (is_event_supported(code, dev->sndbit, SND_MAX)) {
if (!!test_bit(code, dev->snd) != !!value)
__change_bit(code, dev->snd);
disposition = INPUT_PASS_TO_ALL;
}
break;
case EV_REP:
if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
dev->rep[code] = value;
disposition = INPUT_PASS_TO_ALL;
}
break;
case EV_FF:
if (value >= 0)
disposition = INPUT_PASS_TO_ALL;
break;
case EV_PWR:
disposition = INPUT_PASS_TO_ALL;
break;
}
//如果此事件处理类型为忽略,且不是EV_SYN同步事件,将同步信号设置成false
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
dev->sync = false;
//如果此device支持事件处理,而且事件处理方式为指向设备的
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
dev->event(dev, type, code, value);
//这是主流流程,事件处理方式是传向handler,则进入handler的事件流处理
if (disposition & INPUT_PASS_TO_HANDLERS)
input_pass_event(dev, type, code, value);
}
下面以EVDEVhandler为例子来讲解handler的消息传递流程
在注册此handler的时候,已经初始化了event事件处理函数
函数为evdev_event
/*
**
*/
static void evdev_event(struct input_handle *handle,
unsigned int type, unsigned int code, int value)
{
struct evdev *evdev = handle->private;
struct evdev_client *client;
struct input_event event;
struct timespec ts;
//首先获取事件的时间戳
ktime_get_ts(&ts);
//填充事件的属性参数
event.time.tv_sec = ts.tv_sec;
event.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
event.type = type;//事件类型
event.code = code;//事件码
event.value = value;//事件码
rcu_read_lock();//获取读RCU锁
//首先判断此handler是否被某个event_client给grab住
client = rcu_dereference(evdev->grab);
if (client)
evdev_pass_event(client, &event);//如果有,则将此事件只传给此client
else
//否则将此事件传递给所有相关联的client
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_event(client, &event);
rcu_read_unlock();//释放读RCU锁
//如果是同步事件,则唤醒等待队列
if (type == EV_SYN && code == SYN_REPORT)
wake_up_interruptible(&evdev->wait);
}
下面进入函数:
/*
**
*/
static void evdev_pass_event(struct evdev_client *client,
struct input_event *event)
{
/* Interrupts are disabled, just acquire the lock. */
//首先获取共享资源buffer的操作锁
spin_lock(&client->buffer_lock);
//将此事件,添加进buffer头
client->buffer[client->head++] = *event;
client->head &= client->bufsize - 1;
if (unlikely(client->head == client->tail)) {
/*
* This effectively "drops" all unconsumed events, leaving
* EV_SYN/SYN_DROPPED plus the newest event in the queue.
*/
client->tail = (client->head - 2) & (client->bufsize - 1);
client->buffer[client->tail].time = event->time;
client->buffer[client->tail].type = EV_SYN;
client->buffer[client->tail].code = SYN_DROPPED;
client->buffer[client->tail].value = 0;
client->packet_head = client->tail;
if (client->use_wake_lock)
wake_unlock(&client->wake_lock);
}
if (event->type == EV_SYN && event->code == SYN_REPORT) {
client->packet_head = client->head;
if (client->use_wake_lock)
wake_lock(&client->wake_lock);
kill_fasync(&client->fasync, SIGIO, POLL_IN);
}
spin_unlock(&client->buffer_lock);
}
//inputmanager系统
Inputmanager系统
综述:此模型大致关系
InputmanageràInputReaderInterface负责读取input子系统上报的事件
àInputDispatcherInterface负责将读取到的事件上报给上层
首先来看InputManager.cpp/.h
InputManager类有四个对外的公有成员函数
virtual status_t start();
virtual status_t stop();
virtual sp<InputReaderInterface> getReader();
virtual sp<InputDispatcherInterface> getDispatcher();
下面对这几个函数进行简单的解析
/*
**1.开启发送消息的线程
**2.开启获取消息的线程
*/
status_t InputManager::start() {
status_t result=mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
return OK;
}
/*
**1.停止获取消息的线程
**2.停止发送消息的线程
*/
status_t InputManager::stop() {
status_t result = mReaderThread->requestExitAndWait();
result = mDispatcherThread->requestExitAndWait();
return OK;
}
/*
**获取读消息的类实例
*/
sp<InputReaderInterface> InputManager::getReader() {
return mReader;
}
/*
**获取发送消息的类实例
*/
sp<InputDispatcherInterface> InputManager::getDispatcher() {
return mDispatcher;
}
下面进入类
InputReader
InputReaderThread
InputReaderThread类主要就是继承了系统thread的属性
/*
**类的构造函数,实例化继承的类thread和mread类
*/
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
Thread(/*canCallJava*/ true), mReader(reader) {
}
/*
**类的析构函数
*/
InputReaderThread::~InputReaderThread() {
}
/**
**线程循环的回调函数,mread类对事件的获取函数式looponce,是事件获取的主脉络
*/
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
下面进入到InputReader类中
主要来看对外的函数public函数:
/*
**构造函数
*/
InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener);
/*
**析构函数
*/
virtual ~InputReader();
/*
**打印dumplog
*/
virtual void dump(String8& dump);
/*
**监测函数,防止死锁
*/
virtual void monitor();
/*
**线程回调函数
*/
virtual void loopOnce();
/*
**获得输入设备的配置信息
*/
virtual void getInputConfiguration(InputConfiguration* outConfiguration);
/*
**获取输入设备的信息
*/
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
/*
**获取输入设备的ID
*/
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
/*
**获取扫描码
*/
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t scanCode);
/*
**获取key码
*/
virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t keyCode);
/*
**获取switch状态
*/
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
int32_t sw);
/*
**判断是否有KEY
*/
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
/*
**获取更新的配置
*/
virtual void requestRefreshConfiguration(uint32_t changes);
下面主要来看看线程的回调函数looponce
void InputReader::loopOnce() {
int32_t timeoutMillis;
{ // acquire lock
//加锁
AutoMutex _l(mLock);
//判断配置信息是否需要更新
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
refreshConfigurationLocked(changes);
}
timeoutMillis = -1;
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
//调用eventhub的getevent函数来获取事件
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
if (count) {
processEventsLocked(mEventBuffer, count);
}
if (!count || timeoutMillis == 0) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
#if DEBUG_RAW_EVENTS
LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
mNextTimeout = LLONG_MAX;
timeoutExpiredLocked(now);
}
} // release lock
// Flush queued events out to the listener.
// This must happen outside of the lock because the listener could potentially call
// back into the InputReader's methods, such as getScanCodeState, or become blocked
// on another thread similarly waiting to acquire the InputReader lock thereby
// resulting in a deadlock. This situation is actually quite plausible because the
// listener is actually the input dispatcher, which calls into the window manager,
// which occasionally calls into the input reader.
mQueuedListener->flush();
}
下面进入到eventhub类来进一步分析事件的获取流程
Eventhub.cpp
共管理了那些设备
管理了设备的那些状态
怎么管理的?怎么从底层获取数据?怎么上报给上层的!
所有的设备都是用一个devices结构体进行管理。
而这些所有的设备通过一个KeyedVector<int32_t, Device*> mDevices;模版类进行管理。其实就是一个适量的数据结构。
Device对应的数据结构为:
struct Device {
Device* next;//维护一个device的链表
int fd;//设备对应的文件句柄
const int32_t id;//设备对应的ID
const String8 path;//设备文件对应的路劲
const InputDeviceIdentifier identifier;//设备标识
uint32_t classes;//设备属于的类
//设备通常支持的几种事件
uint8_t keyBitmask[(KEY_MAX + 1) / 8];//key事件
uint8_t absBitmask[(ABS_MAX + 1) / 8];//绝对坐标事件
uint8_t relBitmask[(REL_MAX + 1) / 8];//相对坐标事件
uint8_t swBitmask[(SW_MAX + 1) / 8];//switch事件
uint8_t ledBitmask[(LED_MAX + 1) / 8];//led相关的事件
uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8];//设备的属性相关的事件
String8 configurationFile; //目前的理解是对应的配置文件
PropertyMap* configuration;
VirtualKeyMap* virtualKeyMap;//虚拟按键映射
KeyMap keyMap;//实体按键映射
Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);//设备的构造函数接口
~Device();//设备的析构函数的接口
void close();//设备的关闭函数接口
};
这个函数主要是通过ioctl函数接口与kernel的设备文件进行交互。
主要就是以上支持的几种事件,的一些属性状态的获取
主要的函数接口是getevent和openDeviceLocked两个函数,其他的函数主要就是对属性相关的进行设备和获取。
Open所有的设备。
Close所有的设备
GetEvent获取设备的事件
首先看openDeviceLocked函数,根据传进来的文件名称,通过ioct函数接口,获取次文件设备的一系列属性值。其实就是对device的结构体进行初始化。
在opendevice的时候通过epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)机制来监听对应设备文件的事件变化。
在closedevice的时候通过epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL))机制来删除之前建立的监听机制。
GetEvent函数中主要是通过epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);函数进行事件的监听。
InputReader.cpp解析
获取数据的方式:
通过一个线程InputReaderThread进行轮询,去调用EVENThub的getevent接口来获取事件。
Inputmanager.cpp
他是事件处理的核心,处于管理地位。
主要干两件事情:
开启mDispatcherThread线程进行数据发送。在队列上面等待事件的输入,并异步的将事件发送到对应的应用程序。
开启mReaderThread进行数据获取,负责数据原始数据进行处理最终发送到mDispatcherThread线程的队列上面去。
Note:两者间的通信时单方向的。不共享内部的状态
mReaderThreadàmDispatcherThread:通过InputDispatcherPolicyInterface类进行交互。
Note:inputmanager类从来都不和JAVA直接交互,与上层进行交互的是InputDispatcherPolicyInterface类,并且启用Dalvik虚拟机(DVM)。
首先看看eventHub对外的接口函数
class EventHubInterface : public virtual RefBase {
protected:
//构造函数
EventHubInterface() { }
//析构函数
virtual ~EventHubInterface() { }
public:
// Synthetic raw event type codes produced when devices are added or removed.
enum {
// Sent when a device is added.
DEVICE_ADDED = 0x10000000,
// Sent when a device is removed.
DEVICE_REMOVED = 0x20000000,
// Sent when all added/removed devices from the most recent scan have been reported.
// This event is always sent at least once.
FINISHED_DEVICE_SCAN = 0x30000000,
FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
};
/*
**获取设备的类
*/
virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
/*
**获取设备的名字
*/
virtual String8 getDeviceName(int32_t deviceId) const = 0;
/*
**获取设备的配置
*/
virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
/*
**获取设备绝对坐标信息
*/
virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
RawAbsoluteAxisInfo* outAxisInfo) const = 0;
/*
**获取设备的相对坐标信息
*/
virtual bool hasRelativeAxis(int32_t deviceId, int axis) const = 0;
/*
**判断是否具有输入性能
*/
virtual bool hasInputProperty(int32_t deviceId, int property) const = 0;
/*
**键值映射
*/
virtual status_t mapKey(int32_t deviceId, int scancode,
int32_t* outKeycode, uint32_t* outFlags) const = 0;
/*
**坐标轴映射
*/
virtual status_t mapAxis(int32_t deviceId, int scancode,
AxisInfo* outAxisInfo) const = 0;
// Sets devices that are excluded from opening.
// This can be used to ignore input devices for sensors.
virtual void setExcludedDevices(const Vector<String8>& devices) = 0;
/*
* Wait for events to become available and returns them.
* After returning, the EventHub holds onto a wake lock until the next call to getEvent.
* This ensures that the device will not go to sleep while the event is being processed.
* If the device needs to remain awake longer than that, then the caller is responsible
* for taking care of it (say, by poking the power manager user activity timer).
*
* The timeout is advisory only. If the device is asleep, it will not wake just to
* service the timeout.
*
* Returns the number of events obtained, or 0 if the timeout expired.
*/
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
/*
* Query current input state.
*/
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
int32_t* outValue) const = 0;
/*
* Examine key input devices for specific framework keycode support
*/
virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
uint8_t* outFlags) const = 0;
virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
virtual void getVirtualKeyDefinitions(int32_t deviceId,
Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
virtual String8 getKeyCharacterMapFile(int32_t deviceId) const = 0;
/* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
virtual void requestReopenDevices() = 0;
/* Wakes up getEvents() if it is blocked on a read. */
virtual void wake() = 0;
/* Dump EventHub state to a string. */
virtual void dump(String8& dump) = 0;
/* Called by the heatbeat to ensures that the reader has not deadlocked. */
virtual void monitor() = 0;
};
整体来看这个类,核心的接口就是:
Opendevices()
Getevent()
其他的接口都是一些辅助性质的接口
首先看看此类是怎么管理设备的。
//存储所有设备的适量数据结构
KeyedVector<int32_t, Device*> mDevices;
//记录所有打开的设备
Device *mOpeningDevices;
//记录所有关闭的设备
Device *mClosingDevices;
下面首先来看
/*
**1.扫描文件夹,打开对应文件夹下面所有的设备文件
*/
status_t EventHub::scanDirLocked(const char *dirname)
{
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
//打开对应的文件夹,获得文件夹的句柄
dir = opendir(dirname);
if(dir == NULL)
return -1;
strcpy(devname, dirname);
filename = devname + strlen(devname);
*filename++ = '/';
//遍历文件夹下面的设备文件,将合适的设备文件打开
while((de = readdir(dir))) {
if(de->d_name[0] == '.' &&
(de->d_name[1] == '\0' ||
(de->d_name[1] == '.' && de->d_name[2] == '\0')))
continue;
strcpy(filename, de->d_name);
openDeviceLocked(devname);
}
closedir(dir);
return 0;
}
/*
**主要是填充device的结构体
**1.填充InputDeviceIdentifier结构体
** String8 name;//设备名
** String8 location;
** String8 uniqueId;
** uint16_t bus;
** uint16_t vendor;
** uint16_t product;
** uint16_t version;
**2. 检查此设备是否在排除的列表中
**3.获取device driver的version
**4.获取设备标示符
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
**5. 设备此设备文件以非阻塞的方式进行轮询
**6.
**7.
**8.
**9.
**10.
**11.
**12.
*/
status_t EventHub::openDeviceLocked(const char *devicePath) {
char buffer[80];
const char *temp1 = "Button Jack";
//打开设备文件,获取文件句柄
int fd = open(devicePath, O_RDWR);
InputDeviceIdentifier identifier;
// Get device name.
//获取设备的名字
if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
//检查此设备是否在排除的列表中
// Check to see if the device is on our excluded list
for (size_t i = 0; i < mExcludedDevices.size(); i++) {
const String8& item = mExcludedDevices.itemAt(i);
if (identifier.name == item) {
LOGI("ignoring event id %s driver %s\n", devicePath, item.string());
close(fd);
return -1;
}
}
// Get device driver version.
//设备设备驱动的版本号
int driverVersion;
if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
// Get device identifier.
//获取设备标示符
struct input_id inputId;
if(ioctl(fd, EVIOCGID, &inputId)) {
identifier.bus = inputId.bustype;
identifier.product = inputId.product;
identifier.vendor = inputId.vendor;
identifier.version = inputId.version;
// Get device physical location.
//获取设备的物理位置
if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1)
// Get device unique id.
//获取设备独一无二的id
if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1)
//设备此设备文件以非阻塞的方式进行轮询
// Make file descriptor non-blocking for use with poll().
if (fcntl(fd, F_SETFL, O_NONBLOCK))
//将获取的设备信息进行整合new一个新的device结构体此时此设备获取FD的所有权
// Allocate device. (The device object takes ownership of the fd at this point.)
int32_t deviceId = mNextDeviceId++;
Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
// Load the configuration file for the device.
//下载设备的配置信息
loadConfigurationLocked(device);
// Figure out the kinds of events the device reports.
//算出此设备支持的事件类型
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
// See if this is a keyboard. Ignore everything in the button range except for
// joystick and gamepad buttons which are handled like keyboards for the most part.
//判断此设备社否为keyboard,忽略button范围的所有信息,除了joystick(操纵杆)和
bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))
|| containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
sizeof_bit_array(BTN_9))
|| containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
sizeof_bit_array(KEY_MAX + 1));
bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
sizeof_bit_array(BTN_MOUSE))
|| containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
sizeof_bit_array(BTN_DIGI));
if (haveKeyboardKeys || haveGamepadButtons) {
device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
}
// See if this is a cursor device such as a trackball or mouse.
if (test_bit(BTN_MOUSE, device->keyBitmask)
&& test_bit(REL_X, device->relBitmask)
&& test_bit(REL_Y, device->relBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_CURSOR;
}
// See if this is a touch pad.
// Is this a new modern multi-touch driver?
if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
&& test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
// Some joysticks such as the PS3 controller report axes that conflict
// with the ABS_MT range. Try to confirm that the device really is
// a touch screen.
if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
}
// Is this an old style single-touch driver?
} else if (test_bit(BTN_TOUCH, device->keyBitmask)
&& test_bit(ABS_X, device->absBitmask)
&& test_bit(ABS_Y, device->absBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH;
}
// See if this device is a joystick.
// Assumes that joysticks always have gamepad buttons in order to distinguish them
// from other devices such as accelerometers that also have absolute axes.
if (haveGamepadButtons) {
uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
for (int i = 0; i <= ABS_MAX; i++) {
if (test_bit(i, device->absBitmask)
&& (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
device->classes = assumedClasses;
break;
}
}
}
// Check whether this device has switches.
for (int i = 0; i <= SW_MAX; i++) {
if (test_bit(i, device->swBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_SWITCH;
break;
}
}
// Configure virtual keys.
if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
// Load the virtual keys for the touch screen, if any.
// We do this now so that we can make sure to load the keymap if necessary.
status_t status = loadVirtualKeyMapLocked(device);
if (!status) {
device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
}
}
// Load the key map.
// We need to do this for joysticks too because the key layout may specify axes.
status_t keyMapStatus = NAME_NOT_FOUND;
if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
// Load the keymap for the device.
keyMapStatus = loadKeyMapLocked(device);
}
// Configure the keyboard, gamepad or virtual keyboard.
if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
// Register the keyboard as a built-in keyboard if it is eligible.
if (!keyMapStatus
&& mBuiltInKeyboardId == -1
&& isEligibleBuiltInKeyboard(device->identifier,
device->configuration, &device->keyMap)) {
mBuiltInKeyboardId = device->id;
}
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
if (hasKeycodeLocked(device, AKEYCODE_Q)) {
device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
}
// See if this device has a DPAD.
if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
device->classes |= INPUT_DEVICE_CLASS_DPAD;
}
// See if this device has a gamepad.
for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
break;
}
}
}
// If the device isn't recognized as something we handle, don't monitor it.
if (device->classes == 0) {
LOGV("Dropping device: id=%d, path='%s', name='%s'",
deviceId, devicePath, device->identifier.name.string());
delete device;
return -1;
}
// Determine whether the device is external or internal.
if (isExternalDeviceLocked(device)) {
device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
}
// Register with epoll.
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN;
eventItem.data.u32 = deviceId;
if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
LOGE("Could not add device fd to epoll instance. errno=%d", errno);
delete device;
return -1;
}
LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
deviceId, fd, devicePath, device->identifier.name.string(),
device->classes,
device->configurationFile.string(),
device->keyMap.keyLayoutFile.string(),
device->keyMap.keyCharacterMapFile.string(),
toString(mBuiltInKeyboardId == deviceId));
mDevices.add(deviceId, device);
device->next = mOpeningDevices;
mOpeningDevices = device;
return 0;
}
做Android的同学说起Activity,那绝对是熟悉的不能再熟悉了,但是越熟悉的东西往往越陌生。我们真的了解她吗?她是我们所认识的那样吗?或许是,或许不是!了解与否,让我们往下看。首先借Android官网的这张图来展现Activity的生命周期,这张金字塔图比起那张所有书上都有的生命周期流程图绝对要来的爽快:
从上图可以看到,最右边下方的Android机器人代表启动一个Activity,经过一系列的操作和过程,经过三个生命周期回调方法,到达金字塔的顶层,爬到顶层就可以供用户操作了。然后从金字塔顶往下,再经过三个生命周期方法,就又到了金字塔的另一边底层,Activity就销毁了。但是当下金字塔的时候,只要没到最下面,都有通道可以回到最顶层。这有几点或许是平时我们没有注意的:
1.Activity在onStart方法调用后,就处于可见状态了(visible)
2.当经过onPause方法后处于暂停状态(Paused),这时Activity处于半透明状态,为不可操作的,比如弹出一个模态框。这时Activity不会执行任何代码
3.Activity在调用onStop方法后即处于用户不可见的状态了(invisible)
4.onCreate方法在整个生命周期只会被调用一次
5.自定义Activity继承Activity类后有没有需要必须实现的方法?答案是没有,但是要想启动和显示一个Activity,就必须实现onCreate方法并指定布局文件
6.大部分的清理操作应该在onPause和onStop中执行,如果在onCreate中开启了耗时线程或耗资源的线程操纵,应该在onDestroy中杀死线程
官方文档中有这么一段注释值得我们注意:
Note: The
system calls onDestroy() after
it has already called onPause() and onStop() in
all situations except one: when you call finish() from
within the onCreate() method.
In some cases, such as when your activity operates as a temporary decision maker to launch another activity, you might call finish()from
within onCreate() to
destroy the activity. In this case, the system immediately calls onDestroy()without
calling any of the other lifecycle methods.
系统一般都是在执行完onPause和onStop方法后再执行onDestroy方法,但是当在onCreate方法中调用了Activity的finish()方法后,比如在onCreate方法里启动新的Activity并调用了finish方法,这时系统会直接调用onDestroy方法!
以上就是关于Activity一些你可能不知道或是忽视的,欢迎大家补充交流!
加入我们的QQ群或微信公众账号请查看:Ryan's
zone公众账号及QQ群