APIs to watch active op changes

System singed components can watch for starting/finishing of
long running app ops. Also protected the APIs to watch op mode
changes with a singature permission for the cross-uid use case.

Test: atest com.android.server.appops.AppOpsActiveWatcherTest

bug:64085448

Change-Id: Id7fe79ce1de4c5690b4f52786424ec5a5d9eb0fa
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4c9fb74..f7b10c3 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -34,8 +35,10 @@
 import android.os.UserManager;
 import android.util.ArrayMap;
 
+import com.android.internal.app.IAppOpsActiveCallback;
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -74,8 +77,9 @@
 
     final Context mContext;
     final IAppOpsService mService;
-    final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers
-            = new ArrayMap<OnOpChangedListener, IAppOpsCallback>();
+    final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers = new ArrayMap<>();
+    final ArrayMap<OnOpActiveChangedListener, IAppOpsActiveCallback> mActiveWatchers =
+            new ArrayMap<>();
 
     static IBinder sToken;
 
@@ -1533,6 +1537,23 @@
     }
 
     /**
+     * Callback for notification of changes to operation active state.
+     *
+     * @hide
+     */
+    public interface OnOpActiveChangedListener {
+        /**
+         * Called when the active state of an app op changes.
+         *
+         * @param code The op code.
+         * @param uid The UID performing the operation.
+         * @param packageName The package performing the operation.
+         * @param active Whether the operation became active or inactive.
+         */
+        void onOpActiveChanged(int code, int uid, String packageName, boolean active);
+    }
+
+    /**
      * Callback for notification of changes to operation state.
      * This allows you to see the raw op codes instead of strings.
      * @hide
@@ -1696,6 +1717,8 @@
 
     /**
      * Monitor for changes to the operating mode for the given op in the given app package.
+     * You can watch op changes only for your UID.
+     *
      * @param op The operation to monitor, one of OPSTR_*.
      * @param packageName The name of the application to monitor.
      * @param callback Where to report changes.
@@ -1707,11 +1730,17 @@
 
     /**
      * Monitor for changes to the operating mode for the given op in the given app package.
+     *
+     * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
+     * to watch changes only for your UID.
+     *
      * @param op The operation to monitor, one of OP_*.
      * @param packageName The name of the application to monitor.
      * @param callback Where to report changes.
      * @hide
      */
+    // TODO: Uncomment below annotation once b/73559440 is fixed
+    // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
     public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
         synchronized (mModeWatchers) {
             IAppOpsCallback cb = mModeWatchers.get(callback);
@@ -1753,6 +1782,74 @@
         }
     }
 
+    /**
+     * Start watching for changes to the active state of app ops. An app op may be
+     * long running and it has a clear start and stop delimiters. If an op is being
+     * started or stopped by any package you will get a callback. To change the
+     * watched ops for a registered callback you need to unregister and register it
+     * again.
+     *
+     * @param ops The ops to watch.
+     * @param callback Where to report changes.
+     *
+     * @see #isOperationActive(int, int, String)
+     * @see #stopWatchingActive(OnOpActiveChangedListener)
+     * @see #startOp(int, int, String)
+     * @see #finishOp(int, int, String)
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.WATCH_APPOPS)
+    public void startWatchingActive(@NonNull int[] ops,
+            @NonNull OnOpActiveChangedListener callback) {
+        Preconditions.checkNotNull(ops, "ops cannot be null");
+        Preconditions.checkNotNull(callback, "callback cannot be null");
+        IAppOpsActiveCallback cb;
+        synchronized (mActiveWatchers) {
+            cb = mActiveWatchers.get(callback);
+            if (cb != null) {
+                return;
+            }
+            cb = new IAppOpsActiveCallback.Stub() {
+                @Override
+                public void opActiveChanged(int op, int uid, String packageName, boolean active) {
+                    callback.onOpActiveChanged(op, uid, packageName, active);
+                }
+            };
+            mActiveWatchers.put(callback, cb);
+        }
+        try {
+            mService.startWatchingActive(ops, cb);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Stop watching for changes to the active state of an app op. An app op may be
+     * long running and it has a clear start and stop delimiters. Unregistering a
+     * non-registered callback has no effect.
+     *
+     * @see #isOperationActive#(int, int, String)
+     * @see #startWatchingActive(int[], OnOpActiveChangedListener)
+     * @see #startOp(int, int, String)
+     * @see #finishOp(int, int, String)
+     *
+     * @hide
+     */
+    public void stopWatchingActive(@NonNull OnOpActiveChangedListener callback) {
+        synchronized (mActiveWatchers) {
+            final IAppOpsActiveCallback cb = mActiveWatchers.get(callback);
+            if (cb != null) {
+                try {
+                    mService.stopWatchingActive(cb);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+        }
+    }
+
     private String buildSecurityExceptionMsg(int op, int uid, String packageName) {
         return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
     }
@@ -2146,6 +2243,7 @@
     }
 
     /** @hide */
+    @RequiresPermission(Manifest.permission.WATCH_APPOPS)
     public boolean isOperationActive(int code, int uid, String packageName) {
         try {
             return mService.isOperationActive(code, uid, packageName);
diff --git a/core/java/com/android/internal/app/IAppOpsActiveCallback.aidl b/core/java/com/android/internal/app/IAppOpsActiveCallback.aidl
new file mode 100644
index 0000000..510af77
--- /dev/null
+++ b/core/java/com/android/internal/app/IAppOpsActiveCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2018 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.app;
+
+// Iterface to observe op active changes
+oneway interface IAppOpsActiveCallback {
+    void opActiveChanged(int op, int uid, String packageName, boolean active);
+}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 2b975fe..fabda4a 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -19,6 +19,7 @@
 import android.app.AppOpsManager;
 import android.os.Bundle;
 import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsActiveCallback;
 
 interface IAppOpsService {
     // These first methods are also called by native code, so must
@@ -49,5 +50,7 @@
     void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, in String[] exceptionPackages);
     void removeUser(int userHandle);
 
+    void startWatchingActive(in int[] ops, IAppOpsActiveCallback callback);
+    void stopWatchingActive(IAppOpsActiveCallback callback);
     boolean isOperationActive(int code, int uid, String packageName);
 }
diff --git a/core/java/com/android/internal/util/function/HexConsumer.java b/core/java/com/android/internal/util/function/HexConsumer.java
new file mode 100644
index 0000000..ef6aee2
--- /dev/null
+++ b/core/java/com/android/internal/util/function/HexConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.function;
+
+import java.util.function.Consumer;
+
+/**
+ * A 6-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface HexConsumer<A, B, C, D, E, F> {
+    void accept(A a, B b, C c, D d, E e, F f);
+}
diff --git a/core/java/com/android/internal/util/function/HexFunction.java b/core/java/com/android/internal/util/function/HexFunction.java
new file mode 100644
index 0000000..6268daf
--- /dev/null
+++ b/core/java/com/android/internal/util/function/HexFunction.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.function;
+
+import java.util.function.Function;
+
+/**
+ * A 6-argument {@link Function}
+ *
+ * @hide
+ */
+public interface HexFunction<A, B, C, D, E, F, R> {
+    R apply(A a, B b, C c, D d, E e, F f);
+}
diff --git a/core/java/com/android/internal/util/function/HexPredicate.java b/core/java/com/android/internal/util/function/HexPredicate.java
new file mode 100644
index 0000000..c6ebf6a
--- /dev/null
+++ b/core/java/com/android/internal/util/function/HexPredicate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.function;
+
+import java.util.function.Predicate;
+
+/**
+ * A 6-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface HexPredicate<A, B, C, D, E, F> {
+    boolean test(A a, B b, C c, D d, E e, F f);
+}
diff --git a/core/java/com/android/internal/util/function/QuintConsumer.java b/core/java/com/android/internal/util/function/QuintConsumer.java
new file mode 100644
index 0000000..ebbc5ad
--- /dev/null
+++ b/core/java/com/android/internal/util/function/QuintConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.function;
+
+import java.util.function.Consumer;
+
+/**
+ * A 5-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface QuintConsumer<A, B, C, D, E> {
+    void accept(A a, B b, C c, D d, E e);
+}
diff --git a/core/java/com/android/internal/util/function/QuintFunction.java b/core/java/com/android/internal/util/function/QuintFunction.java
new file mode 100644
index 0000000..1b58f1f
--- /dev/null
+++ b/core/java/com/android/internal/util/function/QuintFunction.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.function;
+
+import java.util.function.Function;
+
+/**
+ * A 5-argument {@link Function}
+ *
+ * @hide
+ */
+public interface QuintFunction<A, B, C, D, E, R> {
+    R apply(A a, B b, C c, D d, E e);
+}
diff --git a/core/java/com/android/internal/util/function/QuintPredicate.java b/core/java/com/android/internal/util/function/QuintPredicate.java
new file mode 100644
index 0000000..5e1f11d
--- /dev/null
+++ b/core/java/com/android/internal/util/function/QuintPredicate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.function;
+
+import java.util.function.Predicate;
+
+/**
+ * A 5-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface QuintPredicate<A, B, C, D, E> {
+    boolean test(A a, B b, C c, D d, E e);
+}
diff --git a/core/java/com/android/internal/util/function/pooled/OmniFunction.java b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
index c0f506e..9378869 100755
--- a/core/java/com/android/internal/util/function/pooled/OmniFunction.java
+++ b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
@@ -18,8 +18,12 @@
 
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
+import com.android.internal.util.function.HexConsumer;
+import com.android.internal.util.function.HexFunction;
 import com.android.internal.util.function.QuadConsumer;
 import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.QuintConsumer;
+import com.android.internal.util.function.QuintFunction;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
 
@@ -33,58 +37,59 @@
  *
  * @hide
  */
-abstract class OmniFunction<A, B, C, D, R> implements
+abstract class OmniFunction<A, B, C, D, E, F, R> implements
         PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>,
-        QuadFunction<A, B, C, D, R>,
-        PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>,
-        PooledPredicate<A>, BiPredicate<A, B>,
-        PooledSupplier<R>, PooledRunnable,
-        ThrowingRunnable, ThrowingSupplier<R>,
+        QuadFunction<A, B, C, D, R>, QuintFunction<A, B, C, D, E, R>,
+        HexFunction<A, B, C, D, E, F, R>, PooledConsumer<A>, BiConsumer<A, B>,
+        TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>, QuintConsumer<A, B, C, D, E>,
+        HexConsumer<A, B, C, D, E, F>, PooledPredicate<A>, BiPredicate<A, B>,
+        PooledSupplier<R>, PooledRunnable, ThrowingRunnable, ThrowingSupplier<R>,
         PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
 
-    abstract R invoke(A a, B b, C c, D d);
+    abstract R invoke(A a, B b, C c, D d, E e, F f);
 
     @Override
     public R apply(A o, B o2) {
-        return invoke(o, o2, null, null);
+        return invoke(o, o2, null, null, null, null);
     }
 
     @Override
     public R apply(A o) {
-        return invoke(o, null, null, null);
+        return invoke(o, null, null, null, null, null);
     }
 
-    abstract public <V> OmniFunction<A, B, C, D, V> andThen(Function<? super R, ? extends V> after);
-    abstract public OmniFunction<A, B, C, D, R> negate();
+    abstract public <V> OmniFunction<A, B, C, D, E, F, V> andThen(
+            Function<? super R, ? extends V> after);
+    abstract public OmniFunction<A, B, C, D, E, F, R> negate();
 
     @Override
     public void accept(A o, B o2) {
-        invoke(o, o2, null, null);
+        invoke(o, o2, null, null, null, null);
     }
 
     @Override
     public void accept(A o) {
-        invoke(o, null, null, null);
+        invoke(o, null, null, null, null, null);
     }
 
     @Override
     public void run() {
-        invoke(null, null, null, null);
+        invoke(null, null, null, null, null, null);
     }
 
     @Override
     public R get() {
-        return invoke(null, null, null, null);
+        return invoke(null, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o, B o2) {
-        return (Boolean) invoke(o, o2, null, null);
+        return (Boolean) invoke(o, o2, null, null, null, null);
     }
 
     @Override
     public boolean test(A o) {
-        return (Boolean) invoke(o, null, null, null);
+        return (Boolean) invoke(o, null, null, null, null, null);
     }
 
     @Override
@@ -99,22 +104,42 @@
 
     @Override
     public R apply(A a, B b, C c) {
-        return invoke(a, b, c, null);
+        return invoke(a, b, c, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c) {
-        invoke(a, b, c, null);
+        invoke(a, b, c, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d) {
-        return invoke(a, b, c, d);
+        return invoke(a, b, c, d, null, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e) {
+        return invoke(a, b, c, d, e, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e, F f) {
+        return invoke(a, b, c, d, e, f);
     }
 
     @Override
     public void accept(A a, B b, C c, D d) {
-        invoke(a, b, c, d);
+        invoke(a, b, c, d, null, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e) {
+        invoke(a, b, c, d, e, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e, F f) {
+        invoke(a, b, c, d, e, f);
     }
 
     @Override
@@ -128,5 +153,5 @@
     }
 
     @Override
-    abstract public OmniFunction<A, B, C, D, R> recycleOnUse();
+    abstract public OmniFunction<A, B, C, D, E, F, R> recycleOnUse();
 }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index 87c25e9..15698cc 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -21,8 +21,12 @@
 
 import android.os.Message;
 
+import com.android.internal.util.function.HexConsumer;
+import com.android.internal.util.function.HexFunction;
 import com.android.internal.util.function.QuadConsumer;
 import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.QuintConsumer;
+import com.android.internal.util.function.QuintFunction;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
 import com.android.internal.util.function.pooled.PooledLambdaImpl.LambdaType.ReturnType;
@@ -170,7 +174,7 @@
             Consumer<? super A> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.VOID, arg1, null, null, null);
+                function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null);
     }
 
     /**
@@ -186,7 +190,7 @@
             Predicate<? super A> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null);
+                function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null);
     }
 
     /**
@@ -202,7 +206,7 @@
             Function<? super A, ? extends R> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.OBJECT, arg1, null, null, null);
+                function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null);
     }
 
     /**
@@ -232,7 +236,7 @@
             A arg1) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 1, 0, ReturnType.VOID, arg1, null, null, null);
+                    function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -251,7 +255,7 @@
             BiConsumer<? super A, ? super B> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.VOID, arg1, arg2, null, null);
+                function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -268,7 +272,7 @@
             BiPredicate<? super A, ? super B> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null);
+                function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -285,7 +289,7 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null);
+                function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -302,7 +306,7 @@
             BiConsumer<? super A, ? super B> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null);
+                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -319,7 +323,7 @@
             BiPredicate<? super A, ? super B> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null);
+                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -336,7 +340,7 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null);
+                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -353,7 +357,7 @@
             BiConsumer<? super A, ? super B> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null);
+                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -370,7 +374,7 @@
             BiPredicate<? super A, ? super B> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null);
+                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -387,7 +391,7 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null);
+                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
     }
 
     /**
@@ -418,7 +422,7 @@
             A arg1, B arg2) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 2, 0, ReturnType.VOID, arg1, arg2, null, null);
+                    function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -438,7 +442,7 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null);
+                function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
     }
 
     /**
@@ -456,7 +460,7 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null);
+                function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
     }
 
     /**
@@ -474,7 +478,7 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
     }
 
     /**
@@ -492,7 +496,7 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
     }
 
     /**
@@ -510,7 +514,7 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
     }
 
     /**
@@ -528,7 +532,7 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
     }
 
     /**
@@ -546,7 +550,7 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
     }
 
     /**
@@ -564,7 +568,7 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
     }
 
     /**
@@ -596,7 +600,7 @@
             A arg1, B arg2, C arg3) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null);
+                    function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -617,7 +621,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4);
+                function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -636,7 +640,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
+                function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -655,7 +659,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -674,7 +678,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -693,7 +697,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -712,7 +716,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -731,7 +735,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -750,7 +754,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -769,7 +773,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -788,7 +792,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
     }
 
     /**
@@ -821,7 +825,164 @@
             A arg1, B arg2, C arg3, D arg4) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4);
+                    function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5) }
+     */
+    static <A, B, C, D, E> PooledRunnable obtainRunnable(
+            QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5) }
+     */
+    static <A, B, C, D, E, R> PooledSupplier<R> obtainSupplier(
+            QuintFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? extends R>
+                    function, A arg1, B arg2, C arg3, D arg4, E arg5) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5) } when
+     *         handled
+     */
+    static <A, B, C, D, E> Message obtainMessage(
+            QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6) }
+     */
+    static <A, B, C, D, E, F> PooledRunnable obtainRunnable(
+            HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6) }
+     */
+    static <A, B, C, D, E, F, R> PooledSupplier<R> obtainSupplier(
+            HexFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6) }
+     *         when handled
+     */
+    static <A, B, C, D, E, F> Message obtainMessage(
+            HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index 03e013c..565ae11 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -24,9 +24,15 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
+import com.android.internal.util.function.HexConsumer;
+import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.HexPredicate;
 import com.android.internal.util.function.QuadConsumer;
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.QuadPredicate;
+import com.android.internal.util.function.QuintConsumer;
+import com.android.internal.util.function.QuintFunction;
+import com.android.internal.util.function.QuintPredicate;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.util.function.TriFunction;
 import com.android.internal.util.function.TriPredicate;
@@ -44,12 +50,13 @@
  * @see PooledLambda
  * @hide
  */
-final class PooledLambdaImpl<R> extends OmniFunction<Object, Object, Object, Object, R> {
+final class PooledLambdaImpl<R> extends OmniFunction<Object,
+        Object, Object, Object, Object, Object, R> {
 
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "PooledLambdaImpl";
 
-    private static final int MAX_ARGS = 4;
+    private static final int MAX_ARGS = 5;
 
     private static final int MAX_POOL_SIZE = 50;
 
@@ -151,16 +158,17 @@
     }
 
     @Override
-    R invoke(Object a1, Object a2, Object a3, Object a4) {
+    R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) {
         checkNotRecycled();
         if (DEBUG) {
             Log.i(LOG_TAG, this + ".invoke("
                     + commaSeparateFirstN(
-                            new Object[] { a1, a2, a3, a4 },
+                            new Object[] { a1, a2, a3, a4, a5, a6 },
                             LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
                     + ")");
         }
-        boolean ignored = fillInArg(a1) && fillInArg(a2) && fillInArg(a3) && fillInArg(a4);
+        final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3)
+                && fillInArg(a4) && fillInArg(a5) && fillInArg(a6);
         int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
         if (argCount != LambdaType.MASK_ARG_COUNT) {
             for (int i = 0; i < argCount; i++) {
@@ -289,6 +297,42 @@
                     }
                 }
             } break;
+
+            case 5: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((QuintConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((QuintPredicate) mFunc).test(
+                                popArg(0), popArg(1), popArg(2), popArg(3), popArg(4));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((QuintFunction) mFunc).apply(
+                                popArg(0), popArg(1), popArg(2), popArg(3),  popArg(4));
+                    }
+                }
+            } break;
+
+            case 6: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((HexConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((HexPredicate) mFunc).test(popArg(0),
+                                popArg(1), popArg(2), popArg(3), popArg(4), popArg(5));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((HexFunction) mFunc).apply(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4), popArg(5));
+                    }
+                }
+            }
         }
         throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
     }
@@ -350,14 +394,14 @@
     /**
      * Internal non-typesafe factory method for {@link PooledLambdaImpl}
      */
-    static <E extends PooledLambda> E acquire(Pool pool, Object f,
+    static <E extends PooledLambda> E acquire(Pool pool, Object func,
             int fNumArgs, int numPlaceholders, int fReturnType,
-            Object a, Object b, Object c, Object d) {
+            Object a, Object b, Object c, Object d, Object e, Object f) {
         PooledLambdaImpl r = acquire(pool);
         if (DEBUG) {
             Log.i(LOG_TAG,
                     "acquire(this = @" + hashCodeHex(r)
-                            + ", f = " + f
+                            + ", func = " + func
                             + ", fNumArgs = " + fNumArgs
                             + ", numPlaceholders = " + numPlaceholders
                             + ", fReturnType = " + LambdaType.ReturnType.toString(fReturnType)
@@ -365,9 +409,11 @@
                             + ", b = " + b
                             + ", c = " + c
                             + ", d = " + d
+                            + ", e = " + e
+                            + ", f = " + f
                             + ")");
         }
-        r.mFunc = f;
+        r.mFunc = func;
         r.setFlags(MASK_FUNC_TYPE, LambdaType.encode(fNumArgs, fReturnType));
         r.setFlags(MASK_EXPOSED_AS, LambdaType.encode(numPlaceholders, fReturnType));
         if (ArrayUtils.size(r.mArgs) < fNumArgs) r.mArgs = new Object[fNumArgs];
@@ -375,6 +421,8 @@
         setIfInBounds(r.mArgs, 1, b);
         setIfInBounds(r.mArgs, 2, c);
         setIfInBounds(r.mArgs, 3, d);
+        setIfInBounds(r.mArgs, 4, e);
+        setIfInBounds(r.mArgs, 5, f);
         return (E) r;
     }
 
@@ -400,12 +448,12 @@
     }
 
     @Override
-    public OmniFunction<Object, Object, Object, Object, R> negate() {
+    public OmniFunction<Object, Object, Object, Object, Object, Object, R> negate() {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public <V> OmniFunction<Object, Object, Object, Object, V> andThen(
+    public <V> OmniFunction<Object, Object, Object, Object, Object, Object, V> andThen(
             Function<? super R, ? extends V> after) {
         throw new UnsupportedOperationException();
     }
@@ -426,7 +474,7 @@
     }
 
     @Override
-    public OmniFunction<Object, Object, Object, Object, R> recycleOnUse() {
+    public OmniFunction<Object, Object, Object, Object, Object, Object, R> recycleOnUse() {
         if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
         mFlags |= FLAG_RECYCLE_ON_USE;
         return this;
@@ -507,6 +555,8 @@
                 case 2: return "Bi";
                 case 3: return "Tri";
                 case 4: return "Quad";
+                case 5: return "Quint";
+                case 6: return "Hex";
                 default: throw new IllegalArgumentException("" + argCount);
             }
         }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3a527b5..caeca592 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3839,6 +3839,11 @@
     <permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an application to watch changes and/or active state of app ops.
+         @hide <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.WATCH_APPOPS"
+        android:protectionLevel="signature" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"