diff options
10 files changed, 359 insertions, 232 deletions
diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java new file mode 100644 index 000000000000..c4e4e06be749 --- /dev/null +++ b/core/java/android/content/pm/BaseParceledListSlice.java @@ -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); +} diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java index 945858e6d3c6..d12e8846aabb 100644 --- a/core/java/android/content/pm/ParceledListSlice.java +++ b/core/java/android/content/pm/ParceledListSlice.java @@ -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; - - /* - * 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 static <T extends Parcelable> ParceledListSlice<T> emptyList() { - return new ParceledListSlice<T>(Collections.<T> emptyList()); - } - +public class ParceledListSlice<T extends Parcelable> extends BaseParceledListSlice<T> { 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(); - } + super(list); } - 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()); - } + private ParceledListSlice(Parcel in, ClassLoader loader) { + super(in, loader); } - public List<T> getList() { - return mList; + public static <T extends Parcelable> ParceledListSlice<T> emptyList() { + return new ParceledListSlice<T>(Collections.<T> emptyList()); } @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); - - final T parcelable = mList.get(i); - verifySameType(listElementClass, parcelable.getClass()); - parcelable.writeToParcel(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); + 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(reply, callFlags); + @Override + protected void writeParcelableCreator(T parcelable, Parcel dest) { + dest.writeParcelableCreator((Parcelable) parcelable); + } - 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]; } diff --git a/core/java/android/content/pm/StringParceledListSlice.aidl b/core/java/android/content/pm/StringParceledListSlice.aidl new file mode 100644 index 000000000000..345f3a7b5e3e --- /dev/null +++ b/core/java/android/content/pm/StringParceledListSlice.aidl @@ -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; diff --git a/core/java/android/content/pm/StringParceledListSlice.java b/core/java/android/content/pm/StringParceledListSlice.java new file mode 100644 index 000000000000..95407449a018 --- /dev/null +++ b/core/java/android/content/pm/StringParceledListSlice.java @@ -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]; + } + }; +} diff --git a/core/java/com/android/internal/util/ParcelableString.java b/core/java/com/android/internal/util/ParcelableString.java deleted file mode 100644 index 6bd856f5521d..000000000000 --- a/core/java/com/android/internal/util/ParcelableString.java +++ /dev/null @@ -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]; - } - }; -}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java index e5a92bf23bdc..5dd3c2ce6b5d 100644 --- a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java +++ b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java @@ -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. */ diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index deea9726403f..b68543146a51 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -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); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 14b1741346b9..d715ef1f275d 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -167,7 +167,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; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/MonitoringCertNotificationTask.java b/services/devicepolicy/java/com/android/server/devicepolicy/MonitoringCertNotificationTask.java index 03c137a95b85..fb95f8e4d919 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/MonitoringCertNotificationTask.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/MonitoringCertNotificationTask.java @@ -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; diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index d65a9bfbf897..756514bbecc4 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -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)); } } |