Merge "Add KeyPairGenerator.EC backed by Android KeyStore."
diff --git a/Android.mk b/Android.mk
index 5d9c5b3..15afe90 100644
--- a/Android.mk
+++ b/Android.mk
@@ -202,6 +202,7 @@
 	core/java/android/os/IUpdateLock.aidl \
 	core/java/android/os/IUserManager.aidl \
 	core/java/android/os/IVibratorService.aidl \
+	core/java/android/security/IKeystoreService.aidl \
 	core/java/android/service/notification/INotificationListener.aidl \
 	core/java/android/service/notification/IStatusBarNotificationHolder.aidl \
 	core/java/android/service/notification/IConditionListener.aidl \
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 20355ec..09d6c29 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2330,6 +2330,15 @@
             reply.writeNoException();
             return true;
         }
+
+        case NOTIFY_CLEARTEXT_NETWORK_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            final int uid = data.readInt();
+            final byte[] firstPacket = data.createByteArray();
+            notifyCleartextNetwork(uid, firstPacket);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -5381,5 +5390,18 @@
         reply.recycle();
     }
 
+    @Override
+    public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(uid);
+        data.writeByteArray(firstPacket);
+        mRemote.transact(NOTIFY_CLEARTEXT_NETWORK_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f15a1e0..9d821e1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1061,8 +1061,7 @@
             WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
         }
 
-        @Override
-        public void dumpDbInfo(FileDescriptor fd, String[] args) {
+        private void dumpDatabaseInfo(FileDescriptor fd, String[] args) {
             PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
             PrintWriterPrinter printer = new PrintWriterPrinter(pw);
             SQLiteDebug.dump(printer, args);
@@ -1070,6 +1069,22 @@
         }
 
         @Override
+        public void dumpDbInfo(final FileDescriptor fd, final String[] args) {
+            if (mSystemThread) {
+                // Ensure this invocation is asynchronous to prevent
+                // writer waiting due to buffer cannot be consumed.
+                AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
+                    @Override
+                    public void run() {
+                        dumpDatabaseInfo(fd, args);
+                    }
+                });
+            } else {
+                dumpDatabaseInfo(fd, args);
+            }
+        }
+
+        @Override
         public void unstableProviderDied(IBinder provider) {
             sendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
         }
@@ -1153,9 +1168,17 @@
             sendMessage(H.BACKGROUND_VISIBLE_BEHIND_CHANGED, token, visible ? 1 : 0);
         }
 
+        @Override
         public void scheduleEnterAnimationComplete(IBinder token) {
             sendMessage(H.ENTER_ANIMATION_COMPLETE, token);
         }
+
+        @Override
+        public void notifyCleartextNetwork(byte[] firstPacket) {
+            if (StrictMode.vmCleartextNetworkEnabled()) {
+                StrictMode.onCleartextNetworkDetected(firstPacket);
+            }
+        }
     }
 
     private class H extends Handler {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 0123e16..b2bfc13 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -667,6 +667,15 @@
             reply.writeNoException();
             return true;
         }
+
+        case NOTIFY_CLEARTEXT_NETWORK_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            final byte[] firstPacket = data.createByteArray();
+            notifyCleartextNetwork(firstPacket);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1346,4 +1355,13 @@
         mRemote.transact(ENTER_ANIMATION_COMPLETE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
         data.recycle();
     }
+
+    @Override
+    public void notifyCleartextNetwork(byte[] firstPacket) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeByteArray(firstPacket);
+        mRemote.transact(NOTIFY_CLEARTEXT_NETWORK_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index d1279ad..de47147 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -464,6 +464,8 @@
     public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException;
     public void notifyEnterAnimationComplete(IBinder token) throws RemoteException;
 
+    public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -782,4 +784,7 @@
     int BOOT_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+237;
     int GET_TASK_DESCRIPTION_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+238;
     int LAUNCH_ASSIST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+239;
+
+    // Start of M transactions
+    int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index f53075c..7ff207f 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -146,6 +146,7 @@
     void scheduleCancelVisibleBehind(IBinder token) throws RemoteException;
     void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean enabled) throws RemoteException;
     void scheduleEnterAnimationComplete(IBinder token) throws RemoteException;
+    void notifyCleartextNetwork(byte[] firstPacket) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -203,4 +204,5 @@
     int CANCEL_VISIBLE_BEHIND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+52;
     int BACKGROUND_VISIBLE_BEHIND_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+53;
     int ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+54;
+    int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+55;
 }
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 16250c7..07649e7 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -284,6 +284,8 @@
      */
     void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces);
 
+    void setUidCleartextNetworkPolicy(int uid, int policy);
+
     /**
      * Return status of bandwidth control module.
      */
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 6db5f67..5018711 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -32,14 +32,17 @@
 import android.view.IWindowManager;
 
 import com.android.internal.os.RuntimeInit;
-
 import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.HexDump;
+
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import dalvik.system.VMDebug;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -137,6 +140,13 @@
      */
     public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual";
 
+    /**
+     * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK}
+     * in {@link VmPolicy.Builder#detectAll()}. Apps can still always opt-into
+     * detection using {@link VmPolicy.Builder#detectCleartextNetwork()}.
+     */
+    private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.nonssl";
+
     // Only log a duplicate stack trace to the logs every second.
     private static final long MIN_LOG_INTERVAL_MS = 1000;
 
@@ -150,7 +160,7 @@
     // of the Looper.
     private static final int MAX_OFFENSES_PER_LOOP = 10;
 
-    // Thread-policy:
+    // Byte 1: Thread-policy
 
     /**
      * @hide
@@ -177,83 +187,91 @@
     private static final int ALL_THREAD_DETECT_BITS =
             DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM;
 
-    // Process-policy:
+    // Byte 2: Process-policy
 
     /**
      * Note, a "VM_" bit, not thread.
      * @hide
      */
-    public static final int DETECT_VM_CURSOR_LEAKS = 0x200;  // for VmPolicy
+    public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8;  // for VmPolicy
 
     /**
      * Note, a "VM_" bit, not thread.
      * @hide
      */
-    public static final int DETECT_VM_CLOSABLE_LEAKS = 0x400;  // for VmPolicy
+    public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8;  // for VmPolicy
 
     /**
      * Note, a "VM_" bit, not thread.
      * @hide
      */
-    public static final int DETECT_VM_ACTIVITY_LEAKS = 0x800;  // for VmPolicy
+    public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8;  // for VmPolicy
 
     /**
      * @hide
      */
-    private static final int DETECT_VM_INSTANCE_LEAKS = 0x1000;  // for VmPolicy
+    private static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8;  // for VmPolicy
 
     /**
      * @hide
      */
-    public static final int DETECT_VM_REGISTRATION_LEAKS = 0x2000;  // for VmPolicy
+    public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8;  // for VmPolicy
 
     /**
      * @hide
      */
-    private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x4000;  // for VmPolicy
+    private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8;  // for VmPolicy
+
+    /**
+     * @hide
+     */
+    private static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8;  // for VmPolicy
 
     private static final int ALL_VM_DETECT_BITS =
             DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
             DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
-            DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE;
+            DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE |
+            DETECT_VM_CLEARTEXT_NETWORK;
+
+    // Byte 3: Penalty
 
     /**
      * @hide
      */
-    public static final int PENALTY_LOG = 0x10;  // normal android.util.Log
+    public static final int PENALTY_LOG = 0x01 << 16;  // normal android.util.Log
 
     // Used for both process and thread policy:
 
     /**
      * @hide
      */
-    public static final int PENALTY_DIALOG = 0x20;
+    public static final int PENALTY_DIALOG = 0x02 << 16;
 
     /**
      * Death on any detected violation.
      *
      * @hide
      */
-    public static final int PENALTY_DEATH = 0x40;
+    public static final int PENALTY_DEATH = 0x04 << 16;
 
     /**
      * Death just for detected network usage.
      *
      * @hide
      */
-    public static final int PENALTY_DEATH_ON_NETWORK = 0x200;
+    public static final int PENALTY_DEATH_ON_NETWORK = 0x08 << 16;
 
     /**
      * Flash the screen during violations.
      *
      * @hide
      */
-    public static final int PENALTY_FLASH = 0x800;
+    public static final int PENALTY_FLASH = 0x10 << 16;
 
     /**
      * @hide
      */
-    public static final int PENALTY_DROPBOX = 0x80;
+    public static final int PENALTY_DROPBOX = 0x20 << 16;
 
     /**
      * Non-public penalty mode which overrides all the other penalty
@@ -266,7 +284,14 @@
      *
      * @hide
      */
-    public static final int PENALTY_GATHER = 0x100;
+    public static final int PENALTY_GATHER = 0x40 << 16;
+
+    /**
+     * Death when cleartext network traffic is detected.
+     *
+     * @hide
+     */
+    public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x80 << 16;
 
     /**
      * Mask of all the penalty bits valid for thread policies.
@@ -275,13 +300,18 @@
             PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER |
             PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH;
 
-
     /**
      * Mask of all the penalty bits valid for VM policies.
      */
-    private static final int VM_PENALTY_MASK =
-            PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX;
+    private static final int VM_PENALTY_MASK = PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX
+            | PENALTY_DEATH_ON_CLEARTEXT_NETWORK;
 
+    /** {@hide} */
+    public static final int NETWORK_POLICY_ACCEPT = 0;
+    /** {@hide} */
+    public static final int NETWORK_POLICY_LOG = 1;
+    /** {@hide} */
+    public static final int NETWORK_POLICY_REJECT = 2;
 
     // TODO: wrap in some ImmutableHashMap thing.
     // Note: must be before static initialization of sVmPolicy.
@@ -636,9 +666,17 @@
              * but will likely expand in future releases.
              */
             public Builder detectAll() {
-                return enable(DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
+                int flags = DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
                         | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS
-                        | DETECT_VM_FILE_URI_EXPOSURE);
+                        | DETECT_VM_FILE_URI_EXPOSURE;
+
+                // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have facility
+                // for apps to mark sockets that should be ignored
+                if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
+                    flags |= DETECT_VM_CLEARTEXT_NETWORK;
+                }
+
+                return enable(flags);
             }
 
             /**
@@ -686,15 +724,49 @@
             }
 
             /**
-             * Crashes the whole process on violation.  This penalty runs at
-             * the end of all enabled penalties so yo you'll still get
-             * your logging or other violations before the process dies.
+             * Detect any network traffic from the calling app which is not
+             * wrapped in SSL/TLS. This can help you detect places that your app
+             * is inadvertently sending cleartext data across the network.
+             * <p>
+             * Using {@link #penaltyDeath()} or
+             * {@link #penaltyDeathOnCleartextNetwork()} will block further
+             * traffic on that socket to prevent accidental data leakage, in
+             * addition to crashing your process.
+             * <p>
+             * Using {@link #penaltyDropBox()} will log the raw contents of the
+             * packet that triggered the violation.
+             * <p>
+             * This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it
+             * may be subject to false positives, such as when STARTTLS
+             * protocols or HTTP proxies are used.
+             *
+             * @hide
+             */
+            public Builder detectCleartextNetwork() {
+                return enable(DETECT_VM_CLEARTEXT_NETWORK);
+            }
+
+            /**
+             * Crashes the whole process on violation. This penalty runs at the
+             * end of all enabled penalties so you'll still get your logging or
+             * other violations before the process dies.
              */
             public Builder penaltyDeath() {
                 return enable(PENALTY_DEATH);
             }
 
             /**
+             * Crashes the whole process when cleartext network traffic is
+             * detected.
+             *
+             * @see #detectCleartextNetwork()
+             * @hide
+             */
+            public Builder penaltyDeathOnCleartextNetwork() {
+                return enable(PENALTY_DEATH_ON_CLEARTEXT_NETWORK);
+            }
+
+            /**
              * Log detected violations to the system log.
              */
             public Builder penaltyLog() {
@@ -1422,7 +1494,7 @@
     }
 
     private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
-        public void report (String message, Throwable allocationSite) {
+        public void report(String message, Throwable allocationSite) {
             onVmPolicyViolation(message, allocationSite);
         }
     }
@@ -1508,6 +1580,27 @@
                     sIsIdlerRegistered = true;
                 }
             }
+
+            int networkPolicy = NETWORK_POLICY_ACCEPT;
+            if ((sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
+                if ((sVmPolicyMask & PENALTY_DEATH) != 0
+                        || (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
+                    networkPolicy = NETWORK_POLICY_REJECT;
+                } else {
+                    networkPolicy = NETWORK_POLICY_LOG;
+                }
+            }
+
+            final INetworkManagementService netd = INetworkManagementService.Stub.asInterface(
+                    ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
+            if (netd != null) {
+                try {
+                    netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy);
+                } catch (RemoteException ignored) {
+                }
+            } else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
+                Log.w(TAG, "Dropping requested network policy due to missing service!");
+            }
         }
     }
 
@@ -1570,6 +1663,13 @@
     /**
      * @hide
      */
+    public static boolean vmCleartextNetworkEnabled() {
+        return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
+    }
+
+    /**
+     * @hide
+     */
     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
         onVmPolicyViolation(message, originStack);
     }
@@ -1600,7 +1700,39 @@
      */
     public static void onFileUriExposed(String location) {
         final String message = "file:// Uri exposed through " + location;
-        onVmPolicyViolation(message, new Throwable(message));
+        onVmPolicyViolation(null, new Throwable(message));
+    }
+
+    /**
+     * @hide
+     */
+    public static void onCleartextNetworkDetected(byte[] firstPacket) {
+        byte[] rawAddr = null;
+        if (firstPacket != null) {
+            if (firstPacket.length >= 20 && (firstPacket[0] & 0xf0) == 0x40) {
+                // IPv4
+                rawAddr = new byte[4];
+                System.arraycopy(firstPacket, 16, rawAddr, 0, 4);
+            } else if (firstPacket.length >= 40 && (firstPacket[0] & 0xf0) == 0x60) {
+                // IPv6
+                rawAddr = new byte[16];
+                System.arraycopy(firstPacket, 24, rawAddr, 0, 16);
+            }
+        }
+
+        final int uid = android.os.Process.myUid();
+        String msg = "Detected cleartext network traffic from UID " + uid;
+        if (rawAddr != null) {
+            try {
+                msg = "Detected cleartext network traffic from UID " + uid + " to "
+                        + InetAddress.getByAddress(rawAddr);
+            } catch (UnknownHostException ignored) {
+            }
+        }
+
+        final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
+        onVmPolicyViolation(HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg),
+                forceDeath);
     }
 
     // Map from VM violation fingerprint to uptime millis.
@@ -1610,10 +1742,18 @@
      * @hide
      */
     public static void onVmPolicyViolation(String message, Throwable originStack) {
+        onVmPolicyViolation(message, originStack, false);
+    }
+
+    /**
+     * @hide
+     */
+    public static void onVmPolicyViolation(String message, Throwable originStack,
+            boolean forceDeath) {
         final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
-        final boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
+        final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath;
         final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
-        final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
+        final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicyMask);
 
         // Erase stuff not relevant for process-wide violations
         info.numAnimationsRunning = 0;
@@ -2057,6 +2197,8 @@
      * @hide
      */
     public static class ViolationInfo {
+        public String message;
+
         /**
          * Stack and other stuff info.
          */
@@ -2118,10 +2260,15 @@
             policy = 0;
         }
 
+        public ViolationInfo(Throwable tr, int policy) {
+            this(null, tr, policy);
+        }
+
         /**
          * Create an instance of ViolationInfo initialized from an exception.
          */
-        public ViolationInfo(Throwable tr, int policy) {
+        public ViolationInfo(String message, Throwable tr, int policy) {
+            this.message = message;
             crashInfo = new ApplicationErrorReport.CrashInfo(tr);
             violationUptimeMillis = SystemClock.uptimeMillis();
             this.policy = policy;
@@ -2184,6 +2331,7 @@
          *   and the gathering penalty should be removed.
          */
         public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
+            message = in.readString();
             crashInfo = new ApplicationErrorReport.CrashInfo(in);
             int rawPolicy = in.readInt();
             if (unsetGatheringBit) {
@@ -2204,6 +2352,7 @@
          * Save a ViolationInfo instance to a parcel.
          */
         public void writeToParcel(Parcel dest, int flags) {
+            dest.writeString(message);
             crashInfo.writeToParcel(dest, flags);
             int start = dest.dataPosition();
             dest.writeInt(policy);
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
new file mode 100644
index 0000000..bf51ed1
--- /dev/null
+++ b/core/java/android/security/IKeystoreService.aidl
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.security.KeystoreArguments;
+
+/**
+ * This must be kept manually in sync with system/security/keystore until AIDL
+ * can generate both Java and C++ bindings.
+ *
+ * @hide
+ */
+interface IKeystoreService {
+    int test();
+    byte[] get(String name);
+    int insert(String name, in byte[] item, int uid, int flags);
+    int del(String name, int uid);
+    int exist(String name, int uid);
+    String[] saw(String namePrefix, int uid);
+    int reset();
+    int password(String password);
+    int lock();
+    int unlock(String password);
+    int zero();
+    int generate(String name, int uid, int keyType, int keySize, int flags,
+        in KeystoreArguments args);
+    int import_key(String name, in byte[] data, int uid, int flags);
+    byte[] sign(String name, in byte[] data);
+    int verify(String name, in byte[] data, in byte[] signature);
+    byte[] get_pubkey(String name);
+    int del_key(String name, int uid);
+    int grant(String name, int granteeUid);
+    int ungrant(String name, int granteeUid);
+    long getmtime(String name);
+    int duplicate(String srcKey, int srcUid, String destKey, int destUid);
+    int is_hardware_backed(String string);
+    int clear_uid(long uid);
+    int reset_uid(int uid);
+    int sync_uid(int sourceUid, int targetUid);
+    int password_uid(String password, int uid);
+}
diff --git a/core/java/android/security/IKeystoreService.java b/core/java/android/security/IKeystoreService.java
deleted file mode 100644
index 7e9aba0..0000000
--- a/core/java/android/security/IKeystoreService.java
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Parcel;
-import android.os.RemoteException;
-
-/**
- * This must be kept manually in sync with system/security/keystore until AIDL
- * can generate both Java and C++ bindings.
- *
- * @hide
- */
-public interface IKeystoreService extends IInterface {
-    public static abstract class Stub extends Binder implements IKeystoreService {
-        private static class Proxy implements IKeystoreService {
-            private final IBinder mRemote;
-
-            Proxy(IBinder remote) {
-                mRemote = remote;
-            }
-
-            public IBinder asBinder() {
-                return mRemote;
-            }
-
-            public String getInterfaceDescriptor() {
-                return DESCRIPTOR;
-            }
-
-            public int test() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_test, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public byte[] get(String name) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                byte[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    mRemote.transact(Stub.TRANSACTION_get, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createByteArray();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int insert(String name, byte[] item, int uid, int flags) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeByteArray(item);
-                    _data.writeInt(uid);
-                    _data.writeInt(flags);
-                    mRemote.transact(Stub.TRANSACTION_insert, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int del(String name, int uid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeInt(uid);
-                    mRemote.transact(Stub.TRANSACTION_del, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int exist(String name, int uid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeInt(uid);
-                    mRemote.transact(Stub.TRANSACTION_exist, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public String[] saw(String name, int uid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeInt(uid);
-                    mRemote.transact(Stub.TRANSACTION_saw, _data, _reply, 0);
-                    _reply.readException();
-                    int size = _reply.readInt();
-                    _result = new String[size];
-                    for (int i = 0; i < size; i++) {
-                        _result[i] = _reply.readString();
-                    }
-                    int _ret = _reply.readInt();
-                    if (_ret != 1) {
-                        return null;
-                    }
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public int reset() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_reset, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int password(String password) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(password);
-                    mRemote.transact(Stub.TRANSACTION_password, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int lock() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_lock, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int unlock(String password) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(password);
-                    mRemote.transact(Stub.TRANSACTION_unlock, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public int zero() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_zero, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int generate(String name, int uid, int keyType, int keySize, int flags,
-                    byte[][] args) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeInt(uid);
-                    _data.writeInt(keyType);
-                    _data.writeInt(keySize);
-                    _data.writeInt(flags);
-                    if (args == null) {
-                        _data.writeInt(0);
-                    } else {
-                        _data.writeInt(args.length);
-                        for (int i = 0; i < args.length; i++) {
-                            _data.writeByteArray(args[i]);
-                        }
-                    }
-                    mRemote.transact(Stub.TRANSACTION_generate, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int import_key(String name, byte[] data, int uid, int flags)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeByteArray(data);
-                    _data.writeInt(uid);
-                    _data.writeInt(flags);
-                    mRemote.transact(Stub.TRANSACTION_import, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public byte[] sign(String name, byte[] data) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                byte[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeByteArray(data);
-                    mRemote.transact(Stub.TRANSACTION_sign, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createByteArray();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int verify(String name, byte[] data, byte[] signature) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeByteArray(data);
-                    _data.writeByteArray(signature);
-                    mRemote.transact(Stub.TRANSACTION_verify, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public byte[] get_pubkey(String name) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                byte[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    mRemote.transact(Stub.TRANSACTION_get_pubkey, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createByteArray();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int del_key(String name, int uid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeInt(uid);
-                    mRemote.transact(Stub.TRANSACTION_del_key, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int grant(String name, int granteeUid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeInt(granteeUid);
-                    mRemote.transact(Stub.TRANSACTION_grant, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int ungrant(String name, int granteeUid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    _data.writeInt(granteeUid);
-                    mRemote.transact(Stub.TRANSACTION_ungrant, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public long getmtime(String name) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                long _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    mRemote.transact(Stub.TRANSACTION_getmtime, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readLong();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public int duplicate(String srcKey, int srcUid, String destKey, int destUid)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(srcKey);
-                    _data.writeInt(srcUid);
-                    _data.writeString(destKey);
-                    _data.writeInt(destUid);
-                    mRemote.transact(Stub.TRANSACTION_duplicate, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public int is_hardware_backed(String keyType) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(keyType);
-                    mRemote.transact(Stub.TRANSACTION_is_hardware_backed, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public int clear_uid(long uid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeLong(uid);
-                    mRemote.transact(Stub.TRANSACTION_clear_uid, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int reset_uid(int uid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(uid);
-                    mRemote.transact(Stub.TRANSACTION_reset_uid, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int sync_uid(int srcUid, int dstUid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(srcUid);
-                    _data.writeInt(dstUid);
-                    mRemote.transact(Stub.TRANSACTION_sync_uid, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int password_uid(String password, int uid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(password);
-                    _data.writeInt(uid);
-                    mRemote.transact(Stub.TRANSACTION_password_uid, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-        }
-
-        private static final String DESCRIPTOR = "android.security.keystore";
-
-        static final int TRANSACTION_test = IBinder.FIRST_CALL_TRANSACTION + 0;
-        static final int TRANSACTION_get = IBinder.FIRST_CALL_TRANSACTION + 1;
-        static final int TRANSACTION_insert = IBinder.FIRST_CALL_TRANSACTION + 2;
-        static final int TRANSACTION_del = IBinder.FIRST_CALL_TRANSACTION + 3;
-        static final int TRANSACTION_exist = IBinder.FIRST_CALL_TRANSACTION + 4;
-        static final int TRANSACTION_saw = IBinder.FIRST_CALL_TRANSACTION + 5;
-        static final int TRANSACTION_reset = IBinder.FIRST_CALL_TRANSACTION + 6;
-        static final int TRANSACTION_password = IBinder.FIRST_CALL_TRANSACTION + 7;
-        static final int TRANSACTION_lock = IBinder.FIRST_CALL_TRANSACTION + 8;
-        static final int TRANSACTION_unlock = IBinder.FIRST_CALL_TRANSACTION + 9;
-        static final int TRANSACTION_zero = IBinder.FIRST_CALL_TRANSACTION + 10;
-        static final int TRANSACTION_generate = IBinder.FIRST_CALL_TRANSACTION + 11;
-        static final int TRANSACTION_import = IBinder.FIRST_CALL_TRANSACTION + 12;
-        static final int TRANSACTION_sign = IBinder.FIRST_CALL_TRANSACTION + 13;
-        static final int TRANSACTION_verify = IBinder.FIRST_CALL_TRANSACTION + 14;
-        static final int TRANSACTION_get_pubkey = IBinder.FIRST_CALL_TRANSACTION + 15;
-        static final int TRANSACTION_del_key = IBinder.FIRST_CALL_TRANSACTION + 16;
-        static final int TRANSACTION_grant = IBinder.FIRST_CALL_TRANSACTION + 17;
-        static final int TRANSACTION_ungrant = IBinder.FIRST_CALL_TRANSACTION + 18;
-        static final int TRANSACTION_getmtime = IBinder.FIRST_CALL_TRANSACTION + 19;
-        static final int TRANSACTION_duplicate = IBinder.FIRST_CALL_TRANSACTION + 20;
-        static final int TRANSACTION_is_hardware_backed = IBinder.FIRST_CALL_TRANSACTION + 21;
-        static final int TRANSACTION_clear_uid = IBinder.FIRST_CALL_TRANSACTION + 22;
-        static final int TRANSACTION_reset_uid = IBinder.FIRST_CALL_TRANSACTION + 23;
-        static final int TRANSACTION_sync_uid = IBinder.FIRST_CALL_TRANSACTION + 24;
-        static final int TRANSACTION_password_uid = IBinder.FIRST_CALL_TRANSACTION + 25;
-
-        /**
-         * Cast an IBinder object into an IKeystoreService interface, generating
-         * a proxy if needed.
-         */
-        public static IKeystoreService asInterface(IBinder obj) {
-            if (obj == null) {
-                return null;
-            }
-            IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
-            if (iin != null && iin instanceof IKeystoreService) {
-                return (IKeystoreService) iin;
-            }
-            return new IKeystoreService.Stub.Proxy(obj);
-        }
-
-        /** Construct the stub at attach it to the interface. */
-        public Stub() {
-            attachInterface(this, DESCRIPTOR);
-        }
-
-        public IBinder asBinder() {
-            return this;
-        }
-
-        @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-                throws RemoteException {
-            switch (code) {
-                case INTERFACE_TRANSACTION: {
-                    reply.writeString(DESCRIPTOR);
-                    return true;
-                }
-                case TRANSACTION_test: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int resultCode = test();
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-            }
-            return super.onTransact(code, data, reply, flags);
-        }
-    }
-
-    public int test() throws RemoteException;
-
-    public byte[] get(String name) throws RemoteException;
-
-    public int insert(String name, byte[] item, int uid, int flags) throws RemoteException;
-
-    public int del(String name, int uid) throws RemoteException;
-
-    public int exist(String name, int uid) throws RemoteException;
-
-    public String[] saw(String name, int uid) throws RemoteException;
-
-    public int reset() throws RemoteException;
-
-    public int password(String password) throws RemoteException;
-
-    public int lock() throws RemoteException;
-
-    public int unlock(String password) throws RemoteException;
-
-    public int zero() throws RemoteException;
-
-    public int generate(String name, int uid, int keyType, int keySize, int flags, byte[][] args)
-            throws RemoteException;
-
-    public int import_key(String name, byte[] data, int uid, int flags) throws RemoteException;
-
-    public byte[] sign(String name, byte[] data) throws RemoteException;
-
-    public int verify(String name, byte[] data, byte[] signature) throws RemoteException;
-
-    public byte[] get_pubkey(String name) throws RemoteException;
-
-    public int del_key(String name, int uid) throws RemoteException;
-
-    public int grant(String name, int granteeUid) throws RemoteException;
-
-    public int ungrant(String name, int granteeUid) throws RemoteException;
-
-    public long getmtime(String name) throws RemoteException;
-
-    public int duplicate(String srcKey, int srcUid, String destKey, int destUid)
-            throws RemoteException;
-
-    public int is_hardware_backed(String string) throws RemoteException;
-
-    public int clear_uid(long uid) throws RemoteException;
-
-    public int reset_uid(int uid) throws RemoteException;
-
-    public int sync_uid(int sourceUid, int targetUid) throws RemoteException;
-
-    public int password_uid(String password, int uid) throws RemoteException;
-}
diff --git a/core/java/android/security/KeystoreArguments.aidl b/core/java/android/security/KeystoreArguments.aidl
new file mode 100644
index 0000000..d636414
--- /dev/null
+++ b/core/java/android/security/KeystoreArguments.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+/* @hide */
+parcelable KeystoreArguments;
diff --git a/core/java/android/security/KeystoreArguments.java b/core/java/android/security/KeystoreArguments.java
new file mode 100644
index 0000000..16054e5
--- /dev/null
+++ b/core/java/android/security/KeystoreArguments.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Class for handling the additional arguments to some keystore binder calls.
+ * This must be kept in sync with the deserialization code in system/security/keystore.
+ * @hide
+ */
+public class KeystoreArguments implements Parcelable {
+    public byte[][] args;
+
+    public static final Parcelable.Creator<KeystoreArguments> CREATOR = new
+            Parcelable.Creator<KeystoreArguments>() {
+                public KeystoreArguments createFromParcel(Parcel in) {
+                    return new KeystoreArguments(in);
+                }
+                public KeystoreArguments[] newArray(int size) {
+                    return new KeystoreArguments[size];
+                }
+            };
+
+    public KeystoreArguments() {
+        args = null;
+    }
+
+    public KeystoreArguments(byte[][] args) {
+        this.args = args;
+    }
+
+    private KeystoreArguments(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        if (args == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(args.length);
+            for (byte[] arg : args) {
+                out.writeByteArray(arg);
+            }
+        }
+    }
+
+    private void readFromParcel(Parcel in) {
+        int length = in.readInt();
+        args = new byte[length][];
+        for (int i = 0; i < length; i++) {
+            args[i] = in.createByteArray();
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/tests/coretests/src/android/net/http/HttpResponseCacheTest.java b/core/tests/coretests/src/android/net/http/HttpResponseCacheTest.java
deleted file mode 100644
index 0421d44..0000000
--- a/core/tests/coretests/src/android/net/http/HttpResponseCacheTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import com.google.mockwebserver.MockResponse;
-import com.google.mockwebserver.MockWebServer;
-import java.io.File;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.ResponseCache;
-import java.net.URI;
-import java.net.URLConnection;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import junit.framework.TestCase;
-
-public final class HttpResponseCacheTest extends TestCase {
-
-    private File cacheDir;
-    private MockWebServer server = new MockWebServer();
-
-    @Override public void setUp() throws Exception {
-        super.setUp();
-        String tmp = System.getProperty("java.io.tmpdir");
-        cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID());
-    }
-
-    @Override protected void tearDown() throws Exception {
-        ResponseCache.setDefault(null);
-        server.shutdown();
-        super.tearDown();
-    }
-
-    public void testInstall() throws Exception {
-        HttpResponseCache installed = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
-        assertNotNull(installed);
-        assertSame(installed, ResponseCache.getDefault());
-        assertSame(installed, HttpResponseCache.getDefault());
-    }
-
-    public void testSecondEquivalentInstallDoesNothing() throws Exception {
-        HttpResponseCache first = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
-        HttpResponseCache another = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
-        assertSame(first, another);
-    }
-
-    public void testInstallClosesPreviouslyInstalled() throws Exception {
-        HttpResponseCache first = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
-        HttpResponseCache another = HttpResponseCache.install(cacheDir, 8 * 1024 * 1024);
-        assertNotSame(first, another);
-        try {
-            first.flush();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testGetInstalledWithWrongTypeInstalled() {
-        ResponseCache.setDefault(new ResponseCache() {
-            @Override public CacheResponse get(URI uri, String requestMethod,
-                    Map<String, List<String>> requestHeaders) {
-                return null;
-            }
-            @Override public CacheRequest put(URI uri, URLConnection connection) {
-                return null;
-            }
-        });
-        assertNull(HttpResponseCache.getInstalled());
-    }
-
-    public void testCloseCloses() throws Exception {
-        HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
-        cache.close();
-        try {
-            cache.flush();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testCloseUninstalls() throws Exception {
-        HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
-        cache.close();
-        assertNull(ResponseCache.getDefault());
-    }
-
-    public void testDeleteUninstalls() throws Exception {
-        HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
-        cache.delete();
-        assertNull(ResponseCache.getDefault());
-    }
-
-    /**
-     * Make sure that statistics tracking are wired all the way through the
-     * wrapper class. http://code.google.com/p/android/issues/detail?id=25418
-     */
-    public void testStatisticsTracking() throws Exception {
-        HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
-
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.play();
-
-        URLConnection c1 = server.getUrl("/").openConnection();
-        InputStream inputStream1 = c1.getInputStream();
-        assertEquals('A', inputStream1.read());
-        inputStream1.close();
-
-        assertEquals(1, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-
-        URLConnection c2 = server.getUrl("/").openConnection();
-        assertEquals('A', c2.getInputStream().read());
-
-        URLConnection c3 = server.getUrl("/").openConnection();
-        assertEquals('A', c3.getInputStream().read());
-        assertEquals(3, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(2, cache.getHitCount());
-    }
-}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index f812df4..e753a7c 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -205,7 +205,8 @@
     public boolean generate(String key, int uid, int keyType, int keySize, int flags,
             byte[][] args) {
         try {
-            return mBinder.generate(key, uid, keyType, keySize, flags, args) == NO_ERROR;
+            return mBinder.generate(key, uid, keyType, keySize, flags,
+                    new KeystoreArguments(args)) == NO_ERROR;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return false;
diff --git a/libs/androidfw/misc.cpp b/libs/androidfw/misc.cpp
index 29686ef..a9b46d2 100644
--- a/libs/androidfw/misc.cpp
+++ b/libs/androidfw/misc.cpp
@@ -56,9 +56,11 @@
             return kFileTypeBlockDev;
         else if (S_ISFIFO(sb.st_mode))
             return kFileTypeFifo;
-#ifdef HAVE_SYMLINKS
+#if defined(S_ISLNK)
         else if (S_ISLNK(sb.st_mode))
             return kFileTypeSymlink;
+#endif
+#if defined(S_ISSOCK)
         else if (S_ISSOCK(sb.st_mode))
             return kFileTypeSocket;
 #endif
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 114042d..fb8ae5d 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -302,6 +302,46 @@
         rsnContextResume(mContext);
     }
 
+    native long rsnClosureCreate(long con, long kernelID, long returnValue,
+        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
+        long[] depFieldIDs);
+    synchronized long nClosureCreate(long kernelID, long returnValue,
+        long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
+        long[] depFieldIDs) {
+      validate();
+      return rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
+          sizes, depClosures, depFieldIDs);
+    }
+
+    native void rsnClosureSetArg(long con, long closureID, int index,
+      long value, int size);
+    synchronized void nClosureSetArg(long closureID, int index, long value,
+        int size) {
+      validate();
+      rsnClosureSetArg(mContext, closureID, index, value, size);
+    }
+
+    native void rsnClosureSetGlobal(long con, long closureID, long fieldID,
+        long value, int size);
+    // Does this have to be synchronized?
+    synchronized void nClosureSetGlobal(long closureID, long fieldID,
+        long value, int size) {
+      validate(); // TODO: is this necessary?
+      rsnClosureSetGlobal(mContext, closureID, fieldID, value, size);
+    }
+
+    native long rsnScriptGroup2Create(long con, long[] closures);
+    synchronized long nScriptGroup2Create(long[] closures) {
+      validate();
+      return rsnScriptGroup2Create(mContext, closures);
+    }
+
+    native void rsnScriptGroup2Execute(long con, long groupID);
+    synchronized void nScriptGroup2Execute(long groupID) {
+      validate();
+      rsnScriptGroup2Execute(mContext, groupID);
+    }
+
     native void rsnAssignName(long con, long obj, byte[] name);
     synchronized void nAssignName(long obj, byte[] name) {
         validate();
diff --git a/rs/java/android/renderscript/ScriptGroup2.java b/rs/java/android/renderscript/ScriptGroup2.java
new file mode 100644
index 0000000..dcad787
--- /dev/null
+++ b/rs/java/android/renderscript/ScriptGroup2.java
@@ -0,0 +1,319 @@
+package android.renderscript;
+
+import android.util.Log;
+import android.util.Pair;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+   @hide Pending Android public API approval.
+ */
+/**
+
+******************************
+You have tried to change the API from what has been previously approved.
+
+To make these errors go away, you have two choices:
+   1) You can add "@hide" javadoc comments to the methods, etc. listed in the
+      errors above.
+
+   2) You can update current.txt by executing the following command:
+         make update-api
+
+To submit the revised current.txt to the main Android repository,
+you will need approval.
+******************************
+
+   @hide Pending Android public API approval.
+ */
+public class ScriptGroup2 extends BaseObj {
+
+  public static class Closure extends BaseObj {
+    private Allocation mReturnValue;
+    private Map<Script.FieldID, Object> mBindings;
+
+    private Future mReturnFuture;
+    private Map<Script.FieldID, Future> mGlobalFuture;
+
+    private static final String TAG = "Closure";
+
+    public Closure(long id, RenderScript rs) {
+      super(id, rs);
+    }
+
+    public Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
+        Object[] args, Map<Script.FieldID, Object> globals) {
+      super(0, rs);
+
+      mReturnValue = Allocation.createTyped(rs, returnType);
+      mBindings = new HashMap<Script.FieldID, Object>();
+      mGlobalFuture = new HashMap<Script.FieldID, Future>();
+
+      int numValues = args.length + globals.size();
+
+      long[] fieldIDs = new long[numValues];
+      long[] values = new long[numValues];
+      int[] sizes = new int[numValues];
+      long[] depClosures = new long[numValues];
+      long[] depFieldIDs = new long[numValues];
+
+      int i;
+      for (i = 0; i < args.length; i++) {
+        Object obj = args[i];
+        fieldIDs[i] = 0;
+        if (obj instanceof UnboundValue) {
+          UnboundValue unbound = (UnboundValue)obj;
+          unbound.addReference(this, i);
+        } else {
+          retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes,
+              depClosures, depFieldIDs);
+        }
+      }
+
+      for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
+        Object obj = entry.getValue();
+        Script.FieldID fieldID = entry.getKey();
+        fieldIDs[i] = fieldID.getID(rs);
+        if (obj instanceof UnboundValue) {
+          UnboundValue unbound = (UnboundValue)obj;
+          unbound.addReference(this, fieldID);
+        } else {
+          retrieveValueAndDependenceInfo(rs, i, obj, values,
+              sizes, depClosures, depFieldIDs);
+        }
+        i++;
+      }
+
+      long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs),
+          fieldIDs, values, sizes, depClosures, depFieldIDs);
+
+      setID(id);
+    }
+
+    private static void retrieveValueAndDependenceInfo(RenderScript rs,
+        int index, Object obj, long[] values, int[] sizes, long[] depClosures,
+        long[] depFieldIDs) {
+
+      if (obj instanceof Future) {
+        Future f = (Future)obj;
+        obj = f.getValue();
+        depClosures[index] = f.getClosure().getID(rs);
+        Script.FieldID fieldID = f.getFieldID();
+        depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
+      } else {
+        depClosures[index] = 0;
+        depFieldIDs[index] = 0;
+      }
+
+      ValueAndSize vs = new ValueAndSize(rs, obj);
+      values[index] = vs.value;
+      sizes[index] = vs.size;
+    }
+
+    public Future getReturn() {
+      if (mReturnFuture == null) {
+        mReturnFuture = new Future(this, null, mReturnValue);
+      }
+
+      return mReturnFuture;
+    }
+
+    public Future getGlobal(Script.FieldID field) {
+      Future f = mGlobalFuture.get(field);
+
+      if (f == null) {
+        f = new Future(this, field, mBindings.get(field));
+        mGlobalFuture.put(field, f);
+      }
+
+      return f;
+    }
+
+    void setArg(int index, Object obj) {
+      ValueAndSize vs = new ValueAndSize(mRS, obj);
+      mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
+    }
+
+    void setGlobal(Script.FieldID fieldID, Object obj) {
+      ValueAndSize vs = new ValueAndSize(mRS, obj);
+      mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
+    }
+
+    private static final class ValueAndSize {
+      public ValueAndSize(RenderScript rs, Object obj) {
+        if (obj instanceof Allocation) {
+          value = ((Allocation)obj).getID(rs);
+          size = -1;
+        } else if (obj instanceof Boolean) {
+          value = ((Boolean)obj).booleanValue() ? 1 : 0;
+          size = 4;
+        } else if (obj instanceof Integer) {
+          value = ((Integer)obj).longValue();
+          size = 4;
+        } else if (obj instanceof Long) {
+          value = ((Long)obj).longValue();
+          size = 8;
+        } else if (obj instanceof Float) {
+          value = ((Float)obj).longValue();
+          size = 4;
+        } else if (obj instanceof Double) {
+          value = ((Double)obj).longValue();
+          size = 8;
+        }
+      }
+
+      public long value;
+      public int size;
+    }
+  }
+
+  public static class Future {
+    Closure mClosure;
+    Script.FieldID mFieldID;
+    Object mValue;
+
+    Future(Closure closure, Script.FieldID fieldID, Object value) {
+      mClosure = closure;
+      mFieldID = fieldID;
+      mValue = value;
+    }
+
+    Closure getClosure() { return mClosure; }
+    Script.FieldID getFieldID() { return mFieldID; }
+    Object getValue() { return mValue; }
+  }
+
+  public static class UnboundValue {
+    // Either mFieldID or mArgIndex should be set but not both.
+    List<Pair<Closure, Script.FieldID>> mFieldID;
+    // -1 means unset. Legal values are 0 .. n-1, where n is the number of
+    // arguments for the referencing closure.
+    List<Pair<Closure, Integer>> mArgIndex;
+
+    UnboundValue() {
+      mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
+      mArgIndex = new ArrayList<Pair<Closure, Integer>>();
+    }
+
+    void addReference(Closure closure, int index) {
+      mArgIndex.add(Pair.create(closure, Integer.valueOf(index)));
+    }
+
+    void addReference(Closure closure, Script.FieldID fieldID) {
+      mFieldID.add(Pair.create(closure, fieldID));
+    }
+
+    void set(Object value) {
+      for (Pair<Closure, Integer> p : mArgIndex) {
+        Closure closure = p.first;
+        int index = p.second.intValue();
+        closure.setArg(index, value);
+      }
+      for (Pair<Closure, Script.FieldID> p : mFieldID) {
+        Closure closure = p.first;
+        Script.FieldID fieldID = p.second;
+        closure.setGlobal(fieldID, value);
+      }
+    }
+  }
+
+  List<Closure> mClosures;
+  List<UnboundValue> mInputs;
+  Future[] mOutputs;
+
+  private static final String TAG = "ScriptGroup2";
+
+  public ScriptGroup2(long id, RenderScript rs) {
+    super(id, rs);
+  }
+
+  ScriptGroup2(RenderScript rs, List<Closure> closures,
+      List<UnboundValue> inputs, Future[] outputs) {
+    super(0, rs);
+    mClosures = closures;
+    mInputs = inputs;
+    mOutputs = outputs;
+
+    long[] closureIDs = new long[closures.size()];
+    for (int i = 0; i < closureIDs.length; i++) {
+      closureIDs[i] = closures.get(i).getID(rs);
+    }
+    long id = rs.nScriptGroup2Create(closureIDs);
+    setID(id);
+  }
+
+  // TODO: If this was reflected method, we could enforce the number of
+  // arguments.
+  public Object[] execute(Object... inputs) {
+    if (inputs.length < mInputs.size()) {
+      Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
+          "less than expected " + mInputs.size());
+      return null;
+    }
+
+    if (inputs.length > mInputs.size()) {
+      Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
+          "more than expected " + mInputs.size());
+    }
+
+    for (int i = 0; i < mInputs.size(); i++) {
+      Object obj = inputs[i];
+      if (obj instanceof Future || obj instanceof UnboundValue) {
+        Log.e(TAG, this.toString() + ": input " + i +
+            " is a future or unbound value");
+        return null;
+      }
+      UnboundValue unbound = mInputs.get(i);
+      unbound.set(obj);
+    }
+
+    mRS.nScriptGroup2Execute(getID(mRS));
+
+    Object[] outputObjs = new Object[mOutputs.length];
+    int i = 0;
+    for (Future f : mOutputs) {
+      outputObjs[i++] = f.getValue();
+    }
+    return outputObjs;
+  }
+
+  /**
+     @hide Pending Android public API approval.
+   */
+  public static final class Builder {
+    RenderScript mRS;
+    List<Closure> mClosures;
+    List<UnboundValue> mInputs;
+
+    private static final String TAG = "ScriptGroup2.Builder";
+
+    public Builder(RenderScript rs) {
+      mRS = rs;
+      mClosures = new ArrayList<Closure>();
+      mInputs = new ArrayList<UnboundValue>();
+    }
+
+    public Closure addKernel(Script.KernelID k, Type returnType, Object[] args,
+        Map<Script.FieldID, Object> globalBindings) {
+      Closure c = new Closure(mRS, k, returnType, args, globalBindings);
+      mClosures.add(c);
+      return c;
+    }
+
+    public UnboundValue addInput() {
+      UnboundValue unbound = new UnboundValue();
+      mInputs.add(unbound);
+      return unbound;
+    }
+
+    public ScriptGroup2 create(Future... outputs) {
+      // TODO: Save all script groups that have been created and return one that was
+      // saved and matches the outputs.
+      ScriptGroup2 ret = new ScriptGroup2(mRS, mClosures, mInputs, outputs);
+      return ret;
+    }
+
+  }
+}
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 68a0b83..dced99a 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -193,6 +193,88 @@
     rsContextFinish((RsContext)con);
 }
 
+static jlong
+nClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong kernelID,
+               jlong returnValue, jlongArray fieldIDArray,
+               jlongArray valueArray, jintArray sizeArray,
+               jlongArray depClosureArray, jlongArray depFieldIDArray) {
+  jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
+  jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
+  RsScriptFieldID* fieldIDs =
+      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
+  for (int i = 0; i< fieldIDs_length; i++) {
+    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
+  }
+
+  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
+  jsize values_length = _env->GetArrayLength(valueArray);
+  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
+  for (int i = 0; i < values_length; i++) {
+    values[i] = (uintptr_t)jValues[i];
+  }
+
+  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
+  jsize sizes_length = _env->GetArrayLength(sizeArray);
+
+  jlong* jDepClosures =
+      _env->GetLongArrayElements(depClosureArray, nullptr);
+  jsize depClosures_length = _env->GetArrayLength(depClosureArray);
+  RsClosure* depClosures =
+      (RsClosure*)alloca(sizeof(RsClosure) * depClosures_length);
+  for (int i = 0; i < depClosures_length; i++) {
+    depClosures[i] = (RsClosure)jDepClosures[i];
+  }
+
+  jlong* jDepFieldIDs =
+      _env->GetLongArrayElements(depFieldIDArray, nullptr);
+  jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);
+  RsScriptFieldID* depFieldIDs =
+      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * depFieldIDs_length);
+  for (int i = 0; i < depClosures_length; i++) {
+    depFieldIDs[i] = (RsClosure)jDepFieldIDs[i];
+  }
+
+  return (jlong)(uintptr_t)rsClosureCreate(
+      (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
+      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
+      (size_t*)sizes, (size_t)sizes_length,
+      depClosures, (size_t)depClosures_length,
+      depFieldIDs, (size_t)depFieldIDs_length);
+}
+
+static void
+nClosureSetArg(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
+               jint index, jlong value, jint size) {
+  rsClosureSetArg((RsContext)con, (RsClosure)closureID, (uint32_t)index,
+                  (uintptr_t)value, (size_t)size);
+}
+
+static void
+nClosureSetGlobal(JNIEnv *_env, jobject _this, jlong con, jlong closureID,
+                  jlong fieldID, jlong value, jint size) {
+  rsClosureSetGlobal((RsContext)con, (RsClosure)closureID,
+                     (RsScriptFieldID)fieldID, (uintptr_t)value, (size_t)size);
+}
+
+static long
+nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con,
+                    jlongArray closureArray) {
+  jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
+  jsize numClosures = _env->GetArrayLength(closureArray);
+  RsClosure* closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
+  for (int i = 0; i < numClosures; i++) {
+    closures[i] = (RsClosure)jClosures[i];
+  }
+
+  return (jlong)(uintptr_t)rsScriptGroup2Create((RsContext)con, closures,
+                                                numClosures);
+}
+
+static void
+nScriptGroup2Execute(JNIEnv *_env, jobject _this, jlong con, jlong groupID) {
+  rsScriptGroupExecute((RsContext)con, (RsScriptGroup2)groupID);
+}
+
 static void
 nAssignName(JNIEnv *_env, jobject _this, jlong con, jlong obj, jbyteArray str)
 {
@@ -1841,6 +1923,9 @@
 {"rsnContextPause",                  "(J)V",                                  (void*)nContextPause },
 {"rsnContextResume",                 "(J)V",                                  (void*)nContextResume },
 {"rsnContextSendMessage",            "(JI[I)V",                               (void*)nContextSendMessage },
+{"rsnClosureCreate",                 "(JJJ[J[J[I[J[J)J",                      (void*)nClosureCreate },
+{"rsnClosureSetArg",                 "(JJIJI)V",                              (void*)nClosureSetArg },
+{"rsnClosureSetGlobal",              "(JJJJI)V",                              (void*)nClosureSetGlobal },
 {"rsnAssignName",                    "(JJ[B)V",                               (void*)nAssignName },
 {"rsnGetName",                       "(JJ)Ljava/lang/String;",                (void*)nGetName },
 {"rsnObjDestroy",                    "(JJ)V",                                 (void*)nObjDestroy },
@@ -1915,9 +2000,11 @@
 {"rsnScriptKernelIDCreate",          "(JJII)J",                               (void*)nScriptKernelIDCreate },
 {"rsnScriptFieldIDCreate",           "(JJI)J",                                (void*)nScriptFieldIDCreate },
 {"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
+{"rsnScriptGroup2Create",            "(J[J)J",                                (void*)nScriptGroup2Create },
 {"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
 {"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
 {"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
+{"rsnScriptGroup2Execute",           "(JJ)V",                                 (void*)nScriptGroup2Execute },
 
 {"rsnProgramStoreCreate",            "(JZZZZZZIII)J",                         (void*)nProgramStoreCreate },
 
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 020c951..967ee31 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -24,9 +24,6 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_TETHERING;
-import static android.net.RouteInfo.RTN_THROW;
-import static android.net.RouteInfo.RTN_UNICAST;
-import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
@@ -38,6 +35,7 @@
 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
 
+import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.INetworkManagementEventObserver;
@@ -61,6 +59,7 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.telephony.DataConnectionRealTimeInfo;
@@ -70,9 +69,12 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.HexDump;
 import com.android.internal.util.Preconditions;
 import com.android.server.NativeDaemonConnector.Command;
 import com.android.server.NativeDaemonConnector.SensitiveArg;
@@ -87,8 +89,6 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
 import java.net.NetworkInterface;
@@ -145,6 +145,7 @@
         public static final int InterfaceAddressChange    = 614;
         public static final int InterfaceDnsServerInfo    = 615;
         public static final int RouteChange               = 616;
+        public static final int StrictCleartext           = 617;
     }
 
     static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
@@ -174,12 +175,19 @@
     private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
 
     private Object mQuotaLock = new Object();
+
     /** Set of interfaces with active quotas. */
+    @GuardedBy("mQuotaLock")
     private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
     /** Set of interfaces with active alerts. */
+    @GuardedBy("mQuotaLock")
     private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
     /** Set of UIDs with active reject rules. */
+    @GuardedBy("mQuotaLock")
     private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
+    /** Set of UIDs with cleartext penalties. */
+    @GuardedBy("mQuotaLock")
+    private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
 
     private Object mIdleTimerLock = new Object();
     /** Set of interfaces with active idle timers. */
@@ -198,6 +206,7 @@
 
     private volatile boolean mBandwidthControlEnabled;
     private volatile boolean mFirewallEnabled;
+    private volatile boolean mStrictEnabled;
 
     private boolean mMobileActivityFromRadio = false;
     private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
@@ -495,11 +504,18 @@
             }
         }
 
+        try {
+            mConnector.execute("strict", "enable");
+            mStrictEnabled = true;
+        } catch (NativeDaemonConnectorException e) {
+            Log.wtf(TAG, "Failed strict enable", e);
+        }
+
         // push any existing quota or UID rules
         synchronized (mQuotaLock) {
             int size = mActiveQuotas.size();
             if (size > 0) {
-                Slog.d(TAG, "pushing " + size + " active quota rules");
+                Slog.d(TAG, "Pushing " + size + " active quota rules");
                 final HashMap<String, Long> activeQuotas = mActiveQuotas;
                 mActiveQuotas = Maps.newHashMap();
                 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
@@ -509,7 +525,7 @@
 
             size = mActiveAlerts.size();
             if (size > 0) {
-                Slog.d(TAG, "pushing " + size + " active alert rules");
+                Slog.d(TAG, "Pushing " + size + " active alert rules");
                 final HashMap<String, Long> activeAlerts = mActiveAlerts;
                 mActiveAlerts = Maps.newHashMap();
                 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
@@ -519,13 +535,23 @@
 
             size = mUidRejectOnQuota.size();
             if (size > 0) {
-                Slog.d(TAG, "pushing " + size + " active uid rules");
+                Slog.d(TAG, "Pushing " + size + " active UID rules");
                 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota;
                 mUidRejectOnQuota = new SparseBooleanArray();
                 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
                     setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i));
                 }
             }
+
+            size = mUidCleartextPolicy.size();
+            if (size > 0) {
+                Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
+                final SparseIntArray local = mUidCleartextPolicy;
+                mUidCleartextPolicy = new SparseIntArray();
+                for (int i = 0; i < local.size(); i++) {
+                    setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
+                }
+            }
         }
 
         // TODO: Push any existing firewall state
@@ -792,6 +818,14 @@
                     }
                     throw new IllegalStateException(errorMessage);
                     // break;
+            case NetdResponseCode.StrictCleartext:
+                final int uid = Integer.parseInt(cooked[1]);
+                final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
+                try {
+                    ActivityManagerNative.getDefault().notifyCleartextNetwork(uid, firstPacket);
+                } catch (RemoteException ignored) {
+                }
+                break;
             default: break;
             }
             return false;
@@ -1641,6 +1675,49 @@
     }
 
     @Override
+    public void setUidCleartextNetworkPolicy(int uid, int policy) {
+        if (Binder.getCallingUid() != uid) {
+            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        }
+
+        synchronized (mQuotaLock) {
+            final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
+            if (oldPolicy == policy) {
+                return;
+            }
+
+            if (!mStrictEnabled) {
+                // Module isn't enabled yet; stash the requested policy away to
+                // apply later once the daemon is connected.
+                mUidCleartextPolicy.put(uid, policy);
+                return;
+            }
+
+            final String policyString;
+            switch (policy) {
+                case StrictMode.NETWORK_POLICY_ACCEPT:
+                    policyString = "accept";
+                    break;
+                case StrictMode.NETWORK_POLICY_LOG:
+                    policyString = "log";
+                    break;
+                case StrictMode.NETWORK_POLICY_REJECT:
+                    policyString = "reject";
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown policy " + policy);
+            }
+
+            try {
+                mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
+                mUidCleartextPolicy.put(uid, policy);
+            } catch (NativeDaemonConnectorException e) {
+                throw e.rethrowAsParcelableException();
+            }
+        }
+    }
+
+    @Override
     public boolean isBandwidthControlEnabled() {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         return mBandwidthControlEnabled;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 138bedc..668d62b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1197,6 +1197,7 @@
     static final int FINISH_BOOTING_MSG = 45;
     static final int START_USER_SWITCH_MSG = 46;
     static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47;
+    static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 50;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1902,6 +1903,23 @@
                 }
                 break;
             }
+            case NOTIFY_CLEARTEXT_NETWORK_MSG: {
+                final int uid = msg.arg1;
+                final byte[] firstPacket = (byte[]) msg.obj;
+
+                synchronized (mPidsSelfLocked) {
+                    for (int i = 0; i < mPidsSelfLocked.size(); i++) {
+                        final ProcessRecord p = mPidsSelfLocked.valueAt(i);
+                        if (p.uid == uid) {
+                            try {
+                                p.thread.notifyCleartextNetwork(firstPacket);
+                            } catch (RemoteException ignored) {
+                            }
+                        }
+                    }
+                }
+                break;
+            }
             }
         }
     };
@@ -2303,7 +2321,7 @@
             ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
 
         mConfiguration.setToDefaults();
-        mConfiguration.setLocale(Locale.getDefault());
+        mConfiguration.locale = Locale.getDefault();
 
         mConfigurationSeq = mConfiguration.seq = 1;
         mProcessCpuTracker.init();
@@ -10106,6 +10124,11 @@
     }
 
     @Override
+    public void notifyCleartextNetwork(int uid, byte[] firstPacket) {
+        mHandler.obtainMessage(NOTIFY_CLEARTEXT_NETWORK_MSG, uid, 0, firstPacket).sendToTarget();
+    }
+
+    @Override
     public boolean shutdown(int timeout) {
         if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -11727,8 +11750,12 @@
             sb.append("\n");
             if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
                 sb.append(info.crashInfo.stackTrace);
+                sb.append("\n");
             }
-            sb.append("\n");
+            if (info.message != null) {
+                sb.append(info.message);
+                sb.append("\n");
+            }
 
             // Only buffer up to ~64k.  Various logging bits truncate
             // things at 128k.
@@ -16197,6 +16224,7 @@
         Configuration ci;
         synchronized(this) {
             ci = new Configuration(mConfiguration);
+            ci.userSetLocale = false;
         }
         return ci;
     }
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 3d981ab..3fd0f84 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -21,7 +21,9 @@
 #include "jni.h"
 #include <utils/Log.h>
 #include <utils/misc.h>
+#include <utils/String8.h>
 
+#include <dirent.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
@@ -80,8 +82,8 @@
 class AlarmImplTimerFd : public AlarmImpl
 {
 public:
-    AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd) :
-        AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd) { }
+    AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) :
+        AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { }
     ~AlarmImplTimerFd();
 
     int set(int type, struct timespec *ts);
@@ -90,6 +92,7 @@
 
 private:
     int epollfd;
+    int rtc_id;
 };
 
 AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]),
@@ -170,9 +173,16 @@
         return -1;
     }
 
-    fd = open("/dev/rtc0", O_RDWR);
+    if (rtc_id < 0) {
+        ALOGV("Not setting RTC because wall clock RTC was not found");
+        errno = ENODEV;
+        return -1;
+    }
+
+    android::String8 rtc_dev = String8::format("/dev/rtc%d", rtc_id);
+    fd = open(rtc_dev.string(), O_RDWR);
     if (fd < 0) {
-        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
+        ALOGV("Unable to open %s: %s\n", rtc_dev.string(), strerror(errno));
         return res;
     }
 
@@ -283,6 +293,66 @@
     return reinterpret_cast<jlong>(ret);
 }
 
+static const char rtc_sysfs[] = "/sys/class/rtc";
+
+static bool rtc_is_hctosys(unsigned int rtc_id)
+{
+    android::String8 hctosys_path = String8::format("%s/rtc%u/hctosys",
+            rtc_sysfs, rtc_id);
+
+    FILE *file = fopen(hctosys_path.string(), "re");
+    if (!file) {
+        ALOGE("failed to open %s: %s", hctosys_path.string(), strerror(errno));
+        return false;
+    }
+
+    unsigned int hctosys;
+    bool ret = false;
+    int err = fscanf(file, "%u", &hctosys);
+    if (err == EOF)
+        ALOGE("failed to read from %s: %s", hctosys_path.string(),
+                strerror(errno));
+    else if (err == 0)
+        ALOGE("%s did not have expected contents", hctosys_path.string());
+    else
+        ret = hctosys;
+
+    fclose(file);
+    return ret;
+}
+
+static int wall_clock_rtc()
+{
+    DIR *dir = opendir(rtc_sysfs);
+    if (!dir) {
+        ALOGE("failed to open %s: %s", rtc_sysfs, strerror(errno));
+        return -1;
+    }
+
+    struct dirent *dirent;
+    while (errno = 0, dirent = readdir(dir)) {
+        unsigned int rtc_id;
+        int matched = sscanf(dirent->d_name, "rtc%u", &rtc_id);
+
+        if (matched < 0)
+            break;
+        else if (matched != 1)
+            continue;
+
+        if (rtc_is_hctosys(rtc_id)) {
+            ALOGV("found wall clock RTC %u", rtc_id);
+            return rtc_id;
+        }
+    }
+
+    if (errno == 0)
+        ALOGW("no wall clock RTC found");
+    else
+        ALOGE("failed to enumerate RTCs: %s", strerror(errno));
+
+    return -1;
+}
+
 static jlong init_timerfd()
 {
     int epollfd;
@@ -308,7 +378,7 @@
         }
     }
 
-    AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd);
+    AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc());
 
     for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
         epoll_event event;