Merge "Add MediaParceledListSlice as @SystemApi"
This commit is contained in:
@@ -15,21 +15,21 @@
|
||||
//
|
||||
|
||||
filegroup {
|
||||
name: "stable-mediasession2-aidl-srcs",
|
||||
name: "stable-media-aidl-srcs",
|
||||
srcs: ["stable/**/*.aidl"],
|
||||
path: "stable",
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "private-mediasession2-aidl-srcs",
|
||||
name: "private-media-aidl-srcs",
|
||||
srcs: ["private/**/I*.aidl"],
|
||||
path: "private",
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "mediasession2-aidl-srcs",
|
||||
name: "media-aidl-srcs",
|
||||
srcs: [
|
||||
":private-mediasession2-aidl-srcs",
|
||||
":stable-mediasession2-aidl-srcs",
|
||||
":private-media-aidl-srcs",
|
||||
":stable-media-aidl-srcs",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2020, 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.media;
|
||||
|
||||
parcelable MediaParceledListSlice<T>;
|
||||
@@ -54,9 +54,10 @@ java_library {
|
||||
filegroup {
|
||||
name: "updatable-media-srcs",
|
||||
srcs: [
|
||||
":media-aidl-srcs",
|
||||
":mediaparceledlistslice-java-srcs",
|
||||
":mediaparser-srcs",
|
||||
":mediasession2-java-srcs",
|
||||
":mediasession2-aidl-srcs",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -76,6 +77,15 @@ filegroup {
|
||||
path: "java",
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "mediaparceledlistslice-java-srcs",
|
||||
srcs: [
|
||||
"java/android/media/MediaParceledListSlice.java",
|
||||
"java/android/media/BaseMediaParceledListSlice.java",
|
||||
],
|
||||
path: "java",
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "mediaparser-srcs",
|
||||
srcs: [
|
||||
|
||||
@@ -1 +1,15 @@
|
||||
// Signature format: 2.0
|
||||
package android.media {
|
||||
|
||||
public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
|
||||
ctor public MediaParceledListSlice(@NonNull java.util.List<T>);
|
||||
method public int describeContents();
|
||||
method @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
|
||||
method public java.util.List<T> getList();
|
||||
method public void setInlineCountLimit(int);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2020 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.media;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a copied version of BaseParceledListSlice in framework with hidden API usages
|
||||
* removed.
|
||||
*
|
||||
* Transfer a large list of Parcelable objects across an IPC. Splits into
|
||||
* multiple transactions if needed.
|
||||
*
|
||||
* Caveat: for efficiency and security, all elements must be the same concrete type.
|
||||
* In order to avoid writing the class name of each object, we must ensure that
|
||||
* each object is the same type, or else unparceling then reparceling the data may yield
|
||||
* a different result if the class name encoded in the Parcelable is a Base type.
|
||||
* See b/17671747.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
abstract class BaseMediaParceledListSlice<T> implements Parcelable {
|
||||
private static String TAG = "BaseMediaParceledListSlice";
|
||||
private static boolean DEBUG = false;
|
||||
|
||||
/*
|
||||
* TODO get this number from somewhere else. For now set it to a quarter of
|
||||
* the 1MB limit.
|
||||
*/
|
||||
// private static final int MAX_IPC_SIZE = IBinder.getSuggestedMaxIpcSizeBytes();
|
||||
private static final int MAX_IPC_SIZE = 64 * 1024;
|
||||
|
||||
private final List<T> mList;
|
||||
|
||||
private int mInlineCountLimit = Integer.MAX_VALUE;
|
||||
|
||||
public BaseMediaParceledListSlice(List<T> list) {
|
||||
mList = list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
BaseMediaParceledListSlice(Parcel p, ClassLoader loader) {
|
||||
final int N = p.readInt();
|
||||
mList = new ArrayList<T>(N);
|
||||
if (DEBUG) Log.d(TAG, "Retrieving " + N + " items");
|
||||
if (N <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Parcelable.Creator<?> creator = readParcelableCreator(p, loader);
|
||||
Class<?> listElementClass = null;
|
||||
|
||||
int i = 0;
|
||||
while (i < N) {
|
||||
if (p.readInt() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
final T parcelable = readCreator(creator, p, loader);
|
||||
if (listElementClass == null) {
|
||||
listElementClass = parcelable.getClass();
|
||||
} else {
|
||||
verifySameType(listElementClass, parcelable.getClass());
|
||||
}
|
||||
|
||||
mList.add(parcelable);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
|
||||
i++;
|
||||
}
|
||||
if (i >= N) {
|
||||
return;
|
||||
}
|
||||
final IBinder retriever = p.readStrongBinder();
|
||||
while (i < N) {
|
||||
if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever);
|
||||
Parcel data = Parcel.obtain();
|
||||
Parcel reply = Parcel.obtain();
|
||||
data.writeInt(i);
|
||||
try {
|
||||
retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
|
||||
return;
|
||||
}
|
||||
while (i < N && reply.readInt() != 0) {
|
||||
final T parcelable = readCreator(creator, reply, loader);
|
||||
verifySameType(listElementClass, parcelable.getClass());
|
||||
|
||||
mList.add(parcelable);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
|
||||
i++;
|
||||
}
|
||||
reply.recycle();
|
||||
data.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
private T readCreator(Parcelable.Creator<?> creator, Parcel p, ClassLoader loader) {
|
||||
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
|
||||
Parcelable.ClassLoaderCreator<?> classLoaderCreator =
|
||||
(Parcelable.ClassLoaderCreator<?>) creator;
|
||||
return (T) classLoaderCreator.createFromParcel(p, loader);
|
||||
}
|
||||
return (T) creator.createFromParcel(p);
|
||||
}
|
||||
|
||||
private static void verifySameType(final Class<?> expected, final Class<?> actual) {
|
||||
if (!actual.equals(expected)) {
|
||||
throw new IllegalArgumentException("Can't unparcel type "
|
||||
+ (actual == null ? null : actual.getName()) + " in list of type "
|
||||
+ (expected == null ? null : expected.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> getList() {
|
||||
return mList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a limit on the maximum number of entries in the array that will be included
|
||||
* inline in the initial parcelling of this object.
|
||||
*/
|
||||
public void setInlineCountLimit(int maxCount) {
|
||||
mInlineCountLimit = maxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this to another Parcel. Note that this discards the internal Parcel
|
||||
* and should not be used anymore. This is so we can pass this to a Binder
|
||||
* where we won't have a chance to call recycle on this.
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
final int N = mList.size();
|
||||
final int callFlags = flags;
|
||||
dest.writeInt(N);
|
||||
if (DEBUG) Log.d(TAG, "Writing " + N + " items");
|
||||
if (N > 0) {
|
||||
final Class<?> listElementClass = mList.get(0).getClass();
|
||||
writeParcelableCreator(mList.get(0), dest);
|
||||
int i = 0;
|
||||
while (i < N && i < mInlineCountLimit && dest.dataSize() < MAX_IPC_SIZE) {
|
||||
dest.writeInt(1);
|
||||
|
||||
final T parcelable = mList.get(i);
|
||||
verifySameType(listElementClass, parcelable.getClass());
|
||||
writeElement(parcelable, dest, callFlags);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
|
||||
i++;
|
||||
}
|
||||
if (i < N) {
|
||||
dest.writeInt(0);
|
||||
Binder retriever = new Binder() {
|
||||
@Override
|
||||
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
|
||||
throws RemoteException {
|
||||
if (code != FIRST_CALL_TRANSACTION) {
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
}
|
||||
int i = data.readInt();
|
||||
if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
|
||||
while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
|
||||
reply.writeInt(1);
|
||||
|
||||
final T parcelable = mList.get(i);
|
||||
verifySameType(listElementClass, parcelable.getClass());
|
||||
writeElement(parcelable, reply, callFlags);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
|
||||
i++;
|
||||
}
|
||||
if (i < N) {
|
||||
if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
|
||||
reply.writeInt(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever);
|
||||
dest.writeStrongBinder(retriever);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract void writeElement(T parcelable, Parcel reply, int callFlags);
|
||||
|
||||
abstract void writeParcelableCreator(T parcelable, Parcel dest);
|
||||
|
||||
abstract Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2020 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.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a copied version of MediaParceledListSlice in framework with hidden API usages removed,
|
||||
* and also with some lint error fixed.
|
||||
*
|
||||
* Transfer a large list of Parcelable objects across an IPC. Splits into
|
||||
* multiple transactions if needed.
|
||||
*
|
||||
* @see BaseMediaParceledListSlice
|
||||
*
|
||||
* TODO: Remove this from @SystemApi once all the MediaSession related classes are moved
|
||||
* to apex (or ParceledListSlice moved to apex). This class is temporaily added to system API
|
||||
* for moving classes step by step.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||
public final class MediaParceledListSlice<T extends Parcelable>
|
||||
extends BaseMediaParceledListSlice<T> {
|
||||
public MediaParceledListSlice(@NonNull List<T> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
private MediaParceledListSlice(Parcel in, ClassLoader loader) {
|
||||
super(in, loader);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <T extends Parcelable> MediaParceledListSlice<T> emptyList() {
|
||||
return new MediaParceledListSlice<T>(Collections.<T> emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
int contents = 0;
|
||||
final List<T> list = getList();
|
||||
for (int i=0; i<list.size(); i++) {
|
||||
contents |= list.get(i).describeContents();
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeElement(T parcelable, Parcel dest, int callFlags) {
|
||||
parcelable.writeToParcel(dest, callFlags);
|
||||
}
|
||||
|
||||
@Override
|
||||
void writeParcelableCreator(T parcelable, Parcel dest) {
|
||||
dest.writeParcelableCreator((Parcelable) parcelable);
|
||||
}
|
||||
|
||||
@Override
|
||||
Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader) {
|
||||
return from.readParcelableCreator(loader);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final Parcelable.ClassLoaderCreator<MediaParceledListSlice> CREATOR =
|
||||
new Parcelable.ClassLoaderCreator<MediaParceledListSlice>() {
|
||||
public MediaParceledListSlice createFromParcel(Parcel in) {
|
||||
return new MediaParceledListSlice(in, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaParceledListSlice createFromParcel(Parcel in, ClassLoader loader) {
|
||||
return new MediaParceledListSlice(in, loader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaParceledListSlice[] newArray(int size) {
|
||||
return new MediaParceledListSlice[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -57,6 +57,16 @@ package android.media {
|
||||
ctor public MediaMetadata.Builder(@NonNull android.media.MediaMetadata, @IntRange(from=1) int);
|
||||
}
|
||||
|
||||
public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
|
||||
ctor public MediaParceledListSlice(@NonNull java.util.List<T>);
|
||||
method public int describeContents();
|
||||
method @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
|
||||
method public java.util.List<T> getList();
|
||||
method public void setInlineCountLimit(int);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.media.session {
|
||||
|
||||
Reference in New Issue
Block a user