ParceledListSlice.java revision 0e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3
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 190e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootimport android.os.Parcel; 200e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootimport android.os.Parcelable; 210e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 220e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootimport java.util.List; 230e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 240e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root/** 250e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Builds up a parcel that is discarded when written to another parcel or 260e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * written to a list. This is useful for API that sends huge lists across a 270e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Binder that may be larger than the IPC limit. 280e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 290e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @hide 300e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 310e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Rootpublic class ParceledListSlice<T extends Parcelable> implements Parcelable { 320e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root /* 330e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * TODO get this number from somewhere else. For now set it to a quarter of 340e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * the 1MB limit. 350e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 360e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root private static final int MAX_IPC_SIZE = 256 * 1024; 370e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 380e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root private Parcel mParcel; 390e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 400e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root private int mNumItems; 410e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 420e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root private boolean mIsLastSlice; 430e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 440e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public ParceledListSlice() { 450e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mParcel = Parcel.obtain(); 460e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 470e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 480e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root private ParceledListSlice(Parcel p, int numItems, boolean lastSlice) { 490e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mParcel = p; 500e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mNumItems = numItems; 510e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mIsLastSlice = lastSlice; 520e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 530e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 540e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root @Override 550e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public int describeContents() { 560e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root return 0; 570e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 580e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 590e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root /** 600e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Write this to another Parcel. Note that this discards the internal Parcel 610e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * and should not be used anymore. This is so we can pass this to a Binder 620e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * where we won't have a chance to call recycle on this. 630e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 640e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root @Override 650e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public void writeToParcel(Parcel dest, int flags) { 660e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root dest.writeInt(mNumItems); 670e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root dest.writeInt(mIsLastSlice ? 1 : 0); 680e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 690e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root if (mNumItems > 0) { 700e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root final int parcelSize = mParcel.dataSize(); 710e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root dest.writeInt(parcelSize); 720e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root dest.appendFrom(mParcel, 0, parcelSize); 730e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 740e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 750e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mNumItems = 0; 760e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mParcel.recycle(); 770e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mParcel = null; 780e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 790e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 800e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root /** 810e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Appends a parcel to this list slice. 820e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 830e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @param item Parcelable item to append to this list slice 840e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @return true when the list slice is full and should not be appended to 850e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * anymore 860e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 870e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public boolean append(T item) { 880e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root if (mParcel == null) { 890e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root throw new IllegalStateException("ParceledListSlice has already been recycled"); 900e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 910e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 920e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root item.writeToParcel(mParcel, PARCELABLE_WRITE_RETURN_VALUE); 930e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mNumItems++; 940e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 950e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root return mParcel.dataSize() > MAX_IPC_SIZE; 960e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 970e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 980e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root /** 990e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Populates a list and discards the internal state of the 1000e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * ParceledListSlice in the process. The instance should 1010e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * not be used anymore. 1020e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 1030e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @param list list to insert items from this slice. 1040e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @param creator creator that knows how to unparcel the 1050e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * target object type. 1060e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @return the last item inserted into the list or null if none. 1070e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 1080e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public T populateList(List<T> list, Creator<T> creator) { 1090e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mParcel.setDataPosition(0); 1100e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1110e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root T item = null; 1120e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root for (int i = 0; i < mNumItems; i++) { 1130e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root item = creator.createFromParcel(mParcel); 1140e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root list.add(item); 1150e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1160e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1170e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mParcel.recycle(); 1180e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mParcel = null; 1190e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1200e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root return item; 1210e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1220e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1230e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root /** 1240e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Sets whether this is the last list slice in the series. 1250e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 1260e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @param lastSlice 1270e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 1280e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public void setLastSlice(boolean lastSlice) { 1290e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root mIsLastSlice = lastSlice; 1300e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1310e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1320e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root /** 1330e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * Returns whether this is the last slice in a series of slices. 1340e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * 1350e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root * @return true if this is the last slice in the series. 1360e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root */ 1370e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public boolean isLastSlice() { 1380e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root return mIsLastSlice; 1390e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1400e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1410e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root @SuppressWarnings("unchecked") 1420e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public static final Parcelable.Creator<ParceledListSlice> CREATOR = 1430e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root new Parcelable.Creator<ParceledListSlice>() { 1440e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public ParceledListSlice createFromParcel(Parcel in) { 1450e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root final int numItems = in.readInt(); 1460e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root final boolean lastSlice = in.readInt() == 1; 1470e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1480e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root if (numItems > 0) { 1490e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root final int parcelSize = in.readInt(); 1500e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1510e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root // Advance within this Parcel 1520e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root int offset = in.dataPosition(); 1530e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root in.setDataPosition(offset + parcelSize); 1540e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1550e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root Parcel p = Parcel.obtain(); 1560e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root p.setDataPosition(0); 1570e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root p.appendFrom(in, offset, parcelSize); 1580e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root p.setDataPosition(0); 1590e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1600e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root return new ParceledListSlice(p, numItems, lastSlice); 1610e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } else { 1620e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root return new ParceledListSlice(); 1630e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1640e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1650e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root 1660e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root public ParceledListSlice[] newArray(int size) { 1670e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root return new ParceledListSlice[size]; 1680e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root } 1690e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root }; 1700e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root} 171