fast-screen-capture.cpp
Go to the documentation of this file.
00001 #if (ANDROID_VER < 420)
00002     #error must define ANDROID_VER >= 420
00003 #endif
00004 #include <unistd.h>
00005 #include <sys/types.h>
00006 #include <fcntl.h>
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <stdarg.h>
00010 #include <errno.h>
00011 #include <sys/ioctl.h>
00012 #include <sys/mman.h>
00013 #include <math.h>
00014 #include <err.h>
00015 #include <stdbool.h>
00016 #include <sys/time.h>
00017 #include <time.h>
00018 #include <signal.h>
00019 #include <termios.h>
00020 #include <pthread.h>
00021 #include <linux/input.h>
00022 #include <sys/un.h>
00023 #include <sys/socket.h>
00024 
00025 #include "libcutils.h"
00026 #include "libgui.h"
00027 #include "libui.h"
00028 #include "libskia.h"
00029 #include "libstagefright.h"
00030 
00031 using namespace android;
00032 
00033 struct ASC_PRIV_DATA;
00034 struct ASC {
00035     ASC_PRIV_DATA* priv_data;
00036     char* data;
00037     int size;
00038     int w; //short size
00039     int h; //long size
00040     char pixfmtName[32];
00041 };
00042 
00043 static bool needLog = true;
00044 #define LOG(fmt, arg...)         ({static bool __logged=false; if (needLog||!__logged){_LOG("%s" fmt "%s", needLog?"":"--------rare case--------", ##arg, needLog?"":"\n\n");__logged=true;}})
00045 #define LOGI(fmt, arg...)        LOG("--------" fmt "\n\n", ##arg)
00046 #define ABORT(fmt, arg...)       ({_LOG(fmt ". Now exit", ##arg); exit(0);})
00047 #define ABORT_ERRNO(fmt, arg...) ({_LOG(fmt " [errno %d(%s)] Now exit", errno, strerror(errno), ##arg); exit(0);})
00048 
00049 static void _LOG(const char* format, ...) {
00050     char buf[4096];
00051     int cnt;
00052     va_list va;
00053     struct timespec ct;
00054     struct tm * st;
00055     clock_gettime(CLOCK_REALTIME, &ct);
00056     st = localtime(&ct.tv_sec);
00057     cnt = sprintf(buf, "%02d/%02d %02d:%02d:%02d.%03d [ASC %d] ", st->tm_mon+1, st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec, (int)(ct.tv_nsec/1000000), gettid());
00058     va_start(va, format);
00059     cnt += vsnprintf(buf+cnt, sizeof(buf)-cnt, format, va);
00060     va_end(va);
00061     if (cnt > sizeof(buf)) cnt = sizeof(buf); else if (cnt <= 0) {cnt = 7; strcpy(buf, "LogErr");};
00062     if (buf[cnt-1]==0) cnt--; //always true
00063     if (buf[cnt-1]!='\n') buf[cnt++] = '\n';
00064     write(STDERR_FILENO, buf, cnt);
00065 }
00066 
00067 static bool isPaused = false;
00068 static bool isScreenOff = false;
00069 static char* blackscreen = NULL;
00070 static int blackscreen_extra_count = 0;
00071 
00072 static Mutex mutex;
00073 static Condition cond;
00074 
00075 static bool isFirstTime = true;
00076 
00077 static void chkDev() {
00078     char k[128] = {0};
00079     char _sn[256] = {0};
00080     char *sn = _sn;
00081     char hb[4+1] = {'0','0','0','0', 0};
00082     char now[6+1] = {0};
00083     const char* es;
00084     char* ds;
00085     char* err;
00086     int i=0, esLen, snLen, dsLen;
00087     unsigned int ec, sc, dc;
00088     struct timespec ct;
00089     struct tm * st;
00090 
00091     es=getenv("ASC_");
00092     if (!es || !es[0]) ABORT("!nes");
00093     esLen = strlen(es);
00094     if (esLen%(2*6) != 0) ABORT("!esl");
00095     dsLen = esLen/2;
00096 
00097     //getprop android_id from net.hostname
00098     k[i=0] = 'n'; k[++i] = 'e'; k[++i] = 't'; k[++i] = '.'; k[++i] = 'h'; k[++i] = 'o'; k[++i] = 's'; k[++i] = 't'; k[++i] = 'n'; k[++i] = 'a'; k[++i] = 'm'; k[++i] = 'e'; k[++i] = 0;
00099     property_get(k, sn, " ");
00100     snLen = strlen(sn);
00101     if (snLen > 8) {
00102         sn += 8;
00103         snLen -= 8;
00104     } else {
00105         //getprop ro.serialno
00106         k[i=0] = 'r'; k[++i] = 'o'; k[++i] = '.'; k[++i] = 's'; k[++i] = 'e'; k[++i] = 'r'; k[++i] = 'i'; k[++i] = 'a'; k[++i] = 'l'; k[++i] = 'n'; k[++i] = 'o'; k[++i] = 0;
00107         property_get(k, sn, " ");
00108         snLen = strlen(sn);
00109     }
00110 
00111     if ( dsLen != (snLen+6-1)/6*6 ) ABORT("!esms %d %d %d", snLen, (snLen+6-1)/6*6, dsLen);
00112 
00113     ds = (char*)calloc(dsLen+1, 1);
00114     for(i=0; i < dsLen; i++) {
00115         //hb[0] = hb[1] = '0';
00116         hb[2] = es[i*2];
00117         hb[3] = es[i*2+1];
00118         ec = (unsigned int)strtoul(hb, &err, 16);
00119         if (err&&err[0]) ABORT("!ec", err);
00120         sc = (unsigned int)(unsigned char)sn[i%snLen];
00121         dc = ec ^ sc;
00122         if (dc < '0' || dc > '9') ABORT("!dcd");
00123         ds[i] = (char)dc;
00124     }
00125     for (i = 6; i < dsLen; i += 6)
00126         if ( 0 != memcmp(ds, &ds[i], 6)) ABORT("!dsfd");
00127 
00128     clock_gettime(CLOCK_REALTIME, &ct);
00129     st = localtime(&ct.tv_sec);
00130     sprintf(now, "%02d%02d%02d", (st->tm_year+1900-2000), st->tm_mon+1, st->tm_mday);
00131 
00132     if (memcmp(now, ds, 6) > 0) ABORT("!to");
00133     free(ds);
00134 }
00135 
00136 static void* thread_cmd_socket_server(void* thd_param) {
00137     int socket_server_fd = (int)thd_param;
00138     for(;;) {
00139         LOG("accept");
00140         int connection_fd = accept(socket_server_fd, NULL, NULL);
00141         if (connection_fd == -1) {
00142             LOG("accept err %d", errno);
00143             continue;
00144         }
00145 
00146         for(;;) {
00147             unsigned char cmd;
00148             LOG("read cmd");
00149             if (read(connection_fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
00150                 LOG("read err %d", errno);
00151                 break;
00152             }
00153             LOGI("handle cmd: %c (%d)", cmd, cmd);
00154 
00155             AutoMutex autoLock(mutex);
00156             switch (cmd) {
00157             case '+': //start
00158                 if (isPaused) {
00159                     isPaused = false;
00160                     cond.signal();
00161                 }
00162                 break;
00163             case '-': //pause
00164                 if (!isPaused) {
00165                     isPaused = true;
00166                     cond.signal();
00167                 }
00168                 break;
00169             case '1': //screen on
00170                 isScreenOff = isPaused = false;
00171                 cond.signal();
00172                 break;
00173             case '0': //screen off
00174                 isScreenOff = isPaused = true;
00175                 cond.signal();
00176                 break;
00177             }
00178         } //end of for(;;)
00179 
00180         LOG("close cmd connection");
00181         close(connection_fd);
00182     }
00183     return 0;
00184 }
00185 
00186 static int touch_dev_fd = -1;
00187 
00188 static void* thread_touch_socket_server(void* thd_param) {
00189     int socket_server_fd = (int)thd_param;
00190     for(;;) {
00191         LOG("accept");
00192         int connection_fd = accept(socket_server_fd, NULL, NULL);
00193         if (connection_fd == -1) {
00194             LOG("accept err %d", errno);
00195             continue;
00196         }
00197 
00198         struct input_event event = {0};
00199         const int event_core_size = (((char*)&event.value) + sizeof(event.value)) - ((char*)&event.type);
00200         for(;;) {
00201             LOG("read touch event");
00202             if (read(connection_fd, &event.type, event_core_size) != event_core_size) {
00203                 LOG("read err %d", errno);
00204                 break;
00205             }
00206             LOGI("handle touch event %d %d %d", event.type, event.code, event.value);
00207             if (write(touch_dev_fd, &event, sizeof(event)) != sizeof(event)) {
00208                 LOG("write err %d", errno);
00209                 break;
00210             }
00211         } //end of for(;;)
00212 
00213         LOG("close touch connection");
00214         close(connection_fd);
00215     }
00216     return 0;
00217 }
00218 
00219 static void create_cmd_socket_server() {
00220     char* socket_name = getenv("ASC_CMD_SOCKET");
00221     if (socket_name && socket_name[0]) {
00222 
00223         LOG("c s r %s", socket_name);
00224         int socket_server_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
00225         if (socket_server_fd == -1) {
00226             LOG("socket err %d", errno);
00227             return;
00228         }
00229 
00230         struct sockaddr_un addr = {0};
00231         addr.sun_family = AF_LOCAL;
00232         int namelen = strlen(socket_name);
00233         if (1/*\0*/+namelen > sizeof(addr.sun_path)) ABORT("socket name too long");
00234         memcpy(&addr.sun_path[1], socket_name, namelen);
00235         int addrlen = offsetof(struct sockaddr_un, sun_path) + 1/*\0*/ + namelen;
00236 
00237         LOG("bnd");
00238         if (bind(socket_server_fd, (struct sockaddr*)&addr, addrlen)) {
00239             LOG("bind err %d", errno);
00240             return;
00241         }
00242 
00243         LOG("lstn");
00244         if (listen(socket_server_fd, 1)) {
00245             LOG("listen err %d", errno);
00246             return;
00247         }
00248 
00249         LOG("cthd");
00250         pthread_t thd;
00251         int err = pthread_create(&thd, NULL, thread_cmd_socket_server, (void*)socket_server_fd);
00252         if (err) {
00253             LOG("pthread_create err %d", err);
00254             return;
00255         }
00256     }
00257 }
00258 
00259 static void create_touch_socket_server() {
00260     char* socket_name = getenv("ASC_TOUCH_SOCKET");
00261     if (socket_name && socket_name[0]) {
00262 
00263         LOG("o t d %s", socket_name);
00264         touch_dev_fd = open(socket_name, O_WRONLY);
00265         if (touch_dev_fd==-1) {
00266             LOG("open err %d", errno);
00267             return;
00268         }
00269 
00270         LOG("c s r %s", socket_name);
00271         int socket_server_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
00272         if (socket_server_fd == -1) {
00273             LOG("socket err %d", errno);
00274             return;
00275         }
00276 
00277         struct sockaddr_un addr = {0};
00278         addr.sun_family = AF_LOCAL;
00279         int namelen = strlen(socket_name);
00280         if (1/*\0*/+namelen > sizeof(addr.sun_path)) ABORT("socket name too long");
00281         memcpy(&addr.sun_path[1], socket_name, namelen);
00282         int addrlen = offsetof(struct sockaddr_un, sun_path) + 1/*\0*/ + namelen;
00283 
00284         LOG("bnd");
00285         if (bind(socket_server_fd, (struct sockaddr*)&addr, addrlen)) {
00286             LOG("bind err %d", errno);
00287             return;
00288         }
00289 
00290         LOG("lstn");
00291         if (listen(socket_server_fd, 1)) {
00292             LOG("listen err %d", errno);
00293             return;
00294         }
00295 
00296         LOG("cthd");
00297         pthread_t thd;
00298         int err = pthread_create(&thd, NULL, thread_touch_socket_server, (void*)socket_server_fd);
00299         if (err) {
00300             LOG("pthread_create err %d", err);
00301             return;
00302         }
00303     }
00304 }
00305 
00306 #define ENABLE_RESEND 1
00307 
00308 #if ENABLE_RESEND 
00309     struct timespec origTime = {0};
00310     struct timespec lastRereadTime = {0};
00311     static int resend_count = 0;
00312     #define RESEND_INTERVAL_NS ((int)(1000000000*0.25))
00313     #define RESEND_COUNT 2
00314 #endif
00315 
00316 #define toEvenInt(n) ((int)(ceil(((float)(n))/2)*2))
00317 #define min(a,b) ((a) < (b) ? (a) : (b))
00318 #define max(a,b) ((a) > (b) ? (a) : (b))
00319 
00320 static sp<IBinder> __csBinder;
00321 // static sp<ISurfaceComposer> __cs;
00322 static sp<IBinder> mainDisp, virtDisp;
00323 static DisplayInfo mainDispInfo;
00324 static bool internal_w_gt_h = false;
00325 static int capture_w, capture_h, logicalFrameSize;
00326 class MyGraphicBufferProducer;
00327 static MyGraphicBufferProducer* bp;
00328 // static Vector<ComposerState> _emptyComposerStates; //dummy
00329 // static Vector<DisplayState > _displayStates;
00330 // static DisplayState* virtDispState = NULL;
00331 static DisplayState* virtDispState = new DisplayState();
00332 static int TRANS_ID_GET_DISPLAY_INFO = 0;
00333 static int TRANS_ID_SET_DISPLAY_STATE = 0;
00334 #define BPP 4
00335 
00336 struct CallbackStep {
00337     int ind;
00338     const char* name;
00339 };
00340 static CallbackStep bpSteps[1/*invalid step 0*/+32] = {0};
00341 static int bpStepMax = 0;
00342 static int step_queueBuffer = 0;
00343 static int step_requestBuffer = 0;
00344 
00345 
00346 
00347 typedef void* VADDR;
00348 typedef VADDR* PVTBL;
00349 #define PVTBL_OF(inst) (*((PVTBL*)(inst)))
00350 #define getVirtFuncIndex(f) _getVirtFuncIndex(0, f)
00351 static int _getVirtFuncIndex(int dummy, ...) {
00352     int i;
00353     va_list va;
00354     va_start(va, dummy);
00355     i = va_arg(va, int);
00356     va_end(va);
00357     return i/sizeof(VADDR);
00358 }
00359 
00360 #define INIT_NEXT_CALLBACK_STEP(virtFuncName) ({ \
00361     if (++bpStepMax >= sizeof(bpSteps)/sizeof(bpSteps[0])-1) ABORT("too many bpSteps"); \
00362     bpSteps[bpStepMax].ind = getVirtFuncIndex(&IGraphicBufferProducer::virtFuncName); \
00363     bpSteps[bpStepMax].name = #virtFuncName; \
00364 })
00365 
00366 static void bpInitCallbackSteps() {
00367     LOG("bpics");
00368     INIT_NEXT_CALLBACK_STEP(query);
00369     INIT_NEXT_CALLBACK_STEP(connect);
00370     #if (ANDROID_VER<440)
00371         INIT_NEXT_CALLBACK_STEP(setSynchronousMode);
00372     #endif
00373     INIT_NEXT_CALLBACK_STEP(dequeueBuffer);
00374     INIT_NEXT_CALLBACK_STEP(requestBuffer);
00375     step_requestBuffer = bpStepMax;
00376     INIT_NEXT_CALLBACK_STEP(queueBuffer);
00377     step_queueBuffer = bpStepMax;
00378 }
00379 
00380 static int bpCodeToVirtIndex(uint32_t code) {
00381     static int diff = -1;
00382     if (diff == -1)
00383         diff = getVirtFuncIndex(&IGraphicBufferProducer::requestBuffer)-1/*code*/;
00384     if (diff <= 0) ABORT("bad rbf vi");
00385     return code + diff;
00386 }
00387 
00388 static int convertOrient(int orient) {
00389     //orient: 1=90 2=180 3=270
00390     if (internal_w_gt_h) { //sample device: FUJITSU F-02F 4.2.2
00391         if (capture_w < capture_h) //normal case: draw in portrait canvas
00392             return (orient+1)%4;
00393         else //special case: draw in landscape canvas
00394             return orient;
00395     } else { //this is for normal device
00396         if (capture_w < capture_h) //normal case: draw in portrait canvas
00397             return orient;
00398         else //special case: draw in landscape canvas
00399             return (orient+3)%4;
00400     }
00401 }
00402 
00403 #if (ANDROID_VER>=500)
00404     #define MIN_DISP_INFO_HEAD_SIZE 2*sizeof(int)  //vector head
00405 #else
00406     #define MIN_DISP_INFO_HEAD_SIZE 0
00407 #endif
00408 #define MIN_DISP_INFO_SIZE  (MIN_DISP_INFO_HEAD_SIZE + ((size_t)&(((DisplayInfo*)NULL)->reserved)))
00409 
00410 static int getOrient() {
00411     LOG("r go");
00412     // status_t err = __cs->getDisplayInfo(mainDisp, &mainDispInfo);
00413 
00414     Parcel data, reply;
00415     data.writeInterfaceToken(ISurfaceComposer::descriptor);
00416     data.writeStrongBinder(mainDisp);
00417     status_t err = __csBinder->transact(TRANS_ID_GET_DISPLAY_INFO, data, &reply);
00418     if (err) ABORT("r go e %d", err);
00419     if (reply.dataSize() < MIN_DISP_INFO_SIZE) ABORT("r go s t l");
00420     DisplayInfo* info = (DisplayInfo*)(reply.data() + MIN_DISP_INFO_HEAD_SIZE);
00421     LOG("r go o %d", info->orientation);
00422     return info->orientation;
00423 }
00424 
00425 static void setVirtDispOrient(int orient) {
00426     virtDispState->what = DisplayState::eDisplayProjectionChanged;
00427     virtDispState->orientation = convertOrient(orient);
00428     LOGI("r sds o %d mo %d", virtDispState->orientation, orient);
00429     //Although specified No wait, but android 4.2 still cause wait max 5 seconds, so do not use ISurfaceComposer nor SurfaceComposerClient
00430     // status_t err = __cs->setTransactionState(_emptyComposerStates, _displayStates, 0);
00431 
00432     Parcel data;
00433     data.writeInterfaceToken(ISurfaceComposer::descriptor);
00434     data.writeInt32(0);
00435     data.writeInt32(1);
00436     virtDispState->write(data);
00437     data.writeInt32(0/*flags*/);
00438     status_t err = __csBinder->transact(TRANS_ID_SET_DISPLAY_STATE, data, NULL, 1/*TF_ONE_WAY*/);
00439 
00440     if (err) ABORT("r sds e %d", err);
00441     LOG(".r sds");
00442 }
00443 
00444 struct MyGraphicBufferProducer : public BnGraphicBufferProducer {
00445     int mWidth;
00446     int mHeight;
00447     volatile int mInUsing;
00448     bool mIsGBufferRequested;
00449     sp<Fence> mFence;
00450     PixelFormat mFormat;
00451     GraphicBuffer* mGBuf;
00452     int mGBufUsage;
00453     char* mGBufData;
00454     int mInternalWidth;
00455     bool mHaveData;
00456     int mConsumerUsage;
00457     int64_t mSeq;
00458     void* mBufferInput_flattened_buf;
00459     size_t mBufferInput_flattened_size;
00460     int* mBufferInput_flattened_fds;
00461     size_t mBufferInput_flattened_fd_count;
00462 
00463     MyGraphicBufferProducer(int w, int h) : BnGraphicBufferProducer() {
00464         LOG("bp c w %d h %d", w, h);
00465         mWidth = w;
00466         mHeight = h;
00467         mInUsing = 0;
00468         mIsGBufferRequested = false;
00469         mGBuf = NULL;
00470         mGBufData = NULL;
00471         mHaveData = false;
00472         mFence = Fence::NO_FENCE;
00473         mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
00474         mConsumerUsage = GRALLOC_USAGE_SW_READ_OFTEN;
00475         mSeq = 0;
00476         mBufferInput_flattened_buf = NULL;
00477         mBufferInput_flattened_size = 0;
00478         mBufferInput_flattened_fds = NULL;
00479         mBufferInput_flattened_fd_count = 0;
00480     }
00481 
00482     virtual ~MyGraphicBufferProducer() {
00483         LOG("bp d");
00484         delete mGBuf;
00485     }
00486 
00487     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) {
00488         LOG("rbf %d", slot);
00489         if (slot != 0) ABORT("rbf %d n 0", slot);
00490         if (mGBuf == NULL) ABORT("rbf bg n");
00491         *buf = mGBuf;
00492         mIsGBufferRequested = true;
00493         return 0;
00494     }
00495 
00496     virtual status_t setBufferCount(int bufferCount) {
00497         if (bufferCount==1) LOG("sbc %d", bufferCount);
00498         else ABORT("sbc %d", bufferCount);
00499         return 0;
00500     }
00501 
00502     #if (ANDROID_VER>=440)
00503         virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence, bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
00504     #elif (ANDROID_VER>=430)
00505         virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence, uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
00506     #elif (ANDROID_VER>=420)
00507         virtual status_t dequeueBuffer(int *slot, sp<Fence>& fence, uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
00508     #endif
00509     {
00510         #if (ANDROID_VER>=440)
00511             LOG("d w %d h %d f %d u 0x%x a %d", w, h, format, usage, async);
00512         #elif (ANDROID_VER>=420)
00513             LOG("d w %d h %d f %d u 0x%x", w, h, format, usage);
00514         #endif
00515         if (w != mWidth || h != mHeight) LOG("d w h abn");
00516 
00517         if (mGBuf==NULL) {
00518             if (format!=1 && format!=5) ABORT("f %d u", format);
00519             mFormat = format;
00520             int bpp = bytesPerPixel(format);
00521             if (bpp != BPP) ABORT("bpp %d u", bpp);
00522 
00523             mGBufUsage = (usage&~GRALLOC_USAGE_SW_READ_MASK)|mConsumerUsage;
00524 
00525             LOG("cr gb");
00526             mGBuf = new GraphicBuffer(mWidth, mHeight, mFormat, mGBufUsage);
00527             if (mGBuf==NULL) ABORT("n gb e");
00528             LOG("gb %p", mGBuf);
00529 
00530             LOG("g nb");
00531             ANativeWindowBuffer* nb = mGBuf->getNativeBuffer();
00532             LOGI("g nb r %p w %d h %d f %d s %d h %p", nb, nb->width, nb->height, nb->format, nb->stride, nb->handle);
00533             mInternalWidth = nb->stride;
00534 
00535             LOG("l gb");
00536             status_t err = mGBuf->lock(mConsumerUsage, (void**)&mGBufData);
00537             if (err || !mGBufData) ABORT("l gb e %d", err);
00538             LOG("l gb p %p", mGBufData);
00539         }
00540         else if (format != mFormat)  ABORT("d f %d n %d", format, mFormat);
00541 
00542         *slot = 0;
00543         #if (ANDROID_VER>=430)
00544             *fence = mFence; //set NULL cause android crash!!
00545         #elif (ANDROID_VER>=420)
00546             fence = mFence;
00547         #endif
00548         return mIsGBufferRequested ? 0 : IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
00549     }
00550 
00551     virtual status_t queueBuffer(int slot, const QueueBufferInput& input, QueueBufferOutput* output) {
00552         LOGI("q %d i %p o %p sq %lld", slot, &input, output, ++mSeq);
00553         size_t _fd_count = input.getFdCount();
00554         size_t _fl_size = input.getFlattenedSize();
00555         LOG("_q flsz %d fdc %d", _fl_size, _fd_count);
00556         if (_fd_count > 0) {
00557             if (mBufferInput_flattened_size < _fl_size || mBufferInput_flattened_buf==NULL) {
00558                 mBufferInput_flattened_buf = realloc(mBufferInput_flattened_buf, _fl_size);
00559                 mBufferInput_flattened_size = _fl_size;
00560             }
00561             if (mBufferInput_flattened_fd_count < _fd_count || mBufferInput_flattened_fds==NULL) {
00562                 mBufferInput_flattened_fds = (int*)realloc(mBufferInput_flattened_fds, _fd_count*sizeof(int));
00563                 mBufferInput_flattened_fd_count = _fd_count;
00564             }
00565         }
00566 
00567         if (slot != 0) ABORT("q %d n 0", slot);
00568 
00569         if (output) {
00570             LOG("_q so");
00571             output->width = mWidth;
00572             output->height = mHeight;
00573             output->transformHint = 0;
00574             output->numPendingBuffers = 0;
00575         }
00576 
00577         int orient = getOrient();
00578 
00579         AutoMutex autoLock(mutex);
00580         if (mBufferInput_flattened_fd_count > 0 && mBufferInput_flattened_buf !=NULL && mBufferInput_flattened_fds != NULL) {
00581             void* _fl_buf = mBufferInput_flattened_buf;
00582             int* _fds = mBufferInput_flattened_fds;
00583             LOG("_q fl");
00584             status_t err = input.flatten(_fl_buf, _fl_size, _fds, _fd_count); 
00585             LOG("_q fl r %d fd %d", err, mBufferInput_flattened_fds[0]);
00586             if (!err) {
00587                 mFence = sp<Fence>(new Fence(dup(mBufferInput_flattened_fds[0])));
00588             }
00589         }
00590 
00591         if (convertOrient(orient) != virtDispState->orientation) {
00592             setVirtDispOrient(orient);
00593         } else {
00594             mHaveData = true;
00595             #if ENABLE_RESEND
00596                 clock_gettime(CLOCK_MONOTONIC, &origTime);
00597                 resend_count = 0;
00598             #endif
00599             if ( isPaused ) {
00600                 //skip
00601             } else {
00602                 cond.signal(); //anyway wake up main or resend thread
00603             }
00604         }
00605         return 0;
00606     }
00607 
00608     #if (ANDROID_VER>=440)
00609         virtual void cancelBuffer(int slot, const sp<Fence>& fence)
00610     #elif (ANDROID_VER>=420)
00611         virtual void cancelBuffer(int slot, sp<Fence> fence)
00612     #endif
00613     {
00614         LOG("cb %d", slot);
00615     }
00616 
00617     virtual int query(int what, int* value) { //what is defined in window.h
00618         int err = 0;
00619         switch(what) {
00620         case NATIVE_WINDOW_WIDTH:
00621         case NATIVE_WINDOW_DEFAULT_WIDTH:
00622             LOG("qr w");
00623             *value = mWidth;
00624             break;
00625         case NATIVE_WINDOW_HEIGHT:
00626         case NATIVE_WINDOW_DEFAULT_HEIGHT:
00627             LOG("qr h");
00628             *value = mHeight;
00629             break;
00630         case NATIVE_WINDOW_FORMAT:
00631             LOG("qr f");
00632             *value = mFormat;
00633             break;
00634         case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
00635             LOG("qr cu");
00636             *value = mConsumerUsage;
00637             break;
00638         case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
00639             LOG("qr mub");
00640             *value = 0;
00641             break;
00642         case NATIVE_WINDOW_TRANSFORM_HINT:
00643             LOG("qr th");
00644             *value = 0;
00645             break;
00646         case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
00647             LOG("qr qwc");
00648             *value = 0;
00649             break;
00650         case NATIVE_WINDOW_CONCRETE_TYPE:
00651             LOG("qr ct");
00652             *value = 0;
00653             break;
00654         default:
00655             LOG("qr %d", what);
00656             err = -EINVAL;
00657         }
00658         return err;
00659     }
00660 
00661     #if (ANDROID_VER<440)
00662     virtual status_t setSynchronousMode(bool enabled) {
00663         LOG("m %d", enabled);
00664         return 0;
00665     }
00666     #endif
00667 
00668     #if (ANDROID_VER>=440)
00669         virtual status_t connect(const sp<IBinder>& token, int api, bool producerControlledByApp, QueueBufferOutput* output)
00670     #elif (ANDROID_VER>=420)
00671         virtual status_t connect(int api, QueueBufferOutput* output)
00672     #endif
00673     {
00674         LOG("c %d %p", api, output);
00675         if (output) {
00676             output->width = mWidth;
00677             output->height = mHeight;
00678             output->transformHint = 0;
00679             output->numPendingBuffers = 0;
00680         }
00681         return 0;
00682     }
00683 
00684     virtual status_t disconnect(int api) {
00685         LOG("dc");
00686     }
00687 
00688     #if (ANDROID_VER>=500)
00689         virtual status_t detachBuffer(int slot) {LOG("dtb %d", slot); return -EINVAL;}
00690         virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {LOG("dtnb"); return -EINVAL;};
00691         virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) {LOG("atb"); return -EINVAL;};
00692         virtual status_t setSidebandStream(/*const sp<NativeHandle>&*/void* stream) {LOG("ssbs"); return -EINVAL;};
00693         virtual void allocateBuffers(bool async, uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {LOG("atb");};
00694     #endif
00695 
00696     virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) {
00697         // analyse time sequence, determin each code
00698         static int bpStepOfCode[32] = {0/*invalid step*/};
00699         if (code <= 0 || code >= sizeof(bpStepOfCode)/sizeof(bpStepOfCode[0])) {
00700             LOG("t. %d ds %d c b", code, data.dataSize());
00701             return reply->writeInt32(-ENOSYS);
00702         }
00703         if (bpStepOfCode[code] < 0) {
00704             LOG("t. %d ds %d sk", code, data.dataSize());
00705             return reply->writeInt32(-ENOSYS);
00706         }
00707         if (bpStepOfCode[code] == 0) { //if not registered
00708             LOGI("t %d ds %d s?", code, data.dataSize());
00709             static int step = 1;
00710             if(step > bpStepMax) {
00711                 bpStepOfCode[code] = -1;
00712                 LOGI(".t %d ds %d s t m", code, data.dataSize());
00713                 return reply->writeInt32(-ENOSYS);
00714             }
00715             if (step==step_requestBuffer && code != 1) {
00716                 ABORT(".t %d ds %d c ! 1", code, data.dataSize());
00717             }
00718             if (step==step_queueBuffer && data.dataSize() < 128) {
00719                 bpStepOfCode[code] = -1;
00720                 LOGI(".t %d ds %d s t s", code, data.dataSize());
00721                 return reply->writeInt32(-ENOSYS);
00722             }
00723             LOGI("rg %d st%d", code, step);
00724             bpStepOfCode[code] = step;
00725 
00726             int ind = bpCodeToVirtIndex(code);
00727             if (ind != bpSteps[step].ind) {
00729                 // Adjust some virtual function's position
00731                 LOG("n rd");
00732                 AutoMutex autoLock(mutex);
00733                 static PVTBL old_vtbl = NULL;
00734                 if (!old_vtbl) {
00735                     LOG("pr pt");
00736                     old_vtbl = PVTBL_OF(this);
00737                     // for(int i=-ghostCnt; i<normalCnt; i++) LOG("vtbl[%d]:%p", i, old_vtbl[i]);
00738                     enum{ ghostCnt = 16, normalCnt=64};
00739                     static VADDR new_vtbl[ghostCnt+normalCnt] = {0};
00740                     memcpy(new_vtbl, old_vtbl-ghostCnt, sizeof(new_vtbl));
00741                     LOG("pt vt %p %p", old_vtbl, new_vtbl + ghostCnt);
00742                     PVTBL_OF(this) = new_vtbl + ghostCnt;
00743                 }
00744 
00745                 LOG("rd %p %p i%d i%d", PVTBL_OF(this)[ind], old_vtbl[bpSteps[step].ind], ind, bpSteps[step].ind);
00746                 PVTBL_OF(this)[ind] = old_vtbl[bpSteps[step].ind];
00747                 LOG(".rd");
00748             }
00749 
00750             step++;
00751         } // end of !bpStepOfCode[code])
00752         else {
00753             LOG("t %d ds %d s %d", code, data.dataSize(), bpStepOfCode[code]);
00754         }
00755 
00756         status_t err = BnGraphicBufferProducer::onTransact(code, data, reply, flags);
00757         LOG(".t %d r %d", code, err);
00758         return err;
00759     }
00760 };
00761 
00762 static uint32_t sniffered_transact_code = 0;
00763 
00764 void sniffTransact(IBinder* binder) {
00765     static VADDR old_addr = NULL;
00766     static VADDR sniffer_addr = NULL;
00767     static VADDR* p_cur_addr = NULL;
00768 
00769     struct TransactSniffer {
00770         virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
00771             LOG("sn tr c %d", code);
00772             sniffered_transact_code = code;
00773             LOG("st sn");
00774             *p_cur_addr = old_addr;
00775             status_t err = ((IBinder*)this)->transact(code, data, reply, flags);
00776             if (reply) {
00777                 LOG("rp %p %d %d", reply->data(), reply->dataSize(), reply->dataPosition());
00778                 int len = reply->dataSize();
00779                 for(int i = 0; i < len/sizeof(void*); i++) {
00780                     LOG("_rp %p", ((void**)reply->data())[i]);
00781                 }
00782             }
00783             return err;
00784         }
00785     };
00786 
00787     if (!p_cur_addr) {
00788         LOG("pr pt");
00789         PVTBL old_vtbl = PVTBL_OF(binder);
00790         // for(int i=-ghostCnt; i<normalCnt; i++) LOG("vtbl[%d]:%p", i, old_vtbl[i]);
00791         enum{ ghostCnt = 8, normalCnt=64};
00792         static VADDR new_vtbl[ghostCnt+normalCnt] = {0};
00793         memcpy(new_vtbl, old_vtbl-ghostCnt, sizeof(new_vtbl));
00794         LOG("pt vt %p %p", old_vtbl, new_vtbl + ghostCnt);
00795         PVTBL_OF(binder) = new_vtbl + ghostCnt;
00796 
00797         int ind = getVirtFuncIndex(&IBinder::transact);
00798         if (ind >= normalCnt || ind <= 0) ABORT("b t vi");
00799         old_addr = old_vtbl[ind];
00800         if (!old_addr) ABORT("b t a");
00801 
00802         TransactSniffer sniffer;
00803         sniffer_addr = PVTBL_OF(&sniffer)[0];
00804         if (!sniffer_addr) ABORT("b s a");
00805 
00806         p_cur_addr = &PVTBL_OF(binder)[ind];
00807     }
00808 
00809     LOG("s sn");
00810     *p_cur_addr = sniffer_addr;
00811 }
00812 
00813 static void asc_init(ASC* asc) {
00814     status_t err;
00815     chkDev();
00816     LOG("p %d", getpid());
00817 
00818     bpInitCallbackSteps();
00819 
00820     #if (ANDROID_VER>=430)
00821         //force loader fails in android 4.3, otherwise can not differ it with 4.4
00822         if (getpid()==-1) {
00823             sp<IBinder> tmp;
00824             SurfaceComposerClient::destroyDisplay(tmp);
00825         }
00826     #endif
00827     #if (ANDROID_VER>=500)
00828         //force loader fails in android 4.4, otherwise can not differ it with 5.0
00829         if (getpid()==-1) {
00830             ScreenshotClient s;
00831             sp<IBinder> d;
00832             status_t err = s.update(d, Rect(), 0, 0, false);
00833         }
00834     #endif
00835 
00836     LOG("stp");
00837     ProcessState::self()->startThreadPool();
00838 
00839     LOG("gs");
00840     __csBinder = defaultServiceManager()->getService(String16("SurfaceFlinger"));
00841     // __cs = ISurfaceComposer::asInterface(__csBinder);
00842 
00843     LOG("gbd");
00844     mainDisp = SurfaceComposerClient::getBuiltInDisplay(0 /*1 is hdmi*/);
00845     if (mainDisp.get()==NULL) ABORT("gbd e");
00846     LOG("bd %p", mainDisp.get());
00847 
00848     sniffTransact(__csBinder);
00849 
00850     LOG("gd");
00851     err = SurfaceComposerClient::getDisplayInfo(mainDisp, &mainDispInfo);
00852     if (err) ABORT("gdi e %d", err);
00853     LOG("gd w %d h %d o %d", mainDispInfo.w, mainDispInfo.h, mainDispInfo.orientation);
00854 
00855     TRANS_ID_GET_DISPLAY_INFO = sniffered_transact_code;
00856 
00857     LOG("r gd");
00858     //some device use strange head file which put ISurfaceComposer::getMainDisplayInfo after getBuiltInDisplay so vptr index changed, so test here
00859     // err = __cs->getDisplayInfo(mainDisp, &mainDispInfo);
00860     {
00861         Parcel data, reply;
00862         data.writeInterfaceToken(ISurfaceComposer::descriptor);
00863         data.writeStrongBinder(mainDisp);
00864         err = __csBinder->transact(TRANS_ID_GET_DISPLAY_INFO, data, &reply);
00865         if (err) ABORT("r gd abn");
00866         if (reply.dataSize() < MIN_DISP_INFO_SIZE) ABORT("r gd s t l");
00867         DisplayInfo* info = (DisplayInfo*)(reply.data() + MIN_DISP_INFO_HEAD_SIZE);
00868         if (info->w != mainDispInfo.w || info->h != mainDispInfo.h) ABORT("r gd abn. w %d h %d", info->w, info->h);
00869         mainDispInfo.orientation = info->orientation;
00870     }
00871     LOG(".r gd w %d h %d o %d", mainDispInfo.w, mainDispInfo.h, mainDispInfo.orientation);
00872 
00873     if (mainDispInfo.w > mainDispInfo.h) {
00874         LOGI("i w gt h");
00875         int h = mainDispInfo.h;
00876         mainDispInfo.h = mainDispInfo.w;
00877         mainDispInfo.w = h;
00878         internal_w_gt_h = true;
00879     }
00880 
00881     //sample mainDispInfo: {w:720, h:1280}
00882 
00883     LOG("o c r w %d h %d", asc->w, asc->h);
00884     if (!asc->w && !asc->h) {  //normal case
00885         capture_w = mainDispInfo.w;
00886         capture_h = mainDispInfo.h;
00887     } else if (asc->w && !asc->h) {
00888         capture_w = toEvenInt(asc->w);
00889         capture_h = toEvenInt(asc->w*mainDispInfo.h/mainDispInfo.w);
00890     } else if (asc->h && !asc->w) {
00891         capture_h = toEvenInt(asc->h);
00892         capture_w = toEvenInt(asc->h*mainDispInfo.w/mainDispInfo.h);
00893     } else { //asc->w && asc->h
00894         capture_w = toEvenInt(asc->w);
00895         capture_h = toEvenInt(asc->h);
00896     }
00897     logicalFrameSize = capture_w*capture_h*BPP;
00898     LOG("c c r w %d h %d ar", capture_w, capture_h);
00899 
00900 
00901     if (isatty(STDOUT_FILENO)) {
00902         LOG("iaty");
00903         struct termios term;
00904         if (tcgetattr(STDOUT_FILENO, &term)) ABORT_ERRNO("tga");
00905         LOG("mkr");
00906         cfmakeraw(&term);
00907         LOG("tsa");
00908         if (tcsetattr(STDOUT_FILENO, TCSANOW, &term)) ABORT_ERRNO("tsa");
00909     }
00910 
00911     create_cmd_socket_server();
00912     create_touch_socket_server();
00913 }
00914 
00915 static void asc_create_virtual_display() {
00916     status_t err;
00917     Rect mainViewPort, virtViewPort;
00918     mainViewPort.right = mainViewPort.bottom = max(mainDispInfo.w, mainDispInfo.h);
00919     virtViewPort.right = virtViewPort.bottom = max(capture_w, capture_h);
00920 
00921     LOG("cd");
00922     virtDisp = SurfaceComposerClient::createDisplay(String8("QJASC"), true /*secure*/);
00923     if (virtDisp.get()==NULL) ABORT("cd e");
00924 
00925     bp = new MyGraphicBufferProducer(capture_w, capture_h);
00926 
00927     LOG("pr ds");
00928     SurfaceComposerClient::openGlobalTransaction();
00929     SurfaceComposerClient::setDisplaySurface(virtDisp, NULL);
00930     SurfaceComposerClient::setDisplayProjection(virtDisp, 0, /*layerStackRect:*/mainViewPort, /*displayRect:*/virtViewPort);
00931     SurfaceComposerClient::setDisplayLayerStack(virtDisp, 0);
00932 
00933     sniffTransact(__csBinder);
00934 
00935     LOG("t sds");
00936     SurfaceComposerClient::closeGlobalTransaction();
00937 
00938     TRANS_ID_SET_DISPLAY_STATE = sniffered_transact_code;
00939 
00940     LOG("pr r ds");
00941     // _displayStates.add();
00942     // virtDispState = _displayStates.editArray();
00943     virtDispState->what = DisplayState::eSurfaceChanged|DisplayState::eLayerStackChanged|DisplayState::eDisplayProjectionChanged;
00944     virtDispState->token = virtDisp;
00945     virtDispState->surface = bp;
00946     virtDispState->orientation = convertOrient(mainDispInfo.orientation);
00947     virtDispState->viewport = mainViewPort;
00948     virtDispState->frame = virtViewPort;
00949     virtDispState->layerStack = 0;
00950     LOG("r sds o %d mo %d", virtDispState->orientation, mainDispInfo.orientation);
00951     // __cs->setTransactionState(_emptyComposerStates, _displayStates, 0);
00952     {
00953         Parcel data;
00954         data.writeInterfaceToken(ISurfaceComposer::descriptor);
00955         data.writeInt32(0);
00956         data.writeInt32(1);
00957         virtDispState->write(data);
00958         data.writeInt32(0/*flags*/);
00959         status_t err = __csBinder->transact(TRANS_ID_SET_DISPLAY_STATE, data, NULL, 1/*TF_ONE_WAY*/);
00960         if (err) ABORT("r sds e %d", err);
00961     }
00962 }
00963 
00964 extern "C" void asc_capture(ASC* asc) {
00965     status_t err;
00966     AutoMutex autoLock(mutex);
00967     static int64_t seq = 0;
00968 
00969     if (isFirstTime) {
00970         asc_init(asc);
00971         asc_create_virtual_display();
00972     }
00973 
00974     #if ENABLE_RESEND
00975         if (!isFirstTime && !bp->mHaveData && !isPaused && resend_count < RESEND_COUNT) {
00976             struct timespec now;
00977             clock_gettime(CLOCK_MONOTONIC, &now);
00978             if ( (now.tv_sec-origTime.tv_sec)*1000000000 + (now.tv_nsec-origTime.tv_nsec) >= RESEND_INTERVAL_NS*RESEND_COUNT) {
00979                 if (resend_count == 0) {
00980                     LOG("rt pr d rs lst sq %lld t c c...", seq);
00981                     resend_count = RESEND_COUNT;
00982                     return; //this cause caller reuse previous buffer pointer which contents maybe has been changed
00983                 }
00984             } else {
00985                 struct timespec untilTime = (resend_count==0) ? origTime : lastRereadTime;
00986                 if ((untilTime.tv_nsec += RESEND_INTERVAL_NS) >= 1000000000) {
00987                     untilTime.tv_nsec -= 1000000000;
00988                     untilTime.tv_sec++;
00989                 }
00990                 LOG("dl mx %d ms 4 ru d", ((untilTime.tv_sec-now.tv_sec)*1000000000 + (untilTime.tv_nsec-now.tv_nsec))/1000000);
00991                 if ((err=cond.waitAbsMono(mutex, &untilTime)) == -ETIMEDOUT) {
00992                     LOG("rt pr d rs sq %lld  t c c...", seq);
00993                     resend_count++;
00994                     #if RESEND_COUNT > 1
00995                         clock_gettime(CLOCK_MONOTONIC, &lastRereadTime);
00996                     #endif
00997                     return; //this cause caller reuse previous buffer pointer which contents maybe has been changed
00998                 }
00999             }
01000         }
01001     #endif
01002 
01003     for(;;) {
01004         if (isPaused && !isFirstTime) {
01005             if (blackscreen==NULL) {
01006                 asc->data = blackscreen = (char*)malloc(asc->size);
01007                 if (!blackscreen) ABORT("oom");
01008                 memset(blackscreen,  isScreenOff ? 0 : 0x40, asc->size);
01009                 LOGI("use blackscreen");
01010                 return;
01011             }
01012             else {
01013                 if (blackscreen_extra_count++ < 3) { //very strange!
01014                     asc->data = blackscreen;
01015                     LOG("use blackscreen");
01016                     return;
01017                 }
01018                 blackscreen_extra_count = 0;
01019                 free(blackscreen);
01020                 blackscreen = NULL;
01021 
01022                 do {
01023                     LOGI("wait for resume");
01024                     cond.wait(mutex);
01025                 } while ( isPaused );
01026 
01027                 bp->mHaveData = true; //force send image
01028                 #if ENABLE_RESEND
01029                     clock_gettime(CLOCK_MONOTONIC, &origTime);
01030                     resend_count = 0;
01031                 #endif
01032             }
01033         } //end of if (isPaused)
01034 
01035         if ( bp->mHaveData )
01036             break;
01037         LOG("w 4 d");
01038         cond.wait(mutex);
01039     }
01040     LOG("g n d e");
01041     bp->mHaveData = false;
01042     asc->data = bp->mGBufData;
01043 
01044     if (bp->mFence && bp->mFence->isValid()) {
01045          LOG("w 4 f");
01046          bp->mFence->wait(-1);
01047     }
01048 
01049     if (isFirstTime) {
01050         asc->w = bp->mInternalWidth;
01051         asc->h = bp->mHeight;
01052         strcpy(asc->pixfmtName, bp->mFormat==1?"rgb0":"bgr0");
01053         asc->size = bp->mInternalWidth*bp->mHeight*BPP;
01054         if (isPaused) {
01055             asc->data = blackscreen = (char*)calloc(asc->size, 1);
01056             if (!blackscreen) ABORT("oom");
01057             memset(blackscreen,  isScreenOff ? 0 : 0x40, asc->size);
01058             LOGI("use blackscreen");
01059         }
01060     }
01061     
01062     seq++;
01063     LOGI("r d sq %lld", seq);
01064 
01065     if (isFirstTime) {
01066         if (! (getenv("ASC_LOG_ALL") && atoi(getenv("ASC_LOG_ALL")) > 0) )
01067             needLog = false;
01068         isFirstTime = false;
01069     }
01070 }
01071 
01072 #if MAKE_TEST==1
01073     extern "C" int main(int argc, char** argv) {
01074         ASC asc;
01075         memset(&asc, 0, sizeof(ASC));
01076         asc.w = argc>1 && atoi(argv[1])> 0 ? atoi(argv[1]) : 0;
01077         asc.h = argc>2 && atoi(argv[2])> 0 ? atoi(argv[2]) : 0;
01078 
01079         for(;;) {
01080             asc_capture(&asc);
01081             static int64_t seq = 0;
01082             LOGI("o i %lld", ++seq);
01083             write(1, asc.data, asc.size);
01084             #if 0
01085                 LOG("encode to jpeg");
01086                 SkData* streamData;
01087                 {
01088                     SkBitmap b;
01089                     if (!b.setConfig(SkBitmap::kARGB_8888_Config, mWidth, mHeight, mInternalWidth*BPP)) ABORT("failed to setConfig");
01090                     b.setPixels(mGBufData);
01091                     SkDynamicMemoryWStream stream;
01092                     if (!SkImageEncoder::EncodeStream(&stream, b, SkImageEncoder::kJPEG_Type, 100)) ABORT("failed to encode to jpeg");
01093                     LOG("get jpeg");
01094                     streamData = stream.copyToData();
01095                     write(1/*stdout*/, streamData->p, streamData->size);
01096                 }
01097                 delete streamData;
01098             #endif
01099         }
01100     }
01101 #endif
01102 


dji_ronin
Author(s):
autogenerated on Sat Jun 8 2019 20:15:31