我们知道binder是android中跨进程通信的一大亮点,但binder通信时如果待传数据较大,可能会出现binder call失败,那怎么才能监控传输多大的size呢。

frameworks/base/core/java/android/os/Binder.java#661687    private boolean execTransact(int code, long dataObj, long replyObj,688            int flags) {689        Parcel data = Parcel.obtain(dataObj);690        Parcel reply = Parcel.obtain(replyObj);......702            res = onTransact(code, data, reply, flags);......723        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");724        reply.recycle();725        data.recycle();

看到binder服务端里面有个checkParcel,这个就是关键,每次java层面收到的binder call 都会调用此方法,无论成功还是失败,那么接收端也是同理,其code如下,发送请求之前就会调用checkParcel

frameworks/base/core/java/android/os/Binder.java#750749    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {750        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");

既然发送和接收都会调用checkParcel,那么问题就归一了,看下其实现

658    static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {660        if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {663            StringBuilder sb = new StringBuilder();664            sb.append(msg);665            sb.append(": on ");......679            Slog.wtfStack(TAG, sb.toString());680        }

只是一个if条件,然后封装字符串,输出wtf的log。如此而已,那么,手机厂商们就可以修改这个if条件了。随你怎么造。

例如:

1,设置版本控制,例如debug版本开、release版本关闭;

2,通过属性动态设置care的size,如将persist属性的值赋值给CHECK_PARCEL_SIZE,就可以完成动态监控;

到此就了解完毕了。

 

下面简单说下WTF log的输出,只是调用了Log.wtf,而且指定了输出到system

frameworks/base/core/java/android/util/Slog.java22public final class Slog {......97    public static int wtfStack(String tag, String msg) {98        return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null, true, true); //可见log是输出到system log99    }

继续看下源码

frameworks/base/core/java/android/util/Log.java301    static int wtf(int logId, String tag, String msg, Throwable tr, boolean localStack,302            boolean system) {303        TerribleFailure what = new TerribleFailure(msg, tr);304        // Only mark this as ERROR, do not use ASSERT since that should be305        // reserved for cases where the system is guaranteed to abort.306        // The onTerribleFailure call does not always cause a crash.307        int bytes = printlns(logId, ERROR, tag, msg, localStack ? what : tr); //类的一个静态方法,输出到system log308        sWtfHandler.onTerribleFailure(tag, what, system); //通知系统309        return bytes;310    }

先看下printlns的方法

393    public static int printlns(int bufID, int priority, String tag, String msg,394            Throwable tr) {395        ImmediateLogWriter logWriter = new ImmediateLogWriter(bufID, priority, tag);396        // Acceptable buffer size. Get the native buffer size, subtract two zero terminators,397        // and the length of the tag.398        // Note: we implicitly accept possible truncation for Modified-UTF8 differences. It399        //       is too expensive to compute that ahead of time.400        int bufferSize = PreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD    // Base.401                - 2                                                // Two terminators.402                - (tag != null ? tag.length() : 0)                 // Tag length.403                - 32;                                              // Some slack.404        // At least assume you can print *some* characters (tag is not too large).405        bufferSize = Math.max(bufferSize, 100);406407        LineBreakBufferedWriter lbbw = new LineBreakBufferedWriter(logWriter, bufferSize);408409        lbbw.println(msg);410411        if (tr != null) {412            // This is to reduce the amount of log spew that apps do in the non-error413            // condition of the network being unavailable.414            Throwable t = tr;415            while (t != null) {416                if (t instanceof UnknownHostException) {417                    break;418                }419                if (t instanceof DeadSystemException) {420                    lbbw.println("DeadSystemException: The system died; "421                            + "earlier logs will point to the root cause");422                    break;423                }424                t = t.getCause();425            }426            if (t == null) {427                tr.printStackTrace(lbbw);428            }429        }430431        lbbw.flush();432433        return logWriter.getWritten();434    }

在了解下sWtfHandler,这是一个匿名内部类

108    private static TerribleFailureHandler sWtfHandler = new TerribleFailureHandler() {109            public void onTerribleFailure(String tag, TerribleFailure what, boolean system) {110                RuntimeInit.wtf(tag, what, system);111            }

又回到了RuntimeInit,真是麻烦啊

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java332    public static void wtf(String tag, Throwable t, boolean system) {333        try {334            if (ActivityManager.getService().handleApplicationWtf(335                    mApplicationObject, tag, system,336                    new ApplicationErrorReport.ParcelableCrashInfo(t))) {337                // The Activity Manager has already written us off -- now exit.338                Process.killProcess(Process.myPid());339                System.exit(10);340            }

我的天呢,一个简单的wtf log,还会binder call到AMS,调用了AMS的handleApplicationWtf,而且如果返回值为true,还好kill掉当前进程。

简单说下ApplicationErrorReport.ParcelableCrashInfo(t),其继承了Parcel,所以可以通过binder 传输

frameworks/base/core/java/android/app/ApplicationErrorReport.java464    public static class ParcelableCrashInfo extends CrashInfo implements Parcelable {.....474        public ParcelableCrashInfo(Throwable tr) {475            super(tr);476        }

还是看handleApplicationWtf吧

15078    public boolean handleApplicationWtf(final IBinder app, final String tag, boolean system,15079            final ApplicationErrorReport.ParcelableCrashInfo crashInfo) {15080        final int callingUid = Binder.getCallingUid();15081        final int callingPid = Binder.getCallingPid();1508215083        if (system) {15084            // If this is coming from the system, we could very well have low-level15085            // system locks held, so we want to do this all asynchronously.  And we15086            // never want this to become fatal, so there is that too.                 //如果来自系统,则跑消息给主线程执行15087            mHandler.post(new Runnable() {15088                @Override public void run() {15089                    handleApplicationWtfInner(callingUid, callingPid, app, tag, crashInfo);15090                }15091            });          //返回false,所以wtf log后,一般不会进程退出15092            return false;15093        }15094     //非系统的话,直接binder线程执行15095        final ProcessRecord r = handleApplicationWtfInner(callingUid, callingPid, app, tag,15096                crashInfo);1509715098        final boolean isFatal = Build.IS_ENG || Settings.Global15099                .getInt(mContext.getContentResolver(), Settings.Global.WTF_IS_FATAL, 0) != 0;15100        final boolean isSystem = (r == null) || r.persistent;1510115102        if (isFatal && !isSystem) {          //只有这一种情况wtf log会导致进程挂掉,即非系统报的wtf,且不是工程版本,设置中也未设置wtf15103            mAppErrors.crashApplication(r, crashInfo);15104            return true;15105        } else {15106            return false;15107        }15108    }

通过handleApplicationWtfInner,可以看到dropbox中有log输出,而且event也有一行输出。

15110    ProcessRecord handleApplicationWtfInner(int callingUid, int callingPid, IBinder app, String tag,15111            final ApplicationErrorReport.CrashInfo crashInfo) {15112        final ProcessRecord r = findAppProcess(app, "WTF");15113        final String processName = app == null ? "system_server"15114                : (r == null ? "unknown" : r.processName);15115        //event log有一行输出15116        EventLog.writeEvent(EventLogTags.AM_WTF, UserHandle.getUserId(callingUid), callingPid,15117                processName, r == null ? -1 : r.info.flags, tag, crashInfo.exceptionMessage);15118     //将wtf写入dropbox15119        addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);1512015121        return r;15122    }

event log类似如下:

08-01 13:24:25.717  1000  1268  1302 I am_wtf  : [0,1268,system_server,-1,PackageManager.DexOptimizer,Well this is awkward; package com.xgame.app.XgameApplication had UID -1]

dropbox log路径:data/system/dropbox,文件名称格式:system_server_wtf@×××××××.txt

完毕。

更多相关文章

  1. Android(安卓)获取IP地址的实现方法
  2. Android(安卓)Studio下的build工具路径和设置位置
  3. Android界面基本属性
  4. 理解onMeasure
  5. Android(安卓)应用语言设置的实现
  6. Android动态设置edittext的hint属性显示的提示文字大小
  7. listview自定义背景以及item自定义背景
  8. android客户端程序访问服务器端webservice,几篇不错的文章!
  9. Android(安卓)Logcat 直接输出JSON格式的数据

随机推荐

  1. Android Notifications
  2. xoom recovery
  3. 使用OpenGLES 在 android 上显示摄像头滤
  4. android 控件状态配置文件
  5. android_14 线性布局2
  6. 记Android(安卓)版本 和 市场占有率
  7. Android中隐藏光标
  8. Android(安卓)Beginning Dev
  9. Android(安卓)框架布局 FrameLayout
  10. Android(安卓)热修复(全网最简单的热修复