All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.android.media.session.ParcelableListBinder Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 15-robolectric-12650502
Show newest version
/*
 * 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.session;

import android.annotation.NonNull;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;

import com.android.internal.annotations.GuardedBy;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Binder to receive a list that has a large number of {@link Parcelable} items.
 *
 * It's similar to {@link android.content.pm.ParceledListSlice}, but transactions are performed in
 * the opposite direction.
 *
 * @param  the type of {@link Parcelable}
 * @hide
 */
public class ParcelableListBinder extends Binder {

    private static final int SUGGESTED_MAX_IPC_SIZE = IBinder.getSuggestedMaxIpcSizeBytes();

    private static final int END_OF_PARCEL = 0;
    private static final int ITEM_CONTINUED = 1;

    private final Consumer> mConsumer;

    private final Object mLock = new Object();

    @GuardedBy("mLock")
    private final List mList = new ArrayList<>();

    @GuardedBy("mLock")
    private int mCount;

    @GuardedBy("mLock")
    private boolean mConsumed;

    /**
     * Creates an instance.
     *
     * @param consumer a consumer that consumes the list received
     */
    public ParcelableListBinder(@NonNull Consumer> consumer) {
        mConsumer = consumer;
    }

    @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);
        }
        List listToBeConsumed;
        synchronized (mLock) {
            if (mConsumed) {
                return false;
            }
            int i = mList.size();
            if (i == 0) {
                mCount = data.readInt();
            }
            while (i < mCount && data.readInt() != END_OF_PARCEL) {
                mList.add(data.readParcelable(null));
                i++;
            }
            if (i >= mCount) {
                listToBeConsumed = mList;
                mConsumed = true;
            } else {
                listToBeConsumed = null;
            }
        }
        if (listToBeConsumed != null) {
            mConsumer.accept(listToBeConsumed);
        }
        return true;
    }

    /**
     * Sends a list of {@link Parcelable} to a binder.
     *
     * @param binder a binder interface backed by {@link ParcelableListBinder}
     * @param list a list to send
     */
    public static  void send(@NonNull IBinder binder, @NonNull List list)
            throws RemoteException {
        int count = list.size();
        int i = 0;
        do {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            if (i == 0) {
                data.writeInt(count);
            }
            while (i < count && data.dataSize() < SUGGESTED_MAX_IPC_SIZE) {
                data.writeInt(ITEM_CONTINUED);
                data.writeParcelable(list.get(i), 0);
                i++;
            }
            if (i < count) {
                data.writeInt(END_OF_PARCEL);
            }
            binder.transact(FIRST_CALL_TRANSACTION, data, reply, 0);
            reply.recycle();
            data.recycle();
        } while (i < count);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy