diff options
| -rw-r--r-- | core/java/android/app/servertransaction/LaunchActivityItem.java | 38 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java | 43 |
2 files changed, 58 insertions, 23 deletions
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java index 6d674ae7df14..9ab6e7fc9f58 100644 --- a/core/java/android/app/servertransaction/LaunchActivityItem.java +++ b/core/java/android/app/servertransaction/LaunchActivityItem.java @@ -186,8 +186,8 @@ public class LaunchActivityItem extends ClientTransactionItem { && Objects.equals(mOverrideConfig, other.mOverrideConfig) && Objects.equals(mCompatInfo, other.mCompatInfo) && Objects.equals(mReferrer, other.mReferrer) - && mProcState == other.mProcState && areBundlesEqual(mState, other.mState) - && areBundlesEqual(mPersistentState, other.mPersistentState) + && mProcState == other.mProcState && areBundlesEqualRoughly(mState, other.mState) + && areBundlesEqualRoughly(mPersistentState, other.mPersistentState) && Objects.equals(mPendingResults, other.mPendingResults) && Objects.equals(mPendingNewIntents, other.mPendingNewIntents) && mIsForward == other.mIsForward @@ -205,8 +205,8 @@ public class LaunchActivityItem extends ClientTransactionItem { result = 31 * result + Objects.hashCode(mCompatInfo); result = 31 * result + Objects.hashCode(mReferrer); result = 31 * result + Objects.hashCode(mProcState); - result = 31 * result + (mState != null ? mState.size() : 0); - result = 31 * result + (mPersistentState != null ? mPersistentState.size() : 0); + result = 31 * result + getRoughBundleHashCode(mState); + result = 31 * result + getRoughBundleHashCode(mPersistentState); result = 31 * result + Objects.hashCode(mPendingResults); result = 31 * result + Objects.hashCode(mPendingNewIntents); result = 31 * result + (mIsForward ? 1 : 0); @@ -225,25 +225,19 @@ public class LaunchActivityItem extends ClientTransactionItem { && Objects.equals(mInfo.getComponentName(), other.getComponentName()); } - private static boolean areBundlesEqual(BaseBundle extras, BaseBundle newExtras) { - if (extras == null || newExtras == null) { - return extras == newExtras; - } - - if (extras.size() != newExtras.size()) { - return false; - } + /** + * This method may be used to compare a parceled item with another unparceled item, and the + * parceled bundle may contain customized class that will raise BadParcelableException when + * unparceling if a customized class loader is not set to the bundle. So the hash code is + * simply determined by the bundle is empty or not. + */ + private static int getRoughBundleHashCode(BaseBundle bundle) { + return (bundle == null || bundle.isDefinitelyEmpty()) ? 0 : 1; + } - for (String key : extras.keySet()) { - if (key != null) { - final Object value = extras.get(key); - final Object newValue = newExtras.get(key); - if (!Objects.equals(value, newValue)) { - return false; - } - } - } - return true; + /** Compares the bundles without unparceling them (avoid BadParcelableException). */ + private static boolean areBundlesEqualRoughly(BaseBundle a, BaseBundle b) { + return getRoughBundleHashCode(a) == getRoughBundleHashCode(b); } @Override diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index f4fbefe9dde4..3766cf72d99e 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -63,7 +63,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; -import java.util.List; import java.util.Map; /** @@ -213,6 +212,7 @@ public class TransactionParcelTests { int procState = 4; Bundle bundle = new Bundle(); bundle.putString("key", "value"); + bundle.putParcelable("data", new ParcelableData(1)); PersistableBundle persistableBundle = new PersistableBundle(); persistableBundle.putInt("k", 4); @@ -374,6 +374,47 @@ public class TransactionParcelTests { mParcel.setDataPosition(0); } + /** + * The parcelable class to make sure that when comparing the {@link LaunchActivityItem} or + * getting its hash code, the bundle is not unparceled. System shouldn't touch the data from + * application, otherwise it will cause exception as: + * android.os.BadParcelableException: ClassNotFoundException when unmarshalling: + * android.app.servertransaction.TransactionParcelTests$ParcelableData". + */ + public static class ParcelableData implements Parcelable { + int mValue; + + ParcelableData() {} + + ParcelableData(int value) { + mValue = value; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mValue); + } + + public static final Creator<ParcelableData> CREATOR = new Creator<ParcelableData>() { + @Override + public ParcelableData createFromParcel(Parcel source) { + final ParcelableData data = new ParcelableData(); + data.mValue = source.readInt(); + return data; + } + + @Override + public ParcelableData[] newArray(int size) { + return new ParcelableData[size]; + } + }; + } + /** Stub implementation of IApplicationThread that can be presented as {@link Binder}. */ class StubAppThread extends android.app.IApplicationThread.Stub { |