Merge "Revert "Replace RemoteCallback with AndroidFuture in PermControler""
diff --git a/Android.bp b/Android.bp
index 8ed86d3..e70c707 100644
--- a/Android.bp
+++ b/Android.bp
@@ -421,7 +421,6 @@
         "core/java/com/android/internal/appwidget/IAppWidgetHost.aidl",
         "core/java/com/android/internal/backup/IBackupTransport.aidl",
         "core/java/com/android/internal/backup/IObbBackupService.aidl",
-        "core/java/com/android/internal/infra/IAndroidFuture.aidl",
         "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
         "core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl",
         "core/java/com/android/internal/inputmethod/IMultiClientInputMethod.aidl",
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index ec0fe92..45c01bc 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -20,7 +20,6 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
-import com.android.internal.infra.AndroidFuture;
 
 /**
  * Interface for system apps to communication with the permission controller.
@@ -29,17 +28,17 @@
  */
 oneway interface IPermissionController {
     void revokeRuntimePermissions(in Bundle request, boolean doDryRun, int reason,
-            String callerPackageName, in AndroidFuture callback);
+            String callerPackageName, in RemoteCallback callback);
     void getRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
     void restoreRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
     void restoreDelayedRuntimePermissionBackup(String packageName, in UserHandle user,
-            in AndroidFuture callback);
-    void getAppPermissions(String packageName, in AndroidFuture callback);
+            in RemoteCallback callback);
+    void getAppPermissions(String packageName, in RemoteCallback callback);
     void revokeRuntimePermission(String packageName, String permissionName);
     void countPermissionApps(in List<String> permissionNames, int flags,
-            in AndroidFuture callback);
-    void getPermissionUsages(boolean countSystem, long numMillis, in AndroidFuture callback);
+            in RemoteCallback callback);
+    void getPermissionUsages(boolean countSystem, long numMillis, in RemoteCallback callback);
     void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName,
-                String permission, int grantState, in AndroidFuture callback);
-    void grantOrUpgradeDefaultRuntimePermissions(in AndroidFuture callback);
+            String permission, int grantState, in RemoteCallback callback);
+    void grantOrUpgradeDefaultRuntimePermissions(in RemoteCallback callback);
 }
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 566ba8a..de0bcb6 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -46,6 +46,7 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.RemoteCallback;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -56,6 +57,7 @@
 import com.android.internal.infra.RemoteStream;
 import com.android.internal.infra.ServiceConnector;
 import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.Preconditions;
 
 import libcore.util.EmptyArray;
 
@@ -65,6 +67,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
@@ -91,6 +94,14 @@
     private static ArrayMap<Pair<Integer, Thread>, ServiceConnector<IPermissionController>>
             sRemoteServices = new ArrayMap<>(1);
 
+    /**
+     * The key for retrieving the result from the returned bundle.
+     *
+     * @hide
+     */
+    public static final String KEY_RESULT =
+            "android.permission.PermissionControllerManager.key.result";
+
     /** @hide */
     @IntDef(prefix = { "REASON_" }, value = {
             REASON_MALWARE,
@@ -280,17 +291,31 @@
                         new ArrayList<>(appRequest.getValue()));
             }
 
-            AndroidFuture<Map<String, List<String>>> revokeRuntimePermissionsResult =
-                    new AndroidFuture<>();
+            AndroidFuture<Bundle> revokeRuntimePermissionsResult = new AndroidFuture<>();
             service.revokeRuntimePermissions(bundledizedRequest, doDryRun, reason,
                     mContext.getPackageName(),
-                    revokeRuntimePermissionsResult);
+                    new RemoteCallback(revokeRuntimePermissionsResult::complete));
             return revokeRuntimePermissionsResult;
+        }).thenApply(revokeRuntimePermissionsResult -> {
+            Map<String, List<String>> revoked = new ArrayMap<>();
+            Bundle bundleizedRevoked = revokeRuntimePermissionsResult.getBundle(KEY_RESULT);
+
+            for (String packageName : bundleizedRevoked.keySet()) {
+                Preconditions.checkNotNull(packageName);
+
+                ArrayList<String> permissions =
+                        bundleizedRevoked.getStringArrayList(packageName);
+                Preconditions.checkCollectionElementsNotNull(permissions,
+                        "permissions");
+
+                revoked.put(packageName, permissions);
+            }
+            return revoked;
         }).whenCompleteAsync((revoked, err) -> {
             long token = Binder.clearCallingIdentity();
             try {
                 if (err != null) {
-                    Log.e(TAG, "Failure when revoking runtime permissions " + revoked, err);
+                    Log.e(TAG, "Failure when revoking runtime permissions", err);
                     callback.onRevokeRuntimePermissions(Collections.emptyMap());
                 } else {
                     callback.onRevokeRuntimePermissions(revoked);
@@ -331,10 +356,11 @@
         checkNotNull(callback);
 
         mRemoteService.postAsync(service -> {
-            AndroidFuture<Boolean> setRuntimePermissionGrantStateResult = new AndroidFuture<>();
+            CompletableFuture<Bundle> setRuntimePermissionGrantStateResult =
+                    new CompletableFuture<>();
             service.setRuntimePermissionGrantStateByDeviceAdmin(
                     callerPackageName, packageName, permission, grantState,
-                    setRuntimePermissionGrantStateResult);
+                    new RemoteCallback(setRuntimePermissionGrantStateResult::complete));
             return setRuntimePermissionGrantStateResult;
         }).whenCompleteAsync((setRuntimePermissionGrantStateResult, err) -> {
             long token = Binder.clearCallingIdentity();
@@ -344,7 +370,8 @@
                             err);
                     callback.accept(false);
                 } else {
-                    callback.accept(setRuntimePermissionGrantStateResult);
+                    callback.accept(
+                            setRuntimePermissionGrantStateResult.getBoolean(KEY_RESULT, false));
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -426,10 +453,10 @@
         checkNotNull(callback);
 
         mRemoteService.postAsync(service -> {
-            AndroidFuture<Boolean> restoreDelayedRuntimePermissionBackupResult =
-                    new AndroidFuture<>();
+            CompletableFuture<Bundle> restoreDelayedRuntimePermissionBackupResult =
+                    new CompletableFuture<>();
             service.restoreDelayedRuntimePermissionBackup(packageName, user,
-                    restoreDelayedRuntimePermissionBackupResult);
+                    new RemoteCallback(restoreDelayedRuntimePermissionBackupResult::complete));
             return restoreDelayedRuntimePermissionBackupResult;
         }).whenCompleteAsync((restoreDelayedRuntimePermissionBackupResult, err) -> {
             long token = Binder.clearCallingIdentity();
@@ -439,7 +466,8 @@
                     callback.accept(true);
                 } else {
                     callback.accept(
-                            Boolean.TRUE.equals(restoreDelayedRuntimePermissionBackupResult));
+                            restoreDelayedRuntimePermissionBackupResult
+                                    .getBoolean(KEY_RESULT, false));
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -464,16 +492,20 @@
         Handler finalHandler = handler != null ? handler : mHandler;
 
         mRemoteService.postAsync(service -> {
-            AndroidFuture<List<RuntimePermissionPresentationInfo>> getAppPermissionsResult =
-                    new AndroidFuture<>();
-            service.getAppPermissions(packageName, getAppPermissionsResult);
+            CompletableFuture<Bundle> getAppPermissionsResult = new CompletableFuture<>();
+            service.getAppPermissions(packageName,
+                    new RemoteCallback(getAppPermissionsResult::complete));
             return getAppPermissionsResult;
         }).whenComplete((getAppPermissionsResult, err) -> finalHandler.post(() -> {
             if (err != null) {
                 Log.e(TAG, "Error getting app permission", err);
                 callback.onGetAppPermissions(Collections.emptyList());
             } else {
-                callback.onGetAppPermissions(CollectionUtils.emptyIfNull(getAppPermissionsResult));
+                List<RuntimePermissionPresentationInfo> permissions = null;
+                if (getAppPermissionsResult != null) {
+                    permissions = getAppPermissionsResult.getParcelableArrayList(KEY_RESULT);
+                }
+                callback.onGetAppPermissions(CollectionUtils.emptyIfNull(permissions));
             }
         }));
     }
@@ -516,15 +548,18 @@
         Handler finalHandler = handler != null ? handler : mHandler;
 
         mRemoteService.postAsync(service -> {
-            AndroidFuture<Integer> countPermissionAppsResult = new AndroidFuture<>();
-            service.countPermissionApps(permissionNames, flags, countPermissionAppsResult);
+            CompletableFuture<Bundle> countPermissionAppsResult = new CompletableFuture<>();
+            service.countPermissionApps(permissionNames, flags,
+                    new RemoteCallback(countPermissionAppsResult::complete));
             return countPermissionAppsResult;
         }).whenComplete((countPermissionAppsResult, err) -> finalHandler.post(() -> {
             if (err != null) {
                 Log.e(TAG, "Error counting permission apps", err);
                 callback.onCountPermissionApps(0);
             } else {
-                callback.onCountPermissionApps(countPermissionAppsResult);
+                callback.onCountPermissionApps(countPermissionAppsResult != null
+                        ? countPermissionAppsResult.getInt(KEY_RESULT)
+                        : 0);
             }
         }));
     }
@@ -549,9 +584,9 @@
 
 
         mRemoteService.postAsync(service -> {
-            AndroidFuture<List<RuntimePermissionUsageInfo>> getPermissionUsagesResult =
-                    new AndroidFuture<>();
-            service.getPermissionUsages(countSystem, numMillis, getPermissionUsagesResult);
+            CompletableFuture<Bundle> getPermissionUsagesResult = new CompletableFuture<>();
+            service.getPermissionUsages(countSystem, numMillis,
+                    new RemoteCallback(getPermissionUsagesResult::complete));
             return getPermissionUsagesResult;
         }).whenCompleteAsync((getPermissionUsagesResult, err) -> {
             if (err != null) {
@@ -560,8 +595,9 @@
             } else {
                 long token = Binder.clearCallingIdentity();
                 try {
-                    callback.onPermissionUsageResult(
-                            CollectionUtils.emptyIfNull(getPermissionUsagesResult));
+                    callback.onPermissionUsageResult(getPermissionUsagesResult != null
+                            ? getPermissionUsagesResult.getParcelableArrayList(KEY_RESULT)
+                            : Collections.emptyList());
                 } finally {
                     Binder.restoreCallingIdentity(token);
                 }
@@ -583,17 +619,17 @@
     public void grantOrUpgradeDefaultRuntimePermissions(
             @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
         mRemoteService.postAsync(service -> {
-            AndroidFuture<Boolean> grantOrUpgradeDefaultRuntimePermissionsResult =
-                    new AndroidFuture<>();
+            CompletableFuture<Bundle> grantOrUpgradeDefaultRuntimePermissionsResult =
+                    new CompletableFuture<>();
             service.grantOrUpgradeDefaultRuntimePermissions(
-                    grantOrUpgradeDefaultRuntimePermissionsResult);
+                    new RemoteCallback(grantOrUpgradeDefaultRuntimePermissionsResult::complete));
             return grantOrUpgradeDefaultRuntimePermissionsResult;
         }).whenCompleteAsync((grantOrUpgradeDefaultRuntimePermissionsResult, err) -> {
             if (err != null) {
                 Log.e(TAG, "Error granting or upgrading runtime permissions", err);
                 callback.accept(false);
             } else {
-                callback.accept(grantOrUpgradeDefaultRuntimePermissionsResult);
+                callback.accept(grantOrUpgradeDefaultRuntimePermissionsResult != null);
             }
         }, executor);
     }
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index c9a1c38..8ae93a7 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -41,13 +41,12 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteCallback;
 import android.os.UserHandle;
 import android.permission.PermissionControllerManager.CountPermissionAppsFlag;
 import android.util.ArrayMap;
 import android.util.Log;
 
-import com.android.internal.infra.AndroidFuture;
-import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.Preconditions;
 
 import java.io.IOException;
@@ -210,7 +209,7 @@
             @Override
             public void revokeRuntimePermissions(
                     Bundle bundleizedRequest, boolean doDryRun, int reason,
-                    String callerPackageName, AndroidFuture callback) {
+                    String callerPackageName, RemoteCallback callback) {
                 checkNotNull(bundleizedRequest, "bundleizedRequest");
                 checkNotNull(callerPackageName);
                 checkNotNull(callback);
@@ -238,11 +237,22 @@
 
                 onRevokeRuntimePermissions(request,
                         doDryRun, reason, callerPackageName, revoked -> {
-                            CollectionUtils.forEach(revoked, (pkg, perms) -> {
-                                Preconditions.checkNotNull(pkg);
-                                Preconditions.checkCollectionElementsNotNull(perms, "permissions");
-                            });
-                            callback.complete(revoked);
+                            checkNotNull(revoked);
+                            Bundle bundledizedRevoked = new Bundle();
+                            for (Map.Entry<String, List<String>> appRevocation :
+                                    revoked.entrySet()) {
+                                checkNotNull(appRevocation.getKey());
+                                checkCollectionElementsNotNull(appRevocation.getValue(),
+                                        "permissions");
+
+                                bundledizedRevoked.putStringArrayList(appRevocation.getKey(),
+                                        new ArrayList<>(appRevocation.getValue()));
+                            }
+
+                            Bundle result = new Bundle();
+                            result.putBundle(PermissionControllerManager.KEY_RESULT,
+                                    bundledizedRevoked);
+                            callback.sendResult(result);
                         });
             }
 
@@ -284,24 +294,40 @@
 
             @Override
             public void restoreDelayedRuntimePermissionBackup(String packageName, UserHandle user,
-                    AndroidFuture callback) {
+                    RemoteCallback callback) {
                 checkNotNull(packageName);
                 checkNotNull(user);
                 checkNotNull(callback);
 
                 enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null);
 
-                onRestoreDelayedRuntimePermissionsBackup(packageName, user, callback::complete);
+                onRestoreDelayedRuntimePermissionsBackup(packageName, user,
+                        hasMoreBackup -> {
+                            Bundle result = new Bundle();
+                            result.putBoolean(PermissionControllerManager.KEY_RESULT,
+                                    hasMoreBackup);
+                            callback.sendResult(result);
+                        });
             }
 
             @Override
-            public void getAppPermissions(String packageName, AndroidFuture callback) {
+            public void getAppPermissions(String packageName, RemoteCallback callback) {
                 checkNotNull(packageName, "packageName");
                 checkNotNull(callback, "callback");
 
                 enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);
 
-                onGetAppPermissions(packageName, callback::complete);
+                onGetAppPermissions(packageName,
+                        permissions -> {
+                            if (permissions != null && !permissions.isEmpty()) {
+                                Bundle result = new Bundle();
+                                result.putParcelableList(PermissionControllerManager.KEY_RESULT,
+                                        permissions);
+                                callback.sendResult(result);
+                            } else {
+                                callback.sendResult(null);
+                            }
+                        });
             }
 
             @Override
@@ -323,31 +349,43 @@
 
             @Override
             public void countPermissionApps(List<String> permissionNames, int flags,
-                    AndroidFuture callback) {
+                    RemoteCallback callback) {
                 checkCollectionElementsNotNull(permissionNames, "permissionNames");
                 checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
                 checkNotNull(callback, "callback");
 
                 enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);
 
-                onCountPermissionApps(permissionNames, flags, callback::complete);
+                onCountPermissionApps(permissionNames, flags, numApps -> {
+                    Bundle result = new Bundle();
+                    result.putInt(PermissionControllerManager.KEY_RESULT, numApps);
+                    callback.sendResult(result);
+                });
             }
 
             @Override
             public void getPermissionUsages(boolean countSystem, long numMillis,
-                    AndroidFuture callback) {
+                    RemoteCallback callback) {
                 checkArgumentNonnegative(numMillis);
                 checkNotNull(callback, "callback");
 
                 enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);
 
-                onGetPermissionUsages(countSystem, numMillis, callback::complete);
+                onGetPermissionUsages(countSystem, numMillis, users -> {
+                    if (users != null && !users.isEmpty()) {
+                        Bundle result = new Bundle();
+                        result.putParcelableList(PermissionControllerManager.KEY_RESULT, users);
+                        callback.sendResult(result);
+                    } else {
+                        callback.sendResult(null);
+                    }
+                });
             }
 
             @Override
             public void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName,
                     String packageName, String permission, int grantState,
-                    AndroidFuture callback) {
+                    RemoteCallback callback) {
                 checkStringNotEmpty(callerPackageName);
                 checkStringNotEmpty(packageName);
                 checkStringNotEmpty(permission);
@@ -368,17 +406,21 @@
                         null);
 
                 onSetRuntimePermissionGrantStateByDeviceAdmin(callerPackageName,
-                        packageName, permission, grantState, callback::complete);
+                        packageName, permission, grantState, wasSet -> {
+                            Bundle result = new Bundle();
+                            result.putBoolean(PermissionControllerManager.KEY_RESULT, wasSet);
+                            callback.sendResult(result);
+                        });
             }
 
             @Override
-            public void grantOrUpgradeDefaultRuntimePermissions(@NonNull AndroidFuture callback) {
+            public void grantOrUpgradeDefaultRuntimePermissions(@NonNull RemoteCallback callback) {
                 checkNotNull(callback, "callback");
 
                 enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
                         null);
 
-                onGrantOrUpgradeDefaultRuntimePermissions(() -> callback.complete(null));
+                onGrantOrUpgradeDefaultRuntimePermissions(() -> callback.sendResult(Bundle.EMPTY));
             }
         };
     }
diff --git a/core/java/com/android/internal/infra/AndroidFuture.aidl b/core/java/com/android/internal/infra/AndroidFuture.aidl
deleted file mode 100644
index b19aab8..0000000
--- a/core/java/com/android/internal/infra/AndroidFuture.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-** Copyright 2019, 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.infra;
-
-/** @hide */
-parcelable AndroidFuture;
diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java
index 08938a6..c9e2d5f 100644
--- a/core/java/com/android/internal/infra/AndroidFuture.java
+++ b/core/java/com/android/internal/infra/AndroidFuture.java
@@ -23,9 +23,6 @@
 import android.annotation.Nullable;
 import android.os.Handler;
 import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
 import android.util.ExceptionUtils;
 import android.util.Log;
 
@@ -48,7 +45,6 @@
  * A customized {@link CompletableFuture} with focus on reducing the number of allocations involved
  * in a typical future usage scenario for Android.
  *
- * <p>
  * In particular this involves allocations optimizations in:
  * <ul>
  *     <li>{@link #thenCompose(Function)}</li>
@@ -59,20 +55,10 @@
  * </ul>
  * As well as their *Async versions.
  *
- * <p>
- * You can pass {@link AndroidFuture} across an IPC.
- * When doing so, completing the future on the other side will propagate the completion back,
- * effectively acting as an error-aware remote callback.
- *
- * <p>
- * {@link AndroidFuture} is {@link Parcelable} iff its wrapped type {@code T} is
- * effectively parcelable, i.e. is supported by {@link Parcel#readValue}/{@link Parcel#writeValue}.
- *
  * @param <T> see {@link CompletableFuture}
  */
-public class AndroidFuture<T> extends CompletableFuture<T> implements Parcelable {
+public class AndroidFuture<T> extends CompletableFuture<T> {
 
-    private static final boolean DEBUG = false;
     private static final String LOG_TAG = AndroidFuture.class.getSimpleName();
 
     private final @NonNull Object mLock = new Object();
@@ -81,38 +67,6 @@
     @GuardedBy("mLock")
     private @Nullable Executor mListenerExecutor = DIRECT_EXECUTOR;
     private @NonNull Handler mTimeoutHandler = Handler.getMain();
-    private final @Nullable IAndroidFuture mRemoteOrigin;
-
-    public AndroidFuture() {
-        super();
-        mRemoteOrigin = null;
-    }
-
-    AndroidFuture(Parcel in) {
-        super();
-        if (in.readBoolean()) {
-            // Done
-            if (in.readBoolean()) {
-                // Failed
-                try {
-                    in.readException();
-                } catch (Throwable e) {
-                    completeExceptionally(e);
-                }
-                if (!isCompletedExceptionally()) {
-                    throw new IllegalStateException(
-                            "Error unparceling AndroidFuture: exception expected");
-                }
-            } else {
-                // Success
-                complete((T) in.readValue(null));
-            }
-            mRemoteOrigin = null;
-        } else {
-            // Not done
-            mRemoteOrigin = IAndroidFuture.Stub.asInterface(in.readStrongBinder());
-        }
-    }
 
     @Override
     public boolean complete(@Nullable T value) {
@@ -136,11 +90,6 @@
     protected void onCompleted(@Nullable T res, @Nullable Throwable err) {
         cancelTimeout();
 
-        if (DEBUG) {
-            Log.i(LOG_TAG, this + " completed with result " + (err == null ? res : err),
-                    new RuntimeException());
-        }
-
         BiConsumer<? super T, ? super Throwable> listener;
         synchronized (mLock) {
             listener = mListener;
@@ -150,14 +99,6 @@
         if (listener != null) {
             callListenerAsync(listener, res, err);
         }
-
-        if (mRemoteOrigin != null) {
-            try {
-                mRemoteOrigin.complete(this /* resultContainer */);
-            } catch (RemoteException e) {
-                Log.e(LOG_TAG, "Failed to propagate completion", e);
-            }
-        }
     }
 
     @Override
@@ -472,49 +413,4 @@
             }
         }
     }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        boolean done = isDone();
-        dest.writeBoolean(done);
-        if (done) {
-            T result;
-            try {
-                result = get();
-            } catch (Exception t) {
-                dest.writeBoolean(true);
-                dest.writeException(t);
-                return;
-            }
-            dest.writeBoolean(false);
-            dest.writeValue(result);
-        } else {
-            dest.writeStrongBinder(new IAndroidFuture.Stub() {
-                @Override
-                public void complete(AndroidFuture resultContainer) {
-                    try {
-                        AndroidFuture.this.complete((T) resultContainer.get());
-                    } catch (Throwable t) {
-                        completeExceptionally(t);
-                    }
-                }
-            }.asBinder());
-        }
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @NonNull Parcelable.Creator<AndroidFuture> CREATOR =
-            new Parcelable.Creator<AndroidFuture>() {
-                public AndroidFuture createFromParcel(Parcel parcel) {
-                    return new AndroidFuture(parcel);
-                }
-
-                public AndroidFuture[] newArray(int size) {
-                    return new AndroidFuture[size];
-                }
-            };
 }
diff --git a/core/java/com/android/internal/infra/IAndroidFuture.aidl b/core/java/com/android/internal/infra/IAndroidFuture.aidl
deleted file mode 100644
index 302fdde..0000000
--- a/core/java/com/android/internal/infra/IAndroidFuture.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-** Copyright 2019, 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.infra;
-
-import com.android.internal.infra.AndroidFuture;
-
-oneway interface IAndroidFuture {
-    void complete(in AndroidFuture resultContainer);
-}
\ No newline at end of file
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index f9cf23b..78fdfe4 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.ExceptionUtils;
 
@@ -30,7 +29,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.function.BiConsumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
@@ -330,33 +328,6 @@
     }
 
     /**
-     * Applies {@code action} to each element in {@code cur}
-     *
-     * This avoids creating an iterator if the given map is an {@link ArrayMap}
-     * For non-{@link ArrayMap}s it avoids creating {@link Map.Entry} instances
-     */
-    public static <K, V> void forEach(@Nullable Map<K, V> cur, @Nullable BiConsumer<K, V> action) {
-        if (cur == null || action == null) {
-            return;
-        }
-        int size = cur.size();
-        if (size == 0) {
-            return;
-        }
-
-        if (cur instanceof ArrayMap) {
-            ArrayMap<K, V> arrayMap = (ArrayMap<K, V>) cur;
-            for (int i = 0; i < size; i++) {
-                action.accept(arrayMap.keyAt(i), arrayMap.valueAt(i));
-            }
-        } else {
-            for (K key : cur.keySet()) {
-                action.accept(key, cur.get(key));
-            }
-        }
-    }
-
-    /**
      * @return the first element if not empty/null, null otherwise
      */
     public static @Nullable <T> T firstOrNull(@Nullable List<T> cur) {