我们知道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夜间模式实现(系统自带)
  2. Android 获取应用的icon、名字、版本号
  3. 在Android Service中弹出系统全屏对话框
  4. 【笔记】Android高版本Apache HTTPClient变更兼容和HTTP请求
  5. Android系统开发—对View的clipChildren,clipToPadding,importan
  6. Android系统信息获取

随机推荐

  1. Android有时候EditText光标不显示,或者颜
  2. Android(安卓)摇一摇功能实现(类似微信)
  3. Android(安卓)图片加载 —— ImageLoader
  4. 解决 S5pv210 android system.img 烧写失
  5. android 获得一些设备信息的静态函数
  6. Android开发中遇到的bug(1)
  7. Manifest merger failed Suggestion: add
  8. android 读取资源文件的数据
  9. android backlight
  10. Android(安卓)开发调用系统拍照和图片选