binder客户端readException分析

在https://issuetracker.google.com/issues/277822279

里面描述了一种情况,客户端进行了binder方法调用,却因为返回的Exception,发生了crash

Caused by: java.lang.SecurityException: com.adobe.creativesdk.sample: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
	at android.os.Parcel.createExceptionOrNull(Parcel.java:3057)
	at android.os.Parcel.createException(Parcel.java:3041)
	at android.os.Parcel.readException(Parcel.java:3024)
	at android.os.Parcel.readException(Parcel.java:2966)
	at android.app.IActivityManager$Stub$Proxy.registerReceiverWithFeature(IActivityManager.java:5393)
	at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1851)
	at android.app.ContextImpl.registerReceiver(ContextImpl.java:1791)

说明了

1,客户端调用需要添加异常捕获处理,保证程序安全

2,服务端也需要对异常状况进行处理,如果客户端也没有处理,就会出问题

为什么服务端的异常没有在服务端爆发,反而传给了客户端呢,因为服务端的binder方法调用有binder.java里的异常捕获在兜底,

frameworks/base/core/java/android/os/Binder.java

   // Entry point from android_util_Binder.cpp's onTransact
714    private boolean execTransact(int code, long dataObj, long replyObj,
715            int flags) {
716        BinderCallsStats binderCallsStats = BinderCallsStats.getInstance();
717        BinderCallsStats.CallSession callSession = binderCallsStats.callStarted(this, code);
718        Parcel data = Parcel.obtain(dataObj);
719        Parcel reply = Parcel.obtain(replyObj);
720        // theoretically, we should call transact, which will call onTransact,
721        // but all that does is rewind it, and we just got these from an IPC,
722        // so we'll just call it directly.
723        boolean res;
724        // Log any exceptions as warnings, don't silently suppress them.
725        // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
726        final boolean tracingEnabled = Binder.isTracingEnabled();
727        try {
728            if (tracingEnabled) {
729                Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
730            }
731            res = onTransact(code, data, reply, flags);
732        } catch (RemoteException|RuntimeException e) {
733            if (LOG_RUNTIME_EXCEPTION) {
734                Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
735            }
736            if ((flags & FLAG_ONEWAY) != 0) {
737                if (e instanceof RemoteException) {
738                    Log.w(TAG, "Binder call failed.", e);
739                } else {
740                    Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
741                }
742            } else {
743                reply.setDataPosition(0);
744                reply.writeException(e);
745            }
746            res = true;
747        } finally {
748            if (tracingEnabled) {
749                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
750            }
751        }
752        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
753        reply.recycle();
754        data.recycle();
755
756        // Just in case -- we are done with the IPC, so there should be no more strict
757        // mode violations that have gathered for this thread.  Either they have been
758        // parceled and are now in transport off to the caller, or we are returning back
759        // to the main transaction loop to wait for another incoming transaction.  Either
760        // way, strict mode begone!
761        StrictMode.clearGatheredViolations();
762        binderCallsStats.callEnded(callSession);
763
764        return res;
765    }
766}

你可能感兴趣的:(Android)