編輯:關於Android編程
Android系統中關於VSYNC的簡介
92HWComposer::HWComposer(
93 const sp
94 EventHandler& handler)
95 : mFlinger(flinger),
96 mFbDev(0), mHwc(0), mNumDisplays(1),
97 mCBContext(new cb_context),
98 mEventHandler(handler),
99 mVSyncCount(0),mDebugForceFakeVSync(false)
100{
101 for (size_t i =0 ; i 102 mLists[i] = 0; 103 } 104 105 char value[PROPERTY_VALUE_MAX]; 106 property_get("debug.sf.no_hw_vsync", value, "0"); 107 mDebugForceFakeVSync = atoi(value); 108 109 boolneedVSyncThread = true; 110 111 // Note: some devices may insist that theFB HAL be opened before HWC. 112 int fberr = loadFbHalModule(); 113 loadHwcModule(); 114 115 if (mFbDev && mHwc &&hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { 116 // close FB HAL if we don't needed it. 117 // FIXME: this is temporary until we'renot forced to open FB HAL 118 // before HWC. 119 framebuffer_close(mFbDev); 120 mFbDev = NULL; 121 } 122 123 // If we have no HWC, or a pre-1.1 HWC, anFB dev is mandatory. 124 if ((!mHwc || !hwcHasApiVersion(mHwc,HWC_DEVICE_API_VERSION_1_1)) 125 && !mFbDev) { 126 ALOGE("ERROR: failed to openframebuffer (%s), aborting", 127 strerror(-fberr)); 128 abort(); 129 } 130 131 // these display IDs are always reserved 132 for (size_t i=0 ;i 133 mAllocatedDisplayIDs.markBit(i); 134 } 135 136 if (mHwc) { 137 ALOGI("Using %s version%u.%u", HWC_HARDWARE_COMPOSER, 138 (hwcApiVersion(mHwc) >> 24)& 0xff, 139 (hwcApiVersion(mHwc) >> 16)& 0xff); 140 if (mHwc->registerProcs) { 141 mCBContext->hwc = this; 142 mCBContext->procs.invalidate= &hook_invalidate; 143 mCBContext->procs.vsync= &hook_vsync; 144 if (hwcHasApiVersion(mHwc,HWC_DEVICE_API_VERSION_1_1)) 145 mCBContext->procs.hotplug =&hook_hotplug; 146 else 147 mCBContext->procs.hotplug =NULL; 148 memset(mCBContext->procs.zero,0, sizeof(mCBContext->procs.zero)); 149 mHwc->registerProcs(mHwc,&mCBContext->procs); 150 } 151 152 // don't need avsync thread if we have a hardware composer 153 needVSyncThread= false; 154 // always turn vsync off when we start 155 eventControl(HWC_DISPLAY_PRIMARY,HWC_EVENT_VSYNC, 0); 156 157 // the number of displays we actuallyhave depends on the 158 // hw composer version 159 if (hwcHasApiVersion(mHwc,HWC_DEVICE_API_VERSION_1_EXP)) { 160 // 1.?? adds support for virtualdisplays 161 mNumDisplays = MAX_DISPLAYS; 162 } else if (hwcHasApiVersion(mHwc,HWC_DEVICE_API_VERSION_1_1)) { 163 // 1.1 adds support for multipledisplays 164 mNumDisplays = MAX_DISPLAYS; 165 } else { 166 mNumDisplays = 1; 167 } 168 } 169 170 if (mFbDev) { 171 ALOG_ASSERT(!(mHwc &&hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)), 172 "should only have fbdev ifno hwc or hwc is 1.0"); 173 174 DisplayData&disp(mDisplayData[HWC_DISPLAY_PRIMARY]); 175 disp.connected = true; 176 disp.width = mFbDev->width; 177 disp.height = mFbDev->height; 178 disp.format = mFbDev->format; 179 disp.xdpi = mFbDev->xdpi; 180 disp.ydpi = mFbDev->ydpi; 181 if (disp.refresh == 0) { 182 disp.refresh = nsecs_t(1e9 /mFbDev->fps); 183 ALOGW("getting VSYNC periodfrom fb HAL: %lld", disp.refresh); 184 } 185 if (disp.refresh == 0) { 186 disp.refresh = nsecs_t(1e9 / 60.0); 187 ALOGW("getting VSYNC periodfrom thin air: %lld", 188 mDisplayData[HWC_DISPLAY_PRIMARY].refresh); 189 } 190 } else if (mHwc) { 191 // here we're guaranteed to have atleast HWC 1.1 192 for (size_t i =0 ;i 193 queryDisplayProperties(i); 194 } 195 } 196 197 if(needVSyncThread) { 198 // we don't have VSYNC support, we needto fake it 199 mVSyncThread =new VSyncThread(*this); 200 } 201} 在HWComposer構造函數中,如果有硬件HardwareComposer,那麼使用硬件的”hwcVSyncThread”主題vsync_loop查詢vsync_event;否則使用VSyncThread Fake VSYNC。 使用硬件hwcVSyncThread的情況如下 52static void*vsync_loop(void *param) 53{ 54 hwc_context_t * ctx =reinterpret_cast 55 56 char thread_name[64] =HWC_VSYNC_THREAD_NAME; 57 prctl(PR_SET_NAME, (unsigned long)&thread_name, 0, 0, 0); 58 setpriority(PRIO_PROCESS, 0,HAL_PRIORITY_URGENT_DISPLAY + 59 android::PRIORITY_MORE_FAVORABLE); 60 61 const int MAX_DATA = 64; 62 char vdata[MAX_DATA]; 63 bool logvsync = false; 64 65 struct pollfd pfd[2]; 66 int fb_fd[2]; 67 uint64_t timestamp[2] = {0,0}; 68 int num_displays; 69 70 char property[PROPERTY_VALUE_MAX]; 71 if(property_get("debug.hwc.fakevsync", property, NULL) > 0){ 72 if(atoi(property) == 1) 73 ctx->vstate.fakevsync = true; 74 } 75 76 if(property_get("debug.hwc.logvsync", property, 0) > 0) { 77 if(atoi(property) == 1) 78 logvsync = true; 79 } 80 81 if (ctx->mExtDisplay->isConnected()) 82 num_displays = 2; 83 else 84 num_displays = 1; 85 86 char vsync_node_path[MAX_SYSFS_FILE_PATH]; 87 for (int dpy = HWC_DISPLAY_PRIMARY; dpy< num_displays; dpy++) { 88 snprintf(vsync_node_path,sizeof(vsync_node_path), 89 "/sys/class/graphics/fb%d/vsync_event", 90 dpy == HWC_DISPLAY_PRIMARY ? 0: 91 overlay::Overlay::getInstance()-> 92 getFbForDpy(HWC_DISPLAY_EXTERNAL)); 93 ALOGI("%s: Reading vsync fordpy=%d from %s", __FUNCTION__, dpy, 94 vsync_node_path); 95 fb_fd[dpy] = open(vsync_node_path,O_RDONLY); 96 97 if (fb_fd[dpy] < 0) { 98 // Make sure fb device is openedbefore starting this thread so this 99 // never happens. 100 ALOGE ("%s:not able to openvsync node for dpy=%d, %s", 101 __FUNCTION__, dpy,strerror(errno)); 102 if (dpy == HWC_DISPLAY_PRIMARY) { 103 ctx->vstate.fakevsync =true; 104 break; 105 } 106 } 107 // Read once from the fds to clear thefirst notify 108 pread(fb_fd[dpy], vdata , MAX_DATA, 0); 109 110 pfd[dpy].fd = fb_fd[dpy]; 111 if (pfd[dpy].fd >= 0) 112 pfd[dpy].events = POLLPRI |POLLERR; 113 } 114 115 if (LIKELY(!ctx->vstate.fakevsync)) { 116 do { 117 int err = poll(pfd, num_displays,-1); 118 if(err > 0) { 119 for (int dpy =HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) { 120 if (pfd[dpy].revents &POLLPRI) { 121 int len =pread(pfd[dpy].fd, vdata, MAX_DATA, 0); 122 if (UNLIKELY(len <0)) { 123 // If the read wasjust interrupted - it is not a 124 // fatal error.Just continue in this case 125 ALOGE ("%s:Unable to read vsync for dpy=%d : %s", 126 __FUNCTION__,dpy, strerror(errno)); 127 continue; 128 } 129 // extract timestamp 130 if (!strncmp(vdata,"VSYNC=", strlen("VSYNC="))) { 131 timestamp[dpy] =strtoull(vdata + strlen("VSYNC="), 132 NULL, 0); 133 } 134 // send timestamp toSurfaceFlinger 135 ALOGD_IF (logvsync, 136 "%s:timestamp %llu sent to SF for dpy=%d", 137 __FUNCTION__,timestamp[dpy], dpy); 138
ctx->proc->vsync(ctx->proc, dpy, timestamp[dpy]); 139 } 140 } 141 142 } else { 143 ALOGE("%s: vsync pollfailed errno: %s", __FUNCTION__, 144 strerror(errno)); 145 continue; 146 } 147 } while (true); 148 149 } else { 150 151 //Fake vsync is used only when setexplicitly through a property or when 152 //the vsync timestamp node cannot beopened at bootup. There is no 153 //fallback to fake vsync from the truevsync loop, ever, as the 154 //condition can easily escapedetection. 155 //Also, fakevsync is delivered only for the primary display. 156 do { 157 usleep(16666); 158 timestamp[HWC_DISPLAY_PRIMARY] =systemTime(); 159 ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY, 160 timestamp[HWC_DISPLAY_PRIMARY]); 161 162 } while (true); 163 } 164 165 for (int dpy = HWC_DISPLAY_PRIMARY; dpy<= HWC_DISPLAY_EXTERNAL; dpy++ ) { 166 if(fb_fd[dpy] >= 0) 167 close (fb_fd[dpy]); 168 } 169 170 return NULL; 171} 首先讀硬件事件,如果調試fake,則使用usleep fake 60HZ VSYNC,回調hook_vsync; 這是在hwc_registerProcs中注冊的; 85static voidhwc_registerProcs(struct hwc_composer_device_1* dev, 86 hwc_procs_tconst* procs) 87{ 88 ALOGI("%s", __FUNCTION__); 89 hwc_context_t* ctx = (hwc_context_t*)(dev); 90 if(!ctx) { 91 ALOGE("%s: Invalid context",__FUNCTION__); 92 return; 93 } 94 ctx->proc =procs; 95 96 // Now that we have the functions needed,kick off 97 // the uevent & vsync threads 98 init_uevent_thread(ctx); 99 init_vsync_thread(ctx);
啟動”hwcVSyncThread”線程,執行vsync_loop 100} ctx->proc->vsync即調用HWComposer::hook_vsync處理如下。 271voidHWComposer::hook_vsync(const struct hwc_procs* procs, int disp, 272 int64_t timestamp) { 273 cb_context* ctx =reinterpret_cast 274 const_cast 275 ctx->hwc->vsync(disp,timestamp); 276} Ctx->hwc->vsync函數是HWComposer::vsync,代碼如下 289voidHWComposer::vsync(int disp, int64_t timestamp) { 290 ATRACE_INT("VSYNC",++mVSyncCount&1); 291 mEventHandler.onVSyncReceived(disp,timestamp); 292 Mutex::Autolock _l(mLock); 293 mLastHwVSync = timestamp; 294} mEventHandler是SurfaceFlinger自身。 使用VSyncThread模擬的情況 1075boolHWComposer::VSyncThread::threadLoop() { 1076 { // scope for lock 1077 Mutex::Autolock _l(mLock); 1078 while (!mEnabled) { 1079 mCondition.wait(mLock); 1080 } 1081 } 1082 1083 const nsecs_t period = mRefreshPeriod; 1084 const nsecs_t now =systemTime(CLOCK_MONOTONIC); 1085 nsecs_t next_vsync = mNextFakeVSync; 1086 nsecs_t sleep = next_vsync - now; 1087 if (sleep < 0) { 1088 // we missed, find where the next vsyncshould be 1089 sleep = (period - ((now - next_vsync) %period)); 1090 next_vsync = now + sleep; 1091 } 1092 mNextFakeVSync = next_vsync + period; 1093 1094 struct timespec spec; 1095 spec.tv_sec = next_vsync / 1000000000; 1096 spec.tv_nsec = next_vsync % 1000000000; 1097 1098 int err; 1099 do { 1100 err = clock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME, &spec, NULL); 1101 } while (err<0 && errno ==EINTR); 1102 1103 if (err == 0) { 1104 mHwc.mEventHandler.onVSyncReceived(0,next_vsync); 1105 } 1106 1107 return true; 1108} mHwc的mEventHandler就是SurfaceFlinger,這是在SurfaceFlinger的readyToRun時構造HWComposer時初始化的。 474status_tSurfaceFlinger::readyToRun() 475{ 476 ALOGI( "SurfaceFlinger's main thread ready to run. " 477 "Initializing graphicsH/W..."); 478 479 Mutex::Autolock _l(mStateLock); 480 481 // initialize EGL for the default display 482 mEGLDisplay =eglGetDisplay(EGL_DEFAULT_DISPLAY); 483 eglInitialize(mEGLDisplay, NULL, NULL); 484 485 // Initialize the H/W composer object. There may or may not be an 486 // actual hardware composer underneath. 487 mHwc = new HWComposer(this, 488 *static_cast 至此兩種情況都調用到了SurfaceFlinger::onVSyncReceived,該函數處理如下: 704voidSurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) { 705 if (mEventThread == NULL) { 706 // This is a temporary workaround forb/7145521. A non-null pointer 707 // does not mean EventThread hasfinished initializing, so this 708 // is not a correct fix. 709 ALOGW("WARNING: EventThread notstarted, ignoring vsync"); 710 return; 711 } 712 if (uint32_t(type) 713 // we should only receiveDisplayDevice::DisplayType from the vsync callback 714 mEventThread->onVSyncReceived(type,timestamp); 715 } 716} EventThread的onVSyncReceived 114voidEventThread::onVSyncReceived(int type, nsecs_t timestamp) { 115 ALOGE_IF(type >= HWC_NUM_DISPLAY_TYPES, 116 "received vsync event for aninvalid display (id=%d)", type); 117 118 Mutex::Autolock _l(mLock); 119 if (type < HWC_NUM_DISPLAY_TYPES) { 120 mVSyncEvent[type].header.type =
DisplayEventReceiver::DISPLAY_EVENT_VSYNC; 121 mVSyncEvent[type].header.id = type; 122 mVSyncEvent[type].header.timestamp =timestamp; 123 mVSyncEvent[type].vsync.count++; 124 mCondition.broadcast(); 125 } 126} EventThread的threadLoop中,waitForEvent等到VSYNC後,然後postEvent(DISPLAY_EVENT_VSYNC)回Connnections 144boolEventThread::threadLoop() { 145 DisplayEventReceiver::Event event; 146 Vector 147 signalConnections =
waitForEvent(&event); // mCondition.wait 148 149 // dispatch events to listeners... 150 const size_t count =signalConnections.size(); 151 for (size_t i=0 ; i 152 const sp 153 // now see if we still need to reportthis event 154 status_t err =
conn->postEvent(event); 155 if (err == -EAGAIN || err ==-EWOULDBLOCK) { 156 // The destination doesn't acceptevents anymore, it's probably 157 // full. For now, we just drop theevents on the floor. 158 // FIXME: Note that some eventscannot be dropped and would have 159 // to be re-sent later. 160 // Right-now we don't have theability to do this. 161 ALOGW("EventThread: droppingevent (%08x) for connection %p", 162 event.header.type,conn.get()); 163 } else if (err < 0) { 164 // handle any other error on thepipe as fatal. the only 165 // reasonable thing to do is toclean-up this connection. 166 // The most common error we'll gethere is -EPIPE. 167 removeDisplayEventConnection(signalConnections[i]); 168 } 169 } 170 return true; 171} DisplayEventConnection主要有SurfaceFlinger的MessageQueue;其余的Java應用也可以通過NativeDisplayEventReceiver來注冊。下面只關注SurfaceFlinger的MessageQueue。 474status_tSurfaceFlinger::readyToRun() 475{ 476 ALOGI( "SurfaceFlinger's main thread ready to run. " 477 "Initializing graphicsH/W..."); 478 479 Mutex::Autolock _l(mStateLock); 540 mEventQueue.setEventThread(mEventThread); 103voidMessageQueue::setEventThread(const sp 104{ 105 mEventThread = eventThread; 106 mEvents =eventThread->createEventConnection(); 107 mEventTube = mEvents->getDataChannel(); 108 mLooper->addFd(mEventTube->getFd(),0, ALOOPER_EVENT_INPUT, 109 MessageQueue::cb_eventReceiver,this); 110} 177intMessageQueue::cb_eventReceiver(int fd, int events, void* data) { 178 MessageQueue* queue =reinterpret_cast 179 return queue->eventReceiver(fd,events); 180} 181 182intMessageQueue::eventReceiver(int fd, int events){ 183 ssize_t n; 184 DisplayEventReceiver::Event buffer[8]; 185 while ((n =DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) { 186 for (int i=0 ; i 187 if (buffer[i].header.type ==
DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { 188#ifINVALIDATE_ON_VSYNC 189 mHandler->dispatchInvalidate(); 190#else 191 mHandler->dispatchRefresh(); 192#endif 193 break; 194 } 195 } 196 } 197 return 1; 198} 向Handler的隊列中發送消息,在Handler所在消息循環線程中進行處理 52voidMessageQueue::Handler::dispatchRefresh() { 53 if ((android_atomic_or(eventMaskRefresh,&mEventMask) & eventMaskRefresh) == 0) { 54 mQueue.mLooper->sendMessage(this,Message(MessageQueue::REFRESH)); 55 } 56} 57 58voidMessageQueue::Handler::dispatchInvalidate() { 59 if ((android_atomic_or(eventMaskInvalidate,&mEventMask) & eventMaskInvalidate) == 0) { 60 mQueue.mLooper->sendMessage(this,Message(MessageQueue::INVALIDATE)); 61 } 62} 63 64voidMessageQueue::Handler::dispatchTransaction() { 65 if((android_atomic_or(eventMaskTransaction, &mEventMask) &eventMaskTransaction) == 0) { 66 mQueue.mLooper->sendMessage(this,Message(MessageQueue::TRANSACTION)); 67 } 68} 69 70voidMessageQueue::Handler::handleMessage(const Message& message) { 71 switch (message.what) { 72 case INVALIDATE: 73 android_atomic_and(~eventMaskInvalidate, &mEventMask); 74 mQueue.mFlinger->onMessageReceived(message.what); 75 break; 76 case REFRESH: 77 android_atomic_and(~eventMaskRefresh, &mEventMask); 78 mQueue.mFlinger->onMessageReceived(message.what); 79 break; 80 case TRANSACTION: 81 android_atomic_and(~eventMaskTransaction,&mEventMask); 82 mQueue.mFlinger->onMessageReceived(message.what); 83 break; 84 } 85} 明顯應該是調用到了MessageQueue對應的SurfaceFlinger了 130voidSurfaceFlinger::onFirstRef() 131{ 132 mEventQueue.init(this); 133 134 run("SurfaceFlinger",PRIORITY_URGENT_DISPLAY); 135 136 // Wait for the main thread to be done withits initialization 137 mReadyToRunBarrier.wait(); 138} SurfaceFlinger啟動合成處理入口。 745voidSurfaceFlinger::onMessageReceived(int32_t what) { 746 ATRACE_CALL(); 747 switch (what) { 748 case MessageQueue::TRANSACTION: 749 handleMessageTransaction(); 750 break; 751 case MessageQueue::INVALIDATE: 752 handleMessageTransaction(); 753 handleMessageInvalidate(); 754 signalRefresh(); 755 break; 756 case MessageQueue::REFRESH: 757 handleMessageRefresh(); 758 break; 759 } 760}
一、Android Studio 主題的設置1.1 設置Android Studio 自帶的主題及包名字體大小1.2 導入第三方主題:下載了第三方的主題,然後執行:Fil
工具代碼:package com.xiaolei;import java.io.File;import java.util.HashMap;import java.uti
引言最近在研究Android的變形,Android的2D變形(包括縮放,扭曲,平移,旋轉等)可以通過Matrix來實現,3D變形可以通過Camera來實現。接下來就將我這
本文為大家分享了Android模仿新浪微博啟動界面&登陸界面的具體實現代碼,供大家參考,具體內容如下啟動界面主要有兩個功能:1.加載啟動動畫2.判斷網絡,有者直接進入登陸