10e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root/* 20e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Copyright (C) 2011 The Android Open Source Project 30e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 40e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 50e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * you may not use this file except in compliance with the License. 60e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * You may obtain a copy of the License at 70e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 80e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 90e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 100e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Unless required by applicable law or agreed to in writing, software 110e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 120e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * See the License for the specific language governing permissions and 140e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * limitations under the License. 150e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 160e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 170e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootpackage android.content.pm; 180e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 19d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackbornimport android.os.Binder; 20d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackbornimport android.os.IBinder; 210e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootimport android.os.Parcel; 220e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootimport android.os.Parcelable; 23d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackbornimport android.os.RemoteException; 24d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackbornimport android.util.Log; 250e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 26d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackbornimport java.util.ArrayList; 270e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootimport java.util.List; 280e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 290e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root/** 30d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn * Transfer a large list of Parcelable objects across an IPC. Splits into 31d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn * multiple transactions if needed. 320e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 330e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @hide 340e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 350e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootpublic class ParceledListSlice<T extends Parcelable> implements Parcelable { 36d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn private static String TAG = "ParceledListSlice"; 37d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn private static boolean DEBUG = false; 38d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn 390e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root /* 400e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * TODO get this number from somewhere else. For now set it to a quarter of 410e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * the 1MB limit. 420e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 430e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root private static final int MAX_IPC_SIZE = 256 * 1024; 44d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn private static final int MAX_FIRST_IPC_SIZE = MAX_IPC_SIZE / 2; 450e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 46d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn private final List<T> mList; 470e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 48d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn public ParceledListSlice(List<T> list) { 49d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn mList = list; 50d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 510e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 52d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn private ParceledListSlice(Parcel p, ClassLoader loader) { 53d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn final int N = p.readInt(); 54d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn mList = new ArrayList<T>(N); 55d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Retrieving " + N + " items"); 56d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (N <= 0) { 57d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return; 58d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 59d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn Parcelable.Creator<T> creator = p.readParcelableCreator(loader); 60d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn int i = 0; 61d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn while (i < N) { 62d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (p.readInt() == 0) { 63d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn break; 64d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 65d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn mList.add(p.readCreator(creator, loader)); 66d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1)); 67d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn i++; 68d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 69d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (i >= N) { 70d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return; 71d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 72d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn final IBinder retriever = p.readStrongBinder(); 73d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn while (i < N) { 74d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever); 75d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn Parcel data = Parcel.obtain(); 76d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn Parcel reply = Parcel.obtain(); 77d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn data.writeInt(i); 78d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn try { 79d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); 80d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } catch (RemoteException e) { 81d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e); 82d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return; 83d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 84d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn while (i < N && reply.readInt() != 0) { 85d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn mList.add(reply.readCreator(creator, loader)); 86d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1)); 87d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn i++; 88d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 89d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn reply.recycle(); 90d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn data.recycle(); 91d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 920e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 930e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 94d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn public List<T> getList() { 95d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return mList; 960e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 970e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 980e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root @Override 990e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public int describeContents() { 100d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn int contents = 0; 101d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn for (int i=0; i<mList.size(); i++) { 102d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn contents |= mList.get(i).describeContents(); 103d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 104d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return contents; 1050e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1060e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1070e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root /** 1080e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Write this to another Parcel. Note that this discards the internal Parcel 1090e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * and should not be used anymore. This is so we can pass this to a Binder 1100e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * where we won't have a chance to call recycle on this. 1110e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 1120e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root @Override 1130e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public void writeToParcel(Parcel dest, int flags) { 114d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn final int N = mList.size(); 115d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn final int callFlags = flags; 116d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn dest.writeInt(N); 117d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Writing " + N + " items"); 118d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (N > 0) { 119d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn dest.writeParcelableCreator(mList.get(0)); 120d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn int i = 0; 121d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn while (i < N && dest.dataSize() < MAX_FIRST_IPC_SIZE) { 122d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn dest.writeInt(1); 123d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn mList.get(i).writeToParcel(dest, callFlags); 124d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i)); 125d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn i++; 126d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 127d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (i < N) { 128d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn dest.writeInt(0); 129d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn Binder retriever = new Binder() { 130d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn @Override 131d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) 132d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn throws RemoteException { 133d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (code != FIRST_CALL_TRANSACTION) { 134d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return super.onTransact(code, data, reply, flags); 135d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 136d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn int i = data.readInt(); 137d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N); 138d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn while (i < N && reply.dataSize() < MAX_IPC_SIZE) { 139d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn reply.writeInt(1); 140d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn mList.get(i).writeToParcel(reply, callFlags); 141d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i)); 142d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn i++; 143d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 144d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (i < N) { 145d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N); 146d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn reply.writeInt(0); 147d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 148d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return true; 149d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 150d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn }; 151d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever); 152d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn dest.writeStrongBinder(retriever); 153d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 1540e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1550e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1560e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1570e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root @SuppressWarnings("unchecked") 158d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn public static final Parcelable.ClassLoaderCreator<ParceledListSlice> CREATOR = 159d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn new Parcelable.ClassLoaderCreator<ParceledListSlice>() { 1600e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public ParceledListSlice createFromParcel(Parcel in) { 161d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return new ParceledListSlice(in, null); 162d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn } 1630e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 164d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn @Override 165d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn public ParceledListSlice createFromParcel(Parcel in, ClassLoader loader) { 166d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaacDianne Hackborn return new ParceledListSlice(in, loader); 1670e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1680e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1690e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public ParceledListSlice[] newArray(int size) { 1700e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root return new ParceledListSlice[size]; 1710e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1720e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root }; 1730e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root} 174