diff --git a/app/src/main/aidl/aosp/android/content/pm/ParceledListSlice.aidl b/libcore/io/src/main/aidl/aosp/android/content/pm/ParceledListSlice.aidl
similarity index 100%
rename from app/src/main/aidl/aosp/android/content/pm/ParceledListSlice.aidl
rename to libcore/io/src/main/aidl/aosp/android/content/pm/ParceledListSlice.aidl
diff --git a/app/src/main/aidl/aosp/android/content/pm/StringParceledListSlice.aidl b/libcore/io/src/main/aidl/aosp/android/content/pm/StringParceledListSlice.aidl
similarity index 100%
rename from app/src/main/aidl/aosp/android/content/pm/StringParceledListSlice.aidl
rename to libcore/io/src/main/aidl/aosp/android/content/pm/StringParceledListSlice.aidl
diff --git a/libcore/io/src/main/aidl/io/github/muntashirakon/io/IFileSystemService.aidl b/libcore/io/src/main/aidl/io/github/muntashirakon/io/IFileSystemService.aidl
index 51e4e22e6a4..1c4a2e3910e 100644
--- a/libcore/io/src/main/aidl/io/github/muntashirakon/io/IFileSystemService.aidl
+++ b/libcore/io/src/main/aidl/io/github/muntashirakon/io/IFileSystemService.aidl
@@ -2,6 +2,7 @@
package io.github.muntashirakon.io;
+import aosp.android.content.pm.StringParceledListSlice;
import io.github.muntashirakon.io.IOResult;
// Copyright 2022 John "topjohnwu" Wu
@@ -18,7 +19,7 @@ interface IFileSystemService {
long length(String path);
/* (err, bool) */ IOResult createNewFile(String path);
boolean delete(String path);
- String[] list(String path);
+ StringParceledListSlice list(String path);
boolean mkdir(String path);
boolean mkdirs(String path);
boolean renameTo(String path, String dest);
diff --git a/app/src/main/java/aosp/android/content/pm/BaseParceledListSlice.java b/libcore/io/src/main/java/aosp/android/content/pm/BaseParceledListSlice.java
similarity index 96%
rename from app/src/main/java/aosp/android/content/pm/BaseParceledListSlice.java
rename to libcore/io/src/main/java/aosp/android/content/pm/BaseParceledListSlice.java
index deb0fe0225e..f5500635b03 100644
--- a/app/src/main/java/aosp/android/content/pm/BaseParceledListSlice.java
+++ b/libcore/io/src/main/java/aosp/android/content/pm/BaseParceledListSlice.java
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-or-later
+// SPDX-License-Identifier: GPL-3.0-or-later
package aosp.android.content.pm;
@@ -14,12 +14,10 @@
import java.util.ArrayList;
import java.util.List;
-import io.github.muntashirakon.io.IoUtils;
-
/**
* 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
@@ -31,7 +29,7 @@ abstract class BaseParceledListSlice implements Parcelable {
private static final String TAG = "ParceledListSlice";
private static final boolean DEBUG = false;
- private static final int MAX_IPC_SIZE = IoUtils.DEFAULT_BUFFER_SIZE;
+ private static final int MAX_IPC_SIZE = 1024 * 50; /*IoUtils.DEFAULT_BUFFER_SIZE*/
private final List mList;
@@ -69,7 +67,7 @@ public BaseParceledListSlice(List list) {
mList.add(parcelable);
- if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
+ if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size() - 1));
i++;
}
if (i >= N) {
@@ -93,7 +91,7 @@ public BaseParceledListSlice(List list) {
mList.add(parcelable);
- if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
+ if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size() - 1));
i++;
}
reply.recycle();
diff --git a/libcore/io/src/main/java/aosp/android/content/pm/ParcelUtils.java b/libcore/io/src/main/java/aosp/android/content/pm/ParcelUtils.java
new file mode 100644
index 00000000000..23e8748cfb5
--- /dev/null
+++ b/libcore/io/src/main/java/aosp/android/content/pm/ParcelUtils.java
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package aosp.android.content.pm;
+
+import android.os.BadParcelableException;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+public class ParcelUtils {
+ private static final String TAG = ParcelUtils.class.getSimpleName();
+
+ public static void writeParcelableCreator(@NonNull T parcelable, @NonNull Parcel dest) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ dest.writeParcelableCreator((Parcelable) parcelable);
+ } else {
+ String name = parcelable.getClass().getName();
+ dest.writeString(name);
+ }
+ }
+
+ // Cache of previously looked up CREATOR.createFromParcel() methods for
+ // particular classes. Keys are the names of the classes, values are
+ // Method objects.
+ private static final HashMap>> mCreators = new HashMap<>();
+
+ @Nullable
+ public static Parcelable.Creator> readParcelableCreator(@NonNull Parcel from, @Nullable ClassLoader loader) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ return from.readParcelableCreator(loader);
+ }
+ String name = from.readString();
+ if (name == null) {
+ return null;
+ }
+ Parcelable.Creator> creator;
+ synchronized (mCreators) {
+ HashMap> map = mCreators.get(loader);
+ if (map == null) {
+ map = new HashMap<>();
+ mCreators.put(loader, map);
+ }
+ creator = map.get(name);
+ if (creator == null) {
+ try {
+ // If loader == null, explicitly emulate Class.forName(String) "caller
+ // classloader" behavior.
+ ClassLoader parcelableClassLoader = (loader == null ? from.getClass().getClassLoader() : loader);
+ // Avoid initializing the Parcelable class until we know it implements
+ // Parcelable and has the necessary CREATOR field.
+ Class> parcelableClass = Class.forName(name, false /* initialize */,
+ parcelableClassLoader);
+ if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
+ throw new BadParcelableException("Parcelable protocol requires that the "
+ + "class implements Parcelable");
+ }
+ Field f = parcelableClass.getField("CREATOR");
+ if ((f.getModifiers() & Modifier.STATIC) == 0) {
+ throw new BadParcelableException("Parcelable protocol requires "
+ + "the CREATOR object to be static on class " + name);
+ }
+ Class> creatorType = f.getType();
+ if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
+ // Fail before calling Field.get(), not after, to avoid initializing
+ // parcelableClass unnecessarily.
+ throw new BadParcelableException("Parcelable protocol requires a "
+ + "Parcelable.Creator object called "
+ + "CREATOR on class " + name);
+ }
+ creator = (Parcelable.Creator>) f.get(null);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
+ throw new BadParcelableException(
+ "IllegalAccessException when unmarshalling: " + name);
+ } catch (ClassNotFoundException e) {
+ Log.e(TAG, "Class not found when unmarshalling: " + name, e);
+ throw new BadParcelableException("ClassNotFoundException when unmarshalling: " + name);
+ } catch (NoSuchFieldException e) {
+ throw new BadParcelableException("Parcelable protocol requires a "
+ + "Parcelable.Creator object called "
+ + "CREATOR on class " + name);
+ }
+ if (creator == null) {
+ throw new BadParcelableException("Parcelable protocol requires a "
+ + "non-null Parcelable.Creator object called "
+ + "CREATOR on class " + name);
+ }
+ map.put(name, creator);
+ }
+ }
+
+ return creator;
+ }
+}
diff --git a/app/src/main/java/aosp/android/content/pm/ParceledListSlice.java b/libcore/io/src/main/java/aosp/android/content/pm/ParceledListSlice.java
similarity index 94%
rename from app/src/main/java/aosp/android/content/pm/ParceledListSlice.java
rename to libcore/io/src/main/java/aosp/android/content/pm/ParceledListSlice.java
index d98d71ad8c3..af49d0884f8 100644
--- a/app/src/main/java/aosp/android/content/pm/ParceledListSlice.java
+++ b/libcore/io/src/main/java/aosp/android/content/pm/ParceledListSlice.java
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-or-later
+// SPDX-License-Identifier: GPL-3.0-or-later
package aosp.android.content.pm;
@@ -10,8 +10,6 @@
import java.util.Collections;
import java.util.List;
-import io.github.muntashirakon.util.ParcelUtils;
-
/**
* Transfer a large list of Parcelable objects across an IPC. Splits into
* multiple transactions if needed.
diff --git a/app/src/main/java/aosp/android/content/pm/StringParceledListSlice.java b/libcore/io/src/main/java/aosp/android/content/pm/StringParceledListSlice.java
similarity index 96%
rename from app/src/main/java/aosp/android/content/pm/StringParceledListSlice.java
rename to libcore/io/src/main/java/aosp/android/content/pm/StringParceledListSlice.java
index 33b0681db20..48e5fc85067 100644
--- a/app/src/main/java/aosp/android/content/pm/StringParceledListSlice.java
+++ b/libcore/io/src/main/java/aosp/android/content/pm/StringParceledListSlice.java
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-or-later
+// SPDX-License-Identifier: GPL-3.0-or-later
package aosp.android.content.pm;
diff --git a/libcore/io/src/main/java/io/github/muntashirakon/io/FileSystemService.java b/libcore/io/src/main/java/io/github/muntashirakon/io/FileSystemService.java
index eba3d8c920b..4e21dab84dd 100644
--- a/libcore/io/src/main/java/io/github/muntashirakon/io/FileSystemService.java
+++ b/libcore/io/src/main/java/io/github/muntashirakon/io/FileSystemService.java
@@ -23,9 +23,11 @@
import java.io.File;
import java.io.IOException;
+import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import aosp.android.content.pm.StringParceledListSlice;
import io.github.muntashirakon.compat.system.OsCompat;
import io.github.muntashirakon.compat.system.StructTimespec;
@@ -109,8 +111,9 @@ public boolean delete(String path) {
}
@Override
- public String[] list(String path) {
- return mCache.get(path).list();
+ public StringParceledListSlice list(String path) {
+ String[] list = mCache.get(path).list();
+ return list != null ? new StringParceledListSlice(Arrays.asList(list)) : null;
}
@Override
diff --git a/libcore/io/src/main/java/io/github/muntashirakon/io/RemoteFile.java b/libcore/io/src/main/java/io/github/muntashirakon/io/RemoteFile.java
index c5590ee58b2..989b6497a35 100644
--- a/libcore/io/src/main/java/io/github/muntashirakon/io/RemoteFile.java
+++ b/libcore/io/src/main/java/io/github/muntashirakon/io/RemoteFile.java
@@ -15,6 +15,8 @@
import java.io.FileOutputStream;
import java.io.IOException;
+import aosp.android.content.pm.StringParceledListSlice;
+
// Copyright 2022 John "topjohnwu" Wu
// Copyright 2022 Muntashir Al-Islam
class RemoteFile extends FileImpl {
@@ -313,7 +315,8 @@ public void deleteOnExit() {
@Override
public String[] list() {
try {
- return fs.list(getPath());
+ StringParceledListSlice list = fs.list(getPath());
+ return list != null ? list.getList().toArray(new String[0]) : null;
} catch (RemoteException e) {
return null;
}
diff --git a/libcore/ui/src/main/java/io/github/muntashirakon/util/ParcelUtils.java b/libcore/ui/src/main/java/io/github/muntashirakon/util/ParcelUtils.java
index b13a3a4d64c..1ab827fa9b3 100644
--- a/libcore/ui/src/main/java/io/github/muntashirakon/util/ParcelUtils.java
+++ b/libcore/ui/src/main/java/io/github/muntashirakon/util/ParcelUtils.java
@@ -2,24 +2,16 @@
package io.github.muntashirakon.util;
-import android.os.BadParcelableException;
-import android.os.Build;
import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.collection.ArraySet;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
public class ParcelUtils {
- private static final String TAG = ParcelUtils.class.getSimpleName();
-
/**
* Write an array set to the parcel.
*
@@ -70,86 +62,4 @@ public static Map readMap(@NonNull Parcel parcel, @Nullable ClassLo
}
return map;
}
-
- public static void writeParcelableCreator(@NonNull T parcelable, @NonNull Parcel dest) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- dest.writeParcelableCreator((Parcelable) parcelable);
- } else {
- String name = parcelable.getClass().getName();
- dest.writeString(name);
- }
- }
-
- // Cache of previously looked up CREATOR.createFromParcel() methods for
- // particular classes. Keys are the names of the classes, values are
- // Method objects.
- private static final HashMap>> mCreators = new HashMap<>();
-
- @Nullable
- public static Parcelable.Creator> readParcelableCreator(@NonNull Parcel from, @Nullable ClassLoader loader) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- return from.readParcelableCreator(loader);
- }
- String name = from.readString();
- if (name == null) {
- return null;
- }
- Parcelable.Creator> creator;
- synchronized (mCreators) {
- HashMap> map = mCreators.get(loader);
- if (map == null) {
- map = new HashMap<>();
- mCreators.put(loader, map);
- }
- creator = map.get(name);
- if (creator == null) {
- try {
- // If loader == null, explicitly emulate Class.forName(String) "caller
- // classloader" behavior.
- ClassLoader parcelableClassLoader = (loader == null ? from.getClass().getClassLoader() : loader);
- // Avoid initializing the Parcelable class until we know it implements
- // Parcelable and has the necessary CREATOR field.
- Class> parcelableClass = Class.forName(name, false /* initialize */,
- parcelableClassLoader);
- if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
- throw new BadParcelableException("Parcelable protocol requires that the "
- + "class implements Parcelable");
- }
- Field f = parcelableClass.getField("CREATOR");
- if ((f.getModifiers() & Modifier.STATIC) == 0) {
- throw new BadParcelableException("Parcelable protocol requires "
- + "the CREATOR object to be static on class " + name);
- }
- Class> creatorType = f.getType();
- if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
- // Fail before calling Field.get(), not after, to avoid initializing
- // parcelableClass unnecessarily.
- throw new BadParcelableException("Parcelable protocol requires a "
- + "Parcelable.Creator object called "
- + "CREATOR on class " + name);
- }
- creator = (Parcelable.Creator>) f.get(null);
- } catch (IllegalAccessException e) {
- Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
- throw new BadParcelableException(
- "IllegalAccessException when unmarshalling: " + name);
- } catch (ClassNotFoundException e) {
- Log.e(TAG, "Class not found when unmarshalling: " + name, e);
- throw new BadParcelableException("ClassNotFoundException when unmarshalling: " + name);
- } catch (NoSuchFieldException e) {
- throw new BadParcelableException("Parcelable protocol requires a "
- + "Parcelable.Creator object called "
- + "CREATOR on class " + name);
- }
- if (creator == null) {
- throw new BadParcelableException("Parcelable protocol requires a "
- + "non-null Parcelable.Creator object called "
- + "CREATOR on class " + name);
- }
- map.put(name, creator);
- }
- }
-
- return creator;
- }
}