安卓Winscope原理

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

简介

谷歌介绍文档:https://source.android.com/docs/core/graphics/tracing-win-transitions

安卓手机内置抓取Winscope流程:

  1. 打开 开发者选项-快捷设置开发者图块-Winscope跟踪;
  2. 下拉控制中心即会出现Winscope跟踪按钮;
  3. 点击Winscope跟踪按钮开始录制,再次点击停止录制,录制文件保存在手机/data/misc/wmtrace目录下;

谷歌文档说“跟踪记录会被写入/data/misc/wmtrace/wm_trace.winscope和/data/misc/wmtrace/layers_trace.winscope,同时还会包含在错误报告中。”。

本文分析安卓抓取Winscope代码流程。

Winscope发起录制

在设置app中有一个服务DevelopmentTiles$WinscopeTrace用来完成winscope的抓取。其定义在packages/apps/Settings/src/com/android/settings/development/qstile/DevelopmentTiles.java:

    /**
     * Tile to toggle Winscope trace which consists of Window and Layer traces.
     */
    public static class WinscopeTrace extends DevelopmentTiles {
        @VisibleForTesting
        static final int SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE = 1025;
        @VisibleForTesting
        static final int SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE = 1026;
        private IBinder mSurfaceFlinger;
        private IWindowManager mWindowManager;
        private ImeTracing mImeTracing;
        private Toast mToast;

        @Override
        public void onCreate() {
            super.onCreate();
            mWindowManager = WindowManagerGlobal.getWindowManagerService();
            mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
            mImeTracing = ImeTracing.getInstance();
            Context context = getApplicationContext();
            CharSequence text = "Trace files written to /data/misc/wmtrace";
            mToast = Toast.makeText(context, text, Toast.LENGTH_LONG);
        }
        ......
    }

这个服务在onCreate中获取了要抓取Winscope的相关系统服务的binder,其中包括SurfaceFlinger,WindowManager等,还准备了录制完成时弹出的Toast。

这个服务主要是通过点击时调用setIsEnabled方法开开始/结束录制:

        @Override
        protected void setIsEnabled(boolean isEnabled) {
            setWindowTraceEnabled(isEnabled);
            setLayerTraceEnabled(isEnabled);
            setSystemUiTracing(isEnabled);
            setImeTraceEnabled(isEnabled);
            if (!isEnabled) {
                mToast.show();
            }
        }

其中setWindowTraceEnabled方法:

        private void setWindowTraceEnabled(boolean isEnabled) {
            try {
                if (isEnabled) {
                    mWindowManager.startWindowTrace();
                } else {
                    mWindowManager.stopWindowTrace();
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Could not set window trace status." + e.toString());
            }
        }

这等同于执行命令adb shell cmd window tracing start和adb shell cmd window tracing stop。

其中setLayerTraceEnabled方法:

        private void setLayerTraceEnabled(boolean isEnabled) {
            Parcel data = null;
            try {
                if (mSurfaceFlinger != null) {
                    data = Parcel.obtain();
                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
                    data.writeInt(isEnabled ? 1 : 0);
                    mSurfaceFlinger.transact(SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE,
                            data, null, 0 /* flags */);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Could not set layer tracing." + e.toString());
            } finally {
                if (data != null) {
                    data.recycle();
                }
            }
        }

这等同于执行命令adb shell service call SurfaceFlinger 1025 i32 1和adb shell service call SurfaceFlinger 1025 i32 0

WindowManager

开始录制时会调用WindowTracing的startTrace方法:(frameworks/base/services/core/java/com/android/server/wm/WindowTracing.java)

    void startTrace(@Nullable PrintWriter pw) {
        if (IS_USER) { // user版本的镜像不支持抓取Winscope
            logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
            return;
        }
        synchronized (mEnabledLock) {
            ProtoLogImpl.getSingleInstance().startProtoLog(pw);
            logAndPrintln(pw, "Start tracing to " + mTraceFile + ".");
            mBuffer.resetBuffer(); // 存录制数据的buffer
            mEnabled = mEnabledLockFree = true;
        }
        log("trace.enable"); // 录制一帧
    }

首先判断当前系统是否为user版本,如果是user版本则直接return不支持录制。

接下来调用mBuffer的resetBuffer清空这个buffer,后续的录制数据都存储在这个mBuffer中。然后调用log方法录制一帧:(frameworks/base/services/core/java/com/android/server/wm/WindowTracing.java)

    /**
     * Write the current frame to the buffer
     *
     * @param where Logging point descriptor
     */
    private void log(String where) {
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "traceStateLocked");
        try {
            ProtoOutputStream os = new ProtoOutputStream(); // 准备输出流
            long tokenOuter = os.start(ENTRY);
            os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
            os.write(WHERE, where);

            long tokenInner = os.start(WINDOW_MANAGER_SERVICE);
            synchronized (mGlobalLock) {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "dumpDebugLocked");
                try {
                    mService.dumpDebugLocked(os, mLogLevel); // 录制一帧
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                }
            }
            os.end(tokenInner);
            os.end(tokenOuter);
            mBuffer.add(os); // 录制的这一帧数据填入mBuffer
            mScheduled = false;
        } catch (Exception e) {
            Log.wtf(TAG, "Exception while tracing state", e);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        }
    }

其中是通过WindowManagerService的dumpDebugLocked方法录制的:(frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java)

    /**
     * Write to a protocol buffer output stream. Protocol buffer message definition is at
     * {@link com.android.server.wm.WindowManagerServiceDumpProto}.
     *
     * @param proto     Stream to write the WindowContainer object to.
     * @param logLevel  Determines the amount of data to be written to the Protobuf.
     */
    void dumpDebugLocked(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) {
        mPolicy.dumpDebug(proto, POLICY);
        mRoot.dumpDebug(proto, ROOT_WINDOW_CONTAINER, logLevel);
        final DisplayContent topFocusedDisplayContent = mRoot.getTopFocusedDisplayContent();
        if (topFocusedDisplayContent.mCurrentFocus != null) {
            topFocusedDisplayContent.mCurrentFocus.writeIdentifierToProto(proto, FOCUSED_WINDOW);
        }
        if (topFocusedDisplayContent.mFocusedApp != null) {
            topFocusedDisplayContent.mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
        }
        final WindowState imeWindow = mRoot.getCurrentInputMethodWindow();
        if (imeWindow != null) {
            imeWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW);
        }
        proto.write(DISPLAY_FROZEN, mDisplayFrozen);
        proto.write(FOCUSED_DISPLAY_ID, topFocusedDisplayContent.getDisplayId());
        proto.write(HARD_KEYBOARD_AVAILABLE, mHardKeyboardAvailable);

        // This is always true for now since we still update the window frames at the server side.
        // Once we move the window layout to the client side, this can be false when we are waiting
        // for the frames.
        proto.write(WINDOW_FRAMES_VALID, true);
    }

这样就完成了一帧的录制。

这个录制方法后续主要从WindowTracing的logState方法调用:(frameworks/base/services/core/java/com/android/server/wm/WindowTracing.java)

    private final Choreographer.FrameCallback mFrameCallback = (frameTimeNanos) ->
            log("onFrame" /* where */);
    ......
    /**
     * If tracing is enabled, log the current state or schedule the next frame to be logged,
     * according to {@link #mLogOnFrame}.
     *
     * @param where Logging point descriptor
     */
    void logState(String where) {
        if (!isEnabled()) {
            return;
        }

        if (mLogOnFrame) {
            schedule();
        } else {
            log(where);
        }
    }

    /**
     * Schedule the log to trace the next frame
     */
    private void schedule() {
        if (mScheduled) {
            return;
        }

        mScheduled = true;
        mChoreographer.postFrameCallback(mFrameCallback);
    }

logState方法只要isEnabled为true最终会调用log方法录制一帧。然后还根据mLogOnFrame是否为true,来决定是等下次vsync的时候调用,还是直接调用。

logState方法调用的位置是WindowManagerService的closeSurfaceTransaction:(frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java)

    /**
     * Closes a surface transaction.
     * @param where debug string indicating where the transaction originated
     */
    void closeSurfaceTransaction(String where) {
        try {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
            SurfaceControl.closeTransaction();
            mWindowTracing.logState(where);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

也就是说WindowManagerService这边每次提交layer相关改动给SurfaceFlinger的同时会触发Winscope抓取一帧信息。

最终结束录制时调用WindowTracing的stopTrace方法:(frameworks/base/services/core/java/com/android/server/wm/WindowTracing.java)

    /**
     * Stops the trace and write the current buffer to disk
     * @param pw Print writer
     */
    void stopTrace(@Nullable PrintWriter pw) {
        if (IS_USER) {
            logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
            return;
        }
        synchronized (mEnabledLock) {
            logAndPrintln(pw, "Stop tracing to " + mTraceFile + ". Waiting for traces to flush.");
            mEnabled = mEnabledLockFree = false;

            if (mEnabled) {
                logAndPrintln(pw, "ERROR: tracing was re-enabled while waiting for flush.");
                throw new IllegalStateException("tracing enabled while waiting for flush.");
            }
            writeTraceToFileLocked();
            logAndPrintln(pw, "Trace written to " + mTraceFile + ".");
        }
        ProtoLogImpl.getSingleInstance().stopProtoLog(pw, true);
    }

这里调用了writeTraceToFileLocked方法来保存录制文件:(frameworks/base/services/core/java/com/android/server/wm/WindowTracing.java)

    static final String WINSCOPE_EXT = ".winscope";
    private static final String TRACE_FILENAME = "/data/misc/wmtrace/wm_trace" + WINSCOPE_EXT;

    /**
     * Writes the trace buffer to disk. This method has no internal synchronization and should be
     * externally synchronized
     */
    private void writeTraceToFileLocked() {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "writeTraceToFileLocked");
            ProtoOutputStream proto = new ProtoOutputStream();
            proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
            mBuffer.writeTraceToFile(mTraceFile, proto);
        } catch (IOException e) {
            Log.e(TAG, "Unable to write buffer to file", e);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        }
    }

这里mTraceFile的路径是/data/misc/wmtrace/wm_trace.winscope,这也是WindowManager的Winscope保存的位置。

最后调用了TraceBuffer的writeTraceToFile方法保存文件。

SurfaceFlinger

给SurfaceFlinger通信使用code为1025,即可开始或结束抓取Winscope:(frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp)

status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                    uint32_t flags) {
    ......
    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
        ......
        switch (code) {
            ......
            case 1025: { // Set layer tracing
                n = data.readInt32();
                bool tracingEnabledChanged;
                if (n == 1) {
                    int64_t fixedStartingTime = data.readInt64();
                    ALOGD("LayerTracing enabled");
                    tracingEnabledChanged = mLayerTracing.enable();
                    if (tracingEnabledChanged) {
                        int64_t startingTime =
                                (fixedStartingTime) ? fixedStartingTime : systemTime();
                        mScheduler
                                ->schedule([&]() FTL_FAKE_GUARD(mStateLock) {
                                    mLayerTracing.notify("start", startingTime);
                                })
                                .wait();
                } else if (n == 2) {
                    std::string filename = std::string(data.readCString());
                    ALOGD("LayerTracing disabled. Trace wrote to %s", filename.c_str());
                    tracingEnabledChanged = mLayerTracing.disable(filename.c_str());
                } else {
                    ALOGD("LayerTracing disabled");
                    tracingEnabledChanged = mLayerTracing.disable();
                }
                mTracingEnabledChanged = tracingEnabledChanged;
                reply->writeInt32(NO_ERROR);
                return NO_ERROR;
            }
            ......

其中需要传一个整数作为参数,1代表开始,2代表结束并提供一个保存文件的路径,其它值代表结束并保存到默认位置。

开始录制时首先调用了LayerTracing的enable方法(frameworks/native/services/surfaceflinger/Tracing/LayerTracing.cpp):

bool LayerTracing::enable() {
    std::scoped_lock lock(mTraceLock);
    if (mEnabled) {
        return false;
    }
    mBuffer->setSize(mBufferSizeInBytes);
    mEnabled = true;
    return true;
}

这里只是把mEnabled设为了true。

然后调用了LayerTracing的notify方法:(frameworks/native/services/surfaceflinger/Tracing/LayerTracing.cpp)

void LayerTracing::notify(bool visibleRegionDirty, int64_t time) {
    std::scoped_lock lock(mTraceLock);
    if (!mEnabled) {
        return;
    }

    if (!visibleRegionDirty && !flagIsSet(LayerTracing::TRACE_BUFFERS)) {
        return;
    }

    ATRACE_CALL();
    LayersTraceProto entry;
    entry.set_elapsed_realtime_nanos(time);
    const char* where = visibleRegionDirty ? "visibleRegionsDirty" : "bufferLatched";
    entry.set_where(where);
    LayersProto layers(mFlinger.dumpDrawingStateProto(mFlags));

    if (flagIsSet(LayerTracing::TRACE_EXTRA)) {
        mFlinger.dumpOffscreenLayersProto(layers);
    }
    entry.mutable_layers()->Swap(&layers);

    if (flagIsSet(LayerTracing::TRACE_HWC)) {
        std::string hwcDump;
        mFlinger.dumpHwc(hwcDump);
        entry.set_hwc_blob(hwcDump);
    }
    if (!flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
        entry.set_excludes_composition_state(true);
    }
    mFlinger.dumpDisplayProto(entry);
    mBuffer->emplace(std::move(entry));
}

注意第一个参数是bool类型的,但是传入的参数却是"start",编译器认为这是一个不为null的char指针,会被隐式转换成true。(这应该是aosp的一个小bug)

这里依次调用SurfaceFlinger的dumpDrawingStateProto,dumpOffscreenLayersProto,dumpHwc,dumpDisplayProto方法,录制一帧的信息,最终存入mBuffer。

这个录制一帧的notify方法后续会在SurfaceFlinger的commit和composite方法中调用,也就是说当SurfaceFlinger中的layer状态发生更改时或合成一帧时会录制一帧Winscope。

最后录制结束时会调用LayerTracing的disable方法:(frameworks/native/services/surfaceflinger/Tracing/LayerTracing.cpp)

bool LayerTracing::disable(std::string filename) {
    std::scoped_lock lock(mTraceLock);
    if (!mEnabled) {
        return false;
    }
    mEnabled = false;
    LayersTraceFileProto fileProto = createTraceFileProto();
    mBuffer->writeToFile(fileProto, filename);
    mBuffer->reset();
    return true;
}

根据参数filename将录制结果写入文件,继续去看这个方法的定义:(frameworks/native/services/surfaceflinger/Tracing/LayerTracing.h)

class LayerTracing {
public:
    ......
    bool disable(std::string filename = FILE_NAME);
    ......
private:
    static constexpr auto FILE_NAME = "/data/misc/wmtrace/layers_trace.winscope";
    ......
};

这里FILE_NAME的路径是/data/misc/wmtrace/layers_trace.winscope,这就是SurfaceFlinger的Winscope默认保存的位置。

Android 使用 Winscope 跟踪窗口转换 Winscope 是一款 Web 工具,可以让用户在动画和转换期间和之后记录、重放和分析多个系统服务的状态。Winscope 将所有相关的系统服务状态记录在一个跟踪文件中。使用带有跟踪文件的 Winscope 界面,您可以通过重放、单步执行和调试转换来针对每个动画帧检查这些服务的状态(无论是否有屏幕录制)。 阅读详情

相关推荐

frameworks 之 Winscope 工具

frameworks 之 Winscope 工具

u011410770的博客 1944

Android开发中使用的winscope

Android开发中使用的winscope

深入解析 WinscopeAndroid 动画与转换的调试利器

本文深入解析Winscope工具在Android动画与转换调试中的核心价值与实战应用。作为Android团队开发的Web调试工具,Winscope能同时捕捉WindowManager、SurfaceFlinger等关键系统服务的状态,提供时间旅行调试功能,帮助开发者快速定位动画卡顿、黑屏等问题。文章详细介绍了设备端配置、电脑端分析环境搭建以及进阶调试技巧,是Android开发者的必备利器。

weixin_28366053的博客 442

Winscope工具使用

Android系统开发过程中,我们经常会遇到各种瞬时性的窗口显示问题,比如闪黑、冻屏、动画异常、窗口错位等。传统调试方法如dumpsys SurfaceFlinger和dumpsys window windows虽然能提供有用信息,但对于转瞬即逝的问题往往难以捕捉关键瞬间。即便成功捕获到黑屏瞬间的日志,分析时仍需结合前后帧的上下文信息才能准确定位问题根源。这类UI问题的调试面临三大挑战:首先,问题出现时机难以把握;其次,日志文件通常非常庞大,从中提取有效信息费时费力;

Red风信子的博客 569

android display笔记(二)winscope的使用

跟踪记录会被写入 /data/misc/wmtrace/wm_trace.winscope 和 /data/misc/wmtrace/layers_trace.winscope,同时还会包含在错误报告中。通常使用prebuilts/misc/common/winscope下的winscope.html。窗口转换完成后,打开快捷设置,然后点按 Winscope 跟踪记录以停用跟踪记录。依次转到开发者选项 > 快捷设置开发者图块。点按 Winscope 跟踪以启用跟踪。点击Add FILE。

镇元子的博客 5574

android车机手机黑屏闪黑终结者-Winscope工具使用介绍

在开发过程中,经常会遇到各种各样的窗口问题,比如动画异常、窗口异常、闪屏、闪黑、黑屏、错位显示…对于这些问题,添加日志,调试分析代码等手段去解决,但这些 UI 问题往往出现在一瞬间,很难把握出现的时机,录制下来的日志往往也是巨大的,从海量的日志中提取有效的信息是一个枯燥且繁琐的事情,而且也根本没有办法把显示时间戳和日志时间戳完全对好。Android 也意识到了这个问题,WinScope 的出现有效的帮助我们跟踪窗口和显示问题。它向开发者提供一个可视化的工具,让开发者能使用工具跟踪整个界面的变化过程。

learnframework的博客 6604

深入解析AOSP16 Winscope:Perfetto SQL查询在安卓图形调试中的实战应用

本文深入解析了AOSP16 Winscope中基于Perfetto SQL的全局搜索功能,这一革命性工具将安卓图形调试从手动排查带入智能查询时代。通过实战案例,详细展示了如何利用SQL查询精准定位输入法闪烁、任务栏透明度异常等典型图形问题,并提供了数据模型解读、高阶技巧与避坑指南,大幅提升系统与应用开发者的调试效率。

brown的博客 280

Android黑屏别慌!手把手教你用dumpsys和Winscope精准定位问题(附实战案例)

本文详细介绍了Android黑屏问题的排查方法,通过dumpsys和Winscope工具精准定位问题。从显示架构解析到实战案例,帮助开发者理解SurfaceFlinger和WindowManagerService的工作原理,快速解决黑屏问题。

weixin_42692935的博客 392

Winscope如何让你的系统app在可以展示ViewCapture相关数据?

此方法通过避免为每个窗口使用单独的环形缓冲区来避免过度消耗内存,但无法解决针对每个帧在 Perfetto 中存储每个状态的整个视图层次结构的问题。屏幕录制可以直观呈现视图在特定时间的状态,并显示其变化情况,但它们需要大量的 CPU 资源,并且可能会影响性能。此外,ViewCapture 会在视图级别逐帧显示可视化图表,与屏幕录制相比,可更轻松地检查特定时刻的视图状态。ViewCapture 会捕获窗口内各种视图及其属性的相关信息,以便您了解特定时刻的用户体验状态,并跟踪随时间的变化。:(冒号):分隔符。

learnframework的博客 217

Android开发调试利器:Winscope不只是抓黑屏,这些UI疑难杂症也能搞定

本文深入解析Android开发调试利器Winscope,不仅解决黑屏问题,还能有效诊断UI疑难杂症如动画卡顿、画面撕裂等。通过实战指南展示如何配置和使用Winscope进行UI问题分析,提升开发效率。

weixin_30606461的博客 212

Android应用黑屏别慌!手把手教你用dumpsys和winscope精准定位(附抖音案例)

本文详细解析了Android应用黑屏问题的诊断与解决方法,重点介绍了dumpsys和winscope工具的使用技巧,并通过抖音案例展示了如何精准定位问题根源。从SurfaceFlinger状态分析到WindowManagerService诊断,帮助开发者快速应对各类黑屏故障,提升应用稳定性。

weixin_30376083的博客 546

Android U 自由窗口(浮窗)——操作栏相关分析思路

本地通过dump activity containers,View树以及window等方式均未找到自由窗口操作栏相关代码,在android T(13)中的方式已经不再适用,最终通过winscope dumpsys SF找到相关线索。下面主要介绍下分析思路,并找到相关代码。

yimelancholy的博客 920

Android显示问题排查新利器:手把手教你用Winscope‘回放’SurfaceFlinger与Window的每一帧

本文深入解析Android图形系统调试工具Winscope的核心原理与应用实践,特别针对车机系统中的黑屏等显示问题提供解决方案。通过逐帧回放SurfaceFlinger与WindowManager的工作流程,开发者可精准定位UI异常根源,大幅提升调试效率。文章涵盖环境配置、数据采集技巧及高级分析场景,是Android图形问题排查的必备指南。

weixin_33695082的博客 337

学员作业:探索锁屏、桌面壁纸相关差异显示原理

系统中即可以设置桌面壁纸,也可以设置锁屏壁纸,而且二者还可以长得不一样,各自设置各自壁纸,请问这块原理是什么?锁屏壁纸和桌面壁纸是如何区分的差异显示,是同一个Wallpaper的窗口显示不同的bitmap还是说根本就是不同的Wallpaper窗口?简单说他们原来解决办法是锁屏壁纸是作为锁屏界面的一个背景图片bitmap,和锁屏窗口的view是一体的,当然这个解决方案具体还得复现问题尝试验证,这个方案表面理论上看着可行。但有学员朋友又私下问到了,锁屏壁纸和桌面壁纸的相关差异区别原理是啥?

learnframework的博客 431

app开发转framework系统工程师窗口显示方向面试真题

2、framework的承担开发要求精,因为framework毕竟属于系统层面东西,一修改影响整个系统的功能和稳定,分析代码理解代码精通代码才可能可以修改掉系统一些问题,及最小波及的实现系统的一下新功能,不是网络百度复制粘贴一下即可以,所以这里要求是对简历上写出的精通或熟悉模块,面试官会挖的比较深入,会对模块很多重要部分进行提问考察,这个部分就是对你真正是否熟悉这个模块的考察,也是区别你是真懂的实战派还是说看了看blog和记忆性的背书党关键。13、你接过input相关的外设吗,或者说一下input的流程?

learnframework的博客 496

winscope怎么实现user版本上导出方案设计探讨-千里马android framework车载车机手机系统开发

在马哥给讲解怎么用winscope来分析各种闪黑,黑屏等问题后,很多买课的同学都开始使用这个工具用于实际公司的项目了,但是很多同学又开始发现有一个问题,那就发现在user版本的手机设备上发现无法抓取相关的winscope,哪怕可以抓取也发现没办法导出来分析。上面已经分析了bugreport的原理,实际是借助dumpstate来实现获取高权限root的,那么问题来了,为啥wmtrace相关文件夹呢?首先需要了解点bugreport其实本质上也最多只能有shell权限,因为也属于adb shell拉起的进程,

learnframework的博客 957

某学员framework的闭关学习2个月的过程分享

本文分享了一位Android开发者在面临裁员危机时,通过系统学习Framework成功转型的经验。作者原本从事App开发,因市场环境变化决定转战Framework方向。经过2个月的密集学习(基础部分1个月+进阶部分20天),掌握了源码编译、跨进程通信、Input系统等核心知识,重点攻克了WMS/AMS和车载多屏互动等实战项目。学习过程中通过实际修改系统源码和解决问题获得成就感,最终收获2个Framework相关offer。文章强调系统化学习和实战的重要性,建议开发者选择有经验的导师指导,能事半功倍地实现技术

liaosongmao1的专栏 34

Winscope中抓取Transaction相关的原理剖析

首先这个service call就是直接调用到SurfaceFlinger这个service的onTransact方法,1041代表是code,i32代表是data的int类型,1和0代表就是值。那么选着Transaction选项后抓取Winscope,看看winscope_proxy.py程序的相关输出,看看有没有线索可以查到是如何获取系统的相关Transaction数据。在使用Winscope过程经常会有如下的一些选项供我们进行选择,不同的选项最后就会展示不同的数据项出来。具体这些数据是哪里来的呢?

learnframework的博客 1458
上一篇: Steel教程 - 目录
下一篇: 安卓RenderEffect原理
SSSxCCC
博客等级 码龄10年 238粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SSSxCCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值