vysor原理以及Android同屏方案
今天調式個8155 的demo板子,顯示模塊插拔線沒有,無法看到顯示的畫面,但是領導要看畫面,后來想到了使用android模擬器的環境進行搭建,最早調式手機的時候都是沒有屏幕的,都是使用安卓模擬器調式的,下面介紹些vysor的同屏顯示原理
===》vysor 同屏顯示原理
直接上干活
adb shell能夠調用screencap或者screenshot來截取屏幕,那就說明adb shell具備截屏的權限。Surface/SurfaceControl和screenshot/screencap它們內部的實現機制應該是相同的,因此也就是說adb shell是具備截屏權限的也就是可以調用到Surface/SurfaceControl。那么咱們怎么經過adb shell來調用到這兩個類呢,答案就是app_process。app_process能夠直接運行一個普通的java類,詳細的資料你們能夠在網上找到。也就是說咱們經過adb shell運行app_process,而后經過app_process來運行一個java類,在java類中就能夠訪問到Surface/SurfaceControl這兩個類,是否是很巧妙?
adb shell 截屏
H264 壓縮
encoder? 編碼壓縮
public static void main(String[] args) throws Exception {if (args.length > 0) {commandLinePassword = args[0];Log.i(LOGTAG, "Received command line password: " + commandLinePassword);}Looper.prepare();looper = Looper.myLooper();AsyncServer server = new AsyncServer();AsyncHttpServer httpServer = new AsyncHttpServer() {protected boolean onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {Log.i(Main.LOGTAG, request.getHeaders().toString());return super.onRequest(request, response);}};String str = "getInstance";Object[] objArr = new Object[0];InputManager im = (InputManager) InputManager.class.getDeclaredMethod(r20, new Class[0]).invoke(null, objArr);str = "obtain";MotionEvent.class.getDeclaredMethod(r20, new Class[0]).setAccessible(true);str = "injectInputEvent";Method injectInputEventMethod = InputManager.class.getMethod(r20, new Class[]{InputEvent.class, Integer.TYPE});KeyCharacterMap kcm = KeyCharacterMap.load(-1);Class cls = Class.forName("android.os.ServiceManager");Method getServiceMethod = cls.getDeclaredMethod("getService", new Class[]{String.class});IClipboard clipboard = IClipboard.Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"clipboard"}));clipboard.addPrimaryClipChangedListener(new AnonymousClass3(clipboard), null);IPowerManager pm = IPowerManager.Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"power"}));IWindowManager wm = IWindowManager.Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));IRotationWatcher watcher = new Stub() {public void onRotationChanged(int rotation) throws RemoteException {if (Main.webSocket != null) {Point displaySize = SurfaceControlVirtualDisplayFactory.getCurrentDisplaySize();JSONObject json = new JSONObject();try {json.put("type", "displaySize");json.put("screenWidth", displaySize.x);json.put("screenHeight", displaySize.y);json.put("nav", Main.hasNavBar());Main.webSocket.send(json.toString());} catch (JSONException e) {}}}};wm.watchRotation(watcher);httpServer.get("/screenshot.jpg", new AnonymousClass5(wm));httpServer.websocket("/input", "mirror-protocol", new AnonymousClass6(watcher, im, injectInputEventMethod, pm, wm, kcm));httpServer.get("/h264", new AnonymousClass7(im, injectInputEventMethod, pm, wm));Log.i(LOGTAG, "Server starting");AsyncServerSocket rawSocket = server.listen(null, 53517, new AnonymousClass8(wm));if (httpServer.listen(server, 53516) == null || rawSocket == null) {System.out.println("No server socket?");Log.e(LOGTAG, "No server socket?");throw new AssertionError("No server socket?");}System.out.println("Started");Log.i(LOGTAG, "Waiting for exit");Looper.loop();Log.i(LOGTAG, "Looper done");server.stop();if (current != null) {current.stop();current = null;}Log.i(LOGTAG, "Done!");System.exit(0);}這個軟件koushikdutta是由開發的,這個團隊之前發布過一個很是流行的開源網絡庫:async。在這個項目中也用到了這個開源庫。main函數主要是新建了一個httpserver而后開放了幾個接口,經過screenshot.jpg獲取截圖,經過socket input接口來發送點擊信息,經過h264這個接口來獲取實時的屏幕視頻流。每個接口都有對應的響應函數,這里咱們主要研究截圖,因此就看screenshot這個接口。h264這個接口傳輸的是實時的視頻流,因此就流暢性來講應該會更好,它也是經過virtualdisplay來實現的有興趣的讀者能夠自行研究。
接下來咱們來看screenshot對應的響應函數AnonymousClass5的實現代碼。
* renamed from: com.koushikdutta.vysor.Main.5 */static class AnonymousClass5 implements HttpServerRequestCallback {final /* synthetic */ IWindowManager val$wm;AnonymousClass5(IWindowManager iWindowManager) {this.val$wm = iWindowManager;}public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {if (Main.checkPassword(request.getQuery().getString("password"))) {Log.i(Main.LOGTAG, "screenshot authentication success");try {Bitmap bitmap = EncoderFeeder.screenshot(this.val$wm);ByteArrayOutputStream bout = new ByteArrayOutputStream();bitmap.compress(CompressFormat.JPEG, 100, bout);bout.flush();response.send("image/jpeg", bout.toByteArray());return;} catch (Exception e) {response.code(500);response.send(e.toString());return;}}Log.i(Main.LOGTAG, "screenshot authentication failed");response.code(401);response.send("Not Authorized.");}}這個類傳入了一個wm類,這個類是用來監聽屏幕旋轉的,這里不用管它。另外在vysor開始運行時,會隨機生成一個驗證碼,只有驗證經過才能進行鏈接,因此這里有一個驗證的過程,這里也不過管。能夠看到這個類定義的響應函數的代碼很是簡單,就是經過EncoderFeeder.screenshot()函數來過去截圖的bitmap,而后返回給請求端。那么EncoderFeeder.screenshot這個函數是怎樣實現截圖的呢?
總結
以上是生活随笔為你收集整理的vysor原理以及Android同屏方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DDR读写源码测试
- 下一篇: linux strace 用法