首页 文章 精选 留言 我的

精选列表

搜索[键盘快捷键],共4776篇文章
优秀的个人博客,低调大师

Android应用程序键盘(Keyboard)消息处理机制分析(25)

Step 2. ActivityStack.activityIdleInternal 这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中: publicclassActivityStack{ ...... finalvoidactivityIdleInternal(IBindertoken,booleanfromTimeout, Configurationconfig){ ...... ArrayList<ActivityRecord>stops=null; ...... intNS=0; ...... synchronized(mService){ ...... //Atomicallyretrievealloftheotherthingstodo. stops=processStoppingActivitiesLocked(true); NS=stops!=null?stops.size():0; ...... } inti; ...... //Stopanyactivitiesthatarescheduledtodosobuthavebeen //waitingforthenextonetostart. for(i=0;i<NS;i++){ ActivityRecordr=(ActivityRecord)stops.get(i); synchronized(mService){ if(r.finishing){ finishCurrentActivityLocked(r,FINISH_IMMEDIATELY); }else{ ...... } } } ...... } ...... } 这个函数首先会调用processStoppingActivitiesLocked函数把所有处于Stopped状态的Activity取回来,然后逐个分析它们,如果它们的ActivityRecord中的finishing成员变量为true,就说明这个Activity需要销毁了,于是,就调用finishCurrentActivityLocked函数来销毁它们。 Step 3.ActivityStack.finishCurrentActivityLocked 这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中: publicclassActivityStack{ ...... privatefinalActivityRecordfinishCurrentActivityLocked(ActivityRecordr, intmode){ ...... returnfinishCurrentActivityLocked(r,index,mode); } privatefinalActivityRecordfinishCurrentActivityLocked(ActivityRecordr, intindex,intmode){ ...... //makesuretherecordiscleanedoutofotherplaces. mStoppingActivities.remove(r); mWaitingVisibleActivities.remove(r); ...... finalActivityStateprevState=r.state; r.state=ActivityState.FINISHING; if(mode==FINISH_IMMEDIATELY ||prevState==ActivityState.STOPPED ||prevState==ActivityState.INITIALIZING){ //Ifthisactivityisalreadystopped,wecanjustfinish //itrightnow. returndestroyActivityLocked(r,true)?null:r; }else{ ...... } returnr; } ...... } 从上面的Step 2中传进来的参数mode为FINISH_IMMEDIATELY,并且这个即将要被销毁的Activity的状态为Stopped,因此,接下来就会调用destroyActivityLocked函数来销毁它。 Step 4.ActivityStack.destroyActivityLocked 这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中: publicclassActivityStack{ ...... finalbooleandestroyActivityLocked(ActivityRecordr, booleanremoveFromApp){ ...... booleanremovedFromHistory=false; ...... finalbooleanhadApp=r.app!=null; if(hadApp){ ...... try{ ...... r.app.thread.scheduleDestroyActivity(r,r.finishing, r.configChangeFlags); }catch(Exceptione){ ...... } ...... }else{ ...... } ...... returnremovedFromHistory; } ...... } 在前面一篇文章Android应用程序启动过程源代码分析中,我们说到,每一个应用程序进程在ActivityManagerService中,都ProcessRecord记录与之对应,而每一个Activity,都是运行在一个进程上下文中,因此,在ActivityManagerService中,每一个ActivityRecord的app成员变量都应该指向一个ProcessRecord记录,于是,这里得到的hadApp为true。在ProcessRecord类中,有一个成员变量thread,它的类型为IApplicationThread。在文章Android应用程序启动过程源代码分析中,我们也曾经说过,每一个应用程序在启动的时候,它都会在内部创建一个ActivityThread对象,而在这个ActivityThread对象中,有一个成员变量mAppThread,它的类型为ApplicationThread,这是一个Binder对象,专门用来负责在应用程序和ActivityManagerService之间执行进程间通信工作的。应用程序在启动的时候,就会将这个Binder对象传递给ActivityManagerService,而ActivityManagerService就会把它保存在相应的ProcessRecord记录的thread成员变量中。因此,ProcessRecord记录的thread成员变量其实就是ApplicationThread对象的远程接口,于是,执行下面这个语句的时候: r.app.thread.scheduleDestroyActivity(r,r.finishing, r.configChangeFlags); 就会进入到ApplicationThread类中的scheduleDestroyActivity函数来。 Step 5.ApplicationThread.scheduleDestroyActivity 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中: publicfinalclassActivityThread{ ...... privatefinalclassApplicationThreadextendsApplicationThreadNative{ ...... publicfinalvoidscheduleDestroyActivity(IBindertoken,booleanfinishing, intconfigChanges){ queueOrSendMessage(H.DESTROY_ACTIVITY,token,finishing?1:0, configChanges); } ...... } ...... } 这个函数调用外部类ActivityThread的queueOrSendMessage函数来往应用程序的消息队列中发送一个H.DESTROY_ACTIVITY消息,这个消息最终由ActivityThread类的handleDestroyActivity函数来处理。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966656,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android应用程序键盘(Keyboard)消息处理机制分析(6)

Step 21.EventHub.openDevice这个函数定义在frameworks/base/libs/ui/EventHub.cpp文件中: intEventHub::openDevice(constchar*deviceName){ intversion; intfd; structpollfd*new_mFDs; device_t**new_devices; char**new_device_names; charname[80]; charlocation[80]; charidstr[80]; structinput_idid; LOGV("Openingdevice:%s",deviceName); AutoMutex_l(mLock); fd=open(deviceName,O_RDWR); if(fd<0){ LOGE("couldnotopen%s,%s\n",deviceName,strerror(errno)); return-1; } ...... intdevid=0; while(devid<mNumDevicesById){ if(mDevicesById[devid].device==NULL){ break; } devid++; } ...... mDevicesById[devid].seq=(mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK; if(mDevicesById[devid].seq==0){ mDevicesById[devid].seq=1<<SEQ_SHIFT; } new_mFDs=(pollfd*)realloc(mFDs,sizeof(mFDs[0])*(mFDCount+1)); new_devices=(device_t**)realloc(mDevices,sizeof(mDevices[0])*(mFDCount+1)); if(new_mFDs==NULL||new_devices==NULL){ LOGE("outofmemory"); return-1; } mFDs=new_mFDs; mDevices=new_devices; ...... device_t*device=newdevice_t(devid|mDevicesById[devid].seq,deviceName,name); if(device==NULL){ LOGE("outofmemory"); return-1; } device->fd=fd; mFDs[mFDCount].fd=fd; mFDs[mFDCount].events=POLLIN; mFDs[mFDCount].revents=0; //Figureoutthekindsofeventsthedevicereports. uint8_tkey_bitmask[sizeof_bit_array(KEY_MAX+1)]; memset(key_bitmask,0,sizeof(key_bitmask)); LOGV("Gettingkeys..."); if(ioctl(fd,EVIOCGBIT(EV_KEY,sizeof(key_bitmask)),key_bitmask)>=0){ //Seeifthisisakeyboard.Ignoreeverythinginthebuttonrangeexceptfor //gamepadswhicharealsoconsideredkeyboards. if(containsNonZeroByte(key_bitmask,0,sizeof_bit_array(BTN_MISC)) ||containsNonZeroByte(key_bitmask,sizeof_bit_array(BTN_GAMEPAD), sizeof_bit_array(BTN_DIGI)) ||containsNonZeroByte(key_bitmask,sizeof_bit_array(KEY_OK), sizeof_bit_array(KEY_MAX+1))){ device->classes|=INPUT_DEVICE_CLASS_KEYBOARD; device->keyBitmask=newuint8_t[sizeof(key_bitmask)]; if(device->keyBitmask!=NULL){ memcpy(device->keyBitmask,key_bitmask,sizeof(key_bitmask)); }else{ deletedevice; LOGE("outofmemoryallocatingkeybitmask"); return-1; } } } ...... if((device->classes&INPUT_DEVICE_CLASS_KEYBOARD)!=0){ chartmpfn[sizeof(name)]; charkeylayoutFilename[300]; //amoredescriptivename device->name=name; //replaceallthespaceswithunderscores strcpy(tmpfn,name); for(char*p=strchr(tmpfn,'');p&&*p;p=strchr(tmpfn,'')) *p='_'; //findthe.klfileweneedforthisdevice constchar*root=getenv("ANDROID_ROOT"); snprintf(keylayoutFilename,sizeof(keylayoutFilename), "%s/usr/keylayout/%s.kl",root,tmpfn); booldefaultKeymap=false; if(access(keylayoutFilename,R_OK)){ snprintf(keylayoutFilename,sizeof(keylayoutFilename), "%s/usr/keylayout/%s",root,"qwerty.kl"); defaultKeymap=true; } status_tstatus=device->layoutMap->load(keylayoutFilename); if(status){ LOGE("Error%dloadingkeylayout.",status); } //telltheworldaboutthedevname(thedescriptivename) if(!mHaveFirstKeyboard&&!defaultKeymap&&strstr(name,"-keypad")){ //thebuilt-inkeyboardhasawell-knowndeviceIDof0, //thisdevicebetternotgoaway. mHaveFirstKeyboard=true; mFirstKeyboardId=device->id; property_set("hw.keyboards.0.devname",name); }else{ //ensuremFirstKeyboardIdissetto-something-. if(mFirstKeyboardId==0){ mFirstKeyboardId=device->id; } } charpropName[100]; sprintf(propName,"hw.keyboards.%u.devname",device->id); property_set(propName,name); //'Q'keysupport=cheaptestofwhetherthisisanalpha-capablekbd if(hasKeycodeLocked(device,AKEYCODE_Q)){ device->classes|=INPUT_DEVICE_CLASS_ALPHAKEY; } //SeeifthisdevicehasaDPAD. 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; } //Seeifthisdevicehasagamepad. for(size_ti=0;i<sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]);i++){ if(hasKeycodeLocked(device,GAMEPAD_KEYCODES[i])){ device->classes|=INPUT_DEVICE_CLASS_GAMEPAD; break; } } LOGI("Newkeyboard:device->id=0x%xdevname='%s'propName='%s'keylayout='%s'\n", device->id,name,propName,keylayoutFilename); } ...... mDevicesById[devid].device=device; device->next=mOpeningDevices; mOpeningDevices=device; mDevices[mFDCount]=device; mFDCount++; return0; } 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966617,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册