int minicap_try_get_display_info(int32_t displayId, Minicap::DisplayInfo* info) { android::sp<android::IBinder> dpy = android::SurfaceComposerClient::getBuiltInDisplay(displayId); android::Vector<android::DisplayInfo> configs; android::status_t err = android::SurfaceComposerClient::getDisplayConfigs(dpy, &configs); if (err != android::NO_ERROR) { MCERROR("SurfaceComposerClient::getDisplayInfo() failed: %s (%d)\n", error_name(err), err); return err; } int activeConfig = android::SurfaceComposerClient::getActiveConfig(dpy); if(static_cast<size_t>(activeConfig) >= configs.size()) { MCERROR("Active config %d not inside configs (size %zu)\n", activeConfig, configs.size()); return android::BAD_VALUE; } android::DisplayInfo dinfo = configs[activeConfig]; info->width = dinfo.w; info->height = dinfo.h; info->orientation = dinfo.orientation; info->fps = dinfo.fps; info->density = dinfo.density; info->xdpi = dinfo.xdpi; info->ydpi = dinfo.ydpi; info->secure = dinfo.secure; info->size = sqrt(pow(dinfo.w / dinfo.xdpi, 2) + pow(dinfo.h / dinfo.ydpi, 2)); return 0; }
virtual int consumePendingFrame(Minicap::Frame* frame) { android::status_t err; if ((err = mConsumer->lockNextBuffer(&mBuffer)) != android::NO_ERROR) { if (err == -EINTR) { return err; } else { MCERROR("Unable to lock next buffer %s (%d)", error_name(err), err); return err; } } frame->data = mBuffer.data; frame->format = convertFormat(mBuffer.format); frame->width = mBuffer.width; frame->height = mBuffer.height; frame->stride = mBuffer.stride; frame->bpp = android::bytesPerPixel(mBuffer.format); frame->size = mBuffer.stride * mBuffer.height * frame->bpp; mHaveBuffer = true; return 0; }
__declspec(dllexport) BOOL MCPatch(HANDLE hProcess) { const BYTE sig_patch[] = { 0x55, 0x8B, 0xEC, 0x81, 0xEC, 0x2C, 0x01, 0x00, 0x00, 0x53, 0x56, 0x8B, 0xDA, 0x8B, 0xF1, 0x57 }; BYTE* mcpatch = NULL; if (!ReadProcessMemory(hProcess, (void*)0x401000, g__gwdata, 0x49a000, NULL)) { return FALSE; } for (DWORD i = 0; i < 0x49a000; ++i) { if (!memcmp(g__gwdata + i, sig_patch, sizeof(sig_patch))) { mcpatch = (BYTE*)(0x401000 + i); break; } } if (!mcpatch) return FALSE; printf("mcpatch = %X\n",mcpatch); const BYTE payload[] = { 0x31, 0xC0, 0x90, 0xC3 }; if (!WriteProcessMemory(hProcess, mcpatch, payload, sizeof(payload), NULL)) MCERROR("WriteProcessMemory mcpatch"); return TRUE; }
virtual int consumePendingFrame(Minicap::Frame* frame) { uint32_t width, height; android::PixelFormat format; android::status_t err; mHeap = NULL; err = mComposer->captureScreen(mDisplayId, &mHeap, &width, &height, &format, mDesiredWidth, mDesiredHeight, 0, -1UL); if (err != android::NO_ERROR) { MCERROR("ComposerService::captureScreen() failed %s", error_name(err)); return err; } frame->data = mHeap->getBase(); frame->width = width; frame->height = height; frame->format = convertFormat(format); frame->stride = width; frame->bpp = android::bytesPerPixel(format); frame->size = mHeap->getSize(); return 0; }
int minicap_try_get_display_info(int32_t displayId, Minicap::DisplayInfo* info) { android::DisplayInfo dinfo; android::status_t err = android::SurfaceComposerClient::getDisplayInfo(displayId, &dinfo); if (err != android::NO_ERROR) { MCERROR("SurfaceComposerClient::getDisplayInfo() failed: %s (%d)\n", error_name(err), err); return err; } info->width = dinfo.w; info->height = dinfo.h; info->orientation = dinfo.orientation; info->fps = dinfo.fps; info->density = dinfo.density; info->xdpi = dinfo.xdpi; info->ydpi = dinfo.ydpi; info->secure = false; info->size = sqrt(pow(dinfo.w / dinfo.xdpi, 2) + pow(dinfo.h / dinfo.ydpi, 2)); return 0; }
int createVirtualDisplay() { uint32_t sourceWidth, sourceHeight; uint32_t targetWidth, targetHeight; android::status_t err; switch (mDesiredOrientation) { case Minicap::ORIENTATION_90: sourceWidth = mRealHeight; sourceHeight = mRealWidth; targetWidth = mDesiredHeight; targetHeight = mDesiredWidth; break; case Minicap::ORIENTATION_270: sourceWidth = mRealHeight; sourceHeight = mRealWidth; targetWidth = mDesiredHeight; targetHeight = mDesiredWidth; break; case Minicap::ORIENTATION_180: sourceWidth = mRealWidth; sourceHeight = mRealHeight; targetWidth = mDesiredWidth; targetHeight = mDesiredHeight; break; case Minicap::ORIENTATION_0: default: sourceWidth = mRealWidth; sourceHeight = mRealHeight; targetWidth = mDesiredWidth; targetHeight = mDesiredHeight; break; } // Set up virtual display size. android::Rect layerStackRect(sourceWidth, sourceHeight); android::Rect visibleRect(targetWidth, targetHeight); // Create a Surface for the virtual display to write to. MCINFO("Creating SurfaceComposerClient"); android::sp<android::SurfaceComposerClient> sc = new android::SurfaceComposerClient(); MCINFO("Performing SurfaceComposerClient init check"); if ((err = sc->initCheck()) != android::NO_ERROR) { MCERROR("Unable to initialize SurfaceComposerClient"); return err; } // Create virtual display. MCINFO("Creating virtual display"); mVirtualDisplay = android::SurfaceComposerClient::createDisplay( /* const String8& displayName */ android::String8("minicap"), /* bool secure */ true ); MCINFO("Creating buffer queue"); android::BufferQueue::createBufferQueue(&mBufferProducer, &mBufferConsumer); mBufferConsumer->setDefaultBufferSize(targetWidth, targetHeight); mBufferConsumer->setDefaultBufferFormat(android::PIXEL_FORMAT_RGBA_8888); MCINFO("Creating CPU consumer"); mConsumer = new android::CpuConsumer(mBufferConsumer, 3, false); mConsumer->setName(android::String8("minicap")); MCINFO("Creating frame waiter"); mFrameProxy = new FrameProxy(mUserFrameAvailableListener); mConsumer->setFrameAvailableListener(mFrameProxy); MCINFO("Publishing virtual display"); android::SurfaceComposerClient::openGlobalTransaction(); android::SurfaceComposerClient::setDisplaySurface(mVirtualDisplay, mBufferProducer); android::SurfaceComposerClient::setDisplayProjection(mVirtualDisplay, android::DISPLAY_ORIENTATION_0, layerStackRect, visibleRect); android::SurfaceComposerClient::setDisplayLayerStack(mVirtualDisplay, 0); // default stack android::SurfaceComposerClient::closeGlobalTransaction(); mHaveRunningDisplay = true; return 0; }