Merge "Delete ParcelableString, add StringParceledListSlice"
This commit is contained in:
committed by
Android (Google) Code Review
commit
a7aaae881c
201
core/java/android/content/pm/BaseParceledListSlice.java
Normal file
201
core/java/android/content/pm/BaseParceledListSlice.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.content.pm;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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 BaseParceledListSlice<T> implements Parcelable {
|
||||
private static String TAG = "ParceledListSlice";
|
||||
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.MAX_IPC_SIZE;
|
||||
|
||||
private final List<T> mList;
|
||||
|
||||
public BaseParceledListSlice(List<T> list) {
|
||||
mList = list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
BaseParceledListSlice(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 = reply.readCreator(creator, 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.getName() + " in list of type "
|
||||
+ expected.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> getList() {
|
||||
return mList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 && 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void writeElement(T parcelable, Parcel reply, int callFlags);
|
||||
|
||||
protected abstract void writeParcelableCreator(T parcelable, Parcel dest);
|
||||
|
||||
protected abstract Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader);
|
||||
}
|
||||
@@ -16,14 +16,9 @@
|
||||
|
||||
package android.content.pm;
|
||||
|
||||
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.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -31,171 +26,46 @@ import java.util.List;
|
||||
* 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.
|
||||
* @see BaseParceledListSlice
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ParceledListSlice<T extends Parcelable> implements Parcelable {
|
||||
private static String TAG = "ParceledListSlice";
|
||||
private static boolean DEBUG = false;
|
||||
public class ParceledListSlice<T extends Parcelable> extends BaseParceledListSlice<T> {
|
||||
public ParceledListSlice(List<T> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.MAX_IPC_SIZE;
|
||||
|
||||
private final List<T> mList;
|
||||
private ParceledListSlice(Parcel in, ClassLoader loader) {
|
||||
super(in, loader);
|
||||
}
|
||||
|
||||
public static <T extends Parcelable> ParceledListSlice<T> emptyList() {
|
||||
return new ParceledListSlice<T>(Collections.<T> emptyList());
|
||||
}
|
||||
|
||||
public ParceledListSlice(List<T> list) {
|
||||
mList = list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ParceledListSlice(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 = p.readParcelableCreator(loader);
|
||||
Class<?> listElementClass = null;
|
||||
|
||||
int i = 0;
|
||||
while (i < N) {
|
||||
if (p.readInt() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
final T parcelable = p.readCreator(creator, 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 = reply.readCreator(creator, 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 static void verifySameType(final Class<?> expected, final Class<?> actual) {
|
||||
if (!actual.equals(expected)) {
|
||||
throw new IllegalArgumentException("Can't unparcel type "
|
||||
+ actual.getName() + " in list of type "
|
||||
+ expected.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> getList() {
|
||||
return mList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
int contents = 0;
|
||||
for (int i=0; i<mList.size(); i++) {
|
||||
contents |= mList.get(i).describeContents();
|
||||
final List<T> list = getList();
|
||||
for (int i=0; i<list.size(); i++) {
|
||||
contents |= list.get(i).describeContents();
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
dest.writeParcelableCreator(mList.get(0));
|
||||
int i = 0;
|
||||
while (i < N && dest.dataSize() < MAX_IPC_SIZE) {
|
||||
dest.writeInt(1);
|
||||
protected void writeElement(T parcelable, Parcel dest, int callFlags) {
|
||||
parcelable.writeToParcel(dest, callFlags);
|
||||
}
|
||||
|
||||
final T parcelable = mList.get(i);
|
||||
verifySameType(listElementClass, parcelable.getClass());
|
||||
parcelable.writeToParcel(dest, callFlags);
|
||||
@Override
|
||||
protected void writeParcelableCreator(T parcelable, Parcel dest) {
|
||||
dest.writeParcelableCreator((Parcelable) parcelable);
|
||||
}
|
||||
|
||||
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());
|
||||
parcelable.writeToParcel(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);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader) {
|
||||
return from.readParcelableCreator(loader);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -210,6 +80,7 @@ public class ParceledListSlice<T extends Parcelable> implements Parcelable {
|
||||
return new ParceledListSlice(in, loader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParceledListSlice[] newArray(int size) {
|
||||
return new ParceledListSlice[size];
|
||||
}
|
||||
|
||||
19
core/java/android/content/pm/StringParceledListSlice.aidl
Normal file
19
core/java/android/content/pm/StringParceledListSlice.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2017, 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.content.pm;
|
||||
|
||||
parcelable StringParceledListSlice;
|
||||
83
core/java/android/content/pm/StringParceledListSlice.java
Normal file
83
core/java/android/content/pm/StringParceledListSlice.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.content.pm;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Transfer a large list of Parcelable objects across an IPC. Splits into
|
||||
* multiple transactions if needed.
|
||||
*
|
||||
* @see BaseParceledListSlice
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class StringParceledListSlice extends BaseParceledListSlice<String> {
|
||||
public StringParceledListSlice(List<String> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
private StringParceledListSlice(Parcel in, ClassLoader loader) {
|
||||
super(in, loader);
|
||||
}
|
||||
|
||||
public static StringParceledListSlice emptyList() {
|
||||
return new StringParceledListSlice(Collections.<String> emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeElement(String parcelable, Parcel reply, int callFlags) {
|
||||
reply.writeString(parcelable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeParcelableCreator(String parcelable, Parcel dest) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader) {
|
||||
return Parcel.STRING_CREATOR;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final Parcelable.ClassLoaderCreator<StringParceledListSlice> CREATOR =
|
||||
new Parcelable.ClassLoaderCreator<StringParceledListSlice>() {
|
||||
public StringParceledListSlice createFromParcel(Parcel in) {
|
||||
return new StringParceledListSlice(in, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringParceledListSlice createFromParcel(Parcel in, ClassLoader loader) {
|
||||
return new StringParceledListSlice(in, loader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringParceledListSlice[] newArray(int size) {
|
||||
return new StringParceledListSlice[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014, 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.android.internal.util;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Helper class to adapt a simple String to cases where a Parcelable is expected.
|
||||
* @hide
|
||||
*/
|
||||
public class ParcelableString implements Parcelable {
|
||||
public String string;
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(string);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ParcelableString> CREATOR =
|
||||
new Parcelable.Creator<ParcelableString>() {
|
||||
@Override
|
||||
public ParcelableString createFromParcel(Parcel in) {
|
||||
ParcelableString ret = new ParcelableString();
|
||||
ret.string = in.readString();
|
||||
return ret;
|
||||
}
|
||||
@Override
|
||||
public ParcelableString[] newArray(int size) {
|
||||
return new ParcelableString[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -91,6 +91,28 @@ public class ParceledListSliceTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testStringList() throws Exception {
|
||||
final int objectCount = 400;
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (long i = 0; i < objectCount; i++) {
|
||||
list.add(Long.toString(i * (6 - i)));
|
||||
}
|
||||
|
||||
StringParceledListSlice slice;
|
||||
Parcel parcel = Parcel.obtain();
|
||||
try {
|
||||
parcel.writeParcelable(new StringParceledListSlice(list), 0);
|
||||
parcel.setDataPosition(0);
|
||||
slice = parcel.readParcelable(getClass().getClassLoader());
|
||||
} finally {
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
assertNotNull(slice);
|
||||
assertNotNull(slice.getList());
|
||||
assertEquals(list, slice.getList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that only homogeneous elements may be unparceled.
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package android.security;
|
||||
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.StringParceledListSlice;
|
||||
|
||||
/**
|
||||
* Caller is required to ensure that {@link KeyStore#unlock
|
||||
@@ -39,8 +39,8 @@ interface IKeyChainService {
|
||||
// APIs used by Settings
|
||||
boolean deleteCaCertificate(String alias);
|
||||
boolean reset();
|
||||
ParceledListSlice getUserCaAliases();
|
||||
ParceledListSlice getSystemCaAliases();
|
||||
StringParceledListSlice getUserCaAliases();
|
||||
StringParceledListSlice getSystemCaAliases();
|
||||
boolean containsCaAlias(String alias);
|
||||
byte[] getEncodedCaCertificate(String alias, boolean includeDeletedSystem);
|
||||
List<String> getCaCertificateChainAliases(String rootAlias, boolean includeDeletedSystem);
|
||||
|
||||
@@ -168,7 +168,6 @@ import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.JournaledFile;
|
||||
import com.android.internal.util.ParcelableString;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
@@ -35,7 +35,6 @@ import android.security.KeyChain.KeyChainConnection;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.ParcelableString;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -150,12 +149,7 @@ public class MonitoringCertNotificationTask extends AsyncTask<Integer, Void, Voi
|
||||
private List<String> getInstalledCaCertificates(UserHandle userHandle)
|
||||
throws RemoteException, RuntimeException {
|
||||
try (KeyChainConnection conn = mInjector.keyChainBindAsUser(userHandle)) {
|
||||
List<ParcelableString> aliases = conn.getService().getUserCaAliases().getList();
|
||||
List<String> result = new ArrayList<>(aliases.size());
|
||||
for (int i = 0; i < aliases.size(); i++) {
|
||||
result.add(aliases.get(i).string);
|
||||
}
|
||||
return result;
|
||||
return conn.getService().getUserCaAliases().getList();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return null;
|
||||
|
||||
@@ -34,7 +34,7 @@ import android.content.ServiceConnection;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.StringParceledListSlice;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.net.IIpConnectivityMetrics;
|
||||
@@ -56,7 +56,6 @@ import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.ParcelableString;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
@@ -1220,8 +1219,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
mContext.userContexts.put(user, mContext);
|
||||
when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
|
||||
|
||||
ParceledListSlice<ParcelableString> oneCert = asSlice(new String[] {"1"});
|
||||
ParceledListSlice<ParcelableString> fourCerts = asSlice(new String[] {"1", "2", "3", "4"});
|
||||
StringParceledListSlice oneCert = asSlice(new String[] {"1"});
|
||||
StringParceledListSlice fourCerts = asSlice(new String[] {"1", "2", "3", "4"});
|
||||
|
||||
final String TEST_STRING = "Test for exactly 2 certs out of 4";
|
||||
doReturn(TEST_STRING).when(mContext.resources).getQuantityText(anyInt(), eq(2));
|
||||
@@ -1229,7 +1228,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
// Given that we have exactly one certificate installed,
|
||||
when(mContext.keyChainConnection.getService().getUserCaAliases()).thenReturn(oneCert);
|
||||
// when that certificate is approved,
|
||||
dpms.approveCaCert(oneCert.getList().get(0).string, userId, true);
|
||||
dpms.approveCaCert(oneCert.getList().get(0), userId, true);
|
||||
// a notification should not be shown.
|
||||
verify(mContext.notificationManager, timeout(1000))
|
||||
.cancelAsUser(anyString(), anyInt(), eq(user));
|
||||
@@ -1237,8 +1236,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
// Given that we have four certificates installed,
|
||||
when(mContext.keyChainConnection.getService().getUserCaAliases()).thenReturn(fourCerts);
|
||||
// when two of them are approved (one of them approved twice hence no action),
|
||||
dpms.approveCaCert(fourCerts.getList().get(0).string, userId, true);
|
||||
dpms.approveCaCert(fourCerts.getList().get(1).string, userId, true);
|
||||
dpms.approveCaCert(fourCerts.getList().get(0), userId, true);
|
||||
dpms.approveCaCert(fourCerts.getList().get(1), userId, true);
|
||||
// a notification should be shown saying that there are two certificates left to approve.
|
||||
verify(mContext.notificationManager, timeout(1000))
|
||||
.notifyAsUser(anyString(), anyInt(), argThat(
|
||||
@@ -3974,18 +3973,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert String[] to ParceledListSlice<ParcelableString>.
|
||||
* <p>
|
||||
* TODO: This shouldn't be necessary. If ParcelableString does need to exist, it also needs
|
||||
* a real constructor.
|
||||
* Convert String[] to StringParceledListSlice.
|
||||
*/
|
||||
private static ParceledListSlice<ParcelableString> asSlice(String[] s) {
|
||||
List<ParcelableString> list = new ArrayList<>(s.length);
|
||||
for (int i = 0; i < s.length; i++) {
|
||||
ParcelableString item = new ParcelableString();
|
||||
item.string = s[i];
|
||||
list.add(i, item);
|
||||
}
|
||||
return new ParceledListSlice<ParcelableString>(list);
|
||||
private static StringParceledListSlice asSlice(String[] s) {
|
||||
return new StringParceledListSlice(Arrays.asList(s));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user