am e7de36e6: Merge "Throw TransactionTooLargeException when Binder transaction fails. Bug: 5578022" into ics-mr1
* commit 'e7de36e605e0ccf4552c8ee1db40cb9af3227cf4': Throw TransactionTooLargeException when Binder transaction fails. Bug: 5578022
This commit is contained in:
@@ -15132,6 +15132,7 @@ package android.os {
|
||||
|
||||
public class RemoteException extends android.util.AndroidException {
|
||||
ctor public RemoteException();
|
||||
ctor public RemoteException(java.lang.String);
|
||||
}
|
||||
|
||||
public class ResultReceiver implements android.os.Parcelable {
|
||||
@@ -15226,6 +15227,10 @@ package android.os {
|
||||
method public abstract void released();
|
||||
}
|
||||
|
||||
public class TransactionTooLargeException extends android.os.RemoteException {
|
||||
ctor public TransactionTooLargeException();
|
||||
}
|
||||
|
||||
public class Vibrator {
|
||||
method public void cancel();
|
||||
method public boolean hasVibrator();
|
||||
|
||||
@@ -24,4 +24,8 @@ public class RemoteException extends AndroidException {
|
||||
public RemoteException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public RemoteException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
59
core/java/android/os/TransactionTooLargeException.java
Normal file
59
core/java/android/os/TransactionTooLargeException.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.os;
|
||||
import android.os.RemoteException;
|
||||
|
||||
/**
|
||||
* The Binder transaction failed because it was too large.
|
||||
* <p>
|
||||
* During a remote procedure call, the arguments and the return value of the call
|
||||
* are transferred as {@link Parcel} objects stored in the Binder transaction buffer.
|
||||
* If the arguments or the return value are too large to fit in the transaction buffer,
|
||||
* then the call will fail and {@link TransactionTooLargeException} will be thrown.
|
||||
* </p><p>
|
||||
* The Binder transaction buffer has a limited fixed size, currently 1Mb, which
|
||||
* is shared by all transactions in progress for the process. Consequently this
|
||||
* exception can be thrown when there are many transactions in progress even when
|
||||
* most of the individual transactions are of moderate size.
|
||||
* </p><p>
|
||||
* There are two possible outcomes when a remote procedure call throws
|
||||
* {@link TransactionTooLargeException}. Either the client was unable to send
|
||||
* its request to the service (most likely if the arguments were too large to fit in
|
||||
* the transaction buffer), or the service was unable to send its response back
|
||||
* to the client (most likely if the return value was too large to fit
|
||||
* in the transaction buffer). It is not possible to tell which of these outcomes
|
||||
* actually occurred. The client should assume that a partial failure occurred.
|
||||
* </p><p>
|
||||
* The key to avoiding {@link TransactionTooLargeException} is to keep all
|
||||
* transactions relatively small. Try to minimize the amount of memory needed to create
|
||||
* a {@link Parcel} for the arguments and the return value of the remote procedure call.
|
||||
* Avoid transferring huge arrays of strings or large bitmaps.
|
||||
* If possible, try to break up big requests into smaller pieces.
|
||||
* </p><p>
|
||||
* If you are implementing a service, it may help to impose size or complexity
|
||||
* contraints on the queries that clients can perform. For example, if the result set
|
||||
* could become large, then don't allow the client to request more than a few records
|
||||
* at a time. Alternately, instead of returning all of the available data all at once,
|
||||
* return the essential information first and make the client ask for additional information
|
||||
* later as needed.
|
||||
* </p>
|
||||
*/
|
||||
public class TransactionTooLargeException extends RemoteException {
|
||||
public TransactionTooLargeException() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <binder/ProcessState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include <ScopedUtfChars.h>
|
||||
#include <ScopedLocalRef.h>
|
||||
@@ -651,7 +652,8 @@ jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
|
||||
gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc);
|
||||
}
|
||||
|
||||
void signalExceptionForError(JNIEnv* env, jobject obj, status_t err)
|
||||
static void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
|
||||
bool canThrowRemoteException = false)
|
||||
{
|
||||
switch (err) {
|
||||
case UNKNOWN_ERROR:
|
||||
@@ -688,14 +690,25 @@ void signalExceptionForError(JNIEnv* env, jobject obj, status_t err)
|
||||
jniThrowException(env, "java/lang/RuntimeException", "Item already exists");
|
||||
break;
|
||||
case DEAD_OBJECT:
|
||||
jniThrowException(env, "android/os/DeadObjectException", NULL);
|
||||
// DeadObjectException is a checked exception, only throw from certain methods.
|
||||
jniThrowException(env, canThrowRemoteException
|
||||
? "android/os/DeadObjectException"
|
||||
: "java/lang/RuntimeException", NULL);
|
||||
break;
|
||||
case UNKNOWN_TRANSACTION:
|
||||
jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code");
|
||||
break;
|
||||
case FAILED_TRANSACTION:
|
||||
LOGE("!!! FAILED BINDER TRANSACTION !!!");
|
||||
//jniThrowException(env, "java/lang/OutOfMemoryError", "Binder transaction too large");
|
||||
// TransactionTooLargeException is a checked exception, only throw from certain methods.
|
||||
// FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
|
||||
// but it is not the only one. The Binder driver can return BR_FAILED_REPLY
|
||||
// for other reasons also, such as if the transaction is malformed or
|
||||
// refers to an FD that has been closed. We should change the driver
|
||||
// to enable us to distinguish these cases in the future.
|
||||
jniThrowException(env, canThrowRemoteException
|
||||
? "android/os/TransactionTooLargeException"
|
||||
: "java/lang/RuntimeException", NULL);
|
||||
break;
|
||||
case FDS_NOT_ALLOWED:
|
||||
jniThrowException(env, "java/lang/RuntimeException",
|
||||
@@ -703,6 +716,12 @@ void signalExceptionForError(JNIEnv* env, jobject obj, status_t err)
|
||||
break;
|
||||
default:
|
||||
LOGE("Unknown binder error code. 0x%x", err);
|
||||
String8 msg;
|
||||
msg.appendFormat("Unknown binder error code. 0x%x", err);
|
||||
// RemoteException is a checked exception, only throw from certain methods.
|
||||
jniThrowException(env, canThrowRemoteException
|
||||
? "android/os/RemoteException" : "java/lang/RuntimeException", msg.string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1036,8 +1055,7 @@ static bool should_time_binder_calls() {
|
||||
}
|
||||
|
||||
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
|
||||
jint code, jobject dataObj,
|
||||
jobject replyObj, jint flags)
|
||||
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
|
||||
{
|
||||
if (dataObj == NULL) {
|
||||
jniThrowNullPointerException(env, NULL);
|
||||
@@ -1084,12 +1102,12 @@ static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
signalExceptionForError(env, obj, err);
|
||||
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
|
||||
jobject recipient, jint flags)
|
||||
jobject recipient, jint flags) // throws RemoteException
|
||||
{
|
||||
if (recipient == NULL) {
|
||||
jniThrowNullPointerException(env, NULL);
|
||||
@@ -1114,7 +1132,7 @@ static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
|
||||
// Failure adding the death recipient, so clear its reference
|
||||
// now.
|
||||
jdr->clearReference();
|
||||
signalExceptionForError(env, obj, err);
|
||||
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user