NekoX/TMessagesProj/src/main/java/com/google/android/exoplayer2/BundleListRetriever.java

126 lines
3.8 KiB
Java

/*
* Copyright 2021 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 com.google.android.exoplayer2;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList;
import java.util.List;
/**
* A {@link Binder} to transfer a list of {@link Bundle Bundles} across processes by splitting the
* list into multiple transactions.
*
* <p>Note: Using this class causes synchronous binder calls in the opposite direction regardless of
* the "oneway" property.
*
* <p>Example usage:
*
* <pre>{@code
* // Sender
* List<Bundle> list = ...;
* IBinder binder = new BundleListRetriever(list);
* Bundle bundle = new Bundle();
* bundle.putBinder("list", binder);
*
* // Receiver
* Bundle bundle = ...; // Received from the sender
* IBinder binder = bundle.getBinder("list");
* List<Bundle> list = BundleListRetriever.getList(binder);
* }</pre>
*/
public final class BundleListRetriever extends Binder {
// Soft limit of an IPC buffer size
private static final int SUGGESTED_MAX_IPC_SIZE =
Util.SDK_INT >= 30 ? IBinder.getSuggestedMaxIpcSizeBytes() : 64 * 1024;
private static final int REPLY_END_OF_LIST = 0;
private static final int REPLY_CONTINUE = 1;
private static final int REPLY_BREAK = 2;
private final ImmutableList<Bundle> list;
/** Creates a {@link Binder} to send a list of {@link Bundle Bundles} to another process. */
public BundleListRetriever(List<Bundle> list) {
this.list = ImmutableList.copyOf(list);
}
@Override
protected boolean onTransact(int code, Parcel data, @Nullable Parcel reply, int flags)
throws RemoteException {
if (code != FIRST_CALL_TRANSACTION) {
return super.onTransact(code, data, reply, flags);
}
if (reply == null) {
return false;
}
int count = list.size();
int index = data.readInt();
while (index < count && reply.dataSize() < SUGGESTED_MAX_IPC_SIZE) {
reply.writeInt(REPLY_CONTINUE);
reply.writeBundle(list.get(index));
index++;
}
reply.writeInt(index < count ? REPLY_BREAK : REPLY_END_OF_LIST);
return true;
}
/**
* Gets a list of {@link Bundle Bundles} from a {@link BundleListRetriever}.
*
* @param binder A binder interface backed by {@link BundleListRetriever}.
* @return The list of {@link Bundle Bundles}.
*/
public static ImmutableList<Bundle> getList(IBinder binder) {
ImmutableList.Builder<Bundle> builder = ImmutableList.builder();
int index = 0;
int replyCode = REPLY_CONTINUE;
while (replyCode != REPLY_END_OF_LIST) {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInt(index);
try {
binder.transact(FIRST_CALL_TRANSACTION, data, reply, /* flags= */ 0);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
while ((replyCode = reply.readInt()) == REPLY_CONTINUE) {
builder.add(checkNotNull(reply.readBundle()));
index++;
}
} finally {
reply.recycle();
data.recycle();
}
}
return builder.build();
}
}