Android系统截屏的实现分析

来源:互联网 发布:上海大承网络 空中网 编辑:程序博客网 时间:2024/06/06 03:22



先来看看别个总结的流程(自己本来想画个,发现找到个就不造车了)


(该图引自http://blog.csdn.net/hk_256/article/details/7306590)

    源码部分

喔  对鸟,这个是5.1的代码,kk的没有研究过,想必也差不多

interceptKeyBeforeQueueing()拦截按键信息
interceptScreenshotChord():handler调用截屏
    private void interceptScreenshotChord() {        if (mScreenshotChordEnabled                && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered                && !mScreenshotChordVolumeUpKeyTriggered) {            final long now = SystemClock.uptimeMillis();            if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS                    && now <= mScreenshotChordPowerKeyTime                    + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {                mScreenshotChordVolumeDownKeyConsumed = true;                cancelPendingPowerKeyAction();                mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());            }        }    }    private final Runnable mScreenshotRunnable = new Runnable() {        @Override        public void run() {            takeScreenshot();        }    };

private void takeScreenshot() {        synchronized (mScreenshotLock) {            if (mScreenshotConnection != null) {                return;            }            ComponentName cn = new ComponentName("com.android.systemui",                    "com.android.systemui.screenshot.TakeScreenshotService");//实际上是通过启动systemui的TakeScreenshotServiceservice来实现            Intent intent = new Intent();            intent.setComponent(cn);            ServiceConnection conn = new ServiceConnection() {                @Override                public void onServiceConnected(ComponentName name, IBinder service) {                    synchronized (mScreenshotLock) {                        if (mScreenshotConnection != this) {                            return;                        }                        Messenger messenger = new Messenger(service);                        Message msg = Message.obtain(null, 1);                        final ServiceConnection myConn = this;                        Handler h = new Handler(mHandler.getLooper()) {                            @Override                            public void handleMessage(Message msg) {                                synchronized (mScreenshotLock) {                                    if (mScreenshotConnection == myConn) {                                        mContext.unbindService(mScreenshotConnection);                                        mScreenshotConnection = null;                                        mHandler.removeCallbacks(mScreenshotTimeout);                                    }                                }                            }                        };                        msg.replyTo = new Messenger(h);                        msg.arg1 = msg.arg2 = 0;                        if (mStatusBar != null && mStatusBar.isVisibleLw())                            msg.arg1 = 1;                        if (mNavigationBar != null && mNavigationBar.isVisibleLw())                            msg.arg2 = 1;                        try {                            messenger.send(msg);                        } catch (RemoteException e) {                        }                    }                }                @Override                public void onServiceDisconnected(ComponentName name) {}            };            if (mContext.bindServiceAsUser(                    intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {                mScreenshotConnection = conn;                mHandler.postDelayed(mScreenshotTimeout, 10000);            }        }    }


public class TakeScreenshotService extends Service {    private static final String TAG = "TakeScreenshotService";    private static GlobalScreenshot mScreenshot;    private Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case 1:                    final Messenger callback = msg.replyTo;                    if (mScreenshot == null) {                        mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);                    }                    mScreenshot.takeScreenshot(new Runnable() {                        @Override public void run() {                            Message reply = Message.obtain(null, 1);                            try {                                callback.send(reply);                            } catch (RemoteException e) {                            }                        }                    }, msg.arg1 > 0, msg.arg2 > 0);//这个方法执行截屏,以及window的ui效果等            }        }    };    @Override    public IBinder onBind(Intent intent) {        return new Messenger(mHandler).getBinder();    }}

在SurfaceControl类中,在这儿调用底层nativeScreenshot方法截屏

    /**     * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but     * with builtInDisplayId in the screenshot.     *     * @param width The desired width of the returned bitmap; the raw     * screen will be scaled down to this size.     * @param height The desired height of the returned bitmap; the raw     * screen will be scaled down to this size.     * @param builtInDisplayId The Built-in physical display id.     * @return Returns a Bitmap containing the screen contents, or null     * if an error occurs. Make sure to call Bitmap.recycle() as soon as     * possible, once its content is not needed anymore.     *     * @hide     */    public static Bitmap screenshot(int width, int height, int builtInDisplayId) {        IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);        Log.d(TAG, "screenshot, builtInDisplayId = " + builtInDisplayId);        return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true,                false, Surface.ROTATION_0);    }


再找到对应的jni

static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,        jobject surfaceObj, jobject sourceCropObj, jint width, jint height,        jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);    if (displayToken != NULL) {        sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj);        if (consumer != NULL) {            int left = env->GetIntField(sourceCropObj, gRectClassInfo.left);            int top = env->GetIntField(sourceCropObj, gRectClassInfo.top);            int right = env->GetIntField(sourceCropObj, gRectClassInfo.right);            int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom);            Rect sourceCrop(left, top, right, bottom);            if (allLayers) {                minLayer = 0;                maxLayer = -1;            }            ScreenshotClient::capture(displayToken,                    consumer->getIGraphicBufferProducer(), sourceCrop,                    width, height, uint32_t(minLayer), uint32_t(maxLayer),                    useIdentityTransform);        }    }}

再往下

status_t ScreenshotClient::capture(        const sp<IBinder>& display,        const sp<IGraphicBufferProducer>& producer,        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,        uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform) {    sp<ISurfaceComposer> s(ComposerService::getComposerService());    if (s == NULL) return NO_INIT;    return s->captureScreen(display, producer, sourceCrop,            reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);}


再找找

    virtual status_t captureScreen(const sp<IBinder>& display,            const sp<IGraphicBufferProducer>& producer,            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,            uint32_t minLayerZ, uint32_t maxLayerZ,            bool useIdentityTransform,            ISurfaceComposer::Rotation rotation)    {        Parcel data, reply;        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());        data.writeStrongBinder(display);        data.writeStrongBinder(producer->asBinder());        data.write(sourceCrop);        data.writeInt32(reqWidth);        data.writeInt32(reqHeight);        data.writeInt32(minLayerZ);        data.writeInt32(maxLayerZ);        data.writeInt32(static_cast<int32_t>(useIdentityTransform));        data.writeInt32(static_cast<int32_t>(rotation));        remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);        return reply.readInt32();    }

搬个源码做个笔记

再往下就是涉及底层buffer之类的处理了=。=  

0 1
原创粉丝点击