Merge "Support invoking view methods from hierarchy viewer"
diff --git a/api/current.txt b/api/current.txt
index ac367f6..fc60f94 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -57,6 +57,7 @@
     field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
     field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
     field public static final java.lang.String GET_TASKS = "android.permission.GET_TASKS";
+    field public static final java.lang.String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
     field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
     field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
     field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
@@ -2738,6 +2739,7 @@
     method public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+    method public void onProvideAssistData(android.os.Bundle);
     method protected void onRestart();
     method protected void onRestoreInstanceState(android.os.Bundle);
     method protected void onResume();
@@ -3077,7 +3079,9 @@
     method public void onTerminate();
     method public void onTrimMemory(int);
     method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+    method public void registerOnProvideAssistData(android.app.Application.OnProvideAssistData);
     method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+    method public void unregisterOnProvideAssistData(android.app.Application.OnProvideAssistData);
   }
 
   public static abstract interface Application.ActivityLifecycleCallbacks {
@@ -3090,6 +3094,10 @@
     method public abstract void onActivityStopped(android.app.Activity);
   }
 
+  public static abstract interface Application.OnProvideAssistData {
+    method public abstract void onProvideAssistData(android.app.Activity, android.os.Bundle);
+  }
+
   public class ApplicationErrorReport implements android.os.Parcelable {
     ctor public ApplicationErrorReport();
     method public int describeContents();
@@ -5114,6 +5122,7 @@
     method public int bulkInsert(android.net.Uri, android.content.ContentValues[]);
     method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle);
     method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public final android.content.Context getContext();
     method public final android.content.pm.PathPermission[] getPathPermissions();
     method public final java.lang.String getReadPermission();
@@ -5901,6 +5910,8 @@
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
     field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
+    field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
+    field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
     field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
     field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
     field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
@@ -6627,6 +6638,7 @@
     method public abstract void verifyPendingInstall(int, int);
     field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
     field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2
+    field public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4; // 0x4
     field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3
     field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1
     field public static final int DONT_KILL_APP = 1; // 0x1
@@ -6673,6 +6685,7 @@
     field public static final int GET_ACTIVITIES = 1; // 0x1
     field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
     field public static final int GET_DISABLED_COMPONENTS = 512; // 0x200
+    field public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
     field public static final int GET_GIDS = 256; // 0x100
     field public static final int GET_INSTRUMENTATION = 16; // 0x10
     field public static final int GET_INTENT_FILTERS = 32; // 0x20
@@ -10688,6 +10701,7 @@
     method public boolean hasAltitude();
     method public boolean hasBearing();
     method public boolean hasSpeed();
+    method public boolean isFromMockProvider();
     method public void removeAccuracy();
     method public void removeAltitude();
     method public void removeBearing();
@@ -21512,6 +21526,7 @@
 
   public class MockContentResolver extends android.content.ContentResolver {
     ctor public MockContentResolver();
+    ctor public MockContentResolver(android.content.Context);
     method public void addProvider(java.lang.String, android.content.ContentProvider);
   }
 
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 42c9d34..f0e3370 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -135,6 +135,11 @@
             return;
         }
 
+        if ("disable-until-used".equals(op)) {
+            runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
+            return;
+        }
+
         if ("grant".equals(op)) {
             runGrantRevokePermission(true);
             return;
@@ -321,17 +326,8 @@
     @SuppressWarnings("unchecked")
     private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
             throws RemoteException {
-        final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
-        PackageInfo lastItem = null;
-        ParceledListSlice<PackageInfo> slice;
-
-        do {
-            final String lastKey = lastItem != null ? lastItem.packageName : null;
-            slice = pm.getInstalledPackages(flags, lastKey, userId);
-            lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
-        } while (!slice.isLastSlice());
-
-        return packageInfos;
+        ParceledListSlice<PackageInfo> slice = pm.getInstalledPackages(flags, userId);
+        return slice.getList();
     }
 
     /**
@@ -1187,6 +1183,8 @@
                 return "disabled";
             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
                 return "disabled-user";
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
+                return "disabled-until-used";
         }
         return "unknown";
     }
@@ -1468,6 +1466,7 @@
         System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
+        System.err.println("       pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm grant PACKAGE PERMISSION");
         System.err.println("       pm revoke PACKAGE PERMISSION");
         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 2337790..3602fc4 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -132,6 +132,12 @@
     public static final int DISPLAY_SHOW_CUSTOM = 0x10;
 
     /**
+     * Allow the title to wrap onto multiple lines if space is available
+     * @hide pending API approval
+     */
+    public static final int DISPLAY_TITLE_MULTIPLE_LINES = 0x20;
+
+    /**
      * Set the action bar into custom navigation mode, supplying a view
      * for custom navigation.
      *
@@ -680,6 +686,15 @@
     public Context getThemedContext() { return null; }
 
     /**
+     * Returns true if the Title field has been truncated during layout for lack
+     * of available space.
+     *
+     * @return true if the Title field has been truncated
+     * @hide pending API approval
+     */
+    public boolean isTitleTruncated() { return false; }
+
+    /**
      * Listener interface for ActionBar navigation events.
      */
     public interface OnNavigationListener {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d6ddeb6..18ccd53 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1346,6 +1346,20 @@
     }
 
     /**
+     * This is called when the user is requesting an assist, to build a full
+     * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
+     * application.  You can override this method to place into the bundle anything
+     * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
+     * of the assist Intent.  The default implementation does nothing.
+     *
+     * <p>This function will be called after any global assist callbacks that had
+     * been registered with {@link Application#registerOnProvideAssistData
+     * Application.registerOnProvideAssistData}.
+     */
+    public void onProvideAssistData(Bundle data) {
+    }
+
+    /**
      * Called when you are no longer visible to the user.  You will next
      * receive either {@link #onRestart}, {@link #onDestroy}, or nothing,
      * depending on later user activity.
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 61b2067..bc27a57d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1818,6 +1818,24 @@
             return true;
         }
 
+        case GET_TOP_ACTIVITY_EXTRAS_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int requestType = data.readInt();
+            Bundle res = getTopActivityExtras(requestType);
+            reply.writeNoException();
+            reply.writeBundle(res);
+            return true;
+        }
+
+        case REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            Bundle extras = data.readBundle();
+            reportTopActivityExtras(token, extras);
+            reply.writeNoException();
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -4149,5 +4167,30 @@
         return res;
     }
 
+    public Bundle getTopActivityExtras(int requestType) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(requestType);
+        mRemote.transact(GET_TOP_ACTIVITY_EXTRAS_TRANSACTION, data, reply, 0);
+        reply.readException();
+        Bundle res = reply.readBundle();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
+    public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        data.writeBundle(extras);
+        mRemote.transact(REPORT_TOP_ACTIVITY_EXTRAS_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 60d4363..570fb80 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -187,7 +187,8 @@
             = new ArrayList<Application>();
     // set of instantiated backup agents, keyed by package name
     final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
-    static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>();
+    /** Reference to singleton {@link ActivityThread} */
+    private static ActivityThread sCurrentActivityThread;
     Instrumentation mInstrumentation;
     String mInstrumentationAppDir = null;
     String mInstrumentationAppLibraryDir = null;
@@ -532,6 +533,12 @@
         String pkg;
         CompatibilityInfo info;
     }
+
+    static final class RequestActivityExtras {
+        IBinder activityToken;
+        IBinder requestToken;
+        int requestType;
+    }
     
     private native void dumpGraphicsInfo(FileDescriptor fd);
 
@@ -1107,6 +1114,16 @@
             queueOrSendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
         }
 
+        @Override
+        public void requestActivityExtras(IBinder activityToken, IBinder requestToken,
+                int requestType) {
+            RequestActivityExtras cmd = new RequestActivityExtras();
+            cmd.activityToken = activityToken;
+            cmd.requestToken = requestToken;
+            cmd.requestType = requestType;
+            queueOrSendMessage(H.REQUEST_ACTIVITY_EXTRAS, cmd);
+        }
+
         private void printRow(PrintWriter pw, String format, Object...objs) {
             pw.println(String.format(format, objs));
         }
@@ -1172,6 +1189,7 @@
         public static final int TRIM_MEMORY             = 140;
         public static final int DUMP_PROVIDER           = 141;
         public static final int UNSTABLE_PROVIDER_DIED  = 142;
+        public static final int REQUEST_ACTIVITY_EXTRAS = 143;
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -1218,6 +1236,7 @@
                     case TRIM_MEMORY: return "TRIM_MEMORY";
                     case DUMP_PROVIDER: return "DUMP_PROVIDER";
                     case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
+                    case REQUEST_ACTIVITY_EXTRAS: return "REQUEST_ACTIVITY_EXTRAS";
                 }
             }
             return Integer.toString(code);
@@ -1429,6 +1448,9 @@
                 case UNSTABLE_PROVIDER_DIED:
                     handleUnstableProviderDied((IBinder)msg.obj, false);
                     break;
+                case REQUEST_ACTIVITY_EXTRAS:
+                    handleRequestActivityExtras((RequestActivityExtras)msg.obj);
+                    break;
             }
             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
         }
@@ -1564,7 +1586,7 @@
     }
 
     public static ActivityThread currentActivityThread() {
-        return sThreadLocal.get();
+        return sCurrentActivityThread;
     }
 
     public static String currentPackageName() {
@@ -2321,6 +2343,23 @@
         performNewIntents(data.token, data.intents);
     }
 
+    public void handleRequestActivityExtras(RequestActivityExtras cmd) {
+        Bundle data = new Bundle();
+        ActivityClientRecord r = mActivities.get(cmd.activityToken);
+        if (r != null) {
+            r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
+            r.activity.onProvideAssistData(data);
+        }
+        if (data.isEmpty()) {
+            data = null;
+        }
+        IActivityManager mgr = ActivityManagerNative.getDefault();
+        try {
+            mgr.reportTopActivityExtras(cmd.requestToken, data);
+        } catch (RemoteException e) {
+        }
+    }
+    
     private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
 
     /**
@@ -4894,7 +4933,7 @@
     }
 
     private void attach(boolean system) {
-        sThreadLocal.set(this);
+        sCurrentActivityThread = this;
         mSystemThread = system;
         if (!system) {
             ViewRootImpl.addFirstDrawHandler(new Runnable() {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4cea6a0..b1d0305 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -44,19 +44,44 @@
     public static final int OP_WRITE_CONTACTS = 5;
     public static final int OP_READ_CALL_LOG = 6;
     public static final int OP_WRITE_CALL_LOG = 7;
+    public static final int OP_READ_CALENDAR = 8;
+    public static final int OP_WRITE_CALENDAR = 9;
+    public static final int OP_WIFI_SCAN = 10;
 
-    public static String opToString(int op) {
-        switch (op) {
-            case OP_COARSE_LOCATION: return "COARSE_LOCATION";
-            case OP_FINE_LOCATION: return "FINE_LOCATION";
-            case OP_GPS: return "GPS";
-            case OP_VIBRATE: return "VIBRATE";
-            case OP_READ_CONTACTS: return "READ_CONTACTS";
-            case OP_WRITE_CONTACTS: return "WRITE_CONTACTS";
-            case OP_READ_CALL_LOG: return "READ_CALL_LOG";
-            case OP_WRITE_CALL_LOG: return "WRITE_CALL_LOG";
-            default: return "Unknown(" + op + ")";
-        }
+    private static String[] sOpNames = new String[] {
+        "COARSE_LOCATION",
+        "FINE_LOCATION",
+        "GPS",
+        "VIBRATE",
+        "READ_CONTACTS",
+        "WRITE_CONTACTS",
+        "READ_CALL_LOG",
+        "WRITE_CALL_LOG",
+        "READ_CALENDAR",
+        "WRITE_CALENDAR",
+        "WIFI_SCAN",
+    };
+
+    private static String[] sOpPerms = new String[] {
+        android.Manifest.permission.ACCESS_COARSE_LOCATION,
+        android.Manifest.permission.ACCESS_FINE_LOCATION,
+        android.Manifest.permission.ACCESS_FINE_LOCATION,
+        android.Manifest.permission.VIBRATE,
+        android.Manifest.permission.READ_CONTACTS,
+        android.Manifest.permission.WRITE_CONTACTS,
+        android.Manifest.permission.READ_CALL_LOG,
+        android.Manifest.permission.WRITE_CALL_LOG,
+        android.Manifest.permission.READ_CALENDAR,
+        android.Manifest.permission.WRITE_CALENDAR,
+        android.Manifest.permission.ACCESS_WIFI_STATE,
+    };
+
+    public static String opToName(int op) {
+        return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")");
+    }
+
+    public static String opToPermission(int op) {
+        return sOpPerms[op];
     }
 
     public static class PackageOps implements Parcelable {
@@ -120,12 +145,16 @@
 
     public static class OpEntry implements Parcelable {
         private final int mOp;
+        private final int mMode;
         private final long mTime;
+        private final long mRejectTime;
         private final int mDuration;
 
-        public OpEntry(int op, long time, int duration) {
+        public OpEntry(int op, int mode, long time, long rejectTime, int duration) {
             mOp = op;
+            mMode = mode;
             mTime = time;
+            mRejectTime = rejectTime;
             mDuration = duration;
         }
 
@@ -133,10 +162,18 @@
             return mOp;
         }
 
+        public int getMode() {
+            return mMode;
+        }
+
         public long getTime() {
             return mTime;
         }
 
+        public long getRejectTime() {
+            return mRejectTime;
+        }
+
         public boolean isRunning() {
             return mDuration == -1;
         }
@@ -153,13 +190,17 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mOp);
+            dest.writeInt(mMode);
             dest.writeLong(mTime);
+            dest.writeLong(mRejectTime);
             dest.writeInt(mDuration);
         }
 
         OpEntry(Parcel source) {
             mOp = source.readInt();
+            mMode = source.readInt();
             mTime = source.readLong();
+            mRejectTime = source.readLong();
             mDuration = source.readInt();
         }
 
@@ -187,6 +228,21 @@
         return null;
     }
 
+    public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
+        try {
+            return mService.getOpsForPackage(uid, packageName, ops);
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    public void setMode(int code, int uid, String packageName, int mode) {
+        try {
+            mService.setMode(code, uid, packageName, mode);
+        } catch (RemoteException e) {
+        }
+    }
+
     public int checkOp(int op, int uid, String packageName) {
         try {
             int mode = mService.checkOperation(op, uid, packageName);
@@ -228,7 +284,7 @@
     }
 
     public int noteOp(int op) {
-        return noteOp(op, Process.myUid(), mContext.getPackageName());
+        return noteOp(op, Process.myUid(), mContext.getBasePackageName());
     }
 
     public int startOp(int op, int uid, String packageName) {
@@ -252,7 +308,7 @@
     }
 
     public int startOp(int op) {
-        return startOp(op, Process.myUid(), mContext.getPackageName());
+        return startOp(op, Process.myUid(), mContext.getBasePackageName());
     }
 
     public void finishOp(int op, int uid, String packageName) {
@@ -263,6 +319,6 @@
     }
 
     public void finishOp(int op) {
-        finishOp(op, Process.myUid(), mContext.getPackageName());
+        finishOp(op, Process.myUid(), mContext.getBasePackageName());
     }
 }
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 3a67cec..132388e 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -22,6 +22,7 @@
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.Bundle;
 
@@ -45,6 +46,7 @@
             new ArrayList<ComponentCallbacks>();
     private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
             new ArrayList<ActivityLifecycleCallbacks>();
+    private ArrayList<OnProvideAssistData> mAssistCallbacks = null;
 
     /** @hide */
     public LoadedApk mLoadedApk;
@@ -59,6 +61,21 @@
         void onActivityDestroyed(Activity activity);
     }
 
+    /**
+     * Callback interface for use with {@link Application#registerOnProvideAssistData}
+     * and {@link Application#unregisterOnProvideAssistData}.
+     */
+    public interface OnProvideAssistData {
+        /**
+         * This is called when the user is requesting an assist, to build a full
+         * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
+         * application.  You can override this method to place into the bundle anything
+         * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
+         * of the assist Intent.
+         */
+        public void onProvideAssistData(Activity activity, Bundle data);
+    }
+
     public Application() {
         super(null);
     }
@@ -137,7 +154,24 @@
             mActivityLifecycleCallbacks.remove(callback);
         }
     }
-    
+
+    public void registerOnProvideAssistData(OnProvideAssistData callback) {
+        synchronized (this) {
+            if (mAssistCallbacks == null) {
+                mAssistCallbacks = new ArrayList<OnProvideAssistData>();
+            }
+            mAssistCallbacks.add(callback);
+        }
+    }
+
+    public void unregisterOnProvideAssistData(OnProvideAssistData callback) {
+        synchronized (this) {
+            if (mAssistCallbacks != null) {
+                mAssistCallbacks.remove(callback);
+            }
+        }
+    }
+
     // ------------------ Internal API ------------------
     
     /**
@@ -232,4 +266,19 @@
         }
         return callbacks;
     }
+
+    /* package */ void dispatchOnProvideAssistData(Activity activity, Bundle data) {
+        Object[] callbacks;
+        synchronized (this) {
+            if (mAssistCallbacks == null) {
+                return;
+            }
+            callbacks = mAssistCallbacks.toArray();
+        }
+        if (callbacks != null) {
+            for (int i=0; i<callbacks.length; i++) {
+                ((OnProvideAssistData)callbacks[i]).onProvideAssistData(activity, data);
+            }
+        }
+    }
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 2ef3944..f09c2fe 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -426,17 +426,8 @@
     @Override
     public List<PackageInfo> getInstalledPackages(int flags, int userId) {
         try {
-            final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
-            PackageInfo lastItem = null;
-            ParceledListSlice<PackageInfo> slice;
-
-            do {
-                final String lastKey = lastItem != null ? lastItem.packageName : null;
-                slice = mPM.getInstalledPackages(flags, lastKey, userId);
-                lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
-            } while (!slice.isLastSlice());
-
-            return packageInfos;
+            ParceledListSlice<PackageInfo> slice = mPM.getInstalledPackages(flags, userId);
+            return slice.getList();
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -448,17 +439,9 @@
             String[] permissions, int flags) {
         final int userId = mContext.getUserId();
         try {
-            final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
-            PackageInfo lastItem = null;
-            ParceledListSlice<PackageInfo> slice;
-
-            do {
-                final String lastKey = lastItem != null ? lastItem.packageName : null;
-                slice = mPM.getPackagesHoldingPermissions(permissions, flags, lastKey, userId);
-                lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
-            } while (!slice.isLastSlice());
-
-            return packageInfos;
+            ParceledListSlice<PackageInfo> slice = mPM.getPackagesHoldingPermissions(
+                    permissions, flags, userId);
+            return slice.getList();
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
@@ -469,17 +452,8 @@
     public List<ApplicationInfo> getInstalledApplications(int flags) {
         final int userId = mContext.getUserId();
         try {
-            final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>();
-            ApplicationInfo lastItem = null;
-            ParceledListSlice<ApplicationInfo> slice;
-
-            do {
-                final String lastKey = lastItem != null ? lastItem.packageName : null;
-                slice = mPM.getInstalledApplications(flags, lastKey, userId);
-                lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR);
-            } while (!slice.isLastSlice());
-
-            return applicationInfos;
+            ParceledListSlice<ApplicationInfo> slice = mPM.getInstalledApplications(flags, userId);
+            return slice.getList();
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
         }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 63aa5f9..f0e367c 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -587,6 +587,17 @@
             reply.writeNoException();
             return true;
         }
+
+        case REQUEST_ACTIVITY_EXTRAS_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            IBinder activityToken = data.readStrongBinder();
+            IBinder requestToken = data.readStrongBinder();
+            int requestType = data.readInt();
+            requestActivityExtras(activityToken, requestToken, requestType);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1185,4 +1196,15 @@
         mRemote.transact(UNSTABLE_PROVIDER_DIED_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
         data.recycle();
     }
+
+    public void requestActivityExtras(IBinder activityToken, IBinder requestToken, int requestType)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeStrongBinder(activityToken);
+        data.writeStrongBinder(requestToken);
+        data.writeInt(requestType);
+        mRemote.transact(REQUEST_ACTIVITY_EXTRAS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4925bf1..fd4389e 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -628,6 +628,12 @@
         return "android";
     }
 
+    /** @hide */
+    @Override
+    public String getBasePackageName() {
+        return mBasePackageName != null ? mBasePackageName : getPackageName();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         if (mPackageInfo != null) {
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 32e40ee..26dc60d 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1085,6 +1085,7 @@
         values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, -1);
         values.putNull(Downloads.Impl._DATA);
         values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING);
+        values.put(Downloads.Impl.COLUMN_FAILED_CONNECTIONS, 0);
         mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), getWhereArgsForIds(ids));
     }
 
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 8af17a4..baac07f 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -368,6 +368,10 @@
 
     public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException;
 
+    public Bundle getTopActivityExtras(int requestType) throws RemoteException;
+
+    public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -624,4 +628,6 @@
     int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
     int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
     int GET_INTENT_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+160;
+    int GET_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+161;
+    int REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+162;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 03a26d4..8516694 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -130,6 +130,8 @@
     void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void unstableProviderDied(IBinder provider) throws RemoteException;
+    void requestActivityExtras(IBinder activityToken, IBinder requestToken, int requestType)
+            throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -179,4 +181,5 @@
     int DUMP_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+44;
     int DUMP_DB_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+45;
     int UNSTABLE_PROVIDER_DIED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+46;
+    int REQUEST_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+47;
 }
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index e0856ae..39186c6 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.PerformanceCollector;
 import android.os.Process;
@@ -1637,7 +1638,7 @@
     }
     
     private final void validateNotAppThread() {
-        if (ActivityThread.currentActivityThread() != null) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
             throw new RuntimeException(
                 "This method can not be called from the main application thread");
         }
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 6382cee..7dfc589f 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -846,8 +846,8 @@
      *
      * @hide
      */
-    public Intent getAssistIntent(Context context) {
-        return getAssistIntent(context, UserHandle.myUserId());
+    public Intent getAssistIntent(Context context, boolean inclContext) {
+        return getAssistIntent(context, inclContext, UserHandle.myUserId());
     }
 
     /**
@@ -856,7 +856,7 @@
      *
      * @hide
      */
-    public Intent getAssistIntent(Context context, int userHandle) {
+    public Intent getAssistIntent(Context context, boolean inclContext, int userHandle) {
         try {
             if (mService == null) {
                 return null;
@@ -867,6 +867,13 @@
             }
             Intent intent = new Intent(Intent.ACTION_ASSIST);
             intent.setComponent(comp);
+            if (inclContext) {
+                IActivityManager am = ActivityManagerNative.getDefault();
+                Bundle extras = am.getTopActivityExtras(0);
+                if (extras != null) {
+                    intent.replaceExtras(extras);
+                }
+            }
             return intent;
         } catch (RemoteException re) {
             Log.e(TAG, "getAssistIntent() failed: " + re);
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index a6f7abc..4b977ab 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -190,8 +190,13 @@
         public Cursor query(String callingPkg, Uri uri, String[] projection,
                 String selection, String[] selectionArgs, String sortOrder,
                 ICancellationSignal cancellationSignal) {
-            // XXX need content provider to help return correct result.
-            enforceReadPermission(callingPkg, uri);
+            if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+                // The read is not allowed...  to fake it out, we replace the given
+                // selection statement with a dummy one that will always be false.
+                // This way we will get a cursor back that has the correct structure
+                // but contains no rows.
+                selection = "'A' = 'B'";
+            }
             return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder,
                     CancellationSignal.fromTransport(cancellationSignal));
         }
@@ -203,8 +208,14 @@
 
         @Override
         public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
-            // XXX need content provider to help return correct result.
-            enforceWritePermission(callingPkg, uri);
+            if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+                // If not allowed, we need to return some reasonable URI.  Maybe the
+                // content provider should be responsible for this, but for now we
+                // will just return the base URI with a dummy '0' tagged on to it.
+                // You shouldn't be able to read if you can't write, anyway, so it
+                // shouldn't matter much what is returned.
+                return uri.buildUpon().appendPath("0").build();
+            }
             return ContentProvider.this.insert(uri, initialValues);
         }
 
@@ -1189,12 +1200,10 @@
      * Print the Provider's state into the given stream.  This gets invoked if
      * you run "adb shell dumpsys activity provider &lt;provider_component_name&gt;".
      *
-     * @param prefix Desired prefix to prepend at each line of output.
      * @param fd The raw file descriptor that the dump is being sent to.
      * @param writer The PrintWriter to which you should dump your state.  This will be
      * closed for you after you return.
      * @param args additional arguments to the dump request.
-     * @hide
      */
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         writer.println("nothing to dump");
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 51c9aa5..63c97ba 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -20,6 +20,7 @@
 
 import android.accounts.Account;
 import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
 import android.app.AppGlobals;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.AssetFileDescriptor;
@@ -206,8 +207,8 @@
     private final Random mRandom = new Random();  // guarded by itself
 
     public ContentResolver(Context context) {
-        mContext = context;
-        mPackageName = context.getPackageName();
+        mContext = context != null ? context : ActivityThread.currentApplication();
+        mPackageName = context.getBasePackageName();
     }
 
     /** @hide */
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 14f2847..f7c28b6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -418,6 +418,9 @@
     /** Return the name of this application's package. */
     public abstract String getPackageName();
 
+    /** @hide Return the name of the base context this context is derived from. */
+    public abstract String getBasePackageName();
+
     /** Return the full application info for this context's package. */
     public abstract ApplicationInfo getApplicationInfo();
 
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 6a61884..b63f45e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -135,6 +135,12 @@
         return mBase.getPackageName();
     }
 
+    /** @hide */
+    @Override
+    public String getBasePackageName() {
+        return mBase.getBasePackageName();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         return mBase.getApplicationInfo();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 89b1bbd..dc367dd 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1140,14 +1140,33 @@
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
+
     /**
      * Activity Action: Perform assist action.
      * <p>
-     * Input: nothing
+     * Input: {@link #EXTRA_ASSIST_PACKAGE} and {@link #EXTRA_ASSIST_CONTEXT} can provide
+     * additional optional contextual information about where the user was when they requested
+     * the assist.
      * Output: nothing.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_ASSIST = "android.intent.action.ASSIST";
+
+    /**
+     * An optional field on {@link #ACTION_ASSIST} containing the name of the current
+     * foreground application package at the time the assist was invoked.
+     */
+    public static final String EXTRA_ASSIST_PACKAGE
+            = "android.intent.extra.ASSIST_PACKAGE";
+
+    /**
+     * An optional field on {@link #ACTION_ASSIST} containing additional contextual
+     * information supplied by the current foreground app at the time of the assist
+     * request.  This is a {@link Bundle} of additional data.
+     */
+    public static final String EXTRA_ASSIST_CONTEXT
+            = "android.intent.extra.ASSIST_CONTEXT";
+
     /**
      * Activity Action: List all available applications
      * <p>Input: Nothing.
@@ -1588,7 +1607,7 @@
      * <ul>
      * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
      * <li> {@link #EXTRA_CHANGED_COMPONENT_NAME_LIST} containing the class name
-     * of the changed components.
+     * of the changed components (or the package name itself).
      * <li> {@link #EXTRA_DONT_KILL_APP} containing boolean field to override the
      * default action of restarting the application.
      * </ul>
@@ -2969,7 +2988,9 @@
 
     /**
      * This field is part of {@link android.content.Intent#ACTION_PACKAGE_CHANGED},
-     * and contains a string array of all of the components that have changed.
+     * and contains a string array of all of the components that have changed.  If
+     * the state of the overall package has changed, then it will contain an entry
+     * with the package name itself.
      */
     public static final String EXTRA_CHANGED_COMPONENT_NAME_LIST =
             "android.intent.extra.changed_component_name_list";
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4c9c278..0445b39 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -127,7 +127,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
-    ParceledListSlice getInstalledPackages(int flags, in String lastRead, in int userId);
+    ParceledListSlice getInstalledPackages(int flags, in int userId);
 
     /**
      * This implements getPackagesHoldingPermissions via a "last returned row"
@@ -136,7 +136,7 @@
      * returned.
      */
     ParceledListSlice getPackagesHoldingPermissions(in String[] permissions,
-            int flags, in String lastRead, int userId);
+            int flags, int userId);
 
     /**
      * This implements getInstalledApplications via a "last returned row"
@@ -144,7 +144,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
-    ParceledListSlice getInstalledApplications(int flags, in String lastRead, int userId);
+    ParceledListSlice getInstalledApplications(int flags, int userId);
 
     /**
      * Retrieve all applications that are marked as persistent.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a69f220..d80598c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -175,6 +175,14 @@
     public static final int GET_CONFIGURATIONS = 0x00004000;
 
     /**
+     * {@link PackageInfo} flag: include disabled components which are in
+     * that state only because of {@link #COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED}
+     * in the returned info.  Note that if you set this flag, applications
+     * that are in this disabled state will be reported as enabled.
+     */
+    public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 0x00008000;
+
+    /**
      * Resolution and querying flag: if set, only filters that support the
      * {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for
      * matching.  This is a synonym for including the CATEGORY_DEFAULT in your
@@ -265,6 +273,19 @@
     public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
 
     /**
+     * Flag for {@link #setApplicationEnabledSetting(String, int, int)} only: This
+     * application should be considered, until the point where the user actually
+     * wants to use it.  This means that it will not normally show up to the user
+     * (such as in the launcher), but various parts of the user interface can
+     * use {@link #GET_DISABLED_UNTIL_USED_COMPONENTS} to still see it and allow
+     * the user to select it (as for example an IME, device admin, etc).  Such code,
+     * once the user has selected the app, should at that point also make it enabled.
+     * This option currently <strong>can not</strong> be used with
+     * {@link #setComponentEnabledSetting(ComponentName, int, int)}.
+     */
+    public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;
+
+    /**
      * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
      * indicate that this package should be installed as forward locked, i.e. only the app itself
      * should have access to its code and non-resource assets.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3e8c2a8..e1887bc 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3527,29 +3527,45 @@
         return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
     }
 
+    private static void updateApplicationInfo(ApplicationInfo ai, int flags,
+            PackageUserState state) {
+        // CompatibilityMode is global state.
+        if (!sCompatibilityModeEnabled) {
+            ai.disableCompatibilityMode();
+        }
+        if (state.installed) {
+            ai.flags |= ApplicationInfo.FLAG_INSTALLED;
+        } else {
+            ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
+        }
+        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+            ai.enabled = true;
+        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+            ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
+        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+            ai.enabled = false;
+        }
+        ai.enabledSetting = state.enabled;
+    }
+
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
             PackageUserState state, int userId) {
         if (p == null) return null;
         if (!checkUseInstalled(flags, state)) {
             return null;
         }
-        if (!copyNeeded(flags, p, state, null, userId)) {
-            // CompatibilityMode is global state. It's safe to modify the instance
-            // of the package.
-            if (!sCompatibilityModeEnabled) {
-                p.applicationInfo.disableCompatibilityMode();
-            }
-            // Make sure we report as installed.  Also safe to do, since the
-            // default state should be installed (we will always copy if we
-            // need to report it is not installed).
-            p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
-            if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
-                p.applicationInfo.enabled = true;
-            } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                    || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
-                p.applicationInfo.enabled = false;
-            }
-            p.applicationInfo.enabledSetting = state.enabled;
+        if (!copyNeeded(flags, p, state, null, userId)
+                && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
+                        || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
+            // In this case it is safe to directly modify the internal ApplicationInfo state:
+            // - CompatibilityMode is global state, so will be the same for every call.
+            // - We only come in to here if the app should reported as installed; this is the
+            // default state, and we will do a copy otherwise.
+            // - The enable state will always be reported the same for the application across
+            // calls; the only exception is for the UNTIL_USED mode, and in that case we will
+            // be doing a copy.
+            updateApplicationInfo(p.applicationInfo, flags, state);
             return p.applicationInfo;
         }
 
@@ -3565,26 +3581,12 @@
         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
             ai.sharedLibraryFiles = p.usesLibraryFiles;
         }
-        if (!sCompatibilityModeEnabled) {
-            ai.disableCompatibilityMode();
-        }
         if (state.stopped) {
             ai.flags |= ApplicationInfo.FLAG_STOPPED;
         } else {
             ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
         }
-        if (state.installed) {
-            ai.flags |= ApplicationInfo.FLAG_INSTALLED;
-        } else {
-            ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
-        }
-        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
-            ai.enabled = true;
-        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
-            ai.enabled = false;
-        }
-        ai.enabledSetting = state.enabled;
+        updateApplicationInfo(ai, flags, state);
         return ai;
     }
 
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index f3a98db4..8a43472 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -16,44 +16,92 @@
 
 package android.content.pm;
 
+import android.os.Binder;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteException;
+import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Builds up a parcel that is discarded when written to another parcel or
- * written to a list. This is useful for API that sends huge lists across a
- * Binder that may be larger than the IPC limit.
+ * Transfer a large list of Parcelable objects across an IPC.  Splits into
+ * multiple transactions if needed.
  *
  * @hide
  */
 public class ParceledListSlice<T extends Parcelable> implements Parcelable {
+    private static String TAG = "ParceledListSlice";
+    private static boolean DEBUG = false;
+
     /*
      * TODO get this number from somewhere else. For now set it to a quarter of
      * the 1MB limit.
      */
     private static final int MAX_IPC_SIZE = 256 * 1024;
+    private static final int MAX_FIRST_IPC_SIZE = MAX_IPC_SIZE / 2;
 
-    private Parcel mParcel;
+    private final List<T> mList;
 
-    private int mNumItems;
-
-    private boolean mIsLastSlice;
-
-    public ParceledListSlice() {
-        mParcel = Parcel.obtain();
+    public ParceledListSlice(List<T> list) {
+        mList = list;
     }
 
-    private ParceledListSlice(Parcel p, int numItems, boolean lastSlice) {
-        mParcel = p;
-        mNumItems = numItems;
-        mIsLastSlice = lastSlice;
+    private ParceledListSlice(Parcel p, ClassLoader loader) {
+        final int N = p.readInt();
+        mList = new ArrayList<T>(N);
+        if (DEBUG) Log.d(TAG, "Retrieving " + N + " items");
+        if (N <= 0) {
+            return;
+        }
+        Parcelable.Creator<T> creator = p.readParcelableCreator(loader);
+        int i = 0;
+        while (i < N) {
+            if (p.readInt() == 0) {
+                break;
+            }
+            mList.add(p.readCreator(creator, loader));
+            if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
+            i++;
+        }
+        if (i >= N) {
+            return;
+        }
+        final IBinder retriever = p.readStrongBinder();
+        while (i < N) {
+            if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever);
+            Parcel data = Parcel.obtain();
+            Parcel reply = Parcel.obtain();
+            data.writeInt(i);
+            try {
+                retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
+                return;
+            }
+            while (i < N && reply.readInt() != 0) {
+                mList.add(reply.readCreator(creator, loader));
+                if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
+                i++;
+            }
+            reply.recycle();
+            data.recycle();
+        }
+    }
+
+    public List<T> getList() {
+        return mList;
     }
 
     @Override
     public int describeContents() {
-        return 0;
+        int contents = 0;
+        for (int i=0; i<mList.size(); i++) {
+            contents |= mList.get(i).describeContents();
+        }
+        return contents;
     }
 
     /**
@@ -63,104 +111,59 @@
      */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mNumItems);
-        dest.writeInt(mIsLastSlice ? 1 : 0);
-
-        if (mNumItems > 0) {
-            final int parcelSize = mParcel.dataSize();
-            dest.writeInt(parcelSize);
-            dest.appendFrom(mParcel, 0, parcelSize);
+        final int N = mList.size();
+        final int callFlags = flags;
+        dest.writeInt(N);
+        if (DEBUG) Log.d(TAG, "Writing " + N + " items");
+        if (N > 0) {
+            dest.writeParcelableCreator(mList.get(0));
+            int i = 0;
+            while (i < N && dest.dataSize() < MAX_FIRST_IPC_SIZE) {
+                dest.writeInt(1);
+                mList.get(i).writeToParcel(dest, callFlags);
+                if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
+                i++;
+            }
+            if (i < N) {
+                dest.writeInt(0);
+                Binder retriever = new Binder() {
+                    @Override
+                    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                            throws RemoteException {
+                        if (code != FIRST_CALL_TRANSACTION) {
+                            return super.onTransact(code, data, reply, flags);
+                        }
+                        int i = data.readInt();
+                        if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
+                        while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
+                            reply.writeInt(1);
+                            mList.get(i).writeToParcel(reply, callFlags);
+                            if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
+                            i++;
+                        }
+                        if (i < N) {
+                            if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
+                            reply.writeInt(0);
+                        }
+                        return true;
+                    }
+                };
+                if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever);
+                dest.writeStrongBinder(retriever);
+            }
         }
-
-        mNumItems = 0;
-        mParcel.recycle();
-        mParcel = null;
-    }
-
-    /**
-     * Appends a parcel to this list slice.
-     *
-     * @param item Parcelable item to append to this list slice
-     * @return true when the list slice is full and should not be appended to
-     *         anymore
-     */
-    public boolean append(T item) {
-        if (mParcel == null) {
-            throw new IllegalStateException("ParceledListSlice has already been recycled");
-        }
-
-        item.writeToParcel(mParcel, PARCELABLE_WRITE_RETURN_VALUE);
-        mNumItems++;
-
-        return mParcel.dataSize() > MAX_IPC_SIZE;
-    }
-
-    /**
-     * Populates a list and discards the internal state of the
-     * ParceledListSlice in the process. The instance should
-     * not be used anymore.
-     *
-     * @param list list to insert items from this slice.
-     * @param creator creator that knows how to unparcel the
-     *        target object type.
-     * @return the last item inserted into the list or null if none.
-     */
-    public T populateList(List<T> list, Creator<T> creator) {
-        mParcel.setDataPosition(0);
-
-        T item = null;
-        for (int i = 0; i < mNumItems; i++) {
-            item = creator.createFromParcel(mParcel);
-            list.add(item);
-        }
-
-        mParcel.recycle();
-        mParcel = null;
-
-        return item;
-    }
-
-    /**
-     * Sets whether this is the last list slice in the series.
-     *
-     * @param lastSlice
-     */
-    public void setLastSlice(boolean lastSlice) {
-        mIsLastSlice = lastSlice;
-    }
-
-    /**
-     * Returns whether this is the last slice in a series of slices.
-     *
-     * @return true if this is the last slice in the series.
-     */
-    public boolean isLastSlice() {
-        return mIsLastSlice;
     }
 
     @SuppressWarnings("unchecked")
-    public static final Parcelable.Creator<ParceledListSlice> CREATOR =
-            new Parcelable.Creator<ParceledListSlice>() {
+    public static final Parcelable.ClassLoaderCreator<ParceledListSlice> CREATOR =
+            new Parcelable.ClassLoaderCreator<ParceledListSlice>() {
         public ParceledListSlice createFromParcel(Parcel in) {
-            final int numItems = in.readInt();
-            final boolean lastSlice = in.readInt() == 1;
+            return new ParceledListSlice(in, null);
+        }
 
-            if (numItems > 0) {
-                final int parcelSize = in.readInt();
-
-                // Advance within this Parcel
-                int offset = in.dataPosition();
-                in.setDataPosition(offset + parcelSize);
-
-                Parcel p = Parcel.obtain();
-                p.setDataPosition(0);
-                p.appendFrom(in, offset, parcelSize);
-                p.setDataPosition(0);
-
-                return new ParceledListSlice(p, numItems, lastSlice);
-            } else {
-                return new ParceledListSlice();
-            }
+        @Override
+        public ParceledListSlice createFromParcel(Parcel in, ClassLoader loader) {
+            return new ParceledListSlice(in, loader);
         }
 
         public ParceledListSlice[] newArray(int size) {
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 846443d..c0a894b 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -24,6 +24,7 @@
 import java.net.SocketException;
 import java.security.KeyManagementException;
 import java.security.cert.X509Certificate;
+import java.security.interfaces.ECPrivateKey;
 import javax.net.SocketFactory;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
@@ -88,6 +89,7 @@
     private TrustManager[] mTrustManagers = null;
     private KeyManager[] mKeyManagers = null;
     private byte[] mNpnProtocols = null;
+    private ECPrivateKey mChannelIdPrivateKey = null;
 
     private final int mHandshakeTimeoutMillis;
     private final SSLClientSessionCache mSessionCache;
@@ -319,6 +321,20 @@
     }
 
     /**
+     * Sets the {@link ECPrivateKey} to be used for TLS Channel ID by connections made by this
+     * factory.
+     *
+     * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
+     *        TLS Channel ID). The private key has to be an Elliptic Curve (EC) key based on the
+     *        NIST P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1).
+     *
+     * @hide
+     */
+    public void setChannelIdPrivateKey(ECPrivateKey privateKey) {
+        mChannelIdPrivateKey = privateKey;
+    }
+
+    /**
      * Enables <a href="http://tools.ietf.org/html/rfc5077#section-3.2">session ticket</a>
      * support on the given socket.
      *
@@ -378,6 +394,7 @@
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {
             verifyHostname(s, host);
         }
@@ -397,6 +414,7 @@
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket();
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
     }
 
@@ -414,6 +432,7 @@
                 addr, port, localAddr, localPort);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
     }
 
@@ -429,6 +448,7 @@
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
     }
 
@@ -445,6 +465,7 @@
                 host, port, localAddr, localPort);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {
             verifyHostname(s, host);
         }
@@ -462,6 +483,7 @@
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
         s.setNpnProtocols(mNpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {
             verifyHostname(s, host);
         }
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 1044931..d0e5019 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -352,14 +352,4 @@
     void setFirewallEgressSourceRule(String addr, boolean allow);
     void setFirewallEgressDestRule(String addr, int port, boolean allow);
     void setFirewallUidRule(int uid, boolean allow);
-
-    /**
-     * Set a process (pid) to use the name servers associated with the specified interface.
-     */
-    void setDnsIfaceForPid(String iface, int pid);
-
-    /**
-     * Clear a process (pid) from being associated with an interface.
-     */
-    void clearDnsIfaceForPid(int pid);
 }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index d69fef0..31d323b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1254,6 +1254,12 @@
         p.writeToParcel(this, parcelableFlags);
     }
 
+    /** @hide */
+    public final void writeParcelableCreator(Parcelable p) {
+        String name = p.getClass().getName();
+        writeString(name);
+    }
+
     /**
      * Write a generic serializable object in to a Parcel.  It is strongly
      * recommended that this method be avoided, since the serialization
@@ -2046,6 +2052,28 @@
      * was an error trying to instantiate the Parcelable.
      */
     public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
+        Parcelable.Creator<T> creator = readParcelableCreator(loader);
+        if (creator == null) {
+            return null;
+        }
+        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
+            return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
+        }
+        return creator.createFromParcel(this);
+    }
+
+    /** @hide */
+    public final <T extends Parcelable> T readCreator(Parcelable.Creator<T> creator,
+            ClassLoader loader) {
+        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
+            return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
+        }
+        return creator.createFromParcel(this);
+    }
+
+    /** @hide */
+    public final <T extends Parcelable> Parcelable.Creator<T> readParcelableCreator(
+            ClassLoader loader) {
         String name = readString();
         if (name == null) {
             return null;
@@ -2101,10 +2129,7 @@
             }
         }
 
-        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
-            return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
-        }
-        return creator.createFromParcel(this);
+        return creator;
     }
 
     /**
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 05099fb..facab4c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -806,7 +806,15 @@
      */
     public static final native void setProcessGroup(int pid, int group)
             throws IllegalArgumentException, SecurityException;
-    
+
+    /**
+     * Return the scheduling group of requested process.
+     *
+     * @hide
+     */
+    public static final native int getProcessGroup(int pid)
+            throws IllegalArgumentException, SecurityException;
+
     /**
      * Set the priority of the calling thread, based on Linux priorities.  See
      * {@link #setThreadPriority(int, int)} for more information.
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 54ea385..08eba4f 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -38,7 +38,7 @@
     }
 
     public SystemVibrator(Context context) {
-        mPackageName = context.getPackageName();
+        mPackageName = context.getBasePackageName();
         mService = IVibratorService.Stub.asInterface(
                 ServiceManager.getService("vibrator"));
     }
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 69118fe..b79bdee 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -11,7 +11,7 @@
  */
 public class WorkSource implements Parcelable {
     static final String TAG = "WorkSource";
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
     int mNum;
     int[] mUids;
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 31ad12b..9999760 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -407,6 +407,9 @@
          */
         public static final String COLUMN_LAST_UPDATESRC = "lastUpdateSrc";
 
+        /** The column that is used to count retries */
+        public static final String COLUMN_FAILED_CONNECTIONS = "numfailed";
+
         /**
          * default value for {@link #COLUMN_LAST_UPDATESRC}.
          * This value is used when this column's value is not relevant.
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 30a8626..f52b5e3 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -479,6 +479,7 @@
     }
 
     private final Context mContext;
+    private Connection mConnectingServiceConnection;
     private Connection mServiceConnection;
     private OnInitListener mInitListener;
     // Written from an unspecified application thread, read from
@@ -554,21 +555,24 @@
         initTts();
     }
 
-    private <R> R runActionNoReconnect(Action<R> action, R errorResult, String method) {
-        return runAction(action, errorResult, method, false);
+    private <R> R runActionNoReconnect(Action<R> action, R errorResult, String method,
+            boolean onlyEstablishedConnection) {
+        return runAction(action, errorResult, method, false, onlyEstablishedConnection);
     }
 
     private <R> R runAction(Action<R> action, R errorResult, String method) {
-        return runAction(action, errorResult, method, true);
+        return runAction(action, errorResult, method, true, true);
     }
 
-    private <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
+    private <R> R runAction(Action<R> action, R errorResult, String method,
+            boolean reconnect, boolean onlyEstablishedConnection) {
         synchronized (mStartLock) {
             if (mServiceConnection == null) {
                 Log.w(TAG, method + " failed: not bound to TTS engine");
                 return errorResult;
             }
-            return mServiceConnection.runAction(action, errorResult, method, reconnect);
+            return mServiceConnection.runAction(action, errorResult, method, reconnect,
+                    onlyEstablishedConnection);
         }
     }
 
@@ -631,6 +635,7 @@
             return false;
         } else {
             Log.i(TAG, "Sucessfully bound to " + engine);
+            mConnectingServiceConnection = connection;
             return true;
         }
     }
@@ -654,6 +659,16 @@
      * so the TextToSpeech engine can be cleanly stopped.
      */
     public void shutdown() {
+        // Special case, we are asked to shutdown connection that did finalize its connection.
+        synchronized (mStartLock) {
+            if (mConnectingServiceConnection != null) {
+                mContext.unbindService(mConnectingServiceConnection);
+                mConnectingServiceConnection = null;
+                return;
+            }
+        }
+
+        // Post connection case
         runActionNoReconnect(new Action<Void>() {
             @Override
             public Void run(ITextToSpeechService service) throws RemoteException {
@@ -671,7 +686,7 @@
                 mCurrentEngine = null;
                 return null;
             }
-        }, null, "shutdown");
+        }, null, "shutdown", false);
     }
 
     /**
@@ -1310,7 +1325,9 @@
     private class Connection implements ServiceConnection {
         private ITextToSpeechService mService;
 
-        private OnServiceConnectedAsyncTask mOnServiceConnectedAsyncTask;
+        private SetupConnectionAsyncTask mOnSetupConnectionAsyncTask;
+
+        private boolean mEstablished;
 
         private final ITextToSpeechCallback.Stub mCallback = new ITextToSpeechCallback.Stub() {
             @Override
@@ -1338,13 +1355,11 @@
             }
         };
 
-        private class OnServiceConnectedAsyncTask extends AsyncTask<Void, Void, Integer> {
+        private class SetupConnectionAsyncTask extends AsyncTask<Void, Void, Integer> {
             private final ComponentName mName;
-            private final ITextToSpeechService mConnectedService;
 
-            public OnServiceConnectedAsyncTask(ComponentName name, IBinder service) {
+            public SetupConnectionAsyncTask(ComponentName name) {
                 mName = name;
-                mConnectedService = ITextToSpeechService.Stub.asInterface(service);
             }
 
             @Override
@@ -1355,8 +1370,8 @@
                     }
 
                     try {
-                        mConnectedService.setCallback(getCallerIdentity(), mCallback);
-                        String[] defaultLanguage = mConnectedService.getClientDefaultLanguage();
+                        mService.setCallback(getCallerIdentity(), mCallback);
+                        String[] defaultLanguage = mService.getClientDefaultLanguage();
 
                         mParams.putString(Engine.KEY_PARAM_LANGUAGE, defaultLanguage[0]);
                         mParams.putString(Engine.KEY_PARAM_COUNTRY, defaultLanguage[1]);
@@ -1374,13 +1389,10 @@
             @Override
             protected void onPostExecute(Integer result) {
                 synchronized(mStartLock) {
-                    if (mOnServiceConnectedAsyncTask == this) {
-                        mOnServiceConnectedAsyncTask = null;
+                    if (mOnSetupConnectionAsyncTask == this) {
+                        mOnSetupConnectionAsyncTask = null;
                     }
-
-                    mServiceConnection = Connection.this;
-                    mService = mConnectedService;
-
+                    mEstablished = true;
                     dispatchOnInit(result);
                 }
             }
@@ -1389,14 +1401,20 @@
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized(mStartLock) {
+                mConnectingServiceConnection = null;
+
                 Log.i(TAG, "Connected to " + name);
 
-                if (mOnServiceConnectedAsyncTask != null) {
-                    mOnServiceConnectedAsyncTask.cancel(false);
+                if (mOnSetupConnectionAsyncTask != null) {
+                    mOnSetupConnectionAsyncTask.cancel(false);
                 }
 
-                mOnServiceConnectedAsyncTask = new OnServiceConnectedAsyncTask(name, service);
-                mOnServiceConnectedAsyncTask.execute();
+                mService = ITextToSpeechService.Stub.asInterface(service);
+                mServiceConnection = Connection.this;
+
+                mEstablished = false;
+                mOnSetupConnectionAsyncTask = new SetupConnectionAsyncTask(name);
+                mOnSetupConnectionAsyncTask.execute();
             }
         }
 
@@ -1407,14 +1425,14 @@
         /**
          * Clear connection related fields and cancel mOnServiceConnectedAsyncTask if set.
          *
-         * @return true if we cancel mOnServiceConnectedAsyncTask in progress.
+         * @return true if we cancel mOnSetupConnectionAsyncTask in progress.
          */
         private boolean clearServiceConnection() {
             synchronized(mStartLock) {
                 boolean result = false;
-                if (mOnServiceConnectedAsyncTask != null) {
-                    result = mOnServiceConnectedAsyncTask.cancel(false);
-                    mOnServiceConnectedAsyncTask = null;
+                if (mOnSetupConnectionAsyncTask != null) {
+                    result = mOnSetupConnectionAsyncTask.cancel(false);
+                    mOnSetupConnectionAsyncTask = null;
                 }
 
                 mService = null;
@@ -1445,13 +1463,22 @@
             clearServiceConnection();
         }
 
-        public <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
+        public boolean isEstablished() {
+            return mService != null && mEstablished;
+        }
+
+        public <R> R runAction(Action<R> action, R errorResult, String method,
+                boolean reconnect, boolean onlyEstablishedConnection) {
             synchronized (mStartLock) {
                 try {
                     if (mService == null) {
                         Log.w(TAG, method + " failed: not connected to TTS engine");
                         return errorResult;
                     }
+                    if (onlyEstablishedConnection && !isEstablished()) {
+                        Log.w(TAG, method + " failed: TTS engine connection not fully set up");
+                        return errorResult;
+                    }
                     return action.run(mService);
                 } catch (RemoteException ex) {
                     Log.e(TAG, method + " failed", ex);
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
new file mode 100644
index 0000000..34b6126
--- /dev/null
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2007 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.util;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+
+/**
+ * Map of {@code long} to {@code long}. Unlike a normal array of longs, there
+ * can be gaps in the indices. It is intended to be more efficient than using a
+ * {@code HashMap}.
+ *
+ * @hide
+ */
+public class LongSparseLongArray implements Cloneable {
+    private long[] mKeys;
+    private long[] mValues;
+    private int mSize;
+
+    /**
+     * Creates a new SparseLongArray containing no mappings.
+     */
+    public LongSparseLongArray() {
+        this(10);
+    }
+
+    /**
+     * Creates a new SparseLongArray containing no mappings that will not
+     * require any additional memory allocation to store the specified
+     * number of mappings.
+     */
+    public LongSparseLongArray(int initialCapacity) {
+        initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
+
+        mKeys = new long[initialCapacity];
+        mValues = new long[initialCapacity];
+        mSize = 0;
+    }
+
+    @Override
+    public LongSparseLongArray clone() {
+        LongSparseLongArray clone = null;
+        try {
+            clone = (LongSparseLongArray) super.clone();
+            clone.mKeys = mKeys.clone();
+            clone.mValues = mValues.clone();
+        } catch (CloneNotSupportedException cnse) {
+            /* ignore */
+        }
+        return clone;
+    }
+
+    /**
+     * Gets the long mapped from the specified key, or <code>0</code>
+     * if no such mapping has been made.
+     */
+    public long get(long key) {
+        return get(key, 0);
+    }
+
+    /**
+     * Gets the long mapped from the specified key, or the specified value
+     * if no such mapping has been made.
+     */
+    public long get(long key, long valueIfKeyNotFound) {
+        int i = Arrays.binarySearch(mKeys, 0, mSize, key);
+
+        if (i < 0) {
+            return valueIfKeyNotFound;
+        } else {
+            return mValues[i];
+        }
+    }
+
+    /**
+     * Removes the mapping from the specified key, if there was any.
+     */
+    public void delete(long key) {
+        int i = Arrays.binarySearch(mKeys, 0, mSize, key);
+
+        if (i >= 0) {
+            removeAt(i);
+        }
+    }
+
+    /**
+     * Removes the mapping at the given index.
+     */
+    public void removeAt(int index) {
+        System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
+        System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1));
+        mSize--;
+    }
+
+    /**
+     * Adds a mapping from the specified key to the specified value,
+     * replacing the previous mapping from the specified key if there
+     * was one.
+     */
+    public void put(long key, long value) {
+        int i = Arrays.binarySearch(mKeys, 0, mSize, key);
+
+        if (i >= 0) {
+            mValues[i] = value;
+        } else {
+            i = ~i;
+
+            if (mSize >= mKeys.length) {
+                growKeyAndValueArrays(mSize + 1);
+            }
+
+            if (mSize - i != 0) {
+                System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
+                System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
+            }
+
+            mKeys[i] = key;
+            mValues[i] = value;
+            mSize++;
+        }
+    }
+
+    /**
+     * Returns the number of key-value mappings that this SparseIntArray
+     * currently stores.
+     */
+    public int size() {
+        return mSize;
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the key from the <code>index</code>th key-value mapping that this
+     * SparseLongArray stores.
+     */
+    public long keyAt(int index) {
+        return mKeys[index];
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the value from the <code>index</code>th key-value mapping that this
+     * SparseLongArray stores.
+     */
+    public long valueAt(int index) {
+        return mValues[index];
+    }
+
+    /**
+     * Returns the index for which {@link #keyAt} would return the
+     * specified key, or a negative number if the specified
+     * key is not mapped.
+     */
+    public int indexOfKey(long key) {
+        return Arrays.binarySearch(mKeys, 0, mSize, key);
+    }
+
+    /**
+     * Returns an index for which {@link #valueAt} would return the
+     * specified key, or a negative number if no keys map to the
+     * specified value.
+     * Beware that this is a linear search, unlike lookups by key,
+     * and that multiple keys can map to the same value and this will
+     * find only one of them.
+     */
+    public int indexOfValue(long value) {
+        for (int i = 0; i < mSize; i++)
+            if (mValues[i] == value)
+                return i;
+
+        return -1;
+    }
+
+    /**
+     * Removes all key-value mappings from this SparseIntArray.
+     */
+    public void clear() {
+        mSize = 0;
+    }
+
+    /**
+     * Puts a key/value pair into the array, optimizing for the case where
+     * the key is greater than all existing keys in the array.
+     */
+    public void append(long key, long value) {
+        if (mSize != 0 && key <= mKeys[mSize - 1]) {
+            put(key, value);
+            return;
+        }
+
+        int pos = mSize;
+        if (pos >= mKeys.length) {
+            growKeyAndValueArrays(pos + 1);
+        }
+
+        mKeys[pos] = key;
+        mValues[pos] = value;
+        mSize = pos + 1;
+    }
+
+    private void growKeyAndValueArrays(int minNeededSize) {
+        int n = ArrayUtils.idealLongArraySize(minNeededSize);
+
+        long[] nkeys = new long[n];
+        long[] nvalues = new long[n];
+
+        System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
+        System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
+
+        mKeys = nkeys;
+        mValues = nvalues;
+    }
+}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 0d45bbc..2b4260d 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -173,17 +173,6 @@
     public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw";
 
     /**
-     * Turn on to allow region clipping (see
-     * {@link android.graphics.Canvas#clipPath(android.graphics.Path)} and
-     * {@link android.graphics.Canvas#clipRegion(android.graphics.Region)}.
-     *
-     * When this option is turned on a stencil buffer is always required.
-     * If this option is off a stencil buffer is only created when the overdraw
-     * debugging mode is turned on.
-     */
-    private static final boolean REGION_CLIPPING_ENABLED = false;
-
-    /**
      * A process can set this flag to false to prevent the use of hardware
      * rendering.
      * 
@@ -885,15 +874,6 @@
             if (value != mShowOverdraw) {
                 changed = true;
                 mShowOverdraw = value;
-
-                if (!REGION_CLIPPING_ENABLED) {
-                    if (surface != null && isEnabled()) {
-                        if (validate()) {
-                            sEglConfig = loadEglConfig();
-                            invalidate(surface);
-                        }
-                    }
-                }
             }
 
             if (nLoadProperties()) {
@@ -1764,9 +1744,8 @@
 
         @Override
         int[] getConfig(boolean dirtyRegions) {
-            //noinspection PointlessBooleanExpression
-            final int stencilSize = mShowOverdraw || REGION_CLIPPING_ENABLED ?
-                    GLES20Canvas.getStencilSize() : 0;
+            //noinspection PointlessBooleanExpression,ConstantConditions
+            final int stencilSize = GLES20Canvas.getStencilSize();
             final int swapBehavior = dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
 
             return new int[] {
diff --git a/core/java/android/view/SimulatedTrackball.java b/core/java/android/view/SimulatedDpad.java
similarity index 83%
rename from core/java/android/view/SimulatedTrackball.java
rename to core/java/android/view/SimulatedDpad.java
index 4ab557a..1ee416c 100644
--- a/core/java/android/view/SimulatedTrackball.java
+++ b/core/java/android/view/SimulatedDpad.java
@@ -28,15 +28,15 @@
 import android.util.Log;
 
 /**
- * This class creates trackball events from touchpad events.
+ * This class creates DPAD events from touchpad events.
  * 
  * @see ViewRootImpl
  */
 
 //TODO: Make this class an internal class of ViewRootImpl.java
-class SimulatedTrackball {
+class SimulatedDpad {
 
-    private static final String TAG = "SimulatedTrackball";
+    private static final String TAG = "SimulatedDpad";
 
     // Maximum difference in milliseconds between the down and up of a touch
     // event for it to be considered a tap
@@ -97,7 +97,7 @@
     // How quickly the repeated events die off
     private float mFlickDecay;
 
-    public SimulatedTrackball(Context context) {
+    public SimulatedDpad(Context context) {
         mDistancePerTick = SystemProperties.getInt("persist.vr_dist_tick", 64);
         mDistancePerTickSquared = mDistancePerTick * mDistancePerTick;
         mMaxRepeatDelay = SystemProperties.getInt("persist.vr_repeat_delay", 300);
@@ -140,7 +140,11 @@
         }
     };
 
-    public void updateTrackballDirection(ViewRootImpl viewroot, MotionEvent event) {
+    public void updateTouchPad(ViewRootImpl viewroot, MotionEvent event,
+            boolean synthesizeNewKeys) {
+        if (!synthesizeNewKeys) {
+            mHandler.removeMessages(MSG_FLICK);
+        }
         // Store what time the touchpad event occurred
         final long time = SystemClock.uptimeMillis();
         switch (event.getAction()) {
@@ -159,8 +163,9 @@
                     mEdgeSwipePossible = true;
                 }
                 // Clear any flings
-                mHandler.removeMessages(MSG_FLICK);
-
+                if (synthesizeNewKeys) {
+                    mHandler.removeMessages(MSG_FLICK);
+                }
                 break;
             case MotionEvent.ACTION_MOVE:
                 // Determine whether the move is slop or an intentional move
@@ -177,7 +182,7 @@
 
                     Intent intent =
                             ((SearchManager)mContext.getSystemService(Context.SEARCH_SERVICE))
-                            .getAssistIntent(mContext, UserHandle.USER_CURRENT_OR_SELF);
+                            .getAssistIntent(mContext, false, UserHandle.USER_CURRENT_OR_SELF);
                     if (intent != null) {
                         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                         try {
@@ -226,12 +231,16 @@
                     while (dominantAxis * dominantAxis > mDistancePerTickSquared) {
                         repeatCount++;
                         dominantAxis -= sign * mDistancePerTick;
-                        viewroot.enqueueInputEvent(new KeyEvent(time, time,
-                                KeyEvent.ACTION_DOWN, key, 0, event.getMetaState(),
-                                event.getDeviceId(), 0, KeyEvent.FLAG_FALLBACK, event.getSource()));
-                        viewroot.enqueueInputEvent(new KeyEvent(time, time,
-                                KeyEvent.ACTION_UP, key, 0, event.getMetaState(),
-                                event.getDeviceId(), 0, KeyEvent.FLAG_FALLBACK, event.getSource()));
+                        if (synthesizeNewKeys) {
+                            viewroot.enqueueInputEvent(new KeyEvent(time, time,
+                                    KeyEvent.ACTION_DOWN, key, 0, event.getMetaState(),
+                                    event.getDeviceId(), 0, KeyEvent.FLAG_FALLBACK,
+                                    event.getSource()));
+                            viewroot.enqueueInputEvent(new KeyEvent(time, time,
+                                    KeyEvent.ACTION_UP, key, 0, event.getMetaState(),
+                                    event.getDeviceId(), 0, KeyEvent.FLAG_FALLBACK,
+                                    event.getSource()));
+                        }
                     }
                     // Save new axis values
                     mAccumulatedX = isXAxis ? dominantAxis : 0;
@@ -244,18 +253,16 @@
                 break;
             case MotionEvent.ACTION_UP:
                 if (time - mLastTouchPadStartTimeMs < MAX_TAP_TIME && mAlwaysInTapRegion) {
-                    // Trackball Down
-                    MotionEvent trackballEvent = MotionEvent.obtain(mLastTouchPadStartTimeMs, time,
-                            MotionEvent.ACTION_DOWN, 0, 0, 0, 0, event.getMetaState(),
-                            10f, 10f, event.getDeviceId(), 0);
-                    trackballEvent.setSource(InputDevice.SOURCE_TRACKBALL);
-                    viewroot.enqueueInputEvent(trackballEvent);
-                    // Trackball Release
-                    trackballEvent = MotionEvent.obtain(mLastTouchPadStartTimeMs, time,
-                            MotionEvent.ACTION_UP, 0, 0, 0, 0, event.getMetaState(),
-                            10f, 10f, event.getDeviceId(), 0);
-                    trackballEvent.setSource(InputDevice.SOURCE_TRACKBALL);
-                    viewroot.enqueueInputEvent(trackballEvent);
+                    if (synthesizeNewKeys) {
+                        viewroot.enqueueInputEvent(new KeyEvent(mLastTouchPadStartTimeMs, time,
+                                KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0,
+                                event.getMetaState(), event.getDeviceId(), 0,
+                                KeyEvent.FLAG_FALLBACK, event.getSource()));
+                        viewroot.enqueueInputEvent(new KeyEvent(mLastTouchPadStartTimeMs, time,
+                                KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0,
+                                event.getMetaState(), event.getDeviceId(), 0,
+                                KeyEvent.FLAG_FALLBACK, event.getSource()));
+                    }
                 } else {
                     float xMoveSquared = mLastMoveX * mLastMoveX;
                     float yMoveSquared = mLastMoveY * mLastMoveY;
@@ -267,10 +274,12 @@
                         mLastSource = event.getSource();
                         mLastMetaState = event.getMetaState();
 
-                        Message message = Message.obtain(mHandler, MSG_FLICK,
-                                mKeySendRateMs, mLastKeySent, viewroot);
-                        message.setAsynchronous(true);
-                        mHandler.sendMessageDelayed(message, mKeySendRateMs);
+                        if (synthesizeNewKeys) {
+                            Message message = Message.obtain(mHandler, MSG_FLICK,
+                                    mKeySendRateMs, mLastKeySent, viewroot);
+                            message.setAsynchronous(true);
+                            mHandler.sendMessageDelayed(message, mKeySendRateMs);
+                        }
                     }
                 }
                 mEdgeSwipePossible = false;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1ae69fea..3faac40 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -144,7 +144,7 @@
     final TrackballAxis mTrackballAxisX = new TrackballAxis();
     final TrackballAxis mTrackballAxisY = new TrackballAxis();
 
-    final SimulatedTrackball mSimulatedTrackball;
+    final SimulatedDpad mSimulatedDpad;
 
     int mLastJoystickXDirection;
     int mLastJoystickYDirection;
@@ -391,7 +391,7 @@
         PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mAttachInfo.mScreenOn = powerManager.isScreenOn();
         loadSystemProperties();
-        mSimulatedTrackball = new SimulatedTrackball(context);
+        mSimulatedDpad = new SimulatedDpad(context);
     }
 
     /**
@@ -3535,8 +3535,7 @@
             if (isJoystick) {
                 updateJoystickDirection(event, false);
             } else if (isTouchPad) {
-              //Convert TouchPad motion into a TrackBall event
-              mSimulatedTrackball.updateTrackballDirection(this, event);
+              mSimulatedDpad.updateTouchPad(this, event, false);
             }
             return EVENT_NOT_HANDLED;
         }
@@ -3546,8 +3545,7 @@
             if (isJoystick) {
                 updateJoystickDirection(event, false);
             } else if (isTouchPad) {
-              //Convert TouchPad motion into a TrackBall event
-              mSimulatedTrackball.updateTrackballDirection(this, event);
+              mSimulatedDpad.updateTouchPad(this, event, false);
             }
             return EVENT_HANDLED;
         }
@@ -3559,8 +3557,7 @@
             return EVENT_HANDLED;
         }
         if (isTouchPad) {
-            //Convert TouchPad motion into a TrackBall event
-            mSimulatedTrackball.updateTrackballDirection(this, event);
+            mSimulatedDpad.updateTouchPad(this, event, true);
             return EVENT_HANDLED;
         }
         return EVENT_NOT_HANDLED;
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 6fb8bdf..0b7e92f 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -56,8 +56,8 @@
 import java.util.Set;
 
 import org.apache.harmony.security.provider.cert.X509CertImpl;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKeyHolder;
 
 class BrowserFrame extends Handler {
 
@@ -1127,13 +1127,10 @@
         if (table.IsAllowed(hostAndPort)) {
             // previously allowed
             PrivateKey pkey = table.PrivateKey(hostAndPort);
-            if (pkey instanceof OpenSSLRSAPrivateKey) {
+            if (pkey instanceof OpenSSLKeyHolder) {
+                OpenSSLKey sslKey = ((OpenSSLKeyHolder) pkey).getOpenSSLKey();
                 nativeSslClientCert(handle,
-                                    ((OpenSSLRSAPrivateKey)pkey).getPkeyContext(),
-                                    table.CertificateChain(hostAndPort));
-            } else if (pkey instanceof OpenSSLDSAPrivateKey) {
-                nativeSslClientCert(handle,
-                                    ((OpenSSLDSAPrivateKey)pkey).getPkeyContext(),
+                                    sslKey.getPkeyContext(),
                                     table.CertificateChain(hostAndPort));
             } else {
                 nativeSslClientCert(handle,
diff --git a/core/java/android/webkit/ClientCertRequestHandler.java b/core/java/android/webkit/ClientCertRequestHandler.java
index 6570a9b8..dac1510 100644
--- a/core/java/android/webkit/ClientCertRequestHandler.java
+++ b/core/java/android/webkit/ClientCertRequestHandler.java
@@ -21,8 +21,8 @@
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import org.apache.harmony.xnet.provider.jsse.NativeCrypto;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKeyHolder;
 
 /**
  * ClientCertRequestHandler: class responsible for handling client
@@ -56,14 +56,11 @@
             byte[][] chainBytes = NativeCrypto.encodeCertificates(chain);
             mTable.Allow(mHostAndPort, privateKey, chainBytes);
 
-            if (privateKey instanceof OpenSSLRSAPrivateKey) {
-                setSslClientCertFromCtx(((OpenSSLRSAPrivateKey)privateKey).getPkeyContext(),
-                           chainBytes);
-            } else if (privateKey instanceof OpenSSLDSAPrivateKey) {
-                setSslClientCertFromCtx(((OpenSSLDSAPrivateKey)privateKey).getPkeyContext(),
-                           chainBytes);
+            if (privateKey instanceof OpenSSLKeyHolder) {
+                OpenSSLKey pkey = ((OpenSSLKeyHolder) privateKey).getOpenSSLKey();
+                setSslClientCertFromCtx(pkey.getPkeyContext(), chainBytes);
             } else {
-                setSslClientCertFromPKCS8(privateKey.getEncoded(),chainBytes);
+                setSslClientCertFromPKCS8(privateKey.getEncoded(), chainBytes);
             }
         } catch (CertificateEncodingException e) {
             post(new Runnable() {
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 1a4ccfa..c68b450 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -33,12 +33,15 @@
 import android.widget.EditText;
 import android.widget.TextView;
 
-class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
-        View.OnClickListener {
+/**
+ * @hide
+ */
+public class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
+        View.OnClickListener, WebView.FindListener {
     private View mCustomView;
     private EditText mEditText;
     private TextView mMatches;
-    private WebViewClassic mWebView;
+    private WebView mWebView;
     private InputMethodManager mInput;
     private Resources mResources;
     private boolean mMatchesFound;
@@ -46,7 +49,7 @@
     private int mActiveMatchIndex;
     private ActionMode mActionMode;
 
-    FindActionModeCallback(Context context) {
+    public FindActionModeCallback(Context context) {
         mCustomView = LayoutInflater.from(context).inflate(
                 com.android.internal.R.layout.webview_find, null);
         mEditText = (EditText) mCustomView.findViewById(
@@ -61,7 +64,7 @@
         mResources = context.getResources();
     }
 
-    void finish() {
+    public void finish() {
         mActionMode.finish();
     }
 
@@ -69,7 +72,7 @@
      * Place text in the text field so it can be searched for.  Need to press
      * the find next or find previous button to find all of the matches.
      */
-    void setText(String text) {
+    public void setText(String text) {
         mEditText.setText(text);
         Spannable span = (Spannable) mEditText.getText();
         int length = span.length();
@@ -84,15 +87,23 @@
     }
 
     /*
-     * Set the WebView to search.  Must be non null, and set before calling
-     * startActionMode.
+     * Set the WebView to search.  Must be non null.
      */
-    void setWebView(WebViewClassic webView) {
+    public void setWebView(WebView webView) {
         if (null == webView) {
             throw new AssertionError("WebView supplied to "
                     + "FindActionModeCallback cannot be null");
         }
         mWebView = webView;
+        mWebView.setFindDialogFindListener(this);
+    }
+
+    @Override
+    public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
+            boolean isDoneCounting) {
+        if (isDoneCounting) {
+            updateMatchCount(activeMatchOrdinal, numberOfMatches, numberOfMatches == 0);
+        }
     }
 
     /*
@@ -121,7 +132,7 @@
     /*
      * Highlight all the instances of the string from mEditText in mWebView.
      */
-    void findAll() {
+    public void findAll() {
         if (mWebView == null) {
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::findAll");
@@ -152,7 +163,7 @@
             mActiveMatchIndex = matchIndex;
             updateMatchesString();
         } else {
-            mMatches.setVisibility(View.INVISIBLE);
+            mMatches.setVisibility(View.GONE);
             mNumberOfMatches = 0;
         }
     }
@@ -208,7 +219,8 @@
     public void onDestroyActionMode(ActionMode mode) {
         mActionMode = null;
         mWebView.notifyFindDialogDismissed();
-        mInput.hideSoftInputFromWindow(mWebView.getWebView().getWindowToken(), 0);
+        mWebView.setFindDialogFindListener(null);
+        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
     }
 
     @Override
@@ -222,7 +234,7 @@
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::onActionItemClicked");
         }
-        mInput.hideSoftInputFromWindow(mWebView.getWebView().getWindowToken(), 0);
+        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
         switch(item.getItemId()) {
             case com.android.internal.R.id.find_prev:
                 findNext(false);
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index 096d4cda..1d44b96 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -31,7 +31,8 @@
 
     private static final int WORKING_STREAM_STORAGE = 16 * 1024;
 
-    static final int VERSION = 1;
+    // VERSION = 1 was for pictures encoded using a previous copy of libskia
+    static final int VERSION = 2;
 
     static boolean serializeViewState(OutputStream stream, DrawData draw)
             throws IOException {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1abea2b..5412400 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1329,7 +1329,8 @@
      */
     public void setFindListener(FindListener listener) {
         checkThread();
-        mProvider.setFindListener(listener);
+        setupFindListenerIfNeeded();
+        mFindListener.mUserFindListener = listener;
     }
 
     /**
@@ -1850,11 +1851,60 @@
     }
 
     //-------------------------------------------------------------------------
+    // Package-private internal stuff
+    //-------------------------------------------------------------------------
+
+    // Only used by android.webkit.FindActionModeCallback.
+    void setFindDialogFindListener(FindListener listener) {
+        checkThread();
+        setupFindListenerIfNeeded();
+        mFindListener.mFindDialogFindListener = listener;
+    }
+
+    // Only used by android.webkit.FindActionModeCallback.
+    void notifyFindDialogDismissed() {
+        checkThread();
+        mProvider.notifyFindDialogDismissed();
+    }
+
+    //-------------------------------------------------------------------------
     // Private internal stuff
     //-------------------------------------------------------------------------
 
     private WebViewProvider mProvider;
 
+    /**
+     * In addition to the FindListener that the user may set via the WebView.setFindListener
+     * API, FindActionModeCallback will register it's own FindListener. We keep them separate
+     * via this class so that that the two FindListeners can potentially exist at once.
+     */
+    private class FindListenerDistributor implements FindListener {
+        private FindListener mFindDialogFindListener;
+        private FindListener mUserFindListener;
+
+        @Override
+        public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
+                boolean isDoneCounting) {
+            if (mFindDialogFindListener != null) {
+                mFindDialogFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
+                        isDoneCounting);
+            }
+
+            if (mUserFindListener != null) {
+                mUserFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
+                        isDoneCounting);
+            }
+        }
+    }
+    private FindListenerDistributor mFindListener;
+
+    private void setupFindListenerIfNeeded() {
+        if (mFindListener == null) {
+            mFindListener = new FindListenerDistributor();
+            mProvider.setFindListener(mFindListener);
+        }
+    }
+
     private void ensureProviderCreated() {
         checkThread();
         if (mProvider == null) {
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 9a83964..a867d39 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -3668,7 +3668,7 @@
         mCachedOverlappingActionModeHeight = -1;
         mFindCallback = callback;
         setFindIsUp(true);
-        mFindCallback.setWebView(this);
+        mFindCallback.setWebView(getWebView());
         if (showIme) {
             mFindCallback.showSoftInput();
         } else if (text != null) {
@@ -3770,7 +3770,8 @@
     /**
      * Called when the find ActionMode ends.
      */
-    void notifyFindDialogDismissed() {
+    @Override
+    public void notifyFindDialogDismissed() {
         mFindCallback = null;
         mCachedOverlappingActionModeHeight = -1;
         if (mWebViewCore == null) {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 1020634..fa17ab9 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -240,7 +240,7 @@
     public View findHierarchyView(String className, int hashCode);
 
     //-------------------------------------------------------------------------
-    // Provider glue methods
+    // Provider internal methods
     //-------------------------------------------------------------------------
 
     /**
@@ -255,6 +255,12 @@
      */
     /* package */ ScrollDelegate getScrollDelegate();
 
+    /**
+     * Only used by FindActionModeCallback to inform providers that the find dialog has
+     * been dismissed.
+     */
+    public void notifyFindDialogDismissed();
+
     //-------------------------------------------------------------------------
     // View / ViewGroup delegation methods
     //-------------------------------------------------------------------------
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index e749e63..2b7e162 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -444,21 +444,14 @@
         // We need to know our size for doing the correct computation of positioning in RTL mode
         if (isLayoutRtl() && (myWidth == -1 || isWrapContentWidth)) {
             int w = getPaddingStart() + getPaddingEnd();
-            final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
             for (int i = 0; i < count; i++) {
                 View child = views[i];
                 if (child.getVisibility() != GONE) {
                     LayoutParams params = (LayoutParams) child.getLayoutParams();
-                    // Would be similar to a call to measureChildHorizontal(child, params, -1, myHeight)
-                    // but we cannot change for now the behavior of measureChildHorizontal() for
-                    // taking care or a "-1" for "mywidth" so use here our own version of that code.
-                    int childHeightMeasureSpec;
-                    if (params.width == LayoutParams.MATCH_PARENT) {
-                        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY);
-                    } else {
-                        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST);
-                    }
-                    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+                    int[] rules = params.getRules(View.LAYOUT_DIRECTION_LTR);
+
+                    applyHorizontalSizeRules(params, myWidth, rules);
+                    measureChildHorizontal(child, params, -1, myHeight);
 
                     w += child.getMeasuredWidth();
                     w += params.leftMargin + params.rightMargin;
@@ -476,13 +469,16 @@
             }
         }
 
+        final int layoutDirection = getLayoutDirection();
         for (int i = 0; i < count; i++) {
             View child = views[i];
             if (child.getVisibility() != GONE) {
                 LayoutParams params = (LayoutParams) child.getLayoutParams();
+                int[] rules = params.getRules(layoutDirection);
 
-                applyHorizontalSizeRules(params, myWidth);
+                applyHorizontalSizeRules(params, myWidth, rules);
                 measureChildHorizontal(child, params, myWidth, myHeight);
+
                 if (positionChildHorizontal(child, params, myWidth, isWrapContentWidth)) {
                     offsetHorizontalAxis = true;
                 }
@@ -543,8 +539,6 @@
             }
         }
 
-        final int layoutDirection = getLayoutDirection();
-
         if (isWrapContentWidth) {
             // Width already has left padding in it since it was calculated by looking at
             // the right of each child view
@@ -862,9 +856,7 @@
         return rules[ALIGN_PARENT_BOTTOM] != 0;
     }
 
-    private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) {
-        final int layoutDirection = getLayoutDirection();
-        int[] rules = childParams.getRules(layoutDirection);
+    private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth, int[] rules) {
         RelativeLayout.LayoutParams anchorParams;
 
         // -1 indicated a "soft requirement" in that direction. For example:
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 46478ca..f041f07 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -801,6 +801,11 @@
         return mThemedContext;
     }
     
+    @Override
+    public boolean isTitleTruncated() {
+        return mActionView != null && mActionView.isTitleTruncated();
+    }
+
     /**
      * @hide 
      */
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 827dba6..c4f1bc48 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -20,6 +20,8 @@
 
 interface IAppOpsService {
     List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
+    List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
+    void setMode(int code, int uid, String packageName, int mode);
     int checkOperation(int code, int uid, String packageName);
     int noteOperation(int code, int uid, String packageName);
     int startOperation(int code, int uid, String packageName);
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 20ecace..424c19b 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -153,8 +153,33 @@
 
     public void onPackageUpdateFinished(String packageName, int uid) {
     }
-    
-    public void onPackageChanged(String packageName, int uid, String[] components) {
+
+    /**
+     * Direct reflection of {@link Intent#ACTION_PACKAGE_CHANGED
+     * Intent.ACTION_PACKAGE_CHANGED} being received, informing you of
+     * changes to the enabled/disabled state of components in a package
+     * and/or of the overall package.
+     *
+     * @param packageName The name of the package that is changing.
+     * @param uid The user ID the package runs under.
+     * @param components Any components in the package that are changing.  If
+     * the overall package is changing, this will contain an entry of the
+     * package name itself.
+     * @return Return true to indicate you care about this change, which will
+     * result in {@link #onSomePackagesChanged()} being called later.  If you
+     * return false, no further callbacks will happen about this change.  The
+     * default implementation returns true if this is a change to the entire
+     * package.
+     */
+    public boolean onPackageChanged(String packageName, int uid, String[] components) {
+        if (components != null) {
+            for (String name : components) {
+                if (packageName.equals(name)) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
     
     public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
@@ -189,7 +214,10 @@
      */
     public void onPackageAppeared(String packageName, int reason) {
     }
-    
+
+    /**
+     * Called when an existing package is updated or its disabled state changes.
+     */
     public void onPackageModified(String packageName) {
     }
     
@@ -328,9 +356,10 @@
             if (pkg != null) {
                 mModifiedPackages = mTempArray;
                 mTempArray[0] = pkg;
-                onPackageChanged(pkg, uid, components);
-                // XXX Don't want this to always cause mSomePackagesChanged,
-                // since it can happen a fair amount.
+                mChangeType = PACKAGE_PERMANENT_CHANGE;
+                if (onPackageChanged(pkg, uid, components)) {
+                    mSomePackagesChanged = true;
+                }
                 onPackageModified(pkg);
             }
         } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 4d41e42..3d7e1ff 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -536,7 +536,7 @@
             }
         }
 
-        private String getEnabledInputMethodsStr() {
+        public String getEnabledInputMethodsStr() {
             mEnabledInputMethodsStrCache = Settings.Secure.getStringForUser(
                     mResolver, Settings.Secure.ENABLED_INPUT_METHODS, mCurrentUserId);
             if (DEBUG) {
diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
index df0fcd9..6429aa4 100644
--- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java
+++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
@@ -106,7 +106,7 @@
         }
 
         ThreadGroup group = Thread.currentThread().getThreadGroup();
-        SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupTheadSet(group);
+        SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupThreadSet(group);
         samplingProfiler = new SamplingProfiler(samplingProfilerDepth, threadSet);
         samplingProfiler.start(samplingProfilerMilliseconds);
         startMillis = System.currentTimeMillis();
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 8ccc612..560227d 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -40,6 +40,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.Layout;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -49,7 +50,6 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
-import android.view.TouchDelegate;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
@@ -83,7 +83,8 @@
             ActionBar.DISPLAY_USE_LOGO |
             ActionBar.DISPLAY_HOME_AS_UP |
             ActionBar.DISPLAY_SHOW_CUSTOM |
-            ActionBar.DISPLAY_SHOW_TITLE;
+            ActionBar.DISPLAY_SHOW_TITLE |
+            ActionBar.DISPLAY_TITLE_MULTIPLE_LINES;
 
     private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
     
@@ -100,6 +101,7 @@
     private TextView mTitleView;
     private TextView mSubtitleView;
     private View mTitleUpView;
+    private ViewGroup mUpGoerFive;
 
     private Spinner mSpinner;
     private LinearLayout mListNavLayout;
@@ -137,10 +139,6 @@
 
     Window.Callback mWindowCallback;
 
-    private final Rect mTempRect = new Rect();
-    private int mMaxHomeSlop;
-    private static final int MAX_HOME_SLOP = 32; // dp
-
     private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
             new AdapterView.OnItemSelectedListener() {
         public void onItemSelected(AdapterView parent, View view, int position, long id) {
@@ -219,9 +217,11 @@
                 com.android.internal.R.styleable.ActionBar_homeLayout,
                 com.android.internal.R.layout.action_bar_home);
 
-        mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+        mUpGoerFive = (ViewGroup) inflater.inflate(
+                com.android.internal.R.layout.action_bar_up_container, this, false);
+        mHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
 
-        mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+        mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
         mExpandedHomeLayout.setUp(true);
         mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
         mExpandedHomeLayout.setContentDescription(getResources().getText(
@@ -250,16 +250,14 @@
         a.recycle();
         
         mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
-        mHomeLayout.setOnClickListener(mUpClickListener);
-        mHomeLayout.setClickable(true);
-        mHomeLayout.setFocusable(true);
+
+        mUpGoerFive.setOnClickListener(mUpClickListener);
+        mUpGoerFive.setClickable(true);
+        mUpGoerFive.setFocusable(true);
 
         if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
-
-        mMaxHomeSlop =
-                (int) (MAX_HOME_SLOP * context.getResources().getDisplayMetrics().density + 0.5f);
     }
 
     @Override
@@ -269,8 +267,8 @@
         mTitleView = null;
         mSubtitleView = null;
         mTitleUpView = null;
-        if (mTitleLayout != null && mTitleLayout.getParent() == this) {
-            removeView(mTitleLayout);
+        if (mTitleLayout != null && mTitleLayout.getParent() == mUpGoerFive) {
+            mUpGoerFive.removeView(mTitleLayout);
         }
         mTitleLayout = null;
         if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
@@ -551,19 +549,19 @@
     }
 
     public void setHomeButtonEnabled(boolean enable) {
-        mHomeLayout.setEnabled(enable);
-        mHomeLayout.setFocusable(enable);
+        mUpGoerFive.setEnabled(enable);
+        mUpGoerFive.setFocusable(enable);
         // Make sure the home button has an accurate content description for accessibility.
         if (!enable) {
-            mHomeLayout.setContentDescription(null);
-            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+            mUpGoerFive.setContentDescription(null);
+            mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
         } else {
-            mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+            mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
             if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
-                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                mUpGoerFive.setContentDescription(mContext.getResources().getText(
                         R.string.action_bar_up_description));
             } else {
-                mHomeLayout.setContentDescription(mContext.getResources().getText(
+                mUpGoerFive.setContentDescription(mContext.getResources().getText(
                         R.string.action_bar_home_description));
             }
         }
@@ -600,7 +598,7 @@
                 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
                     initTitle();
                 } else {
-                    removeView(mTitleLayout);
+                    mUpGoerFive.removeView(mTitleLayout);
                 }
             }
 
@@ -608,8 +606,6 @@
                     (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
                 final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
                 mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
-                mTitleLayout.setEnabled(!showHome && homeAsUp);
-                mTitleLayout.setClickable(!showHome && homeAsUp);
             }
 
             if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
@@ -620,6 +616,17 @@
                 }
             }
             
+            if (mTitleLayout != null &&
+                    (flagsChanged & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
+                if ((options & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
+                    mTitleView.setSingleLine(false);
+                    mTitleView.setMaxLines(2);
+                } else {
+                    mTitleView.setMaxLines(1);
+                    mTitleView.setSingleLine(true);
+                }
+            }
+
             requestLayout();
         } else {
             invalidate();
@@ -754,7 +761,8 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        addView(mHomeLayout);
+        mUpGoerFive.addView(mHomeLayout, 0);
+        addView(mUpGoerFive);
 
         if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
             final ViewParent parent = mCustomNavView.getParent();
@@ -776,8 +784,6 @@
             mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
             mTitleUpView = (View) mTitleLayout.findViewById(R.id.up);
 
-            mTitleLayout.setOnClickListener(mUpClickListener);
-
             if (mTitleStyleRes != 0) {
                 mTitleView.setTextAppearance(mContext, mTitleStyleRes);
             }
@@ -797,11 +803,9 @@
             final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0;
             final boolean showTitleUp = !showHome;
             mTitleUpView.setVisibility(showTitleUp ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
-            mTitleLayout.setEnabled(homeAsUp && showTitleUp);
-            mTitleLayout.setClickable(homeAsUp && showTitleUp);
         }
 
-        addView(mTitleLayout);
+        mUpGoerFive.addView(mTitleLayout);
         if (mExpandedActionView != null ||
                 (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
             // Don't show while in expanded mode or with empty text
@@ -821,6 +825,28 @@
         return mIsCollapsed;
     }
 
+    /**
+     * @return True if any characters in the title were truncated
+     */
+    public boolean isTitleTruncated() {
+        if (mTitleView == null) {
+            return false;
+        }
+
+        final Layout titleLayout = mTitleView.getLayout();
+        if (titleLayout == null) {
+            return false;
+        }
+
+        final int lineCount = titleLayout.getLineCount();
+        for (int i = 0; i < lineCount; i++) {
+            if (titleLayout.getEllipsisCount(i) > 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int childCount = getChildCount();
@@ -829,7 +855,16 @@
             for (int i = 0; i < childCount; i++) {
                 final View child = getChildAt(i);
                 if (child.getVisibility() != GONE &&
-                        !(child == mMenuView && mMenuView.getChildCount() == 0)) {
+                        !(child == mMenuView && mMenuView.getChildCount() == 0) &&
+                        child != mUpGoerFive) {
+                    visibleChildren++;
+                }
+            }
+
+            final int upChildCount = mUpGoerFive.getChildCount();
+            for (int i = 0; i < upChildCount; i++) {
+                final View child = mUpGoerFive.getChildAt(i);
+                if (child.getVisibility() != GONE) {
                     visibleChildren++;
                 }
             }
@@ -873,7 +908,8 @@
 
         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
 
-        if (homeLayout.getVisibility() != GONE) {
+        int homeWidth = 0;
+        if (homeLayout.getVisibility() != GONE && homeLayout.getParent() == mUpGoerFive) {
             final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams();
             int homeWidthSpec;
             if (lp.width < 0) {
@@ -881,10 +917,18 @@
             } else {
                 homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
             }
+
+            /*
+             * This is a little weird.
+             * We're only measuring the *home* affordance within the Up container here
+             * on purpose, because we want to give the available space to all other views before
+             * the title text. We'll remeasure the whole up container again later.
+             */
             homeLayout.measure(homeWidthSpec, exactHeightSpec);
-            final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getStartOffset();
-            availableWidth = Math.max(0, availableWidth - homeWidth);
-            leftOfCenter = Math.max(0, availableWidth - homeWidth);
+            homeWidth = homeLayout.getMeasuredWidth();
+            final int homeOffsetWidth = homeWidth + homeLayout.getStartOffset();
+            availableWidth = Math.max(0, availableWidth - homeOffsetWidth);
+            leftOfCenter = Math.max(0, availableWidth - homeOffsetWidth);
         }
         
         if (mMenuView != null && mMenuView.getParent() == this) {
@@ -986,9 +1030,13 @@
             availableWidth -= horizontalMargin + customView.getMeasuredWidth();
         }
 
-        if (mExpandedActionView == null && showTitle) {
-            availableWidth = measureChildView(mTitleLayout, availableWidth,
-                    MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+        /*
+         * Measure the whole up container now, allowing for the full home+title sections.
+         * (This will re-measure the home view.)
+         */
+        availableWidth = measureChildView(mUpGoerFive, availableWidth + homeWidth,
+                MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+        if (mTitleLayout != null) {
             leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
         }
 
@@ -1035,25 +1083,17 @@
         final int y = getPaddingTop();
 
         HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
-        boolean needsTouchDelegate = false;
-        int homeSlop = mMaxHomeSlop;
-        int homeRight = 0;
-        if (homeLayout.getVisibility() != GONE) {
-            final int startOffset = homeLayout.getStartOffset();
-            x += positionChild(homeLayout,
-                            next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
-            x = next(x, startOffset, isLayoutRtl);
-            needsTouchDelegate = homeLayout == mHomeLayout;
-            homeRight = x;
-        }
+        final int startOffset = homeLayout.getVisibility() != GONE &&
+                homeLayout.getParent() == mUpGoerFive ? homeLayout.getStartOffset() : 0;
+
+        // Position the up container based on where the edge of the home layout should go.
+        x += positionChild(mUpGoerFive,
+                next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
+        x = next(x, startOffset, isLayoutRtl);
 
         if (mExpandedActionView == null) {
             final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
                     (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-            if (showTitle) {
-                x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
-                homeSlop = mTitleLayout.getWidth();
-            }
 
             switch (mNavigationMode) {
                 case ActionBar.NAVIGATION_MODE_STANDARD:
@@ -1063,7 +1103,6 @@
                         if (showTitle) {
                             x = next(x, mItemPadding, isLayoutRtl);
                         }
-                        homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
                         x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl);
                         x = next(x, mItemPadding, isLayoutRtl);
                     }
@@ -1071,7 +1110,6 @@
                 case ActionBar.NAVIGATION_MODE_TABS:
                     if (mTabScrollView != null) {
                         if (showTitle) x = next(x, mItemPadding, isLayoutRtl);
-                        homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
                         x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl);
                         x = next(x, mItemPadding, isLayoutRtl);
                     }
@@ -1176,7 +1214,6 @@
             final int customWidth = customView.getMeasuredWidth();
             customView.layout(xpos, ypos, xpos + customWidth,
                     ypos + customView.getMeasuredHeight());
-            homeSlop = Math.min(homeSlop, Math.max(xpos - homeRight, 0));
             x = next(x, customWidth, isLayoutRtl);
         }
 
@@ -1186,14 +1223,6 @@
             mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
                     mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
         }
-
-        if (needsTouchDelegate) {
-            mTempRect.set(homeLayout.getLeft(), homeLayout.getTop(),
-                    homeLayout.getRight() + homeSlop, homeLayout.getBottom());
-            setTouchDelegate(new TouchDelegate(mTempRect, homeLayout));
-        } else {
-            setTouchDelegate(null);
-        }
     }
 
     @Override
@@ -1493,8 +1522,8 @@
             if (mExpandedActionView.getParent() != ActionBarView.this) {
                 addView(mExpandedActionView);
             }
-            if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
-                addView(mExpandedHomeLayout);
+            if (mExpandedHomeLayout.getParent() != mUpGoerFive) {
+                mUpGoerFive.addView(mExpandedHomeLayout);
             }
             mHomeLayout.setVisibility(GONE);
             if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
@@ -1520,7 +1549,7 @@
             }
 
             removeView(mExpandedActionView);
-            removeView(mExpandedHomeLayout);
+            mUpGoerFive.removeView(mExpandedHomeLayout);
             mExpandedActionView = null;
             if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
                 mHomeLayout.setVisibility(VISIBLE);
diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
index 1752e5b..ce31c5b 100644
--- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
+++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
@@ -62,7 +62,9 @@
     uint16_t glyph = codepoint;
 
     paint->getTextWidths(&glyph, sizeof(glyph), &skWidth, &skBounds);
+#if DEBUG_GLYPHS
     ALOGD("returned glyph for %i: width = %f", codepoint, skWidth);
+#endif
     if (width)
         *width = SkScalarToHBFixed(skWidth);
     if (extents) {
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 0290857..5d32328 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -268,6 +268,15 @@
     closedir(d);
 }
 
+jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid)
+{
+    SchedPolicy sp;
+    if (get_sched_policy(pid, &sp) != 0) {
+        signalExceptionForGroupError(env, errno);
+    }
+    return (int) sp;
+}
+
 static void android_os_Process_setCanSelfBackground(JNIEnv* env, jobject clazz, jboolean bgOk) {
     // Establishes the calling thread as illegal to put into the background.
     // Typically used only for the system process's main looper.
@@ -991,7 +1000,8 @@
     {"setThreadPriority",   "(I)V", (void*)android_os_Process_setCallingThreadPriority},
     {"getThreadPriority",   "(I)I", (void*)android_os_Process_getThreadPriority},
     {"setThreadGroup",      "(II)V", (void*)android_os_Process_setThreadGroup},
-    {"setProcessGroup",      "(II)V", (void*)android_os_Process_setProcessGroup},
+    {"setProcessGroup",     "(II)V", (void*)android_os_Process_setProcessGroup},
+    {"getProcessGroup",     "(I)I", (void*)android_os_Process_getProcessGroup},
     {"setOomAdj",   "(II)Z", (void*)android_os_Process_setOomAdj},
     {"setArgV0",    "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
     {"setUid", "(I)I", (void*)android_os_Process_setUid},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a69870b..aafc4bf 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1702,6 +1702,13 @@
         android:description="@string/permdesc_stopAppSwitches"
         android:protectionLevel="signature|system" />
 
+    <!-- Allows an application to retrieve private information about
+         the current top activity, such as any assist context it can provide. -->
+    <permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
+        android:label="@string/permlab_getTopActivityInfo"
+        android:description="@string/permdesc_getTopActivityInfo"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to retrieve the current state of keys and
          switches.  This is only for use by the system.
          @deprecated The API that used this permission has been removed. -->
diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml
index 751d322..0b6122d 100644
--- a/core/res/res/layout-xlarge/screen_action_bar.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar.xml
@@ -20,7 +20,8 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
-    android:fitsSystemWindows="true">
+    android:fitsSystemWindows="true"
+    android:splitMotionEvents="false">
     <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
index f2a1ea1..a95635e 100644
--- a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
@@ -23,7 +23,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/action_bar_overlay_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:splitMotionEvents="false">
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index fe58215..5341f3d 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -17,9 +17,7 @@
 <view xmlns:android="http://schemas.android.com/apk/res/android"
       class="com.android.internal.widget.ActionBarView$HomeView"
       android:layout_width="wrap_content"
-      android:layout_height="match_parent"
-      android:background="?android:attr/actionBarItemBackground"
-      android:animateLayoutChanges="true">
+      android:layout_height="match_parent">
     <ImageView android:id="@android:id/up"
                android:src="?android:attr/homeAsUpIndicator"
                android:layout_gravity="center_vertical|start"
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index df773eb..ccc5b07 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -16,10 +16,9 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
+              android:layout_height="match_parent"
               android:orientation="horizontal"
               android:paddingEnd="8dip"
-              android:background="?android:attr/actionBarItemBackground"
               android:enabled="false">
 
     <ImageView android:id="@android:id/up"
diff --git a/core/res/res/layout/action_bar_up_container.xml b/core/res/res/layout/action_bar_up_container.xml
new file mode 100644
index 0000000..c6fad64
--- /dev/null
+++ b/core/res/res/layout/action_bar_up_container.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+      android:layout_height="match_parent"
+      android:background="?android:attr/actionBarItemBackground"
+      android:gravity="center_vertical"
+      android:enabled="false">
+</LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index b0f1bc5..f0b2313 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -22,7 +22,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:fitsSystemWindows="true">
+    android:fitsSystemWindows="true"
+    android:splitMotionEvents="false">
     <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 20a7db1..c8181d1 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -23,7 +23,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/action_bar_overlay_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:splitMotionEvents="false">
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index ad64eb6..0639da8 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -299,6 +299,8 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Plaas die aktiwiteitbestuurder in \'n afsluitingstatus. Doen nie \'n volledige afsluiting nie."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"verhoed program-oorskakelings"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Verhoed dat die gebruiker na \'n ander program oorskakel."</string>
+    <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"kry huidige program-inligting"</string>
+    <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Laat die houer toe om private inligting oor die huidige program op die voorgrond van die skerm te herwin."</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitor en beheer alle programlaaiery"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Laat die program toe om te monitor en te beheer hoe die stelsel aktiwiteite laai. Kwaadwillige programme kan dalk die stelsel heeltemal in gevaar stel. Hierdie toestemming is net nodig vir ontwikkeling, en nooit vir normale gebruik nie."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"stuur uitsending met pakket verwyder"</string>
@@ -315,6 +317,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Laat \'n program toe om die huidige lae-vlak batteryverbruikdata te lees. Kan die program toelaat om gedetailleerde inligting te vind oor watter programme jy gebruik."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"verander batterystatistieke"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Laat die program toe om versamelde battery-statistieke te verander. Nie vir gebruik deur normale programme nie."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"haal programwerking-statistieke op"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Laat die program toe om versamelde programwerking-statistieke te herwin. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"verander programwerking-statistieke"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Laat die program toe om versamelde programwerking-statistieke te verander. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_backup" msgid="470013022865453920">"beheerstelsel-rugsteun en -teruglaai"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5b8200e..f0ad4bf 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"የእንቅስቃሴውን አደራጅ ወደ ዝጋ ሁነታ አስቀምጥ።ሙሉ ለሙሉ ዝጋ አያከናውንም።"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትግበራ መቀያየርን ተከላከል"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"ተጠቃሚው ከሌላ መተግበሪያ ከመቀየር ይከላከላል።"</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ሁሉንም መተግበሪያ ማስነሻ አሳይ እና ተቆጣጠር"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"እንቅስቃሴዎችን ስርዓቱ እንዴት እንደሚያስጀምር ለመከታተል እና ለመቆጣጠር ለመተግበሪያው ይፈቅዳሉ፡፡ ተንኮል አዘል መተግበሪያዎች የስርዓቱን ክብረ ገመና ሙሉለሙሉ ሊያጋልጡ ይችላሉ፡፡ ይህ ፍቃድ የሚያስፈልገው ለግንባታ ብቻ ነው፤ ለመደበኛ አጠቃቀም ፈጽሞ አይደለም፡፡"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"አካታች የተወገደለት ስርጭት ላክ"</string>
@@ -315,8 +319,10 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"አንድ መተግበሪያ የአሁኑን የዝቅተኛ-ደረጃ ባትሪ አጠቃቀም ውሂብን እንዲያነብ ያስችላል። መተግበሪያው ስለሚጠቀሟቸው መተግበሪያዎች ዝርዝር መረጃ እንዲያገኝ ሊያስችለው ይችላል።"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"የባትሪ ስታስቲክስን ይቀይራል"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"የተሰበሰቡ የባትሪ  ስታስቲክሶችን እንዲቀይር ለመተግበሪያው ያስችለዋል። ለመደበኛ መተግበሪያዎች ጥቅም አይደለም።"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"የመተግበሪያ ክወናዎች ስታቲስቲክስን ሰርስረህ አውጣ"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"መተግበሪያው የተሰበሰቡ የክወና ስታስቲክሶችን ሰርስሮ እንዲያወጣ ይፈቅድለታል። ለመደበኛ መተግበሪያዎች ጥቅም ያልሆነ።"</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"የመተግበሪያ ክወናዎች ስታቲስቲክስን ይቀይሩ"</string>
-    <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"መተግበሪያው የተሰበሰቡ የክወና ስታስቲክሶችን እንዲቀይር ይፈቅድለታል። ለመደበኛ መተግበሪያዎች ጥቅም ያልሆነ።"</string>
+    <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"መተግበሪያው የተሰበሰቡ የክወና ስታስቲክሶችን እንዲቀይር ይፈቅድሎታል። ለመደበኛ መተግበሪያዎች ጥቅም ያልሆነ።"</string>
     <string name="permlab_backup" msgid="470013022865453920">"የስርዓት መጠባበቂያን ተቆጣጠር እናእነበረበት መልስ"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"የስርዓቱን ምትኬ  እና እንደነበር መልስ መንገዶችን ለመቆጣጠር ለመተግበሪያው ይፈቅዳሉ፡፡ በመደበኛ መተግበሪያዎች ለመጠቀም አይሆንም፡፡"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"የሙሉ መጠበቂያ ወይም እነበረበት መልስ ከዋኝ አረጋግጥ"</string>
@@ -943,7 +949,7 @@
   </plurals>
   <plurals name="in_num_hours">
     <item quantity="one" msgid="7164353342477769999">"በ  1 ሰዓት"</item>
-    <item quantity="other" msgid="547290677353727389">"በ <xliff:g id="COUNT">%d</xliff:g> ሰዓታት"</item>
+    <item quantity="other" msgid="547290677353727389">"በ <xliff:g id="COUNT">%d</xliff:g> ሰዓቶች"</item>
   </plurals>
   <plurals name="in_num_days">
     <item quantity="one" msgid="5413088743009839518">"ነገ"</item>
@@ -975,7 +981,7 @@
   </plurals>
   <plurals name="abbrev_in_num_hours">
     <item quantity="one" msgid="3274708118124045246">"በ  1 ሰዓት"</item>
-    <item quantity="other" msgid="3705373766798013406">"በ <xliff:g id="COUNT">%d</xliff:g> ሰዓታት"</item>
+    <item quantity="other" msgid="3705373766798013406">"በ <xliff:g id="COUNT">%d</xliff:g> ሰዓቶች"</item>
   </plurals>
   <plurals name="abbrev_in_num_days">
     <item quantity="one" msgid="2178576254385739855">"ነገ"</item>
@@ -1006,7 +1012,7 @@
   </plurals>
   <plurals name="duration_hours">
     <item quantity="one" msgid="8917467491248809972">"1 ሰዓት"</item>
-    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ሰዓታት"</item>
+    <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ሰዓቶች"</item>
   </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"የቪዲዮ ችግር"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"ይቅርታ፣ ይህ ቪዲዮ በዚህ መሣሪያ ለመልቀቅ ትክክል አይደለም።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d919829..c2f5a35 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -299,6 +299,8 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"لوضع مدير الأنشطة في حالة إيقاف التشغيل. لا يتم تنفيذ إيقاف تشغيل كامل."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"لمنع المستخدم من التبديل إلى تطبيق آخر."</string>
+    <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"الحصول على معلومات عن التطبيق الحالي"</string>
+    <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"للسماح للمالك باسترداد معلومات خاصة عن التطبيق الحالي في مقدمة الشاشة."</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"مراقبة بدء تشغيل جميع التطبيقات والتحكم فيها"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"للسماح للتطبيق بمراقبة كيفية بدء النظام للأنشطة والتحكم فيها. قد تُعرِّض التطبيقات الضارة النظام للضرر بشكل كامل. لن تكون هناك حاجة لهذا الإذن سوى للتطوير فقط، وليس للاستخدام العادي على الإطلاق."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"إرسال بث الحزمة الذي تمت إزالته"</string>
@@ -315,6 +317,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"للسماح لتطبيق بقراءة البيانات الحالية التي تستهلك مستوى منخفضًا من البطارية. قد يتيح التطبيق معرفة معلومات تفصيلية عن التطبيقات التي تستخدمها."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"تعديل إحصاءات البطارية"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"للسماح للتطبيق بتعديل إحصاءات البطارية المجمّعة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"استرداد إحصاءات عمليات التطبيق"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"للسماح للتطبيق باسترداد إحصاءات عمليات التطبيق المجمّعة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"تعديل إحصاءات تشغيل التطبيق"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"للسماح للتطبيق بتعديل إحصاءات تشغيل التطبيق المجمّعة. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_backup" msgid="470013022865453920">"التحكم في النسخة الاحتياطية للنظام واستعادتها"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 0b37f93..0f1fda4 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Спыняе дзейнасць менеджэра. Не выконвае поўнае адключэнне."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"прадухіляць пераключэнне прыкладанняў"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Не дазваляе карыстальніку пераходзіць да іншага прыкладання."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"адсочваць і кантраляваць запуск усіх прыкладанняў"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Дазваляе прыкладанню сачыць і кантраляваць, як сістэма запускае працэсы. Шкоднасныя прыкладанні могуць цалкам парушыць працу сістэмы. Гэты дазвол патрэбны толькі для распрацоўкі, ніколі для звычайнага выкарыстання."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"трансляваць паведамленні аб выдаленні пакетаў"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Прыкладанне можа счытваць бягучыя звесткi пры нiзкi зарад акумулятара. Прыкладанне можа знайсцi падрабязную iнфармацы. пра прыкладаннi, якiя вы выкарыстоўваеце."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"змяняць статыстыку батарэі"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дазваляе прыкладанням змяняць сабраную статыстыку батарэi. Не патрабуецца для звычайных прыкладанняў."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"атрымлiваць статыстыку выкарыстання прыкладання"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Дазваляе прыкладанню атрымлiваць сабраную статыстыку выкарыстання прыкладання. Не для выкарыстання звычайнымі прыкладаннямі."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"змяняць статыстыку выкарыстання прыкладання"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Дазваляе прыкладанню змяняць сабраную статыстыку выкарыстання прыкладання. Не для выкарыстання звычайнымі прыкладаннямі."</string>
     <string name="permlab_backup" msgid="470013022865453920">"кантраляваць рэзервовае капіяванне і аднаўленне сістэмы"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 9bb46c1..54b6198 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Изключва диспечера на дейностите. Не извършва пълно изключване."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"предотвратяване на превключването между приложения"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Не позволява на потребителя да превключва към друго приложение."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"наблюдение и контрол на стартирането на всички приложения"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Разрешава на приложението да наблюдава и контролира как системата стартира дейности. Злонамерените приложения могат изцяло да компрометират системата. Това разрешение е нужно само за програмиране, никога за нормална употреба."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"изпращане на излъчване при премахнат пакет"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Разрешава на приложението да чете текущите данни за работа при ниско ниво на батерията. Може да му разреши да намери подробна информация за ползваните от вас приложения."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"промяна на статистическите данни за батерията"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Разрешава на приложението да променя събраните статистически данни за батерията. Не е предназначено за нормални приложения."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"извличане на статистическите данни за операциите на приложението"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Разрешава на приложението да извлича събраните статистически данни за операциите си. Не е предназначено за нормални приложения."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"промяна на статистическите данни за операциите на приложението"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Разрешава на приложението да променя събраните статистически данни за операциите си. Не е предназначено за нормални приложения."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контролиране на създаването и възстановяването на резервни копия на системата"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index eeda2cc..5acb723 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Posa el gestor d\'activitats en estat d\'apagada. No fa una apagada completa."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impedeix que l\'usuari canviï a una altra aplicació."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"supervisa i controla tots els inicis d\'aplicacions"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permet que l\'aplicació supervisi i controli com el sistema inicia activitats. Les aplicacions malicioses poden comprometre totalment el sistema. Aquest permís només és necessari per al desenvolupament, mai per a l\'ús normal."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar difusió d\'eliminació de paquet"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permet que l\'aplicació llegeixi l\'ús de dades actual quan hi ha poca bateria. Pot permetre que l\'aplicació recopili informació detallada sobre les aplicacions que fas servir."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifica les estadístiques de la bateria"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permet que l\'aplicació modifiqui les estadístiques d\'ús de la bateria recopilades. No ho poden fer servir les aplicacions normals."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"recuperació d\'estadístiques d\'ús de l\'aplicació"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permet que l\'aplicació recuperi les estadístiques d\'ús de l\'aplicació recopilades. No indicat per a les aplicacions normals."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modifica les estadístiques d\'ús de l\'aplicació"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permet que l\'aplicació modifiqui les estadístiques d\'ús de l\'aplicació recopilades. No indicat per a les aplicacions normals."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar la còpia de seguretat i restauració del sistema"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f39e602..f10a217 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Uvede správce činností do vypnutého stavu. Nedojde však k úplnému vypnutí."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabránění přepínání aplikací"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Zabrání uživateli přepnout na jinou aplikaci."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"sledování a řízení spouštění všech aplikací"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Umožňuje aplikaci sledovat a řídit spouštění činností systémem. Škodlivé aplikace mohou systém zcela ovládnout. Toto oprávnění je požadováno pouze pro účely vývoje, nikdy pro běžné použití."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"odeslání vysílání o odstranění balíčku"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Umožňuje aplikaci číst aktuální podrobné údaje o využití baterie. Aplikace to může využít k získání podrobných informací o tom, které aplikace používáte."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"změna statistických údajů o baterii"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Umožňuje aplikaci upravit shromážděné statistiky o baterii. Toto oprávnění není určeno pro běžné aplikace."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"načtení statistik operací aplikace"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Umožňuje aplikaci načíst shromážděné statistiky operací aplikace. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"upravit statistiky operací aplikace"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Umožňuje aplikaci upravit shromážděné statistiky operací aplikace. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_backup" msgid="470013022865453920">"ovládání zálohování a obnovy systému"</string>
@@ -408,19 +414,19 @@
     <string name="permlab_writeContacts" msgid="5107492086416793544">"úprava kontaktů"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Umožňuje aplikaci upravit údaje o kontaktech uložených v tabletu včetně toho, jak často voláte, posíláte e-maily nebo komunikujete jinými způsoby s konkrétními kontakty. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Umožňuje aplikaci upravit údaje o kontaktech uložených v telefonu včetně toho, jak často voláte, posíláte e-maily nebo komunikujete jinými způsoby s konkrétními kontakty. Toto oprávnění aplikacím umožňuje mazat údaje o kontaktech."</string>
-    <string name="permlab_readCallLog" msgid="3478133184624102739">"číst seznam hovorů"</string>
+    <string name="permlab_readCallLog" msgid="3478133184624102739">"čtení seznamu hovorů"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Umožňuje aplikaci číst seznam hovorů v tabletu, včetně dat o příchozích a odchozích hovorech. Toto oprávnění umožňuje aplikaci ukládat údaje ze seznamu hovorů. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Umožňuje aplikaci číst seznam hovorů v telefonu, včetně dat o příchozích a odchozích hovorech. Toto oprávnění umožňuje aplikaci ukládat údaje ze seznamu hovorů. Škodlivé aplikace mohou tyto údaje bez vašeho vědomí sdílet."</string>
-    <string name="permlab_writeCallLog" msgid="8552045664743499354">"zapisovat seznam hovorů"</string>
+    <string name="permlab_writeCallLog" msgid="8552045664743499354">"zápis do seznamu hovorů"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Umožňuje aplikaci upravovat seznam hovorů vašeho tabletu, včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace to mohou zneužít k vymazání nebo změnám seznamu hovorů."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Umožňuje aplikaci upravovat seznam hovorů vašeho telefonu, včetně dat o příchozích a odchozích hovorech. Škodlivé aplikace to mohou zneužít k vymazání nebo změnám seznamu hovorů."</string>
     <string name="permlab_readProfile" msgid="4701889852612716678">"čtení vaší vlastní vizitky"</string>
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Umožňuje aplikaci číst údaje v osobním profilu uložené v zařízení, například jméno nebo kontaktní údaje. Znamená to, že vás aplikace může identifikovat a odeslat údaje z profilu dalším aplikacím."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"úprava vaší vlastní vizitky"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Umožňuje aplikaci změnit nebo přidat údaje osobního profilu uložené v zařízení, například jméno nebo kontaktní údaje. Znamená to, že vás aplikace může identifikovat a odeslat údaje z profilu dalším aplikacím."</string>
-    <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"číst váš sociální stream"</string>
+    <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čtení vašeho sociálního streamu"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikaci získat přístup k sociálním aktualizacím od vašich přátel a synchronizaci těchto aktualizací. Při sdílení informací buďte opatrní – toto oprávnění umožňuje aplikaci číst komunikaci mezi vámi a vašimi přáteli v sociálních sítích bez ohledu na její důvěrnost. Poznámka: Toto oprávnění nemusí platit pro všechny sociální sítě."</string>
-    <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zapisovat do vašeho sociálního streamu"</string>
+    <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zápis do sociálního streamu"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Umožňuje aplikaci zobrazit sociální aktualizace od vašich přátel. Při sdílení informací buďte opatrní – aplikace s tímto oprávněním může vytvářet zprávy, které zdánlivě pochází od vašich přátel. Poznámka: Toto oprávnění nemusí platit pro všechny sociální sítě."</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"čtení událostí kalendáře a důvěrné informace"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Umožňuje aplikaci číst všechny události kalendáře uložené v tabletu, včetně událostí přátel nebo spolupracovníků. Aplikace s tímto oprávněním může sdílet nebo ukládat údaje v kalendáři bez ohledu na důvěrnost nebo citlivost těchto údajů."</string>
@@ -503,8 +509,8 @@
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Umožňuje aplikaci ovládat telefonní funkce zařízení. Aplikace s tímto oprávněním smí bez upozornění přepínat sítě, zapínat a vypínat bezdrátový modul telefonu a podobně."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"čtení stavu a identity telefonu"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikaci získat přístup k telefonním funkcím zařízení. Toto oprávnění umožňuje aplikaci zjistit telefonní číslo telefonu, identifikační čísla zařízení, zda zrovna probíhá hovor, a vzdálené číslo, ke kterému je hovor připojen."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zabránění přechodu tabletu do režimu spánku"</string>
-    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"zabránění přechodu telefonu do režimu spánku"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"bránění přechodu tabletu do režimu spánku"</string>
+    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"bránění přechodu telefonu do režimu spánku"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Umožňuje aplikaci zabránit přechodu tabletu do režimu spánku."</string>
     <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Umožňuje aplikaci zabránit přechodu telefonu do režimu spánku."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"zapnutí či vypnutí tabletu"</string>
@@ -528,12 +534,12 @@
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Umožňuje aplikaci změnit časové pásmo telefonu."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"role služby AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"Umožňuje aplikaci volat funkce AccountAuthenticator."</string>
-    <string name="permlab_getAccounts" msgid="1086795467760122114">"vyhledání účtů v zařízení"</string>
+    <string name="permlab_getAccounts" msgid="1086795467760122114">"vyhledávání účtů v zařízení"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Umožňuje aplikaci získat seznam účtů v tabletu. Mohou sem patřit i účty vytvořené aplikacemi, které jste nainstalovali."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Umožňuje aplikaci získat seznam účtů v telefonu. Mohou sem patřit i účty vytvořené aplikacemi, které jste nainstalovali."</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"vytváření účtů a nastavení hesel"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"Umožňuje aplikaci používat funkce aplikace AccountManager související s ověřováním účtů – včetně vytváření účtů a získávání a nastavování hesel."</string>
-    <string name="permlab_manageAccounts" msgid="4983126304757177305">"přidání nebo odebrání účtů"</string>
+    <string name="permlab_manageAccounts" msgid="4983126304757177305">"přidávání nebo odebírání účtů"</string>
     <string name="permdesc_manageAccounts" msgid="8698295625488292506">"Umožňuje aplikaci provádět operace, jako je přidávání nebo odebírání účtů nebo mazání jejich hesel."</string>
     <string name="permlab_useCredentials" msgid="235481396163877642">"používání účtů v zařízení"</string>
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"Umožňuje aplikaci požadovat ověřovací tokeny."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 45f551c..eec3dd4 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Sætter aktivitetsadministratoren i lukningstilstand. Lukker ikke helt ned."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"undgå programskift"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Forhindrer brugeren i at skifte til en anden app."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"overvåge og kontrollere åbning af alle apps"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Tillader, at appen kan overvåge og kontrollere, hvordan systemet starter aktiviteter. Ondsindede apps kan fuldstændig kompromittere systemet. Denne tilladelse er kun nødvendig til udvikling, aldrig til normal brug."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"send udsendelse om fjernet pakke"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Tillader, at en applikation læser de aktuelle data for batteriforbruget. Kan tillade, at applikationen henter detaljerede oplysninger om, hvilke apps du bruger."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"rediger batteristatistikker"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Tillader, at appen kan ændre indsamlede batteristatistikker. Anvendes ikke af normale apps."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"hent statistikker for handlinger i appen"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Tillader, at appen indhenter statistikker for handlinger i applikationen. Denne handling bruges ikke i almindelige apps."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"lav ændringer i statistik for handlinger i appen"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Tillader, at appen kan ændre indsamlede statistikker for handlinger i applikationen. Dette kan ikke bruges af almindelige apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontroller sikkerhedskopiering af system, og gendan"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 1ef42f6..d5a67f0 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Versetzt den Aktivitätsmanager in einen heruntergefahrenen Zustand. Führt kein vollständiges Herunterfahren aus."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"App-Wechsel verhindern"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hindert den Nutzer daran, zu einer anderen App zu wechseln"</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"Start von Apps überwachen und steuern"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Ermöglicht der App, den Start von Systemaktivitäten zu überwachen und zu steuern. Schädliche Apps können so das gesamte System beeinträchtigen. Diese Berechtigung wird nur zu Entwicklungszwecken und nie für die normale Nutzung benötigt."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"Broadcast ohne Paket senden"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ermöglicht einer Anwendung, den momentan niedrigen Akkustand zu erkennen. Unter Umständen erhält die App detaillierte Informationen darüber, welche Apps Sie verwenden."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"Akkudaten ändern"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ermöglicht der App, erfasste Akkudaten zu ändern. Nicht für normale Apps vorgesehen."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"App-Vorgangsstatistiken abrufen"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Ermöglicht der App, erfasste App-Vorgangsstatistiken abzurufen. Kann nicht von normalen Apps verwendet werden."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"App-Vorgangsstatistiken ändern"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Ermöglicht der App, erfasste App-Vorgangsstatistiken zu ändern. Kann nicht von normalen Apps verwendet werden"</string>
     <string name="permlab_backup" msgid="470013022865453920">"Systemsicherung und -wiederherstellung kontrollieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index f3333dd..cf42a41 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Θέτει το πρόγραμμα διαχείρισης δραστηριοτήτων σε κατάσταση τερματισμού λειτουργιών. Δεν εκτελεί πλήρη τερματισμό λειτουργιών."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"αποτροπή εναλλαγών εφαρμογών"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Δεν επιτρέπει στο χρήστη να μεταβεί σε άλλη εφαρμογή."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"παρακολούθηση και έλεγχος όλων των εκκινήσεων εφαρμογών"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Επιτρέπει στην εφαρμογή να παρακολουθεί και να ελέγχει τον τρόπο με τον οποίο το σύστημα εκκινεί δραστηριότητες. Τυχόν κακόβουλες εφαρμογές ενδέχεται να θέσουν σε κίνδυνο το σύστημα. Αυτή η άδεια είναι απαραίτητη μόνο για σκοπούς ανάπτυξης και ποτέ για συνήθη χρήση."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"αποστολή εκπομπής χωρίς πακέτο"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Επιτρέπει σε μια εφαρμογή να διαβάζει τα δεδομένα τρέχουσας χαμηλού επιπέδου χρήσης μπαταρίας. Ενδέχεται να επιτρέπει στην εφαρμογή να εντοπίσει λεπτομερείς πληροφορίες σχετικά με τις εφαρμογές που χρησιμοποιείτε."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"τροποποίηση στατιστικών στοιχείων μπαταρίας"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Επιτρέπει στην εφαρμογή την τροποποίηση στατιστικών στοιχείων μπαταρίας που έχουν συλλεχθεί. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"ανάκτηση στατιστικών στοιχείων λειτουργίας για εφαρμογές"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Επιτρέπει στην εφαρμογή την ανάκτηση των στατιστικών στοιχείων λειτουργίας για τις εφαρμογές που έχουν συλλεχθεί. Δεν προορίζεται για χρήση από κανονικές εφαρμογές."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"τροποποίηση στατιστικών στοιχείων λειτουργιών εφαρμογών"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Επιτρέπει στην εφαρμογή την τροποποίηση των στατιστικών στοιχείων λειτουργίας εφαρμογών που έχουν συλλεχθεί. Δεν προορίζεται για χρήση από κανονικές εφαρμογές."</string>
     <string name="permlab_backup" msgid="470013022865453920">"αντίγραφο ασφαλείας και επαναφορά συστήματος"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 538dd66..73ee358 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Puts the activity manager into a shut-down state. Does not perform a complete shut down."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"prevent app switches"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Prevents the user from switching to another app."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitor and control all app launching"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Allows the app to monitor and control how the system launches activities. Malicious apps may completely compromise the system. This permission is only needed for development, never for normal use."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"send package removed broadcast"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Allows an application to read the current low-level battery use data. May allow the application to find out detailed information about which apps you use."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modify battery statistics"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Allows the app to modify collected battery statistics. Not for use by normal apps."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"retrieve app ops statistics"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Allows the app to retrieve collected application operation statistics. Not for use by normal apps."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modify app ops statistics"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Allows the app to modify collected component usage statistics. Not for use by normal apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"control system back up and restore"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 590dfee..6bb8e44 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Pone al administrador de la actividad en estado de cierre. No realiza un cierre completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir conmutadores de aplicación"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Evita que el usuario cambie a otra aplicación."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"supervisar y controlar la ejecución de todas las aplicaciones"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite que la aplicación supervise y controle la manera en la que el sistema inicia actividades. Las aplicaciones maliciosas pueden comprometer el sistema por completo. Este permiso es necesario solo para el desarrollo, nunca para el uso habitual."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar emisión de paquete eliminado"</string>
@@ -315,8 +319,10 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite a una aplicación leer los datos actuales de uso de batería de bajo nivel. Puede permitir a la aplicación buscar información detallada sobre las aplicaciones que usas."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar las estadísticas de la batería"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite a la aplicación modificar las estadísticas recopiladas de la batería. Las aplicaciones normales no deben utilizarlo."</string>
-    <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"Modificar estadísticas de operaciones de aplicación"</string>
-    <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que la aplicación modifique las estadísticas recopiladas de operación de la aplicación. Las aplicaciones normales no deben utilizar este permiso."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"Recuperar estadísticas de operaciones de la aplicación"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite que la aplicación recupere las estadísticas recopiladas de operación de la aplicación. Las aplicaciones normales no deben utilizar este permiso."</string>
+    <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificar estadísticas de uso de aplicaciones"</string>
+    <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que la aplicación modifique las estadísticas recopiladas sobre el uso de aplicaciones. Las aplicaciones normales no deben utilizar este permiso."</string>
     <string name="permlab_backup" msgid="470013022865453920">"copia de seguridad y restauración del sistema de control"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Permite que la aplicación controle el mecanismo de copia de seguridad y restauración del sistema. Las aplicaciones normales no deben utilizar este permiso."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Confirmar una copia completa de seguridad o una operación de restauración"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 17a7e86..fbbcf89 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Pone el administrador de actividades en estado de cierre. No realiza un cierre completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar cambios de aplicación"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Evita que el usuario cambie a otra aplicación."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"supervisar y controlar la ejecución de todas las aplicaciones"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite que la aplicación supervise y controle la ejecución de las actividades del sistema. Las aplicaciones malintencionadas pueden vulnerar la seguridad del sistema. Este permiso es necesario únicamente para tareas de desarrollo, nunca para el uso habitual."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar emisión eliminada de paquete"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que una aplicación consulte los datos actuales de uso de batería de nivel inferior. Puede permitir que la aplicación obtenga información detallada sobre las aplicaciones que utilizas."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estadísticas de la batería"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que la aplicación modifique las estadísticas recopiladas sobre la batería. Las aplicaciones normales no deben usar este permiso."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"recuperar estadísticas de operaciones de aplicaciones"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite que la aplicación recupere las estadísticas recopiladas sobre operaciones de aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificar estadísticas de operaciones de aplicaciones"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que la aplicación modifique las estadísticas recopiladas sobre operaciones de aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar las copias de seguridad y las restauraciones del sistema"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 8b4408a..00b5c2d 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Lülitab tegevushalduri väljalülitusolekusse. Ei lülita lõplikult välja."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"väldi rakenduste ümberlülitamist"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Takistab kasutaja lülitumist teisele rakendusele."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"Kõigi rakenduste käivitumise jälgimine ja juhtimine"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Võimaldab rakendusel jälgida ja juhtida, kuidas süsteem tegevusi käivitab. Pahatahtlikud rakendused võivad süsteemi täielikult rikkuda. Seda õigust on vaja ainult arenduseks, mitte tavakasutuse korral."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"saada paketist eemaldatud saade"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lubab rakendusel lugeda madala akutaseme kasutusandmeid. Võib lubada rakendusel hankida üksikasjalikku teavet selle kohta, mis rakendusi te kasutate."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"aku statistika muutmine"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Võimaldab rakendusel muuta aku kohta kogutud statistikat. Mitte kasutada tavarakenduste puhul."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"rakenduse tööstatistika hankimine"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Võimaldab rakendusel hankida kogutud rakenduse tööstatistikat. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"rakenduse tööstatistika muutmine"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Võimaldab rakendusel muuta kogutud rakenduse tööstatistikat. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_backup" msgid="470013022865453920">"juhi süsteemi varundust ja taastet"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3f2da2c..3cbd496 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -299,6 +299,8 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"مدیر فعالیت را در حالت خاموشی قرار می‌دهد. خاموشی را به صورت کامل انجام نمی‌دهد."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ممانعت از جابجایی برنامه"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"اجازه نمی‎دهد کاربر به برنامه دیگری برود."</string>
+    <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"دریافت اطلاعات برنامه فعلی"</string>
+    <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"به دارنده اجازه می‌دهد اطلاعات خصوصی مربوط به برنامه فعلی را در پیش زمینه صفحه بازیابی کند."</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"نظارت و کنترل راه‌اندازی همه برنامه"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"به برنامه اجازه می‎دهد تا نحوه راه‌اندازی فعالیت‌های سیستم را کنترل کند. برنامه‎های مخرب می‎توانند کاملا با سیستم سازگار شوند. این مجوز فقط برای توسعه نیاز است و برای استفاده عادی نیست."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ارسال پخش بسته حذف شده"</string>
@@ -315,6 +317,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"به یک برنامه کاربردی اجازه می‌دهد که داده‌های استفاده کننده از میزان باتری کم کنونی را بخواند. این کار ممکن است به برنامه این امکان را بدهد که اطلاعات جزئی درباره برنامه‌هایی که استفاده می‌کنید، بدست آورد."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"اصلاح آمار باتری"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"به برنامه اجازه می‎دهد تا آمار جمع‌آوری شده باتری را تغییر دهد. برای استفاده برنامه‎های عادی نیست."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"بازیابی آمار مربوط به کارکرد برنامه"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"به برنامه امکان می‌دهد آمار جمع‌آوری شده مربوط به عملکرد برنامه را بازیابی کند. برای استفاده توسط برنامه‌های معمولی، در نظر گرفته نشده است."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"تغییر آمار کارکرد برنامه"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"به برنامه اجازه تغییر آمار کارکرد جمع‌آوری شده از برنامه را می‌دهد. برای استفاده توسط برنامه‌های معمولی نیست."</string>
     <string name="permlab_backup" msgid="470013022865453920">"کنترل نسخهٔ پشتیبان سیستم و بازیابی"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 7573f41..c4dfd6c 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Asettaa toimintojen hallinnan sulkeutumistilaan. Ei sulje puhelinta kokonaan."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"estä sovellusten vaihto"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Estää käyttäjää siirtymästä toiseen sovellukseen."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"kaikkien sovellusten käynnistämisen valvonta ja hallinta"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Antaa sovelluksen valvoa ja hallita sitä, miten laite käynnistää toimintoja. Haitalliset sovellukset voivat vaarantaa laitteen käytön. Tätä oikeutta tarvitaan vain kehityskäyttöön eikä koskaan tavalliseen käyttöön."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"lähetä paketeista poistettuja lähetyksiä"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Antaa sovelluksen lukea nykyisiä alhaisen tason akunkäyttötietoja. Sovellus saattaa saada tietoonsa, mitä sovelluksia käytät."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"muokkaa akkutilastoja"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Antaa sovelluksen muokata kerättyjä akkutilastoja. Ei tavallisten sovellusten käyttöön."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"nouda sovellusten toimintatilastoja"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Antaa sovelluksen noutaa kerättyjä sovellusten toimintatilastoja. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"sovellusten käyttötilastojen muokkaus"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Antaa sovelluksen muokata kerättyjä sovellusten käyttötilastoja. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_backup" msgid="470013022865453920">"hallitse järjestelmän varmuuskopiointia ja palauttamista"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e4aad26..ea1ef50 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Place le gestionnaire d\'activités en état d\'arrêt. N\'effectue pas un arrêt complet."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"empêcher les changements d\'applications"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Empêche l\'utilisateur de changer d\'application."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"suivre et contrôler le lancement de toutes les applications"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permet à l\'application de surveiller et de contrôler la façon dont le système lance les activités. Des applications malveillantes peuvent exploiter cette fonctionnalité pour totalement compromettre le système. Cette autorisation est uniquement destinée aux développeurs. Elle ne doit jamais être activée dans le cadre d\'une utilisation standard."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"Envoyer une diffusion sans paquet"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permet à une application de lire les données de consommation actuelles indiquant le faible niveau de la batterie. Permet éventuellement à l\'application d\'obtenir des informations détaillées sur les applications que vous utilisez."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifier les statistiques de la batterie"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permet à l\'application de modifier les statistiques collectées concernant la batterie. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"récupérer les statistiques de fonctionnement des applications"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permet à l\'application de récupérer les statistiques de fonctionnement des applications recueillies. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modifier les statistiques de fonctionnement des applications"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permet à l\'application de modifier les statistiques de fonctionnement des applications collectées. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_backup" msgid="470013022865453920">"contrôler la sauvegarde et la restauration du système"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f4e2d3e..c3ef672 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"गतिविधि प्रबंधक को शटडाउन स्‍थिति में रखता है. पूर्ण शटडाउन निष्‍पादित नहीं करता है."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"एप्‍लिकेशन स्‍विच करने से रोकता है"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"उपयोगकर्ता को दूसरे एप्‍लिकेशन पर स्‍विच करने से रोकता है."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"सभी एप्‍लिकेशन की लॉन्‍चिंग की निगरानी करें और उसे नियंत्रित करें"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"एप्लिकेशन को यह निगरानी और नियंत्रित करने देता है कि सिस्टम कैसे गतिविधियां लॉन्च करता है. दुर्भावनापूर्ण एप्लिकेशन सिस्टम को पूरी तरह से जोखिम में डाल सकते हैं. इस अनुमति की आवश्यकता केवल विकास के लिए है, सामान्य उपयोग के लिए कभी नहीं."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"पैकेज निकाले गए प्रसारण भेजें"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"एप्लिकेशन को वर्तमान निम्न-स्तरीय बैटरी उपयोग डेटा पढ़ने देती है. एप्लिकेशन को आपके द्वारा उपयोग किए जाने वाले एप्लिकेशन के बारे में विस्तृत जानकारी ढूंढने दे सकती है."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"बैटरी के आंकड़े संशोधित करें"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"एप्‍लिकेशन को बैटरी के संकलित आंकड़ों को संशोधित करने देती है. सामान्‍य एप्‍लिकेशन के द्वारा उपयोग करने के लिए नहीं."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"एप्लिकेशन संचालन आंकड़े प्राप्त करें"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"एप्लिकेशन को संकलित एप्लिकेशन संचालन आंकड़े प्राप्त करने देता है. सामान्य एप्लिकेशन के द्वारा उपयोग के लिए नहीं."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"एप्लिकेशन कार्यवाही के आंकड़े बदलें"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"एप्लिकेशन को एप्लिकेशन कार्यवाही के एकत्रित आंकड़े बदलने देता है. सामान्य एप्लिकेशन के द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_backup" msgid="470013022865453920">"सिस्‍टम बैकअप नियंत्रित और पुनर्स्‍थापित करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a7085f4..72aad27 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Postavlja upravitelja za aktivnost u stanje mirovanja. Ne isključuje ga u potpunosti."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"sprečavanje promjene aplikacije"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Sprječava korisnika u prebacivanju na drugu aplikaciju."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"praćenje i nadzor svih pokretanja aplikacija"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Omogućuje aplikaciji nadzor i upravljanje načinom na koji sustav pokreće aktivnosti. Zlonamjerne aplikacije mogu posve ugroziti sustav. Ta je dozvola potrebna samo za razvoj, nikada za uobičajenu upotrebu."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"slanje paketno uklonjenog prijenosa"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Aplikacija može očitavati podatke o trenutačnoj potrošnji baterije na niskoj razini. Tako može doznati detaljne informacije o aplikacijama koje upotrebljavate."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"izmjena statistike o bateriji"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Omogućuje aplikaciji promjenu prikupljene statistike o potrošnji baterije. Nije namijenjena uobičajenim aplikacijama."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"dohvaćanje statistike o radu aplikacije"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Aplikaciji omogućuje dohvaćanje prikupljene statistike o radu aplikacije. Nije namijenjena uobičajenim aplikacijama."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"izmjena statistike o radu aplikacije"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Aplikaciji omogućuje promjenu prikupljene statistike o radu aplikacije. Nije namijenjena uobičajenim aplikacijama."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sigurnosna kopija i oporavak nadzornog sustava"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 840ed06..6dd4f8f 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Leállítás állapotba helyezi a tevékenységkezelőt. Nem hajtja végre a teljes leállítást."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"alkalmazásváltás megakadályozása"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Megakadályozza, hogy a felhasználó átváltson egy másik alkalmazásra."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"alkalmazásindítások nyomon követése és vezérlése"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Lehetővé teszi az alkalmazás számára, hogy figyelje és vezérelje, hogy a rendszer hogyan indít el tevékenységeket. A rosszindulatú alkalmazások teljesen tönkretehetik a rendszert. Ez az engedély csak fejlesztéshez szükséges, normál használathoz sosem."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"eltávolított csomagú üzenetek küldése"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lehetővé teszi egy alkalmazás számára, hogy leolvassa az aktuális alacsony szintű akkumulátorhasználatra vonatkozó adatokat. Ezáltal az alkalmazás részletes adatokhoz jut az Ön által használt alkalmazásokról."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"akkumulátorstatisztikák módosítása"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Lehetővé teszi az alkalmazás számára az összegyűjtött akkumulátorhasználati statisztikák módosítását. Normál alkalmazások nem használhatják."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"alkalmazásműveleti statisztikák lekérdezése"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Lehetővé teszi az alkalmazás számára az összegyűjtött alkalmazásműveleti statisztikák lekérdezését. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"alkalmazásműveleti statisztikák módosítása"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Lehetővé teszi az alkalmazás számára az összegyűjtött alkalmazásműveleti statisztikák módosítását. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_backup" msgid="470013022865453920">"rendszer biztonsági mentésének és helyreállításának vezérlése"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 638528f..8d3c139 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Letakkan pengelola aktivitas dalam kondisi mati. Tidak melakukan penonaktifan penuh."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"cegah pergantian aplikasi"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Mencegah pengguna beralih ke apl lain."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"memantau dan mengontrol semua peluncuran apl"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Mengizinkan apl memantau dan mengontrol cara sistem meluncurkan kegiatan. Apl berbahaya dapat meretas sistem sepenuhnya. Izin ini hanya diperlukan untuk pengembangan, tidak pernah diperlukan untuk penggunaan normal."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"kirim siaran paket dihapus"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Mengizinkan aplikasi membaca data penggunaan baterai tingkat rendah. Dapat mengizinkan aplikasi mencari informasi mendetail tentang aplikasi mana yang Anda gunakan."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ubah statistik baterai"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Mengizinkan aplikasi mengubah statistik baterai yang dikumpulkan. Tidak untuk digunakan oleh aplikasi normal."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"mengambil statistik pengoperasian aplikasi"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Mengizinkan aplikasi mengambil statistik pengoperasian aplikasi yang dikumpulkan. Tidak untuk digunakan oleh aplikasi normal."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"memodifikasi statistik pengoperasian aplikasi"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Mengizinkan aplikasi memodifikasi statistik pengoperasian aplikasi yang dikumpulkan. Tidak untuk digunakan oleh aplikasi normal."</string>
     <string name="permlab_backup" msgid="470013022865453920">"mengontrol cadangan dan pemulihan sistem"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 7d18dc9..7fc8b73 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Mette il gestore delle attività in uno stato di chiusura. Non esegue una chiusura completa."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedire commutazione applicazione"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impedisce all\'utente di passare a un\'altra applicazione."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitoraggio e controllo avvio di tutte le applicazioni"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Consente all\'applicazione di monitorare e controllare l\'avvio delle attività da parte del sistema. Le applicazioni dannose potrebbero compromettere completamente il sistema. Questa autorizzazione è necessaria solo per lo sviluppo, mai per l\'utilizzo normale."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"invio broadcast rimossi dal pacchetto"</string>
@@ -315,7 +319,9 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Consente a un\'applicazione di leggere i dati di utilizzo della batteria di basso livello correnti. Potrebbe consentire all\'applicazione di trovare informazioni dettagliate sulle applicazioni che utilizzi."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifica statistiche batteria"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Consente all\'applicazione di modificare le statistiche raccolte sulla batteria. Da non usare per normali applicazioni."</string>
-    <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modifica statistiche funzion. app"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"recupero statistiche funzion. app"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Consente all\'applicazione di recuperare le statistiche raccolte sul funzionamento dell\'applicazione. Da non usare per normali applicazioni."</string>
+    <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modifica statistiche funzionamento app"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Consente all\'applicazione di modificare le statistiche raccolte sul funzionamento dell\'applicazione. Da non usare per normali applicazioni."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controllo del backup di sistema e ripristino"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"Consente all\'applicazione di controllare il meccanismo di backup e di ripristino del sistema. Da non usare per normali applicazioni."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 784a893..fff9c52 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -299,6 +299,8 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"מעביר את מנהל הפעילויות למצב כיבוי. לא מבצע כיבוי מלא."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"מנע החלפת יישומים"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"מניעת מעבר ליישום אחר על ידי המשתמש."</string>
+    <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"קבל פרטים על היישום הנוכחי"</string>
+    <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"מאפשר לבעלים לאחזר מידע פרטי לגבי היישום הנוכחי שבקדמת המסך."</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ניהול מעקב ושליטה על כל הפעלות היישומים"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"מאפשר ליישום לנהל מעקב אחר האופן שבו המערכת מפעילה פעילויות, ולשלוט בו. יישומים זדוניים עלולים לסכן את המערכת כולה. הרשאה זו אינה נחוצה לשימוש רגיל, אלא לפיתוח בלבד."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"שלח שידור שהוסר מחבילה"</string>
@@ -315,6 +317,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"מאפשר ליישום לקרוא את נתוני השימוש הנוכחיים של הסוללה ברמה נמוכה. עשוי לאפשר ליישום לגלות מידע מפורט לגבי היישומים שבהם אתה משתמש."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"שינוי הנתונים הסטטיסטיים של הסוללה"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"מאפשר ליישום לשנות נתונים סטטיסטיים שנאספו לגבי הסוללה. לא מיועד לשימוש על ידי יישומים רגילים."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"אחזור נתונים סטטיסטיים של פעולות יישום"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"הרשאה זו מאפשרת ליישום לאחזר נתונים סטטיסטיים שנאספו לגבי פעולות יישום. לא מיועד לשימוש על ידי יישומים רגילים."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"שינוי סטטיסטיקת ההפעלה של היישום"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"מאפשר ליישום לשנות נתונים סטטיסטיים שנאספו לגבי הפעלתו. לא מיועד לשימוש על ידי יישומים רגילים."</string>
     <string name="permlab_backup" msgid="470013022865453920">"שלוט בגיבוי ובשחזור של המערכת"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index e53ff29..0afcbf7 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"アクティビティマネージャをシャットダウン状態にします。完全なシャットダウンは実行しません。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"アプリケーションの切り替えを禁止する"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"ユーザーが別のアプリに切り替えられないようにします。"</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"すべてのアプリ起動の監視と制御"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"システムによるアクティビティ起動方法を監視し制御することをアプリに許可します。この許可を悪意のあるアプリに利用されると、システム全体のセキュリティが侵害される恐れがあります。この許可は開発時にのみ必要で、通常の使用では不要です。"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"パッケージ削除ブロードキャストの送信"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"現在の電池消費量の低レベルデータを読み取ることをアプリに許可します。このアプリが、使用しているアプリの詳細情報を確認できるようになります。"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"電池統計情報の変更"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"電池に関して収集した統計情報の変更をアプリに許可します。通常のアプリでは使用しません。"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"アプリの操作状況に関する統計情報の取得"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"アプリの操作状況に関して収集された統計情報の取得をアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"アプリの操作状況に関する統計情報の変更"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"アプリの操作状況に関して収集された統計情報の変更をアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"システムのバックアップと復元を制御する"</string>
@@ -785,11 +791,11 @@
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"ユーザーガイドをご覧いただくか、お客様サポートにお問い合わせください。"</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIMカードはロックされています。"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIMカードのロック解除中..."</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"正しくないパスワードを<xliff:g id="NUMBER_0">%d</xliff:g>回入力しました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"正しくないPINを<xliff:g id="NUMBER_0">%d</xliff:g>回入力しました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にGoogleへのログインが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にGoogleへのログインが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"正しくないパスワードを<xliff:g id="NUMBER_0">%d</xliff:g>回入力しました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"正しくないPINを<xliff:g id="NUMBER_0">%d</xliff:g>回入力しました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にGoogleへのログインが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にGoogleへのログインが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"タブレットのロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、タブレットは工場出荷状態にリセットされ、ユーザーのデータはすべて失われます。"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"端末のロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、端末は工場出荷状態にリセットされ、ユーザーのデータはすべて失われます。"</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"タブレットのロック解除を<xliff:g id="NUMBER">%d</xliff:g>回失敗しました。タブレットを工場出荷状態にリセットします。"</string>
@@ -1420,7 +1426,7 @@
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"パターンが正しくありません"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"パスワードが正しくありません"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"PINが正しくありません"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"パターンを入力"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PINを入力"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"PINを入力"</string>
@@ -1442,15 +1448,15 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"ユーザー名またはパスワードが無効です。"</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ユーザー名またはパスワードを忘れた場合は"\n" "<b>"google.com/accounts/recovery"</b>" にアクセスしてください。"</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"アカウントをチェックしています…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PINの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"パスワードの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"PINの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"パスワードの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"タブレットのロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、タブレットは出荷時設定にリセットされ、ユーザーのデータはすべて失われます。"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"携帯端末のロック解除に<xliff:g id="NUMBER_0">%d</xliff:g>回失敗しました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回失敗すると、端末は出荷時設定にリセットされ、ユーザーのデータはすべて失われます。"</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"タブレットのロック解除を<xliff:g id="NUMBER">%d</xliff:g>回失敗しました。タブレットは出荷時設定にリセットされます。"</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"携帯端末のロック解除を<xliff:g id="NUMBER">%d</xliff:g>回失敗しました。端末は出荷時設定にリセットされます。"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒以内にもう一度お試しください。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にメールアカウントが必要になります。"\n\n"<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"削除"</string>
     <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"安全レベルを超えるまで音量を上げますか?"\n"大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 17006fd..85b35a7 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"작업 관리자를 종료 상태로 설정합니다. 전체 종료를 수행하지는 않습니다."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"애플리케이션 전환 방지"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"사용자가 다른 앱으로 전환하지 못하게 합니다."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"실행 중인 모든 앱 모니터링 및 제어"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"앱이 시스템에서 활동이 시작되는 방식을 모니터링하고 관리할 수 있도록 허용합니다. 이 경우 악성 앱이 이 기능을 이용하여 시스템을 완전히 손상시킬 수 있습니다. 이 권한은 개발 과정에만 필요하며 일반 사용 시에는 필요하지 않습니다."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"패키지 제거 브로드캐스트 보내기"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"애플리케이션이 현재의 낮은 수준 배터리 사용 데이터를 읽을 수 있도록 합니다. 이 경우 애플리케이션이 내가 사용하는 앱에 대한 세부정보를 파악할 수도 있습니다."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"배터리 통계 수정"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"앱이 수집된 배터리 통계를 수정할 수 있도록 허용합니다. 일반 앱에서는 사용하지 않습니다."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"앱 운영 통계 검색"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"앱이 수집된 애플리케이션 운영 통계를 검색하도록 합니다. 일반 앱에서는 사용하지 않습니다."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"앱 운영 통계 수정"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"앱이 수집된 애플리케이션 운영 통계를 수정하도록 합니다. 일반 앱에서는 사용하지 않습니다."</string>
     <string name="permlab_backup" msgid="470013022865453920">"시스템 백업 및 복원 관리"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7700f1c..86262e9 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Veiklos tvarkyklę perjungia į išsijungimo būseną. Neišjungia visiškai."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"neleisti perjungti programų"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Neleidžiama naudotojui perjungti į kitą programą."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"stebėti ir valdyti visų programų paleidimą"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Leidžiama programai stebėti ir valdyti, kaip sistema paleidžia veiklą. Kenkėjiškos programos gali visiškai pažeisti sistemą. Šis leidimas reikalingas tik kuriant ir jo niekada nereikia naudojant įprastai."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"siųsti pašalinto paketo perdavimą"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Leidžiama programai skaityti dabartinius išsikraunančio akumuliatoriaus naudojimo duomenis. Gali būti leidžiama programai sužinoti išsamią informaciją apie jūsų naudojamas programas."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"keisti akumuliatoriaus statistiką"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Leidžiama programai keisti surinktą akumuliatoriaus statistiką. Neskirta naudoti įprastoms programoms."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"nuskaityti programos naudojimo statistiką"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Programai leidžiama nuskaityti surinktą programos naudojimo statistiką. Neskirta naudoti įprastoms programoms."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"keisti programos naudojimo statistiką"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Programai leidžiama keisti surinktą programos naudojimo statistiką. Neskirta naudoti įprastoms programoms."</string>
     <string name="permlab_backup" msgid="470013022865453920">"valdyti sistemos atsarginę kopiją ir atkūrimą"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 040beb1..cd28e58 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Liek darbību pārvaldniekam pāriet izslēgšanas stāvoklī. Neveic pilnīgu izslēgšanu."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"novērst lietojumprogrammu pārslēgšanu"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Novērš lietotāja pārslēgšanos uz citu lietotni."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"pārraudzīt un kontrolēt visu lietotņu atvēršanu"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Ļauj lietotnei pārraudzīt un kontrolēt, kā sistēmā tiek palaistas darbības. Ļaunprātīgas lietotnes var pilnībā uzlauzt sistēmu. Šī atļauja ir nepieciešama tikai izstrādei, taču ne parastai lietošanai."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"sūtīt apraidi par pakotnes noņemšanu"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ļauj lietojumprogrammai lasīt pašreizējos zema akumulatora enerģijas patēriņa datus. Var atļaut lietojumprogrammai iegūt detalizētu informāciju par to, kuras lietotnes izmantojat."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"akumulatora statistikas pārveidošana"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ļauj lietotnei pārveidot apkopoto statistiku par akumulatoru. Atļauja neattiecas uz parastām lietotnēm."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"Izgūt lietotnes darbību statistiku"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Ļauj lietotnei izgūt apkopoto statistiku par lietojumprogrammas darbību. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"Pārveidot lietotnes darbības statistiku"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Ļauj lietotnei pārveidot apkopoto statistiku par lietojumprogrammas darbību. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolēt sistēmas dublējumu un atjaunošanu"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 436a1db..0ab4384 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -299,6 +299,8 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Meletakkan pengurus aktiviti dalam keadaan tutup. Tidak melaksanakan penutupan lengkap."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"halang pertukaran apl"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Menghalang pengguna daripada bertukar kepada apl lain."</string>
+    <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"dapatkan maklumat apl. semasa"</string>
+    <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Membenarkan pemegang mendapatkan maklumat peribadi tentang permohonan semasa di latar hadapan skrin"</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"pantau dan kawal semua pelancaran apl"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Membenarkan apl untuk memantau dan mengawal cara sistem melancarkan aktiviti. Apl hasad boleh menjejaskan sistem sepenuhnya. Kebenaran ini hanya diperlukan untuk pembangunan, tidak sekali-kali untuk penggunaan biasa."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"hantar siaran bahawa pakej telah dialih keluar"</string>
@@ -315,6 +317,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Membenarkan aplikasi membaca data penggunaan bateri tahap rendah semasa. Boleh membenarkan aplikasi untuk mencari maklumat terperinci tentang apl yang anda gunakan."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ubah suai statistik bateri"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Membenarkan apl mengubah suai statistik bateri yang dikumpul. Bukan untuk penggunaan apl normal."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"dapatkan semula statistik pengendalian apl"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Membenarkan apl mendapatkan semula statistik pengendalian aplikasi yang dikumpul. Bukan untuk kegunaan apl biasa."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"ubah suai apl ops statistik"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Membenarkan apl mengubah suai statistik operasi aplikasi yang dikumpul. Bukan untuk kegunaan apl biasa."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sandaran dan pemulihan sistem kawalan"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 3a7cd46..0969c34 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Lar applikasjonen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"forhindre applikasjonsbytte"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hindrer brukeren i å bytte til en annen app."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"avervåke og kontrollere all oppstart av apper"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Lar appen overvåke og kontrollere hvordan systemet starter opp aktiviteter. Ondsinnede apper kan utsette hele systemet for sikkerhetsbrudd. Denne tillatelsen er bare nødvendig for utviklere, aldri for vanlig bruk."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"kringkaste melding om fjernet pakke"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Lar apper lese gjeldende data på lavt nivå om batteribruk. Kan også la appen finne ut detaljert informasjon om hvilke apper du bruker."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"endre batteristatistikk"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Lar appen endre innsamlet batteristatistikk. Ikke beregnet på vanlige apper."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"hente bruksstatistikk for appen"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Lar appen hente innsamlet bruksstatistikk. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"endre bruksstatistikk for appen"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Lar appen endre innsamlet bruksstatistikk. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrollere sikkerhetskopiering og gjenoppretting"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 1dd9fe9..f82e5dc 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Hiermee wordt activiteitenbeheer uitgeschakeld. Er wordt geen volledige uitschakeling uitgevoerd."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"schakelen tussen apps voorkomen"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hiermee wordt voorkomen dat de gebruiker overschakelt naar een andere app."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"alle startende apps bijhouden en beheren"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Hiermee kan de app de manier bijhouden en beheren waarop het systeem activiteiten start. Schadelijke apps kunnen het systeem volledig in gevaar brengen. Deze machtiging is alleen voor ontwikkeling vereist, nooit voor normaal gebruik."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"melding verzenden dat pakket is verwijderd"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Hiermee kan de app het huidige accugebruik voor gegevens op laag niveau lezen. Een app kan hierdoor mogelijk gedetailleerde informatie achterhalen over de door u gebruikte apps."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"accustatistieken aanpassen"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Hiermee kan de app verzamelde accustatistieken wijzigen. Niet voor gebruik door normale apps."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"bewerkingsstatistieken van apps ophalen"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Hiermee kan de app verzamelde bewerkingsstatistieken van apps ophalen. Niet voor gebruik door normale apps."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"bewerkingsstatistieken van apps wijzigen"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Hiermee kan de app verzamelde bewerkingsstatistieken van apps wijzigen. Niet voor gebruik door normale apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"systeemback-up en -herstel beheren"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 8123bea..749a73e 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Przełącza menedżera aktywności w stan wyłączenia. Nie wykonuje pełnego wyłączenia."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zapobieganie przełączaniu aplikacji"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Uniemożliwia użytkownikowi przełączenie na inną aplikację."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorowanie i kontrolowanie wszystkich uruchamianych aplikacji"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Pozwala aplikacji na monitorowanie i kontrolowanie sposobu uruchamiania działań przez system. Złośliwe aplikacje mogą całkowicie naruszyć zabezpieczenia systemu. To uprawnienie nigdy nie jest potrzebne podczas normalnego użytkowania, a jedynie podczas programowania."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"wysyłanie transmisji informującej o usuniętym pakiecie"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Zezwala aplikacji na odczytywanie bieżących danych niskiego poziomu o wykorzystaniu baterii. Możliwe jest wtedy zbieranie przez aplikację szczegółowych danych o używanych aplikacjach."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"zmienianie statystyk dotyczących baterii"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Zezwala aplikacji na modyfikowanie zebranych statystyk dotyczących baterii. Nieprzeznaczone dla zwykłych aplikacji."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"pobieranie statystyk działania aplikacji"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Zezwala aplikacji na pobieranie zebranych statystyk działania aplikacji. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modyfikowanie statystyk działania aplikacji"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Zezwala aplikacji na modyfikowanie zebranych statystyk działania aplikacji. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolowanie tworzenia i przywracania kopii zapasowych systemu"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 66879ee..09a3d1f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gestor de actividade num estado de encerramento. Não executa um encerramento completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir trocas de aplicações"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impede que o utilizador mude para outra aplicação."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorizar e controlar a iniciação de todas as aplicações"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite que uma aplicação monitorize e controle a forma como o sistema inicia atividades. As aplicações maliciosas podem comprometer totalmente o sistema. Esta autorização só é necessária para programação, nunca para utilização normal."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar difusão de pacote removido"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que uma aplicação leia os atuais dados de utilização da bateria de baixo nível. Poderá permitir que a aplicação encontre informações detalhadas sobre as aplicações que utiliza."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estatísticas da bateria"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que a aplicação modifique as estatísticas recolhidas sobre a bateria. Não se destina a utilização por aplicações normais."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"obter estatísticas de utilização da aplicação"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite que a aplicação obtenha as estatísticas de utilização da aplicação recolhidas. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificar estatísticas de utilização da aplicação"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que a aplicação modifique as estatísticas de utilização de aplicação recolhidas. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar a cópia de segurança e restauro do sistema"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index b9167ef..3d5f68e 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gerenciador de atividades em um estado de desligamento. Não executa o desligamento completo."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar trocas de aplicativo"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impede que o usuário alterne para outro aplicativo."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorar e controlar todos os aplicativos que estão sendo iniciados"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite que o aplicativo monitore e controle a forma como o sistema inicia atividades. Aplicativos maliciosos podem comprometer completamente o sistema. Esta permissão só é necessária para o desenvolvimento, nunca para o uso normal."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar transmissão removida do pacote"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite que o aplicativo leia os dados de uso da bateria de baixo nível atuais. Pode fornecer ao aplicativo informações detalhadas sobre os aplicativos usados por você."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modificar estatísticas da bateria"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite que o aplicativo modifique as estatísticas coletadas da bateria. Não deve ser usado em aplicativos normais."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"recuperar estatísticas de operações de aplicativos"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite que o aplicativo recupere as estatísticas de operações de aplicativos. Não deve ser usado em aplicativos normais."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificar estatísticas de operações de aplicativos"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite que o aplicativo modifique as estatísticas de operações de aplicativos. Não deve ser usado em aplicativos normais."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlar backup e restauração do sistema"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 8d8d882..8ee8779 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -449,6 +449,10 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar il midar tranter applicaziuns"</string>
     <!-- no translation found for permdesc_stopAppSwitches (8262195802582255021) -->
     <skip />
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <!-- no translation found for permlab_runSetActivityWatcher (892239094867182656) -->
     <skip />
     <!-- no translation found for permdesc_runSetActivityWatcher (6003603162578577406) -->
@@ -477,6 +481,10 @@
     <skip />
     <!-- no translation found for permdesc_updateBatteryStats (6862817857178025002) -->
     <skip />
+    <!-- no translation found for permlab_getAppOpsStats (1508779687436585744) -->
+    <skip />
+    <!-- no translation found for permdesc_getAppOpsStats (6243887041577912877) -->
+    <skip />
     <!-- no translation found for permlab_updateAppOpsStats (8829097373851521505) -->
     <skip />
     <!-- no translation found for permdesc_updateAppOpsStats (50784596594403483) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 30276cb..ecfef60 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Plasează Managerul de activităţi într-o stare de închidere. Nu efectuează o închidere completă."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"împiedicare comutare între aplicaţii"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Împiedică trecerea utilizatorului la o altă aplicaţie."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorizare şi control asupra lansării tuturor aplicaţiilor"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite aplicaţiei să monitorizeze şi să controleze modul în care sistemul lansează activităţi. Aplicaţiile rău intenţionate pot să compromită sistemul în întregime. Această permisiune este necesară doar pentru dezvoltare şi niciodată pentru utilizarea normală."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"trimitere mesaj difuzat privind extragerea din pachet"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Permite unei aplicaţii să citească datele actuale privind utilizarea la nivel redus a bateriei. Cu această permisiune, aplicaţia poate afla informaţii detaliate despre aplicaţiile pe care le utilizaţi."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"modifică statistici referitoare la baterie"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Permite aplicaţiei să modifice statisticile colectate despre baterie. Nu se utilizează de aplicaţiile obişnuite."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"preluarea statisticilor privind operațiile aplicației"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Permite aplicației să preia statisticile colectate privind operațiile aplicației. Nu se utilizează de aplicațiile obișnuite."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"modificarea statisticilor privind utilizarea aplicației"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Permite aplicației să modifice statisticile colectate despre utilizarea aplicației. Nu se utilizează de aplicațiile obișnuite."</string>
     <string name="permlab_backup" msgid="470013022865453920">"controlare copiere de rezervă şi restabilire a sistemului"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index bbfd928..f2908f4 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Завершает работу диспетчера активности. Не выполняет полное завершение работы."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запретить переключение приложений"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Запрещает пользователям переключаться между приложениями."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"отслеживание и управление запуском всех приложений"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Приложение сможет отслеживать запуск системных процессов и управлять им. Вредоносные программы смогут получить полный контроль над системой. Это разрешение необходимо только для разработки и не нужно в обычном режиме."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"отправлять рассылку об удалении пакета"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Разрешает приложению получать данные об использовании батареи на низшем уровне. В результате оно может иметь доступ к информации об используемых вами программах."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"изменять статистику батареи"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Приложение сможет изменять собранную статистику использования заряда батареи. Это разрешение не используется обычными приложениями."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"получать статистику операций в приложениях"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Приложение сможет получать собранную статистику операций в приложениях. Это разрешение не используется обычными программами."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"изменять статистику операций в приложениях"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Приложение сможет изменять собранную статистику операций в приложениях. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_backup" msgid="470013022865453920">"управление резервным копированием и восстановлением системы"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c0147eb..9f6702b 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Uvedie správcu činností do vypnutého stavu. Úplné vypnutie však nenastane."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabrániť prepínaniu aplikácií"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Zabráni používateľovi prepnúť na inú aplikáciu."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"sledovať a ovládať všetky spustenia aplikácií"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Umožňuje aplikácii sledovať a ovládať spúšťanie aktivít systémom. Škodlivé aplikácie môžu systém úplne ovládnuť. Toto povolenie je potrebné len na účely vývoja, nikdy nie na bežné používanie."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"odoslanie vysielania o odstránení balíčka"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Umožňuje aplikácii čítať aktuálne údaje nízkej úrovne o používaní batérie. Pomocou tejto funkcie môže aplikácia zistiť podrobnosti o tom, ktoré aplikácie používate."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"zmena štatistických údajov o batérii"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Umožňuje aplikácii zmeniť zhromaždené štatistické údaje o batérii. Bežné aplikácie toto nastavenie nepoužívajú."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"získať štatistické údaje o fungovaní aplikácií"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Umožňuje aplikácii získať zhromaždené štatistické údaje o fungovaní aplikácií. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"upraviť štatistické údaje o fungovaní aplikácií"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Umožňuje aplikácii zmeniť zhromaždené štatistické údaje o fungovaní aplikácií. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_backup" msgid="470013022865453920">"Ovládať zálohovanie a obnovu systému"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5e90928..20e23ce 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Upravitelja dejavnosti preklopi v stanje za zaustavitev. Ne izvede celotne zaustavitve."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"preprečevanje preklopa programov"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Uporabniku preprečuje preklop v drug program."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"spremljanje in nadzor vseh zagonov programov"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Programu omogoča spremljanje in nadziranje načina, kako sistem zažene dejavnosti. Zlonamerni programi lahko v celoti ogrozijo varnost sistema. To dovoljenje je potrebno samo za razvoj, vendar nikoli za običajno uporabo."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"pošiljanje oddaje brez paketa"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Aplikaciji omogoča branje podatkov o trenutni nizki napolnjenosti akumulatorja. Aplikaciji lahko tudi dovoli dostop do podrobnosti o tem, katere aplikacije uporabljate."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"spreminjanje statističnih podatkov o akumulatorju"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Aplikaciji omogoča spreminjanje zbranih statističnih podatkov o akumulatorju. Ni primerno za uporabo z običajnimi aplikacijami."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"pridobi statistične podatke o delovanju aplikacij"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Aplikaciji dovoli pridobivanje zbranih statističnih podatkov o delovanju aplikacij. Ni za uporabo v navadnih aplikacijah."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"spreminjanje statističnih podatkov o delovanju aplikacije"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Aplikaciji dovoli spreminjanje zbranih statističnih podatkov o delovanju aplikacij. Ni za uporabo v navadnih aplikacijah."</string>
     <string name="permlab_backup" msgid="470013022865453920">"nadzor varnostnega kopiranja sistema in obnovitev"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 736a545..b4f2096 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Ставља менаџера активности у стање искључивања. Не искључује га у потпуности."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"спречавање пребацивања са једне апликације на другу"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Спречава да корисник пређе на другу апликацију."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"надгледање и контрола покретања свих апликација"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Дозвољава апликацији да прати начин на који систем покреће активности и да њиме управља. Злонамерне апликације могу у потпуности да угрозе систем. Ова дозвола је потребна само за програмирање, а никада за уобичајено коришћење."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"слање емитовања уклоњеног пакета"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Дозвољава апликацији да чита опште податке о тренутној употреби батерије на измаку. Можда ће апликацији дозволити да сазна детаљне информације о томе које апликације користите."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"измена статистике о батерији"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дозвољава апликацији да мења прикупљену статистику о батерији. Не користе је обичне апликације."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"преузимање статистике о функционисању апликације"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Дозвољава апликацији да преузима прикупљену статистику о функционисању апликације. Не користе је уобичајене апликације."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"измена статистике о функционисању апликације"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Дозвољава апликацији да измени прикупљену статистику о функционисању апликације. Не користе је уобичајене апликације."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контрола резервне копије система и враћање почетних вредности"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e975f68..f858d54 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Sätter aktivitetshanteraren i avstängningsläge. Utför inte en fullständig avstängning."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"förhindrar programbyten"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hindrar användaren från att byta till en annan app."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"övervaka och styra alla appar som öppnas"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Tillåter att appen övervakar och styr hur systemet startar aktiviteter. Skadliga appar kan kompromettera systemet helt. Den här behörigheten behövs bara för programmering, aldrig för vanlig användning."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"skicka meddelande om borttaget paket"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Tillåter att en app läser de aktuella uppgifterna om låg batterianvändningsnivå. Appen kan tillåtas få reda på detaljerade uppgifter om vilka appar du använder."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"ändra batteristatistik"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Tillåter att appen ändrar samlad batteristatistik. Används inte av vanliga appar."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"hämta åtgärdsstatistik för appar"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Tillåter att appen hämtar samlad åtgärdsstatistik för appar. Används inte av vanliga appar."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"ändra appars åtgärdsstatistik"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Tillåter att appen ändrar samlad åtgärdsstatistik för appar. Används inte av vanliga appar."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrollera säkerhetskopiering och återställning av systemet"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index fff8a16..4430ed5 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Huweka kisimamia shughuli katika hali ya kuzima. Haiadhiri uzimaji kamili"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zuia swichi za app"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Huzuia mtumiaji dhidi ya kubadilisha na kwenda kwa programu nyingine."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"Fuatilia na kudhibiti uzinduzi wote wa programu"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Inaruhusu programu kufuatilia na kudhibiti jinsi mfumo unazindua shughuli. Programu hasidi zinaweza kutia mfumo hatarini. Ruhusa inahitajika tu kwa usanidi, kamwe sio kwa matumizi ya kawaida."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"furushi lililotumwa limeondoa tangazo"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Inaruhusu programu kusoma data ya sasa ya matumizi ya kiwango cha chini cha betri. Huenda ikaruhusu kupata maelezo ya kina kuhusu programu unazozitumia."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"rekebisha takwimu za betri"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Inaruhusu programu kurekebisha takwimu za betri zilizokusanywa. Si ya kutumiwa na programu za kawaida."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"epua takwimu za oparesheni ya programu"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Inaruhusu programu kuepua takwimu za matumizi ya programu zilizokusanywa. Si ya kutumiwa na programu za kawaida."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"rekebisha takwimu za oparesheni ya programu"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Inaruhusu programu kurekebisha takwimu za matumizi ya programu zilizokusanywa. Si ya kutumiwa na programu za kawaida."</string>
     <string name="permlab_backup" msgid="470013022865453920">"Dhibiti kuhifadhi nakala na kurejesha kwa mfumo"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 96e03b1..1cad285 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"กำหนดให้ตัวจัดการกิจกรรมอยู่ในสถานะปิดระบบ โดยไม่ได้ปิดระบบอย่างสมบูรณ์"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ป้องกันการเปลี่ยนแอปพลิเคชัน"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"ป้องกันไม่ให้ผู้ใช้สลับไปใช้แอปพลิเคชันอื่น"</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ตรวจสอบและควบคุมแอปพลิเคชันทั้งหมดที่เปิดใช้งาน"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"อนุญาตให้แอปพลิเคชันตรวจสอบและควบคุมวิธีการที่ระบบเปิดกิจกรรมต่างๆ แอปพลิเคชันที่เป็นอันตรายอาจทำอันตรายแก่ระบบได้อย่างสิ้นเชิง การอนุญาตนี้จำเป็นสำหรับการพัฒนาเท่านั้น ไม่ใช้สำหรับแอปพลิเคชันทั่วไปโดยเด็ดขาด"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ส่งการกระจายข้อมูลว่ามีการนำแพคเกจออก"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลการใช้แบตเตอรี่ที่มีพลังงานเหลือน้อยในปัจจุบัน โดยอาจอนุญาตให้แอปพลิเคชันค้นหาข้อมูลรายละเอียดว่าคุณใช้งานแอปพลิเคชันใดบ้าง"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"แก้ไขสถิติของแบตเตอรี่"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"อนุญาตให้แอปพลิเคชันแก้ไขสถิติของแบตเตอรี่่ที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"เรียกคืนสถิติการทำงานของแอปพลิเคชัน"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"อนุญาตให้แอปพลิเคชันเรียกคืนสถิติการทำงานของแอปพลิเคชันที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"แก้ไขสถิติการทำงานของแอปพลิเคชัน"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"อนุญาตให้แอปพลิเคชันแก้ไขสถิติการทำงานของแอปพลิเคชันที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_backup" msgid="470013022865453920">"ควบคุมการสำรองและคืนค่า"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 95d8cf2..6798be9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Inilalagay ang tagapamahala ng aktibidad sa katayuan ng pag-shutdown. Hindi nagsasagawa ng kumpletong pag-shutdown."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"pigilan ang mga paglipat ng app"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Pinipigilan ang mga user sa paglipat sa isa pang app."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"subaybayan at kontrolin ang lahat ng paglunsad ng app"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Pinapayagan ang app na subaybayan at kontrolin kung paano naglulunsad ng mga aktibidad ang system. Maaaring ganap na ikompromiso ng nakakahamak na apps ang system. Kinakailangan lamang ang pahintulot na ito para sa pagpapabuti, hindi kailanman para sa normal na paggamit."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"magpadala ng package inalis ang broadcast"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Binibigyang-daan ang application na basahin ang kasalukuyang data sa paggamit ng mababang antas ng baterya. Maaaring bigyang-daan ang application na malaman ang detalyadong impormasyon tungkol sa kung aling apps ang ginagamit mo."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"baguhin ang mga istatistika ng baterya"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Binibigyang-daan ang app na baguhin ang mga nakolektang istatistika ng baterya. Hindi para sa paggamit ng normal na apps."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"bawiin ang mga istatistika ng pagpapagana ng app"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Binibigyang-daan ang app na bawiin ang mga nakolektang istatistika ng pagpapagana ng application. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"baguhin ang mga istatistika ng pagpapatakbo ng app"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Binibigyang-daan ang app na baguhin ang mga nakolektang istatistika ng pagpapatakbo ng application. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kontrolin ang system backup at pagbawi"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 7308264..015fe1b 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Eylem yöneticisini kapalı duruma getirir. Tam kapatma işlemi gerçekleştirmez."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"uygulama değişimlerini engelle"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Kullanıcının başka bir uygulamaya geçiş yapmasını engeller."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"tüm uygulama başlatma işlemlerini izle ve denetle"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Uygulamaya, sistemin etkinlikleri nasıl başlattığını izleme ve denetleme izni verir. Kötü amaçlı uygulamalar sistemi tamamen tehlikeye atabilir. Bu izin normal kullanım için değildir, sadece geliştirme süreçlerinde kullanılır."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"paket ile kaldırılan yayını gönder"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Uygulamaya, mevcut pil kullanım verilerini alt düzeyde okuma izni verir. Uygulamanın hangi uygulamaları kullandığınızla ilgili ayrıntılı bilgi edinmesine olanak sağlayabilir."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"pil istatistiklerini değiştir"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Uygulamaya, toplanan pil kullanım istatistiklerini değiştirme izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"uygulama çalışma istatistiklerini al"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Uygulamaya, uygulama çalışma istatistiklerini alma izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"uygulama çalışma istatistiklerini değiştir"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Uygulamaya, uygulama çalışma istatistiklerini değiştirme izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="permlab_backup" msgid="470013022865453920">"sistem yedeğini kontrol et ve geri yükle"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 17460f1..17f545c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Переводить диспетчер дій у стан завершення роботи. Не виконує повне завершення роботи."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запобіг. зміні програм"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Запобігати переходу користувача до іншої програми."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"відстежувати та контролювати запуски всіх програм"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Дозволяє програмі відстежувати та контролювати, як саме система запускає дії. Шкідливі програми можуть отримати повний контроль над системою. Цей дозвіл потрібний лише для розробки, а не для звичайного користування."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"надсил. запис про видал. пакета"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Дозволяє програмі зчитувати дані про поточний низький рівень споживання заряду акумулятора. Програма може отримувати докладну інформацію про те, якими програмами ви користуєтеся."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"змінювати статистику акумулятора"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Дозволяє програмі змінювати зібрану статистику акумулятора. Не для використання звичайними програмами."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"отримувати статистику роботи програми"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Дозволяє програмі отримувати зібрану статистику роботи програми. Не використовується звичайними програмами."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"змінювати статистику роботи програми"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Дозволяє програмі змінювати зібрану статистику роботи програми. Не використовується звичайними програмами."</string>
     <string name="permlab_backup" msgid="470013022865453920">"контр. резерв. копіюв. і відн. сист."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 148f4a8..d26ee14 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Đặt trình quản lý hoạt động sang trạng thái tắt. Không thực hiện tắt hoàn toàn."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ngăn chuyển đổi ứng dụng"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Ngăn người dùng chuyển sang ứng dụng khác."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"giám sát và kiểm soát tất cả hoạt động khởi chạy ứng dụng"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống khởi chạy các hoạt động. Ứng dụng độc hại hoàn toàn có thể làm tổn hại hệ thống. Quyền này chỉ cần cho mục đích phát triển, không dành cho mục đích sử dụng thông thường."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gửi truyền phát đã xóa của gói"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Cho phép ứng dụng đọc dữ liệu sử dụng pin mức thấp hiện tại. Có thể cho phép ứng dụng biết thông tin chi tiết về ứng dụng bạn sử dụng."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"sửa đổi số liệu thống kê về pin"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Cho phép ứng dụng sửa đổi các số liệu thống kê về pin đã được thu thập. Không dành cho các ứng dụng thông thường."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"truy xuất số liệu thống kê hoạt động của ứng dụng"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Cho phép ứng dụng truy xuất số liệu thống kê hoạt động của ứng dụng đã thu thập. Không dành cho ứng dụng thông thường."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"sửa đổi số liệu thống kê hoạt động của ứng dụng"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Cho phép ứng dụng sửa đổi số liệu thống kê hoạt động của ứng dụng đã thu thập. Không dành cho ứng dụng thông thường."</string>
     <string name="permlab_backup" msgid="470013022865453920">"kiểm soát sao lưu và khôi phục hệ thống"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index fa43c99..87faf15 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"阻止用户切换到其他应用。"</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"监控所有应用的启动"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"允许应用监视和控制系统是如何启动活动的。恶意应用可能会完全破坏系统。此权限只有在进行开发时才需要,正常使用情况下绝不需要。"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"发送包删除的广播"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"允许应用读取当前电量使用情况的基础数据,此权限可让应用了解关于您使用了哪些应用的详细信息。"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"修改电池使用统计信息"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"允许该应用修改收集到的电池统计信息。普通应用不应使用此权限。"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"检索应用操作统计信息"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"允许该应用检索收集到的应用操作统计信息。普通应用不应使用此权限。"</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"修改应用操作统计信息"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"允许该应用修改收集到的应用操作统计信息。普通应用不应使用此权限。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"控制系统备份和还原"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 3bfed3c..6d1f3bd 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"讓活動管理員進入關機狀態,而不執行完整的關機程序。"</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"防止使用者切換到其他應用程式。"</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"監視及控制所有應用程式的啟動程序"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"允許應用程式監視和控制系統啟動活動的方式。請注意,惡意應用程式可能利用此功能破壞整個系統。這個權限只有開發人員才需要,一般使用者不需使用這個權限。"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"傳送程式已移除廣播"</string>
@@ -315,8 +319,10 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"允許應用程式讀取目前的低電量使用資料。應用程式可能藉此找到一些詳細資訊,例如您所使用的應用程式為何。"</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"修改電池使用統計資料"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"允許應用程式修改收集到的電池使用統計資料 (不建議一般應用程式使用)。"</string>
-    <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"修改應用程式作業統計資料"</string>
-    <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"允許應用程式修改收集到的應用程式作業統計資料 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"擷取應用程式作業統計資料"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"允許應用程式擷取收集到的應用程式作業統計資料 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"修改應用程式操作統計資料"</string>
+    <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"允許應用程式修改收集到的應用程式操作統計資料 (不建議一般應用程式使用)。"</string>
     <string name="permlab_backup" msgid="470013022865453920">"控制系統備份與還原"</string>
     <string name="permdesc_backup" msgid="6912230525140589891">"允許應用程式控制系統備份與還原機制 (不建議一般應用程式使用)。"</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"確認完整備份或還原作業"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 54be6ea..dafec7c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -299,6 +299,10 @@
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Ibeka imeneja yomsebenzi kwisimo sokuvala shaqa. Ayenzi ukuvala shaqa okuphelele."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"gwema ukushintsha kohlelo lokusebenza"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Igwema umsebenzisi ukuthi ashintshele kolunye uhlelo lokusebenza."</string>
+    <!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
+    <skip />
+    <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+    <skip />
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"qapha futhi ulawule ukuqaliswa kwazo zonke izinsiza"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Ivumela insiza ukuthi ihlole futhi ilawule ukuthi isistimu iziqalisa kanjani izehlakalo. Izinzisa ezinobungozi zingensa isistimu ibe sebungozini. Lemvume idingakalela intuthuku kuphela hhay ukusetshenziswa okwejwayelekile."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"thumela iphakheji yomsakazo okhishiwe"</string>
@@ -315,6 +319,8 @@
     <string name="permdesc_batteryStats" msgid="5897346582882915114">"Ivumela uhlelo lokusebenza ukufunda idatha yokusebenza yebhethri leleveli ephansi yamanje. Ingavumela uhlelo lokusebenza ukuthola ulwazi lemininingwane mayelana nokuthi iziphi izinhlelo zokusebenza ozisebenzisayo."</string>
     <string name="permlab_updateBatteryStats" msgid="3719689764536379557">"guqula izibalo zebhetri"</string>
     <string name="permdesc_updateBatteryStats" msgid="6862817857178025002">"Ivumela uhlelo lokusebenza ukuthi luguqule izibalo zebhethri eziqoqiwe. Akwenzelwe ukuthi kusetshenziswe izinhlelo zokusebenza ezijwayelekile."</string>
+    <string name="permlab_getAppOpsStats" msgid="1508779687436585744">"thola izibalo zokusebenza kohlelo lokusebenza"</string>
+    <string name="permdesc_getAppOpsStats" msgid="6243887041577912877">"Ivumela uhlelo lokusebenza ukuthi lithole izibalo zokusebenza kohlelo lokusebenza. Akumele kusetshenziswe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_updateAppOpsStats" msgid="8829097373851521505">"shintsha izinombolo zokusebenza zohlelo lokusebenza"</string>
     <string name="permdesc_updateAppOpsStats" msgid="50784596594403483">"Ivumela uhlelo lokusebenza ukuthi lishintshe izinombolo zokusebenza kohlelo lokusebenza lokuqoqiwe. Akufanele kusetshenziswe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_backup" msgid="470013022865453920">"lawula ukusekela ngokulondoloza uhlelo bese ubuyisela esimweni"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index fa15324..dc921e6 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1541,6 +1541,7 @@
         <enum name="KEYCODE_YEN" value="216" />
         <enum name="KEYCODE_RO" value="217" />
         <enum name="KEYCODE_KANA" value="218" />
+        <enum name="KEYCODE_ASSIST" value="219" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7ef501f..fda554d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -277,8 +277,6 @@
     <!-- Boolean indicating whether the wifi chipset has dual frequency band support -->
     <bool translatable="false" name="config_wifi_dual_band_support">false</bool>
 
-    <!-- Boolean indicating whether the wifi chipset has p2p support -->
-    <bool translatable="false" name="config_wifi_p2p_support">false</bool>
     <!-- Device type information conforming to Annex B format in WiFi Direct specification.
          The default represents a dual-mode smartphone -->
     <string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fa26089..7f0fc0b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -784,6 +784,12 @@
         another app.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_getTopActivityInfo">get current app info</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_getTopActivityInfo">Allows the holder to retrieve private information
+        about the current application in the foreground of the screen.</string>
+    
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_runSetActivityWatcher">monitor and control all app launching</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_runSetActivityWatcher">Allows the app to
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6db89d9..412d4b9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1113,6 +1113,7 @@
   <java-symbol type="layout" name="keyguard_multi_user_selector_widget" />
   <java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
   <java-symbol type="layout" name="keyguard_add_widget" />
+  <java-symbol type="layout" name="action_bar_up_container" />
 
   <java-symbol type="anim" name="slide_in_child_bottom" />
   <java-symbol type="anim" name="slide_in_right" />
@@ -1337,7 +1338,6 @@
   <java-symbol type="id" name="sliding_layout" />
   <java-symbol type="id" name="keyguard_add_widget" />
   <java-symbol type="id" name="keyguard_add_widget_view" />
-  <java-symbol type="id" name="sliding_layout" />
   <java-symbol type="id" name="multi_pane_challenge" />
   <java-symbol type="id" name="keyguard_user_selector" />
   <java-symbol type="id" name="key_enter" />
diff --git a/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java b/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
new file mode 100644
index 0000000..cb468bc
--- /dev/null
+++ b/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007 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.util;
+
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * Tests for {@link LongSparseLongArray}.
+ */
+public class LongSparseLongArrayTest extends TestCase {
+    private static final String TAG = "LongSparseLongArrayTest";
+
+    public void testSimplePut() throws Exception {
+        final LongSparseLongArray array = new LongSparseLongArray(5);
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            array.put(value, value);
+        }
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            assertEquals(value, array.get(value, -1));
+            assertEquals(-1, array.get(-value, -1));
+        }
+    }
+
+    public void testSimplePutBackwards() throws Exception {
+        final LongSparseLongArray array = new LongSparseLongArray(5);
+        for (int i = 47; i >= 0; i--) {
+            final long value = 1 << i;
+            array.put(value, value);
+        }
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            assertEquals(value, array.get(value, -1));
+            assertEquals(-1, array.get(-value, -1));
+        }
+    }
+
+    public void testMiddleInsert() throws Exception {
+        final LongSparseLongArray array = new LongSparseLongArray(5);
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            array.put(value, value);
+        }
+        final long special = (1 << 24) + 5;
+        array.put(special, 1024);
+        for (int i = 0; i < 48; i++) {
+            final long value = 1 << i;
+            assertEquals(value, array.get(value, -1));
+            assertEquals(-1, array.get(-value, -1));
+        }
+        assertEquals(1024, array.get(special, -1));
+    }
+
+    public void testFuzz() throws Exception {
+        final Random r = new Random();
+
+        final HashMap<Long, Long> map = new HashMap<Long, Long>();
+        final LongSparseLongArray array = new LongSparseLongArray(r.nextInt(128));
+
+        for (int i = 0; i < 10240; i++) {
+            if (r.nextBoolean()) {
+                final long key = r.nextLong();
+                final long value = r.nextLong();
+                map.put(key, value);
+                array.put(key, value);
+            }
+            if (r.nextBoolean() && map.size() > 0) {
+                final int index = r.nextInt(map.size());
+                final long key = getKeyAtIndex(map, index);
+                map.remove(key);
+                array.delete(key);
+            }
+        }
+
+        Log.d(TAG, "verifying a map with " + map.size() + " entries");
+
+        for (Map.Entry<Long, Long> e : map.entrySet()) {
+            final long key = e.getKey();
+            final long value = e.getValue();
+            assertEquals(value, array.get(key));
+        }
+    }
+
+    private static <E> E getKeyAtIndex(Map<E, ?> map, int index) {
+        final Iterator<E> keys = map.keySet().iterator();
+        for (int i = 0; i < index; i++) {
+            keys.next();
+        }
+        return keys.next();
+    }
+}
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index c12761b..57fa498 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -51,7 +51,7 @@
               <li class="item carousel-home">
                  <div class="col-8">
                    <img
-src="http://4.bp.blogspot.com/-lfjzgG5Dqrk/UHMThRtpRwI/AAAAAAAABpk/h4d3nsmkgPM/s400/mint.png"
+src="//lh4.ggpht.com/-lfjzgG5Dqrk/UHMThRtpRwI/AAAAAAAABpk/h4d3nsmkgPM/s400/mint.png"
 class="play no-shadow no-transform" />
                  </div>
                 <div class="content-right col-6">
@@ -65,7 +65,7 @@
                <li class="item carousel-home">
                    <div class="col-8">
                      <img
-src="http://1.bp.blogspot.com/-6K1kfNOdek8/T72bXvtTSQI/AAAAAAAABmw/kYzmJt0_328/s1600/google-play-subscriptions.png" class="play"></div>
+src="//lh4.ggpht.com/-6K1kfNOdek8/T72bXvtTSQI/AAAAAAAABmw/kYzmJt0_328/s1600/google-play-subscriptions.png" class="play"></div>
                    <div class="content-right col-6">
                    <h2>In-app Subscriptions with Trials</h2>
                    <p>You can now set up a <strong>free trial period</strong> for any Google Play in-app subscription, making it easy for users try your subscriber content before automatically converting to a full subscription. Free trials give you a new way to bring users into your products and engage them effectively. </p>
@@ -77,7 +77,7 @@
                <li class="item carousel-home">
                    <div class="col-8">
                      <img
-src="http://2.bp.blogspot.com/-MgN5DnoO5XU/UHYGYzTcAOI/AAAAAAAABs4/jTS7sKkfBcM/s1600/pubsites.png" class="play"></div>
+src="//lh4.ggpht.com/-MgN5DnoO5XU/UHYGYzTcAOI/AAAAAAAABs4/jTS7sKkfBcM/s1600/pubsites.png" class="play"></div>
                    <div class="content-right col-6">
                    <p class="title-intro">From the blog:</p>
                    <h2>New Google Play Developer Console</h2>
@@ -90,7 +90,7 @@
                <li class="item carousel-home">
                  <div class="col-8">
                    <img
-src="http://4.bp.blogspot.com/-g05If_eKKRQ/UAcrVLI-OYI/AAAAAAAAAr8/AWvunVb5S-w/s320/nexus7.png"
+src="//lh4.ggpht.com/-g05If_eKKRQ/UAcrVLI-OYI/AAAAAAAAAr8/AWvunVb5S-w/s320/nexus7.png"
 class="play no-shadow no-transform" />
                  </div>
                 <div class="content-right col-6">
@@ -127,7 +127,7 @@
               <p>You can take advantage of the auth APIs in Google Play services to let your back end know which app is calling and for which user....</p>
               </a></li>
             <li><a href="//android-developers.blogspot.com/2012/12/daydream-interactive-screen-savers.html">
-              <div class="feed-image" style="background:url('//3.bp.blogspot.com/-wVsUOo4xGE0/UNy9mZ1nmMI/AAAAAAAAB4w/f6rhyLn5KbI/s1600/daydream-example.jpg') no-repeat 0 0;background-position:right top;"></div>
+              <div class="feed-image" style="background:url('//lh4.ggpht.com/-wVsUOo4xGE0/UNy9mZ1nmMI/AAAAAAAAB4w/f6rhyLn5KbI/s1600/daydream-example.jpg') no-repeat 0 0;background-position:right top;"></div>
               <h4>Daydream: Interactive Screen Savers</h4>
               <p>Daydream is an interactive screen-saver mode introduced in Android 4.2. Learn how to add Daydreams to your apps...</p>
               </a></li>
diff --git a/docs/html/index.jd b/docs/html/index.jd
index cf06324..afda7a9 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -22,7 +22,7 @@
                         <script type="text/javascript">
                             var params = { allowScriptAccess: "always" };
                             var atts = { id: "ytapiplayer" };
-                            swfobject.embedSWF("http://www.youtube.com/v/RRelFvc6Czo?enablejsapi=1&playerapiid=ytplayer&version=3&HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1",
+                            swfobject.embedSWF("//www.youtube.com/v/RRelFvc6Czo?enablejsapi=1&playerapiid=ytplayer&version=3&HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1",
                               "ytapiplayer", "600", "338", "8", null, null, params, atts);
 
                             // Callback used to pause/resume carousel based on video state
diff --git a/docs/html/training/animation/anim_page_transformer_depth.mp4 b/docs/html/training/animation/anim_page_transformer_depth.mp4
new file mode 100644
index 0000000..ba21663
--- /dev/null
+++ b/docs/html/training/animation/anim_page_transformer_depth.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_page_transformer_depth.ogv b/docs/html/training/animation/anim_page_transformer_depth.ogv
new file mode 100644
index 0000000..929735a
--- /dev/null
+++ b/docs/html/training/animation/anim_page_transformer_depth.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_page_transformer_depth.webm b/docs/html/training/animation/anim_page_transformer_depth.webm
new file mode 100644
index 0000000..37ab4e1
--- /dev/null
+++ b/docs/html/training/animation/anim_page_transformer_depth.webm
Binary files differ
diff --git a/docs/html/training/animation/anim_page_transformer_zoomout.mp4 b/docs/html/training/animation/anim_page_transformer_zoomout.mp4
new file mode 100644
index 0000000..598e964
--- /dev/null
+++ b/docs/html/training/animation/anim_page_transformer_zoomout.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_page_transformer_zoomout.ogv b/docs/html/training/animation/anim_page_transformer_zoomout.ogv
new file mode 100644
index 0000000..60b86af
--- /dev/null
+++ b/docs/html/training/animation/anim_page_transformer_zoomout.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_page_transformer_zoomout.webm b/docs/html/training/animation/anim_page_transformer_zoomout.webm
new file mode 100644
index 0000000..fc599a0
--- /dev/null
+++ b/docs/html/training/animation/anim_page_transformer_zoomout.webm
Binary files differ
diff --git a/docs/html/training/animation/cardflip.jd b/docs/html/training/animation/cardflip.jd
index ab3eb3a..1477f9fa 100644
--- a/docs/html/training/animation/cardflip.jd
+++ b/docs/html/training/animation/cardflip.jd
@@ -21,6 +21,16 @@
             <a href="#animate">Animate the Card Flip</a>
           </li>
         </ol>
+        <h2>
+          Try it out
+        </h2>
+        <div class="download-box">
+          <a href="{@docRoot}shareables/training/Animations.zip" class=
+          "button">Download the sample app</a>
+          <p class="filename">
+            Animations.zip
+          </p>
+        </div>
       </div>
     </div>
     <p> This lesson shows you how to do a card flip
diff --git a/docs/html/training/animation/crossfade.jd b/docs/html/training/animation/crossfade.jd
index 99e879b..2fbb6c0 100644
--- a/docs/html/training/animation/crossfade.jd
+++ b/docs/html/training/animation/crossfade.jd
@@ -20,6 +20,16 @@
             <a href="#animate">Crossfade the Views</a>
           </li>
         </ol>
+        <h2>
+          Try it out
+        </h2>
+        <div class="download-box">
+          <a href="{@docRoot}shareables/training/Animations.zip" class=
+          "button">Download the sample app</a>
+          <p class="filename">
+            Animations.zip
+          </p>
+        </div>
     </div>
     </div>
 
diff --git a/docs/html/training/animation/layout.jd b/docs/html/training/animation/layout.jd
index b8e0077..e3a47d6 100644
--- a/docs/html/training/animation/layout.jd
+++ b/docs/html/training/animation/layout.jd
@@ -11,7 +11,16 @@
     <li><a href="#views">Create the Layout</a></li>
     <li><a href="#add">Add, Update, or Remove Items from the Layout</a></li>
   </ol>
-
+  <h2>
+    Try it out
+  </h2>
+        <div class="download-box">
+          <a href="{@docRoot}shareables/training/Animations.zip" class=
+          "button">Download the sample app</a>
+          <p class="filename">
+            Animations.zip
+          </p>
+        </div>
 </div>
 </div>
 
diff --git a/docs/html/training/animation/screen-slide.jd b/docs/html/training/animation/screen-slide.jd
old mode 100755
new mode 100644
index 8a7af67..716805e
--- a/docs/html/training/animation/screen-slide.jd
+++ b/docs/html/training/animation/screen-slide.jd
@@ -9,15 +9,26 @@
          <ol>
             <li><a href="#views">Create the Views</a></li>
             <li><a href="#fragment">Create the Fragment</a></li>
-            <li><a href="#viewpager">Animate the Screen Slide</a></li>
+            <li><a href="#viewpager">Add a ViewPager</a></li>
+            <li><a href="#pagetransformer">Customize the Animation with PageTransformer</a></li>
         </ol>
+        <h2>
+          Try it out
+        </h2>
+        <div class="download-box">
+          <a href="{@docRoot}shareables/training/Animations.zip" class=
+          "button">Download the sample app</a>
+          <p class="filename">
+            Animations.zip
+          </p>
+        </div>
     </div>
   </div>
   <p>
       Screen slides are transitions between one entire screen to another and are common with UIs
       like setup wizards or slideshows. This lesson shows you how to do screen slides with
       a {@link android.support.v4.view.ViewPager} provided by the <a href=
-      "{@docRoot}/tools/extras/support-library.html">support library</a>.
+      "{@docRoot}tools/extras/support-library.html">support library</a>.
       {@link android.support.v4.view.ViewPager}s can animate screen slides
       automatically. Here's what a screen slide looks like that transitions from
       one screen of content to the next:
@@ -89,7 +100,7 @@
 }
 </pre>
 
-<h2 id="viewpager">Screen Slides with ViewPager</h2>
+<h2 id="viewpager">Add a ViewPager</h2>
 
 <p>{@link android.support.v4.view.ViewPager}s have built-in swipe gestures to transition
   through pages, and they display screen slide animations by default, so you don't need to create any. {@link android.support.v4.view.ViewPager}s use
@@ -112,12 +123,12 @@
 
 <ul>
   <li>Sets the content view to be the layout with the {@link android.support.v4.view.ViewPager}.</li>
-  <li>Create a class that extends the {@link android.support.v13.app.FragmentStatePagerAdapter} abstract class. Implement
+  <li>Creates a class that extends the {@link android.support.v13.app.FragmentStatePagerAdapter} abstract class and implements
   the {@link android.support.v4.app.FragmentStatePagerAdapter#getItem getItem()} method to supply
     instances of <code>ScreenSlidePageFragment</code> as new pages. The pager adapter also requires that you implement the
     {@link android.support.v4.view.PagerAdapter#getCount getCount()} method, which returns the amount of pages the adapter will create (five in the example).
   <li>Hooks up the {@link android.support.v4.view.PagerAdapter} to the {@link android.support.v4.view.ViewPager}</code>.</li>
-  <li>Handle's the device's back button by moving backwards in the virtual stack of fragments.
+  <li>Handles the device's back button by moving backwards in the virtual stack of fragments.
     If the user is already on the first page, go back on the activity back stack.</li>
 </ul>
 
@@ -182,4 +193,179 @@
         }
     }
 }
-</pre>
\ No newline at end of file
+</pre>
+
+
+<h2 id="pagetransformer">Customize the Animation with PageTransformer</h2>
+
+<p>To display a different animation from the default screen slide animation, implement the
+  {@link android.support.v4.view.ViewPager.PageTransformer} interface and supply it to
+  the view pager. The interface exposes a single method, {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()}. At each point in the screen's transition, this method is called once for each visible page (generally there's only one visible page) and for adjacent pages just off the screen.
+  For example, if page three is visible and the user drags towards page four,
+  {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()} is called
+  for pages two, three, and four at each step of the gesture.</p>
+
+  <p>
+  In your implementation of {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()},
+  you can then create custom slide animations by determining which pages need to be transformed based on the
+  position of the page on the screen, which is obtained from the <code>position</code> parameter
+  of the {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()} method.</p>
+
+<p>The <code>position</code> parameter indicates where a given page is located relative to the center of the screen. 
+It is a dynamic property that changes as the user scrolls through the pages. When a page fills the screen, its position value is <code>0</code>.
+When a page is drawn just off the right side of the screen, its position value is <code>1</code>. If the user scrolls halfway between pages one and two, page one has a position of -0.5 and page two has a position of 0.5. Based on the position of the pages on the screen, you can create custom slide animations by setting page properties with methods such as {@link android.view.View#setAlpha setAlpha()}, {@link android.view.View#setTranslationX setTranslationX()}, or
+  {@link android.view.View#setScaleY setScaleY()}.</p>
+
+
+<p>When you have an implementation of a {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer},
+call {@link android.support.v4.view.ViewPager#setPageTransformer setPageTransformer()} with
+  your implementation to apply your custom animations. For example, if you have a
+  {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer} named
+  <code>ZoomOutPageTransformer</code>, you can set your custom animations
+  like this:</p>
+<pre>
+ViewPager pager = (ViewPager) findViewById(R.id.pager);
+...
+pager.setPageTransformer(true, new ZoomOutPageTransformer());
+</pre>
+
+
+<p>See the <a href="#zoom-out">Zoom-out page transformer</a> and <a href="#depth-page">Depth page transformer</a>
+sections for examples and videos of a {@link android.support.v4.view.ViewPager.PageTransformer PageTransformer}.</p>
+
+
+<h3 id="zoom-out">Zoom-out page transformer</h3>
+<p>
+ This page transformer shrinks and fades pages when scrolling between
+ adjacent pages. As a page gets closer to the center, it grows back to
+ its normal size and fades in.
+</p>
+
+<div class="framed-galaxynexus-land-span-8">
+  <video class="play-on-hover" autoplay>
+    <source src="anim_page_transformer_zoomout.mp4" type="video/mp4">
+    <source src="anim_page_transformer_zoomout.webm" type="video/webm">
+    <source src="anim_page_transformer_zoomout.ogv" type="video/ogg">
+  </video>
+</div>
+
+<div class="figure-caption">
+  <code>ZoomOutPageTransformer</code> example
+  <div class="video-instructions">&nbsp;</div>
+</div>
+
+
+<pre>
+public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
+    private static float MIN_SCALE = 0.85f;
+    private static float MIN_ALPHA = 0.5f;
+
+    public void transformPage(View view, float position) {
+        int pageWidth = view.getWidth();
+        int pageHeight = view.getHeight();
+
+        if (position &lt; -1) { // [-Infinity,-1)
+            // This page is way off-screen to the left.
+            view.setAlpha(0);
+
+        } else if (position &lt;= 1) { // [-1,1]
+            // Modify the default slide transition to shrink the page as well
+            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
+            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
+            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
+            if (position &lt; 0) {
+                view.setTranslationX(horzMargin - vertMargin / 2);
+            } else {
+                view.setTranslationX(-horzMargin + vertMargin / 2);
+            }
+
+            // Scale the page down (between MIN_SCALE and 1)
+            view.setScaleX(scaleFactor);
+            view.setScaleY(scaleFactor);
+
+            // Fade the page relative to its size.
+            view.setAlpha(MIN_ALPHA +
+                    (scaleFactor - MIN_SCALE) /
+                    (1 - MIN_SCALE) * (1 - MIN_ALPHA));
+
+        } else { // (1,+Infinity]
+            // This page is way off-screen to the right.
+            view.setAlpha(0);
+        }
+    }
+}
+</pre>
+
+<h3 id="depth-page">Depth page transformer</h3>
+<p>
+This page transformer uses the default slide animation for sliding pages
+to the left, while using a "depth" animation for sliding pages to the
+right. This depth animation fades the page out, and scales it down linearly.
+</p>
+
+<div class="framed-galaxynexus-land-span-8">
+  <video class="play-on-hover" autoplay>
+    <source src="anim_page_transformer_depth.mp4" type="video/mp4">
+    <source src="anim_page_transformer_depth.webm" type="video/webm">
+    <source src="anim_page_transformer_depth.ogv" type="video/ogg">
+  </video>
+</div>
+
+<div class="figure-caption">
+  <code>DepthPageTransformer</code> example
+  <div class="video-instructions">&nbsp;</div>
+</div>
+
+<p class="note"><strong>Note:</strong> During the depth animation, the default animation (a screen slide) still
+takes place, so you must counteract the screen slide with a negative X translation.
+
+For example:
+
+<pre>
+view.setTranslationX(-1 * view.getWidth() * position);
+</pre>
+
+The following example shows how to counteract the default screen slide animation
+in a working page transformer:
+</p>
+
+<pre>
+
+public class DepthPageTransformer implements ViewPager.PageTransformer {
+    private static float MIN_SCALE = 0.75f;
+
+    public void transformPage(View view, float position) {
+        int pageWidth = view.getWidth();
+
+        if (position &lt; -1) { // [-Infinity,-1)
+            // This page is way off-screen to the left.
+            view.setAlpha(0);
+
+        } else if (position &lt;= 0) { // [-1,0]
+            // Use the default slide transition when moving to the left page
+            view.setAlpha(1);
+            view.setTranslationX(0);
+            view.setScaleX(1);
+            view.setScaleY(1);
+
+        } else if (position &lt;= 1) { // (0,1]
+            // Fade the page out.
+            view.setAlpha(1 - position);
+
+            // Counteract the default slide transition
+            view.setTranslationX(pageWidth * -position);
+
+            // Scale the page down (between MIN_SCALE and 1)
+            float scaleFactor = MIN_SCALE
+                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
+            view.setScaleX(scaleFactor);
+            view.setScaleY(scaleFactor);
+
+        } else { // (1,+Infinity]
+            // This page is way off-screen to the right.
+            view.setAlpha(0);
+        }
+    }
+}
+</pre>
+
diff --git a/docs/html/training/animation/zoom.jd b/docs/html/training/animation/zoom.jd
index 5dc2b6c..6a38e7d 100644
--- a/docs/html/training/animation/zoom.jd
+++ b/docs/html/training/animation/zoom.jd
@@ -19,6 +19,16 @@
             <a href="#animate">Zoom the View</a>
           </li>
         </ol>
+        <h2>
+          Try it out
+        </h2>
+        <div class="download-box">
+          <a href="{@docRoot}shareables/training/Animations.zip" class=
+          "button">Download the sample app</a>
+          <p class="filename">
+            Animations.zip
+          </p>
+        </div>
       </div>
     </div>
     <p>
diff --git a/docs/html/training/articles/smp.jd b/docs/html/training/articles/smp.jd
index 53d7879..d46787d 100644
--- a/docs/html/training/articles/smp.jd
+++ b/docs/html/training/articles/smp.jd
@@ -628,7 +628,7 @@
 
 <p>The “loop_until” seen in previous examples has been expanded to show the load
 of B into reg0.  reg1 is assigned the numeric value 8, and reg2 is loaded from
-the address [A+reg1] (same location that thread 1 is accessing).</p>
+the address [A+reg1] (the same location that thread 1 is accessing).</p>
 
 <p>This will not behave correctly because the load from B could be observed
 after the load from [A+reg1].  We can fix this with a load/load barrier after
@@ -640,7 +640,7 @@
 <th>Thread 2</th>
 </tr>
 <tr>
-<td><code>A = 41<br />
+<td><code>[A+8] = 41<br />
 <em>store/store barrier</em><br />
 B = 1    // “A is ready”</code></td>
 <td><code>loop:<br />
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
index 66f2c81..0bad7e0 100644
--- a/graphics/java/android/renderscript/Matrix3f.java
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -138,7 +138,7 @@
         mMat[6] =  zx*nc + ys;
         mMat[1] =  xy*nc + zs;
         mMat[4] = y*y*nc +  c;
-        mMat[9] =  yz*nc - xs;
+        mMat[7] =  yz*nc - xs;
         mMat[2] =  zx*nc - ys;
         mMat[6] =  yz*nc + xs;
         mMat[8] = z*z*nc +  c;
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index aabfcae..65d7b8f 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -16,9 +16,8 @@
 
 package android.security;
 
-import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
 import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLKeyHolder;
 
 import android.util.Log;
 
@@ -210,10 +209,8 @@
         byte[] keyBytes = null;
 
         final String pkeyAlias;
-        if (key instanceof OpenSSLRSAPrivateKey) {
-            pkeyAlias = ((OpenSSLRSAPrivateKey) key).getPkeyAlias();
-        } else if (key instanceof OpenSSLDSAPrivateKey) {
-            pkeyAlias = ((OpenSSLDSAPrivateKey) key).getPkeyAlias();
+        if (key instanceof OpenSSLKeyHolder) {
+            pkeyAlias = ((OpenSSLKeyHolder) key).getOpenSSLKey().getAlias();
         } else {
             pkeyAlias = null;
         }
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 628d8a0..ae188be 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -270,9 +270,7 @@
     GammaFontRenderer* fontRenderer;
 
     Dither dither;
-#if STENCIL_BUFFER_SIZE
     Stencil stencil;
-#endif
 
     // Debug methods
     PFNGLINSERTEVENTMARKEREXTPROC eventMark;
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index ee1d391..79dbfb0 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -41,6 +41,7 @@
     renderer = NULL;
     displayList = NULL;
     fbo = 0;
+    stencil = 0;
     debugDrawUpdate = false;
     Caches::getInstance().resourceCache.incrementRefcount(this);
 }
@@ -53,9 +54,67 @@
     deleteTexture();
 }
 
-void Layer::removeFbo() {
+uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
+    return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
+}
+
+uint32_t Layer::computeIdealHeight(uint32_t layerHeight) {
+    return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
+}
+
+bool Layer::resize(const uint32_t width, const uint32_t height) {
+    uint32_t desiredWidth = computeIdealWidth(width);
+    uint32_t desiredHeight = computeIdealWidth(height);
+
+    if (desiredWidth <= getWidth() && desiredHeight <= getHeight()) {
+        return true;
+    }
+
+    uint32_t oldWidth = getWidth();
+    uint32_t oldHeight = getHeight();
+
+    setSize(desiredWidth, desiredHeight);
+
     if (fbo) {
-        LayerRenderer::flushLayer(this);
+        Caches::getInstance().activeTexture(0);
+        bindTexture();
+        allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+
+        if (glGetError() != GL_NO_ERROR) {
+            setSize(oldWidth, oldHeight);
+            return false;
+        }
+    }
+
+    if (stencil) {
+        bindStencilRenderBuffer();
+        allocateStencilRenderBuffer();
+
+        if (glGetError() != GL_NO_ERROR) {
+            setSize(oldWidth, oldHeight);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void Layer::removeFbo(bool flush) {
+    if (stencil) {
+        // TODO: recycle & cache instead of simply deleting
+        GLuint previousFbo;
+        glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
+        if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
+        if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+
+        glDeleteRenderbuffers(1, &stencil);
+        stencil = 0;
+    }
+
+    if (fbo) {
+        if (flush) LayerRenderer::flushLayer(this);
+        // If put fails the cache will delete the FBO
         Caches::getInstance().fboCache.put(fbo);
         fbo = 0;
     }
@@ -75,7 +134,5 @@
     }
 }
 
-
-
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 181eb6c..a551b3f 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -48,7 +48,15 @@
     Layer(const uint32_t layerWidth, const uint32_t layerHeight);
     ~Layer();
 
-    void removeFbo();
+    static uint32_t computeIdealWidth(uint32_t layerWidth);
+    static uint32_t computeIdealHeight(uint32_t layerHeight);
+
+    /**
+     * Calling this method will remove (either by recycling or
+     * destroying) the associated FBO, if present, and any render
+     * buffer (stencil for instance.)
+     */
+    void removeFbo(bool flush = true);
 
     /**
      * Sets this layer's region to a rectangle. Computes the appropriate
@@ -86,6 +94,17 @@
         return texture.height;
     }
 
+    /**
+     * Resize the layer and its texture if needed.
+     *
+     * @param width The new width of the layer
+     * @param height The new height of the layer
+     *
+     * @return True if the layer was resized or nothing happened, false if
+     *         a failure occurred during the resizing operation
+     */
+    bool resize(const uint32_t width, const uint32_t height);
+
     void setSize(uint32_t width, uint32_t height) {
         texture.width = width;
         texture.height = height;
@@ -134,6 +153,14 @@
         return fbo;
     }
 
+    inline void setStencilRenderBuffer(GLuint renderBuffer) {
+        this->stencil = renderBuffer;
+    }
+
+    inline GLuint getStencilRenderBuffer() {
+        return stencil;
+    }
+
     inline GLuint getTexture() {
         return texture.id;
     }
@@ -190,6 +217,12 @@
         }
     }
 
+    inline void bindStencilRenderBuffer() {
+        if (stencil) {
+            glBindRenderbuffer(GL_RENDERBUFFER, stencil);
+        }
+    }
+
     inline void generateTexture() {
         if (!texture.id) {
             glGenTextures(1, &texture.id);
@@ -212,15 +245,20 @@
         texture.id = 0;
     }
 
-    inline void deleteFbo() {
-        if (fbo) glDeleteFramebuffers(1, &fbo);
-    }
-
     inline void allocateTexture(GLenum format, GLenum storage) {
 #if DEBUG_LAYERS
         ALOGD("  Allocate layer: %dx%d", getWidth(), getHeight());
 #endif
-        glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
+        if (texture.id) {
+            glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0,
+                    format, storage, NULL);
+        }
+    }
+
+    inline void allocateStencilRenderBuffer() {
+        if (stencil) {
+            glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWidth(), getHeight());
+        }
     }
 
     inline mat4& getTexTransform() {
@@ -275,6 +313,12 @@
     GLuint fbo;
 
     /**
+     * Name of the render buffer used as the stencil buffer. If the
+     * name is 0, this layer does not have a stencil buffer.
+     */
+    GLuint stencil;
+
+    /**
      * Indicates whether this layer has been used already.
      */
     bool empty;
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index cfc5b04..4278464 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -136,31 +136,6 @@
     }
 }
 
-bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t height) {
-    // TODO: We should be smarter and see if we have a texture of the appropriate
-    //       size already in the cache, and reuse it instead of creating a new one
-
-    LayerEntry entry(width, height);
-    if (entry.mWidth <= layer->getWidth() && entry.mHeight <= layer->getHeight()) {
-        return true;
-    }
-
-    uint32_t oldWidth = layer->getWidth();
-    uint32_t oldHeight = layer->getHeight();
-
-    Caches::getInstance().activeTexture(0);
-    layer->bindTexture();
-    layer->setSize(entry.mWidth, entry.mHeight);
-    layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
-
-    if (glGetError() != GL_NO_ERROR) {
-        layer->setSize(oldWidth, oldHeight);
-        return false;
-    }
-
-    return true;
-}
-
 bool LayerCache::put(Layer* layer) {
     if (!layer->isCacheable()) return false;
 
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index fc2cd91..7720b42 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -72,17 +72,6 @@
      * Clears the cache. This causes all layers to be deleted.
      */
     void clear();
-    /**
-     * Resize the specified layer if needed.
-     *
-     * @param layer The layer to resize
-     * @param width The new width of the layer
-     * @param height The new height of the layer
-     *
-     * @return True if the layer was resized or nothing happened, false if
-     *         a failure occurred during the resizing operation
-     */
-    bool resize(Layer* layer, const uint32_t width, const uint32_t height);
 
     /**
      * Sets the maximum size of the cache in bytes.
@@ -108,8 +97,8 @@
         }
 
         LayerEntry(const uint32_t layerWidth, const uint32_t layerHeight): mLayer(NULL) {
-            mWidth = uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
-            mHeight = uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
+            mWidth = Layer::computeIdealWidth(layerWidth);
+            mHeight = Layer::computeIdealHeight(layerHeight);
         }
 
         LayerEntry(Layer* layer):
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 3484d41..61bedbb 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -100,13 +100,21 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Dirty region tracking
+// Layer support
 ///////////////////////////////////////////////////////////////////////////////
 
 bool LayerRenderer::hasLayer() {
     return true;
 }
 
+void LayerRenderer::ensureStencilBuffer() {
+    attachStencilBufferToLayer(mLayer);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Dirty region tracking
+///////////////////////////////////////////////////////////////////////////////
+
 Region* LayerRenderer::getRegion() {
     if (getSnapshot()->flags & Snapshot::kFlagFboTarget) {
         return OpenGLRenderer::getRegion();
@@ -256,7 +264,7 @@
     if (layer) {
         LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->getFbo(), width, height);
 
-        if (Caches::getInstance().layerCache.resize(layer, width, height)) {
+        if (layer->resize(width, height)) {
             layer->layer.set(0.0f, 0.0f, width, height);
             layer->texCoords.set(0.0f, height / float(layer->getHeight()),
                     width / float(layer->getWidth()), 0.0f);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index c44abce..7a8bdc5 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -64,6 +64,7 @@
     static void flushLayer(Layer* layer);
 
 protected:
+    virtual void ensureStencilBuffer();
     virtual bool hasLayer();
     virtual Region* getRegion();
     virtual GLint getTargetFbo();
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index a924362..79fae2b 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -30,6 +30,16 @@
 namespace android {
 namespace uirenderer {
 
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+static const float EPSILON = 0.0000001f;
+
+///////////////////////////////////////////////////////////////////////////////
+// Matrix
+///////////////////////////////////////////////////////////////////////////////
+
 void Matrix4::loadIdentity() {
     data[kScaleX]       = 1.0f;
     data[kSkewY]        = 0.0f;
@@ -51,44 +61,91 @@
     data[kTranslateZ]   = 0.0f;
     data[kPerspective2] = 1.0f;
 
-    mIsIdentity = true;
-    mSimpleMatrix = true;
+    mType = kTypeIdentity | kTypeRectToRect;
+}
+
+static bool isZero(float f) {
+    return fabs(f) <= EPSILON;
+}
+
+uint32_t Matrix4::getType() const {
+    if (mType & kTypeUnknown) {
+        mType = kTypeIdentity;
+
+        if (data[kPerspective0] != 0.0f || data[kPerspective1] != 0.0f ||
+                data[kPerspective2] != 1.0f) {
+            mType |= kTypePerspective;
+        }
+
+        if (data[kTranslateX] != 0.0f || data[kTranslateY] != 0.0f) {
+            mType |= kTypeTranslate;
+        }
+
+        float m00 = data[kScaleX];
+        float m01 = data[kSkewX];
+        float m10 = data[kSkewY];
+        float m11 = data[kScaleY];
+
+        if (m01 != 0.0f || m10 != 0.0f) {
+            mType |= kTypeAffine;
+        }
+
+        if (m00 != 1.0f || m11 != 1.0f) {
+            mType |= kTypeScale;
+        }
+
+        // The following section determines whether the matrix will preserve
+        // rectangles. For instance, a rectangle transformed by a pure
+        // translation matrix will result in a rectangle. A rectangle
+        // transformed by a 45 degrees rotation matrix is not a rectangle.
+        // If the matrix has a perspective component then we already know
+        // it doesn't preserve rectangles.
+        if (!(mType & kTypePerspective)) {
+            if ((isZero(m00) && isZero(m11) && !isZero(m01) && !isZero(m10)) ||
+                    (isZero(m01) && isZero(m10) && !isZero(m00) && !isZero(m11))) {
+                mType |= kTypeRectToRect;
+            }
+        }
+    }
+    return mType;
+}
+
+uint32_t Matrix4::getGeometryType() const {
+    return getType() & sGeometryMask;
+}
+
+bool Matrix4::rectToRect() const {
+    return getType() & kTypeRectToRect;
 }
 
 bool Matrix4::changesBounds() const {
-    return !(data[0] == 1.0f && data[1] == 0.0f && data[2] == 0.0f && data[4] == 0.0f &&
-             data[5] == 1.0f && data[6] == 0.0f && data[8] == 0.0f && data[9] == 0.0f &&
-             data[10] == 1.0f);
+    return getType() & (kTypeScale | kTypeAffine | kTypePerspective);
 }
 
 bool Matrix4::isPureTranslate() const {
-    return mSimpleMatrix && data[kScaleX] == 1.0f && data[kScaleY] == 1.0f;
+    return getGeometryType() == kTypeTranslate;
 }
 
 bool Matrix4::isSimple() const {
-    return mSimpleMatrix;
+    return getGeometryType() <= (kTypeScale | kTypeTranslate);
 }
 
 bool Matrix4::isIdentity() const {
-    return mIsIdentity;
+    return getGeometryType() == kTypeIdentity;
 }
 
 bool Matrix4::isPerspective() const {
-    return data[kPerspective0] != 0.0f || data[kPerspective1] != 0.0f ||
-            data[kPerspective2] != 1.0f;
+    return getType() & kTypePerspective;
 }
 
 void Matrix4::load(const float* v) {
     memcpy(data, v, sizeof(data));
-    // TODO: Do something smarter here
-    mSimpleMatrix = false;
-    mIsIdentity = false;
+    mType = kTypeUnknown;
 }
 
 void Matrix4::load(const Matrix4& v) {
     memcpy(data, v.data, sizeof(data));
-    mSimpleMatrix = v.mSimpleMatrix;
-    mIsIdentity = v.mIsIdentity;
+    mType = v.getType();
 }
 
 void Matrix4::load(const SkMatrix& v) {
@@ -108,8 +165,14 @@
 
     data[kScaleZ] = 1.0f;
 
-    mSimpleMatrix = (v.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask));
-    mIsIdentity = v.isIdentity();
+    // NOTE: The flags are compatible between SkMatrix and this class.
+    //       However, SkMatrix::getType() does not return the flag
+    //       kRectStaysRect. The return value is masked with 0xF
+    //       so we need the extra rectStaysRect() check
+    mType = v.getType();
+    if (v.rectStaysRect()) {
+        mType |= kTypeRectToRect;
+    }
 }
 
 void Matrix4::copyTo(SkMatrix& v) const {
@@ -158,8 +221,7 @@
     data[kPerspective2] = (v.data[kScaleX] * v.data[kScaleY] -
             v.data[kSkewX] * v.data[kSkewY]) * scale;
 
-    mSimpleMatrix = v.mSimpleMatrix;
-    mIsIdentity = v.mIsIdentity;
+    mType = kTypeUnknown;
 }
 
 void Matrix4::copyTo(float* v) const {
@@ -178,7 +240,7 @@
     for (int i = 0; i < 16; i++) {
         data[i] *= v;
     }
-    mIsIdentity = false;
+    mType = kTypeUnknown;
 }
 
 void Matrix4::loadTranslate(float x, float y, float z) {
@@ -188,7 +250,7 @@
     data[kTranslateY] = y;
     data[kTranslateZ] = z;
 
-    mIsIdentity = false;
+    mType = kTypeTranslate | kTypeRectToRect;
 }
 
 void Matrix4::loadScale(float sx, float sy, float sz) {
@@ -198,7 +260,7 @@
     data[kScaleY] = sy;
     data[kScaleZ] = sz;
 
-    mIsIdentity = false;
+    mType = kTypeScale | kTypeRectToRect;
 }
 
 void Matrix4::loadSkew(float sx, float sy) {
@@ -216,8 +278,23 @@
     data[kPerspective1] = 0.0f;
     data[kPerspective2] = 1.0f;
 
-    mSimpleMatrix = false;
-    mIsIdentity = false;
+    mType = kTypeUnknown;
+}
+
+void Matrix4::loadRotate(float angle) {
+    angle *= float(M_PI / 180.0f);
+    float c = cosf(angle);
+    float s = sinf(angle);
+
+    loadIdentity();
+
+    data[kScaleX]     = c;
+    data[kSkewX]      = -s;
+
+    data[kSkewY]      = s;
+    data[kScaleY]     = c;
+
+    mType = kTypeUnknown;
 }
 
 void Matrix4::loadRotate(float angle, float x, float y, float z) {
@@ -257,8 +334,7 @@
     data[6]       =    yz * nc + xs;
     data[kScaleZ] = z * z * nc +  c;
 
-    mSimpleMatrix = false;
-    mIsIdentity = false;
+    mType = kTypeUnknown;
 }
 
 void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) {
@@ -282,8 +358,7 @@
         set(i, 3, w);
     }
 
-    mSimpleMatrix = u.mSimpleMatrix && v.mSimpleMatrix;
-    mIsIdentity = false;
+    mType = kTypeUnknown;
 }
 
 void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) {
@@ -296,13 +371,13 @@
     data[kTranslateY] = -(top + bottom) / (top - bottom);
     data[kTranslateZ] = -(far + near) / (far - near);
 
-    mIsIdentity = false;
+    mType = kTypeTranslate | kTypeScale | kTypeRectToRect;
 }
 
 #define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
 
 void Matrix4::mapPoint(float& x, float& y) const {
-    if (mSimpleMatrix) {
+    if (isSimple()) {
         MUL_ADD_STORE(x, data[kScaleX], data[kTranslateX]);
         MUL_ADD_STORE(y, data[kScaleY], data[kTranslateY]);
         return;
@@ -318,7 +393,7 @@
 }
 
 void Matrix4::mapRect(Rect& r) const {
-    if (mSimpleMatrix) {
+    if (isSimple()) {
         MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]);
         MUL_ADD_STORE(r.right, data[kScaleX], data[kTranslateX]);
         MUL_ADD_STORE(r.top, data[kScaleY], data[kTranslateY]);
@@ -376,7 +451,7 @@
 }
 
 void Matrix4::dump() const {
-    ALOGD("Matrix4[simple=%d", mSimpleMatrix);
+    ALOGD("Matrix4[simple=%d, type=0x%x", isSimple(), getType());
     ALOGD("  %f %f %f %f", data[kScaleX], data[kSkewX], data[8], data[kTranslateX]);
     ALOGD("  %f %f %f %f", data[kSkewY], data[kScaleY], data[9], data[kTranslateY]);
     ALOGD("  %f %f %f %f", data[2], data[6], data[kScaleZ], data[kTranslateZ]);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index f86823d..46a5597 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -48,6 +48,21 @@
         kPerspective2 = 15
     };
 
+    // NOTE: The flags from kTypeIdentity to kTypePerspective
+    //       must be kept in sync with the type flags found
+    //       in SkMatrix
+    enum Type {
+        kTypeIdentity = 0,
+        kTypeTranslate = 0x1,
+        kTypeScale = 0x2,
+        kTypeAffine = 0x4,
+        kTypePerspective = 0x8,
+        kTypeRectToRect = 0x10,
+        kTypeUnknown = 0x20,
+    };
+
+    static const int sGeometryMask = 0xf;
+
     Matrix4() {
         loadIdentity();
     }
@@ -75,11 +90,14 @@
     void loadTranslate(float x, float y, float z);
     void loadScale(float sx, float sy, float sz);
     void loadSkew(float sx, float sy);
+    void loadRotate(float angle);
     void loadRotate(float angle, float x, float y, float z);
     void loadMultiply(const Matrix4& u, const Matrix4& v);
 
     void loadOrtho(float left, float right, float bottom, float top, float near, float far);
 
+    uint32_t getType() const;
+
     void multiply(const Matrix4& v) {
         Matrix4 u;
         u.loadMultiply(*this, v);
@@ -112,10 +130,14 @@
         multiply(u);
     }
 
-    bool isPureTranslate() const;
+    /**
+     * If the matrix is identity or translate and/or scale.
+     */
     bool isSimple() const;
+    bool isPureTranslate() const;
     bool isIdentity() const;
     bool isPerspective() const;
+    bool rectToRect() const;
 
     bool changesBounds() const;
 
@@ -131,8 +153,7 @@
     void dump() const;
 
 private:
-    bool mSimpleMatrix;
-    bool mIsIdentity;
+    mutable uint32_t mType;
 
     inline float get(int i, int j) const {
         return data[i * 4 + j];
@@ -141,6 +162,9 @@
     inline void set(int i, int j, float v) {
         data[i * 4 + j] = v;
     }
+
+    uint32_t getGeometryType() const;
+
 }; // class Matrix4
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index bb1edbb..f55bc9d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -837,6 +837,8 @@
         return;
     }
 
+    Layer* layer = current->layer;
+    const Rect& rect = layer->layer;
     const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer;
 
     if (fboLayer) {
@@ -844,6 +846,9 @@
 
         // Detach the texture from the FBO
         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+
+        layer->removeFbo(false);
+
         // Unbind current FBO and restore previous one
         glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
         debugOverdraw(true, false);
@@ -851,9 +856,6 @@
         startTiling(previous);
     }
 
-    Layer* layer = current->layer;
-    const Rect& rect = layer->layer;
-
     if (!fboLayer && layer->getAlpha() < 255) {
         drawColorRect(rect.left, rect.top, rect.right, rect.bottom,
                 layer->getAlpha() << 24, SkXfermode::kDstIn_Mode, true);
@@ -881,17 +883,6 @@
         composeLayerRect(layer, rect, true);
     }
 
-    if (fboLayer) {
-        // Note: No need to use glDiscardFramebufferEXT() since we never
-        //       create/compose layers that are not on screen with this
-        //       code path
-        // See LayerRenderer::destroyLayer(Layer*)
-
-        // Put the FBO name back in the cache, if it doesn't fit, it will be destroyed
-        mCaches.fboCache.put(current->fbo);
-        layer->setFbo(0);
-    }
-
     dirtyClip();
 
     // Failing to add the layer to the cache should happen only if the layer is too large
@@ -1001,10 +992,14 @@
         const float texY = 1.0f / float(layer->getHeight());
         const float height = rect.getHeight();
 
+        setupDraw();
+
+        // We must get (and therefore bind) the region mesh buffer
+        // after we setup drawing in case we need to mess with the
+        // stencil buffer in setupDraw()
         TextureVertex* mesh = mCaches.getRegionMesh();
         GLsizei numQuads = 0;
 
-        setupDraw();
         setupDrawWithTexture();
         setupDrawColor(alpha, alpha, alpha, alpha);
         setupDrawColorFilter();
@@ -1089,6 +1084,25 @@
 #endif
 }
 
+void OpenGLRenderer::drawRegionRects(const SkRegion& region, int color,
+        SkXfermode::Mode mode, bool dirty) {
+    int count = 0;
+    Vector<float> rects;
+
+    SkRegion::Iterator it(region);
+    while (!it.done()) {
+        const SkIRect& r = it.rect();
+        rects.push(r.fLeft);
+        rects.push(r.fTop);
+        rects.push(r.fRight);
+        rects.push(r.fBottom);
+        count++;
+        it.next();
+    }
+
+    drawColorRects(rects.array(), count, color, mode, true, dirty);
+}
+
 void OpenGLRenderer::dirtyLayer(const float left, const float top,
         const float right, const float bottom, const mat4 transform) {
     if (hasLayer()) {
@@ -1219,6 +1233,66 @@
     }
 }
 
+void OpenGLRenderer::ensureStencilBuffer() {
+    // Thanks to the mismatch between EGL and OpenGL ES FBO we
+    // cannot attach a stencil buffer to fbo0 dynamically. Let's
+    // just hope we have one when hasLayer() returns false.
+    if (hasLayer()) {
+        attachStencilBufferToLayer(mSnapshot->layer);
+    }
+}
+
+void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) {
+    // The layer's FBO is already bound when we reach this stage
+    if (!layer->getStencilRenderBuffer()) {
+        // TODO: See Layer::removeFbo(). The stencil renderbuffer should be cached
+        GLuint buffer;
+        glGenRenderbuffers(1, &buffer);
+
+        layer->setStencilRenderBuffer(buffer);
+        layer->bindStencilRenderBuffer();
+        layer->allocateStencilRenderBuffer();
+
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer);
+    }
+}
+
+void OpenGLRenderer::setStencilFromClip() {
+    if (!mCaches.debugOverdraw) {
+        if (!mSnapshot->clipRegion->isEmpty()) {
+            // NOTE: The order here is important, we must set dirtyClip to false
+            //       before any draw call to avoid calling back into this method
+            mDirtyClip = false;
+
+            ensureStencilBuffer();
+
+            mCaches.stencil.enableWrite();
+
+            // Clear the stencil but first make sure we restrict drawing
+            // to the region's bounds
+            bool resetScissor = mCaches.enableScissor();
+            if (resetScissor) {
+                // The scissor was not set so we now need to update it
+                setScissorFromClip();
+            }
+            mCaches.stencil.clear();
+            if (resetScissor) mCaches.disableScissor();
+
+            // NOTE: We could use the region contour path to generate a smaller mesh
+            //       Since we are using the stencil we could use the red book path
+            //       drawing technique. It might increase bandwidth usage though.
+
+            // The last parameter is important: we are not drawing in the color buffer
+            // so we don't want to dirty the current layer, if any
+            drawRegionRects(*mSnapshot->clipRegion, 0xff000000, SkXfermode::kSrc_Mode, false);
+
+            mCaches.stencil.enableTest();
+        } else {
+            mCaches.stencil.disable();
+        }
+    }
+}
+
 const Rect& OpenGLRenderer::getClipBounds() {
     return mSnapshot->getLocalClip();
 }
@@ -1284,40 +1358,60 @@
     return rejected;
 }
 
+void OpenGLRenderer::debugClip() {
+#if DEBUG_CLIP_REGIONS
+    if (!isDeferred() && !mSnapshot->clipRegion->isEmpty()) {
+        drawRegionRects(*mSnapshot->clipRegion, 0x7f00ff00, SkXfermode::kSrcOver_Mode);
+    }
+#endif
+}
+
 bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
-    bool clipped = mSnapshot->clip(left, top, right, bottom, op);
+    if (CC_LIKELY(mSnapshot->transform->rectToRect())) {
+        bool clipped = mSnapshot->clip(left, top, right, bottom, op);
+        if (clipped) {
+            dirtyClip();
+        }
+        return !mSnapshot->clipRect->isEmpty();
+    }
+
+    SkPath path;
+    path.addRect(left, top, right, bottom);
+
+    return clipPath(&path, op);
+}
+
+bool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) {
+    SkMatrix transform;
+    mSnapshot->transform->copyTo(transform);
+
+    SkPath transformed;
+    path->transform(transform, &transformed);
+
+    SkRegion clip;
+    if (!mSnapshot->clipRegion->isEmpty()) {
+        clip.setRegion(*mSnapshot->clipRegion);
+    } else {
+        Rect* bounds = mSnapshot->clipRect;
+        clip.setRect(bounds->left, bounds->top, bounds->right, bounds->bottom);
+    }
+
+    SkRegion region;
+    region.setPath(transformed, clip);
+
+    bool clipped = mSnapshot->clipRegionTransformed(region, op);
     if (clipped) {
         dirtyClip();
-#if DEBUG_CLIP_REGIONS
-        if (!isDeferred() && mSnapshot->clipRegion && !mSnapshot->clipRegion->isRect()) {
-            int count = 0;
-            Vector<float> rects;
-            SkRegion::Iterator it(*mSnapshot->clipRegion);
-            while (!it.done()) {
-                const SkIRect& r = it.rect();
-                rects.push(r.fLeft);
-                rects.push(r.fTop);
-                rects.push(r.fRight);
-                rects.push(r.fBottom);
-                count++;
-                it.next();
-            }
-
-            drawColorRects(rects.array(), count, 0x7f00ff00, SkXfermode::kSrcOver_Mode, true);
-        }
-#endif
     }
     return !mSnapshot->clipRect->isEmpty();
 }
 
-bool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) {
-    const SkRect& bounds = path->getBounds();
-    return clipRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, op);
-}
-
 bool OpenGLRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
-    const SkIRect& bounds = region->getBounds();
-    return clipRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, op);
+    bool clipped = mSnapshot->clipRegionTransformed(*region, op);
+    if (clipped) {
+        dirtyClip();
+    }
+    return !mSnapshot->clipRect->isEmpty();
 }
 
 Rect* OpenGLRenderer::getClipRect() {
@@ -1332,8 +1426,11 @@
     // TODO: It would be best if we could do this before quickReject()
     //       changes the scissor test state
     if (clear) clearLayerRegions();
+    // Make sure setScissor & setStencil happen at the beginning of
+    // this method
     if (mDirtyClip) {
         setScissorFromClip();
+        setStencilFromClip();
     }
     mDescription.reset();
     mSetShaderColor = false;
@@ -3085,7 +3182,7 @@
 }
 
 status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color,
-        SkXfermode::Mode mode, bool ignoreTransform) {
+        SkXfermode::Mode mode, bool ignoreTransform, bool dirty) {
 
     float left = FLT_MAX;
     float top = FLT_MAX;
@@ -3103,7 +3200,7 @@
         float r = rects[index + 2];
         float b = rects[index + 3];
 
-        if (!quickRejectNoScissor(left, top, right, bottom)) {
+        if (ignoreTransform || !quickRejectNoScissor(left, top, right, bottom)) {
             Vertex::set(vertex++, l, b);
             Vertex::set(vertex++, l, t);
             Vertex::set(vertex++, r, t);
@@ -3136,7 +3233,7 @@
     setupDrawColorFilterUniforms();
     setupDrawVertices((GLvoid*) &mesh[0].position[0]);
 
-    if (hasLayer()) {
+    if (dirty && hasLayer()) {
         dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
     }
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index f07325f..d4e1eb5 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -287,6 +287,19 @@
     void resumeAfterLayer();
 
     /**
+     * This method is called whenever a stencil buffer is required. Subclasses
+     * should override this method and call attachStencilBufferToLayer() on the
+     * appropriate layer(s).
+     */
+    virtual void ensureStencilBuffer();
+
+    /**
+     * Obtains a stencil render buffer (allocating it if necessary) and
+     * attaches it to the specified layer.
+     */
+    void attachStencilBufferToLayer(Layer* layer);
+
+    /**
      * Compose the layer defined in the current snapshot with the layer
      * defined by the previous snapshot.
      *
@@ -423,6 +436,12 @@
     void setScissorFromClip();
 
     /**
+     * Sets the clipping region using the stencil buffer. The clip region
+     * is defined by the current snapshot's clipRegion member.
+     */
+    void setStencilFromClip();
+
+    /**
      * Performs a quick reject but does not affect the scissor. Returns
      * the transformed rect to test and the current clip.
      */
@@ -524,9 +543,10 @@
      * @param color The rectangles' ARGB color, defined as a packed 32 bits word
      * @param mode The Skia xfermode to use
      * @param ignoreTransform True if the current transform should be ignored
+     * @param dirty True if calling this method should dirty the current layer
      */
     status_t drawColorRects(const float* rects, int count, int color,
-            SkXfermode::Mode mode, bool ignoreTransform = false);
+            SkXfermode::Mode mode, bool ignoreTransform = false, bool dirty = true);
 
     /**
      * Draws the shape represented by the specified path texture.
@@ -774,6 +794,19 @@
      */
     void drawRegionRects(const Region& region);
 
+    /**
+     * Renders the specified region as a series of rectangles. The region
+     * must be in screen-space coordinates.
+     */
+    void drawRegionRects(const SkRegion& region, int color, SkXfermode::Mode mode,
+            bool dirty = false);
+
+    /**
+     * Draws the current clip region if any. Only when DEBUG_CLIP_REGIONS
+     * is turned on.
+     */
+    void debugClip();
+
     void debugOverdraw(bool enable, bool clear);
     void renderOverdraw();
 
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index d947299..22c7dde 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -31,7 +31,7 @@
     transform = &mTransformRoot;
     clipRect = &mClipRectRoot;
     region = NULL;
-    clipRegion = NULL;
+    clipRegion = &mClipRegionRoot;
 }
 
 /**
@@ -39,12 +39,10 @@
  * the previous snapshot.
  */
 Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
-        flags(0), previous(s), layer(NULL), fbo(s->fbo),
+        flags(0), previous(s), layer(s->layer), fbo(s->fbo),
         invisible(s->invisible), empty(false),
         viewport(s->viewport), height(s->height), alpha(s->alpha) {
 
-    clipRegion = NULL;
-
     if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
         mTransformRoot.load(*s->transform);
         transform = &mTransformRoot;
@@ -55,17 +53,13 @@
     if (saveFlags & SkCanvas::kClip_SaveFlag) {
         mClipRectRoot.set(*s->clipRect);
         clipRect = &mClipRectRoot;
-#if STENCIL_BUFFER_SIZE
-        if (s->clipRegion) {
+        if (!s->clipRegion->isEmpty()) {
             mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op);
-            clipRegion = &mClipRegionRoot;
         }
-#endif
+        clipRegion = &mClipRegionRoot;
     } else {
         clipRect = s->clipRect;
-#if STENCIL_BUFFER_SIZE
         clipRegion = s->clipRegion;
-#endif
     }
 
     if (s->flags & Snapshot::kFlagFboTarget) {
@@ -81,41 +75,38 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void Snapshot::ensureClipRegion() {
-#if STENCIL_BUFFER_SIZE
-    if (!clipRegion) {
-        clipRegion = &mClipRegionRoot;
+    if (clipRegion->isEmpty()) {
         clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
     }
-#endif
 }
 
 void Snapshot::copyClipRectFromRegion() {
-#if STENCIL_BUFFER_SIZE
     if (!clipRegion->isEmpty()) {
         const SkIRect& bounds = clipRegion->getBounds();
         clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
 
         if (clipRegion->isRect()) {
             clipRegion->setEmpty();
-            clipRegion = NULL;
         }
     } else {
         clipRect->setEmpty();
-        clipRegion = NULL;
     }
-#endif
 }
 
 bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
-#if STENCIL_BUFFER_SIZE
     SkIRect tmp;
     tmp.set(left, top, right, bottom);
     clipRegion->op(tmp, op);
     copyClipRectFromRegion();
     return true;
-#else
-    return false;
-#endif
+}
+
+bool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
+    ensureClipRegion();
+    clipRegion->op(region, op);
+    copyClipRectFromRegion();
+    flags |= Snapshot::kFlagClipSet;
+    return true;
 }
 
 bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
@@ -129,7 +120,7 @@
 
     switch (op) {
         case SkRegion::kIntersect_Op: {
-            if (CC_UNLIKELY(clipRegion)) {
+            if (CC_UNLIKELY(!clipRegion->isEmpty())) {
                 ensureClipRegion();
                 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
             } else {
@@ -142,7 +133,7 @@
             break;
         }
         case SkRegion::kUnion_Op: {
-            if (CC_UNLIKELY(clipRegion)) {
+            if (CC_UNLIKELY(!clipRegion->isEmpty())) {
                 ensureClipRegion();
                 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
             } else {
@@ -171,12 +162,9 @@
 
 void Snapshot::setClip(float left, float top, float right, float bottom) {
     clipRect->set(left, top, right, bottom);
-#if STENCIL_BUFFER_SIZE
-    if (clipRegion) {
+    if (!clipRegion->isEmpty()) {
         clipRegion->setEmpty();
-        clipRegion = NULL;
     }
-#endif
     flags |= Snapshot::kFlagClipSet;
 }
 
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 9c612ff..ffd4729 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -94,6 +94,12 @@
     bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
 
     /**
+     * Modifies the current clip with the specified region and operation.
+     * The specified region is considered already transformed.
+     */
+    bool clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
+
+    /**
      * Sets the current clip.
      */
     void setClip(float left, float top, float right, float bottom);
@@ -136,7 +142,7 @@
     sp<Snapshot> previous;
 
     /**
-     * Only set when the flag kFlagIsLayer is set.
+     * A pointer to the currently active layer.
      *
      * This snapshot does not own the layer, this pointer must not be freed.
      */
@@ -200,8 +206,6 @@
      *
      * This is a reference to a region owned by this snapshot or another
      * snapshot. This pointer must not be freed. See ::mClipRegionRoot.
-     *
-     * This field is used only if STENCIL_BUFFER_SIZE is > 0.
      */
     SkRegion* clipRegion;
 
@@ -234,9 +238,7 @@
     Rect mClipRectRoot;
     Rect mLocalClip;
 
-#if STENCIL_BUFFER_SIZE
     SkRegion mClipRegionRoot;
-#endif
 
 }; // class Snapshot
 
diff --git a/libs/hwui/Stencil.cpp b/libs/hwui/Stencil.cpp
index 84df82b..4fcd51d 100644
--- a/libs/hwui/Stencil.cpp
+++ b/libs/hwui/Stencil.cpp
@@ -37,7 +37,7 @@
 void Stencil::enableTest() {
     if (mState != kTest) {
         enable();
-        glStencilFunc(GL_EQUAL, 0x1, 0x1);
+        glStencilFunc(GL_EQUAL, 0xff, 0xff);
         // We only want to test, let's keep everything
         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -48,7 +48,7 @@
 void Stencil::enableWrite() {
     if (mState != kWrite) {
         enable();
-        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
+        glStencilFunc(GL_ALWAYS, 0xff, 0xff);
         // The test always passes so the first two values are meaningless
         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 9b32667..f70110c 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -91,6 +91,7 @@
     private boolean mHasAccuracy = false;
     private float mAccuracy = 0.0f;
     private Bundle mExtras = null;
+    private boolean mIsFromMockProvider = false;
 
     // Cache the inputs and outputs of computeDistanceAndBearing
     // so calls to distanceTo() and bearingTo() can share work
@@ -140,6 +141,7 @@
         mHasAccuracy = l.mHasAccuracy;
         mAccuracy = l.mAccuracy;
         mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras);
+        mIsFromMockProvider = l.mIsFromMockProvider;
     }
 
     /**
@@ -160,6 +162,7 @@
         mHasAccuracy = false;
         mAccuracy = 0;
         mExtras = null;
+        mIsFromMockProvider = false;
     }
 
     /**
@@ -840,6 +843,7 @@
         if (mHasAltitude) s.append(" alt=").append(mAltitude);
         if (mHasSpeed) s.append(" vel=").append(mSpeed);
         if (mHasBearing) s.append(" bear=").append(mBearing);
+        if (mIsFromMockProvider) s.append(" mock");
 
         if (mExtras != null) {
             s.append(" {").append(mExtras).append('}');
@@ -871,6 +875,7 @@
             l.mHasAccuracy = in.readInt() != 0;
             l.mAccuracy = in.readFloat();
             l.mExtras = in.readBundle();
+            l.mIsFromMockProvider = in.readInt() != 0;
             return l;
         }
 
@@ -901,6 +906,7 @@
         parcel.writeInt(mHasAccuracy ? 1 : 0);
         parcel.writeFloat(mAccuracy);
         parcel.writeBundle(mExtras);
+        parcel.writeInt(mIsFromMockProvider? 1 : 0);
     }
 
     /**
@@ -934,4 +940,23 @@
         }
         mExtras.putParcelable(key, value);
     }
+
+    /**
+     * Returns true if the Location came from a mock provider.
+     *
+     * @return true if this Location came from a mock provider, false otherwise
+     */
+    public boolean isFromMockProvider() {
+        return mIsFromMockProvider;
+    }
+
+    /**
+     * Flag this Location as having come from a mock provider or not.
+     *
+     * @param isFromMockProvider true if this Location came from a mock provider, false otherwise
+     * @hide
+     */
+    public void setIsFromMockProvider(boolean isFromMockProvider) {
+        mIsFromMockProvider = isFromMockProvider;
+    }
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 0b9286e..989178a 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1549,9 +1549,9 @@
     public GpsStatus getGpsStatus(GpsStatus status) {
         if (status == null) {
             status = new GpsStatus();
-       }
-       status.setStatus(mGpsStatus);
-       return status;
+        }
+        status.setStatus(mGpsStatus);
+        return status;
     }
 
     /**
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 14fe6af..b85121e 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -49,7 +49,8 @@
     <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
     <uses-permission android:name="android.permission.START_ANY_ACTIVITY" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
-
+    <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
+    
     <!-- WindowManager -->
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
diff --git a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
new file mode 100644
index 0000000..03ca729
--- /dev/null
+++ b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml
@@ -0,0 +1,322 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 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.
+*/
+-->
+
+<com.android.systemui.statusbar.phone.NavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:background="#FF000000"
+    >
+
+    <FrameLayout android:id="@+id/rot0"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        >
+
+        <LinearLayout
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="horizontal"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:id="@+id/nav_buttons"
+            android:animateLayoutChanges="true"
+            >
+
+            <!-- navigation controls -->
+            <View
+                android:layout_width="40dp"
+                android:layout_height="match_parent"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                android:layout_width="@dimen/navigation_key_width"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_back"
+                systemui:keyCode="4"
+                android:layout_weight="0"
+                android:scaleType="center"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_back"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
+                android:layout_width="@dimen/navigation_key_width"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_home"
+                systemui:keyCode="3"
+                systemui:keyRepeat="false"
+                android:layout_weight="0"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_home"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
+                android:layout_width="@dimen/navigation_key_width"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_recent"
+                android:layout_weight="0"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                android:contentDescription="@string/accessibility_recent"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                android:layout_width="@dimen/navigation_menu_key_width"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_menu"
+                systemui:keyCode="82"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                android:contentDescription="@string/accessibility_menu"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                />
+        </LinearLayout>
+
+        <!-- lights out layout to match exactly -->
+        <LinearLayout
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="horizontal"
+            android:id="@+id/lights_out"
+            android:visibility="gone"
+            >
+            <ImageView
+                android:layout_width="80dp"
+                android:layout_height="match_parent"
+                android:layout_marginStart="40dp"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <ImageView
+                android:layout_width="80dp"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_large"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <ImageView
+                android:layout_width="80dp"
+                android:layout_marginEnd="40dp"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+        </LinearLayout>
+
+        <com.android.systemui.statusbar.policy.KeyButtonView
+            android:layout_width="80dp"
+            android:id="@+id/search_light"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_horizontal"
+            android:src="@drawable/search_light"
+            android:scaleType="center"
+            android:visibility="gone"
+            />
+
+        <com.android.systemui.statusbar.policy.DeadZone
+            android:id="@+id/deadzone"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            systemui:minSize="@dimen/navigation_bar_deadzone_size"
+            systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+            systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+            systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+            systemui:orientation="horizontal"
+            android:layout_gravity="top"
+            />
+    </FrameLayout>
+
+    <FrameLayout android:id="@+id/rot90"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="gone"
+        android:paddingTop="0dp"
+        >
+
+        <LinearLayout 
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="vertical"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:id="@+id/nav_buttons"
+            android:animateLayoutChanges="true"
+            >
+            
+            <!-- navigation controls -->
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                android:layout_height="40dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_menu_land"
+                systemui:keyCode="82"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                android:contentDescription="@string/accessibility_menu"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_back_land"
+                android:scaleType="center"
+                systemui:keyCode="4"
+                android:layout_weight="0"
+                android:contentDescription="@string/accessibility_back"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                />
+            <View
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_home_land"
+                systemui:keyCode="3"
+                systemui:keyRepeat="false"
+                android:layout_weight="0"
+                android:contentDescription="@string/accessibility_home"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_recent_land"
+                android:layout_weight="0"
+                android:contentDescription="@string/accessibility_recent"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+                />
+            <View
+                android:layout_height="40dp"
+                android:layout_width="match_parent"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                />
+        </LinearLayout>
+
+        <!-- lights out layout to match exactly -->
+        <LinearLayout 
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="vertical"
+            android:id="@+id/lights_out"
+            android:visibility="gone"
+            >
+            <ImageView
+                android:layout_height="80dp"
+                android:layout_marginTop="40dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <ImageView
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_large"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                android:visibility="invisible"
+                />
+            <ImageView
+                android:layout_height="80dp"
+                android:layout_marginBottom="40dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:scaleType="center"
+                android:layout_weight="0"
+                />
+        </LinearLayout>
+
+        <com.android.systemui.statusbar.policy.KeyButtonView
+            android:id="@+id/search_light"
+            android:layout_height="80dp"
+            android:layout_width="match_parent"
+            android:layout_gravity="center_vertical"
+            android:src="@drawable/search_light"
+            android:scaleType="center"
+            android:visibility="gone"
+            />
+
+        <com.android.systemui.statusbar.policy.DeadZone
+            android:id="@+id/deadzone"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            systemui:minSize="@dimen/navigation_bar_deadzone_size"
+            systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+            systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+            systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+            systemui:orientation="vertical"
+            android:layout_gravity="top"
+            />
+    </FrameLayout>
+
+    <!-- not used -->
+    <View android:id="@+id/rot270"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="gone"
+        />
+
+</com.android.systemui.statusbar.phone.NavigationBarView>
diff --git a/packages/SystemUI/res/layout/status_bar_recent_item.xml b/packages/SystemUI/res/layout/status_bar_recent_item.xml
index 7ce3a09..6290bb3 100644
--- a/packages/SystemUI/res/layout/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout/status_bar_recent_item.xml
@@ -48,6 +48,7 @@
             android:ellipsize="marquee"
             android:textColor="@color/status_bar_recents_app_label_color"
             android:importantForAccessibility="no"
+            android:textAlignment="viewStart"
         />
         <FrameLayout android:id="@+id/app_thumbnail"
             android:layout_width="wrap_content"
@@ -101,6 +102,7 @@
             android:layout_marginTop="3dip"
             android:singleLine="true"
             android:ellipsize="marquee"
+            android:textAlignment="viewStart"
         />
 
     </RelativeLayout>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 8c2dd8e..580bfe7 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -147,7 +147,7 @@
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Mode silenci."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificació omesa."</string>
-    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Capa de notificació."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Àrea de notificacions"</string>
     <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configuració ràpida."</string>
     <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicacions recents."</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuari <xliff:g id="USER">%s</xliff:g>."</string>
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index c0a6f56..1f29990 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -103,7 +103,7 @@
         } else {
             // Otherwise, keyguard isn't showing so launch it from here.
             Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                    .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                    .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
             if (intent == null) return;
 
             try {
@@ -180,7 +180,7 @@
 
     private void maybeSwapSearchIcon() {
         Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
         if (intent != null) {
             ComponentName component = intent.getComponent();
             if (component == null || !mGlowPadView.replaceTargetDrawablesIfPresent(component,
@@ -329,6 +329,6 @@
 
     public boolean isAssistantAvailable() {
         return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 17b0b50..280b368 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -72,6 +72,13 @@
     Runnable finisher;
     int iconSize;
     int result;
+
+    void clearImage() {
+        context = null;
+        image = null;
+        imageUri = null;
+        iconSize = 0;
+    }
 }
 
 /**
@@ -165,6 +172,10 @@
     @Override
     protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
         if (params.length != 1) return null;
+        if (isCancelled()) {
+            params[0].clearImage();
+            return null;
+        }
 
         // By default, AsyncTask sets the worker thread to have background thread priority, so bump
         // it back up so that we save a little quicker.
@@ -225,8 +236,7 @@
         } catch (Exception e) {
             // IOException/UnsupportedOperationException may be thrown if external storage is not
             // mounted
-            params[0].imageUri = null;
-            params[0].image = null;
+            params[0].clearImage();
             params[0].result = 1;
         }
 
@@ -240,6 +250,12 @@
 
     @Override
     protected void onPostExecute(SaveImageInBackgroundData params) {
+        if (isCancelled()) {
+            params.finisher.run();
+            params.clearImage();
+            return;
+        }
+
         if (params.result > 0) {
             // Show a message that we've failed to save the image to disk
             GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager);
@@ -308,6 +324,8 @@
     private float mBgPadding;
     private float mBgPaddingScale;
 
+    private AsyncTask<SaveImageInBackgroundData, Void, SaveImageInBackgroundData> mSaveInBgTask;
+
     private MediaActionSound mCameraSound;
 
 
@@ -374,7 +392,10 @@
         data.image = mScreenBitmap;
         data.iconSize = mNotificationIconSize;
         data.finisher = finisher;
-        new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
+        if (mSaveInBgTask != null) {
+            mSaveInBgTask.cancel(false);
+        }
+        mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
                 SCREENSHOT_NOTIFICATION_ID).execute(data);
     }
 
@@ -455,6 +476,7 @@
         // Setup the animation with the screenshot just taken
         if (mScreenshotAnimation != null) {
             mScreenshotAnimation.end();
+            mScreenshotAnimation.removeAllListeners();
         }
 
         mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 28c4113..54c4666 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -75,7 +75,8 @@
 
     private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
     private Drawable mRecentIcon;
-    
+    private Drawable mRecentLandIcon;
+
     private DelegateViewHelper mDelegateHelper;
     private DeadZone mDeadZone;
 
@@ -179,6 +180,7 @@
         mBackAltIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime);
         mBackAltLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime);
         mRecentIcon = res.getDrawable(R.drawable.ic_sysbar_recent);
+        mRecentLandIcon = res.getDrawable(R.drawable.ic_sysbar_recent_land);
     }
 
     @Override
@@ -238,7 +240,7 @@
                 ? (mVertical ? mBackAltLandIcon : mBackAltIcon)
                 : (mVertical ? mBackLandIcon : mBackIcon));
 
-        ((ImageView)getRecentsButton()).setImageDrawable(mRecentIcon);
+        ((ImageView)getRecentsButton()).setImageDrawable(mVertical ? mRecentLandIcon : mRecentIcon);
 
         setDisabledFlags(mDisabledFlags, true);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index e5ef5fe..6eb88be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -135,7 +135,7 @@
         mLastPokeTime = event.getEventTime();
         if (DEBUG)
             Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
-        postInvalidate();
+        if (mShouldFlash) postInvalidate();
     }
 
     public void setFlash(float f) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b5cbdd1..35ff3d6 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2206,7 +2206,7 @@
     private void launchAssistAction() {
         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
         Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
         if (intent != null) {
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_SINGLE_TOP
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index 217e5d7..27d808b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -1567,7 +1567,7 @@
 
     public void showAssistant() {
         final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-          .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+          .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
 
         if (intent == null) return;
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
index 76cbbd5..6859042 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -61,7 +61,7 @@
                 case com.android.internal.R.drawable.ic_action_assist_generic:
                     Intent assistIntent =
                             ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                            .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                            .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
                     if (assistIntent != null) {
                         mActivityLauncher.launchActivity(assistIntent, false, true, null, null);
                     } else {
@@ -195,7 +195,7 @@
                 currentUserHandle);
         boolean searchActionAvailable =
                 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
         mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent
                 || !currentUserSetup;
         mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent
@@ -207,7 +207,7 @@
         // Update the search icon with drawable from the search .apk
         if (!mSearchDisabled) {
             Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                    .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+                    .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
             if (intent != null) {
                 // XXX Hack. We need to substitute the icon here but haven't formalized
                 // the public API. The "_google" metadata will be going away, so
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index fef0613..8e10528 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -1428,6 +1428,6 @@
 
     private boolean isAssistantAvailable() {
         return mSearchManager != null
-                && mSearchManager.getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+                && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
     }
 }
diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java
index 1712806..bf2a5ae 100644
--- a/services/java/com/android/server/AppOpsService.java
+++ b/services/java/com/android/server/AppOpsService.java
@@ -38,6 +38,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.util.AtomicFile;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -93,12 +94,15 @@
 
     final static class Op {
         public final int op;
+        public int mode;
         public int duration;
         public long time;
+        public long rejectTime;
         public int nesting;
 
         public Op(int _op) {
             op = _op;
+            mode = AppOpsManager.MODE_ALLOWED;
         }
     }
 
@@ -127,6 +131,30 @@
         }
     }
 
+    private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
+        ArrayList<AppOpsManager.OpEntry> resOps = null;
+        if (ops == null) {
+            resOps = new ArrayList<AppOpsManager.OpEntry>();
+            for (int j=0; j<pkgOps.size(); j++) {
+                Op curOp = pkgOps.valueAt(j);
+                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
+                        curOp.rejectTime, curOp.duration));
+            }
+        } else {
+            for (int j=0; j<ops.length; j++) {
+                Op curOp = pkgOps.get(ops[j]);
+                if (curOp != null) {
+                    if (resOps == null) {
+                        resOps = new ArrayList<AppOpsManager.OpEntry>();
+                    }
+                    resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
+                            curOp.rejectTime, curOp.duration));
+                }
+            }
+        }
+        return resOps;
+    }
+
     @Override
     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
@@ -136,26 +164,7 @@
             for (int i=0; i<mUidOps.size(); i++) {
                 HashMap<String, Ops> packages = mUidOps.valueAt(i);
                 for (Ops pkgOps : packages.values()) {
-                    ArrayList<AppOpsManager.OpEntry> resOps = null;
-                    if (ops == null) {
-                        resOps = new ArrayList<AppOpsManager.OpEntry>();
-                        for (int j=0; j<pkgOps.size(); j++) {
-                            Op curOp = pkgOps.valueAt(j);
-                            resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time,
-                                    curOp.duration));
-                        }
-                    } else {
-                        for (int j=0; j<ops.length; j++) {
-                            Op curOp = pkgOps.get(ops[j]);
-                            if (curOp != null) {
-                                if (resOps == null) {
-                                    resOps = new ArrayList<AppOpsManager.OpEntry>();
-                                }
-                                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time,
-                                        curOp.duration));
-                            }
-                        }
-                    }
+                    ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
                     if (resOps != null) {
                         if (res == null) {
                             res = new ArrayList<AppOpsManager.PackageOps>();
@@ -171,6 +180,42 @@
     }
 
     @Override
+    public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
+            int[] ops) {
+        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
+                Binder.getCallingPid(), Binder.getCallingUid(), null);
+        synchronized (this) {
+            Ops pkgOps = getOpsLocked(uid, packageName, false);
+            if (pkgOps == null) {
+                return null;
+            }
+            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
+            if (resOps == null) {
+                return null;
+            }
+            ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
+            AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
+                    pkgOps.packageName, pkgOps.uid, resOps);
+            res.add(resPackage);
+            return res;
+        }
+    }
+
+    @Override
+    public void setMode(int code, int uid, String packageName, int mode) {
+        uid = handleIncomingUid(uid);
+        synchronized (this) {
+            Op op = getOpLocked(code, uid, packageName, true);
+            if (op != null) {
+                if (op.mode != mode) {
+                    op.mode = mode;
+                    scheduleWriteNowLocked();
+                }
+            }
+        }
+    }
+
+    @Override
     public int checkOperation(int code, int uid, String packageName) {
         uid = handleIncomingUid(uid);
         synchronized (this) {
@@ -178,8 +223,8 @@
             if (op == null) {
                 return AppOpsManager.MODE_ALLOWED;
             }
+            return op.mode;
         }
-        return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
@@ -188,16 +233,26 @@
         synchronized (this) {
             Op op = getOpLocked(code, uid, packageName, true);
             if (op == null) {
+                if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
+                        + " package " + packageName);
                 return AppOpsManager.MODE_IGNORED;
             }
             if (op.duration == -1) {
                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
                         + " code " + code + " time=" + op.time + " duration=" + op.duration);
             }
-            op.time = System.currentTimeMillis();
             op.duration = 0;
+            if (op.mode != AppOpsManager.MODE_ALLOWED) {
+                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " + code
+                        + " uid " + uid + " package " + packageName);
+                op.rejectTime = System.currentTimeMillis();
+                return op.mode;
+            }
+            if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
+                    + " package " + packageName);
+            op.time = System.currentTimeMillis();
+            return AppOpsManager.MODE_ALLOWED;
         }
-        return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
@@ -206,15 +261,25 @@
         synchronized (this) {
             Op op = getOpLocked(code, uid, packageName, true);
             if (op == null) {
+                if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
+                        + " package " + packageName);
                 return AppOpsManager.MODE_IGNORED;
             }
+            if (op.mode != AppOpsManager.MODE_ALLOWED) {
+                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code " + code
+                        + " uid " + uid + " package " + packageName);
+                op.rejectTime = System.currentTimeMillis();
+                return op.mode;
+            }
+            if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
+                    + " package " + packageName);
             if (op.nesting == 0) {
                 op.time = System.currentTimeMillis();
                 op.duration = -1;
             }
             op.nesting++;
+            return AppOpsManager.MODE_ALLOWED;
         }
-        return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
@@ -252,7 +317,7 @@
         return uid;
     }
 
-    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
+    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
         HashMap<String, Ops> pkgOps = mUidOps.get(uid);
         if (pkgOps == null) {
             if (!edit) {
@@ -289,6 +354,29 @@
             ops = new Ops(packageName, uid);
             pkgOps.put(packageName, ops);
         }
+        return ops;
+    }
+
+    private void scheduleWriteLocked() {
+        if (!mWriteScheduled) {
+            mWriteScheduled = true;
+            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
+        }
+    }
+
+    private void scheduleWriteNowLocked() {
+        if (!mWriteScheduled) {
+            mWriteScheduled = true;
+        }
+        mHandler.removeCallbacks(mWriteRunner);
+        mHandler.post(mWriteRunner);
+    }
+
+    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
+        Ops ops = getOpsLocked(uid, packageName, edit);
+        if (ops == null) {
+            return null;
+        }
         Op op = ops.get(code);
         if (op == null) {
             if (!edit) {
@@ -297,9 +385,8 @@
             op = new Op(code);
             ops.put(code, op);
         }
-        if (edit && !mWriteScheduled) {
-            mWriteScheduled = true;
-            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
+        if (edit) {
+            scheduleWriteLocked();
         }
         return op;
     }
@@ -406,8 +493,22 @@
             String tagName = parser.getName();
             if (tagName.equals("op")) {
                 Op op = new Op(Integer.parseInt(parser.getAttributeValue(null, "n")));
-                op.time = Long.parseLong(parser.getAttributeValue(null, "t"));
-                op.duration = Integer.parseInt(parser.getAttributeValue(null, "d"));
+                String mode = parser.getAttributeValue(null, "m");
+                if (mode != null) {
+                    op.mode = Integer.parseInt(mode);
+                }
+                String time = parser.getAttributeValue(null, "t");
+                if (time != null) {
+                    op.time = Long.parseLong(time);
+                }
+                time = parser.getAttributeValue(null, "r");
+                if (time != null) {
+                    op.rejectTime = Long.parseLong(time);
+                }
+                String dur = parser.getAttributeValue(null, "d");
+                if (dur != null) {
+                    op.duration = Integer.parseInt(dur);
+                }
                 HashMap<String, Ops> pkgOps = mUidOps.get(uid);
                 if (pkgOps == null) {
                     pkgOps = new HashMap<String, Ops>();
@@ -464,8 +565,21 @@
                             AppOpsManager.OpEntry op = ops.get(j);
                             out.startTag(null, "op");
                             out.attribute(null, "n", Integer.toString(op.getOp()));
-                            out.attribute(null, "t", Long.toString(op.getTime()));
-                            out.attribute(null, "d", Integer.toString(op.getDuration()));
+                            if (op.getMode() != AppOpsManager.MODE_ALLOWED) {
+                                out.attribute(null, "m", Integer.toString(op.getMode()));
+                            }
+                            long time = op.getTime();
+                            if (time != 0) {
+                                out.attribute(null, "t", Long.toString(time));
+                            }
+                            time = op.getRejectTime();
+                            if (time != 0) {
+                                out.attribute(null, "r", Long.toString(time));
+                            }
+                            int dur = op.getDuration();
+                            if (dur != 0) {
+                                out.attribute(null, "d", Integer.toString(dur));
+                            }
                             out.endTag(null, "op");
                         }
                         out.endTag(null, "uid");
@@ -497,6 +611,7 @@
 
         synchronized (this) {
             pw.println("Current AppOps Service state:");
+            final long now = System.currentTimeMillis();
             for (int i=0; i<mUidOps.size(); i++) {
                 pw.print("  Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
                 HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
@@ -504,10 +619,16 @@
                     pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
                     for (int j=0; j<ops.size(); j++) {
                         Op op = ops.valueAt(j);
-                        pw.print("      "); pw.print(AppOpsManager.opToString(op.op));
-                        pw.print(": time=");
-                        TimeUtils.formatDuration(System.currentTimeMillis()-op.time, pw);
-                        pw.print(" ago");
+                        pw.print("      "); pw.print(AppOpsManager.opToName(op.op));
+                        pw.print(": mode="); pw.print(op.mode);
+                        if (op.time != 0) {
+                            pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw);
+                            pw.print(" ago");
+                        }
+                        if (op.rejectTime != 0) {
+                            pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw);
+                            pw.print(" ago");
+                        }
                         if (op.duration == -1) {
                             pw.println(" (running)");
                         } else {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 2ccde3b..7cfa8c2 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -183,7 +183,7 @@
      * A per Net list of the PID's that requested access to the net
      * used both as a refcount and for per-PID DNS selection
      */
-    private List<Integer> mNetRequestersPids[];
+    private List mNetRequestersPids[];
 
     // priority order of the nettrackers
     // (excluding dynamically set mNetworkPreference)
@@ -194,12 +194,12 @@
     private int mNetworkPreference;
     private int mActiveDefaultNetwork = -1;
     // 0 is full bad, 100 is full good
-    private int mDefaultInetCondition = 0;
     private int mDefaultInetConditionPublished = 0;
     private boolean mInetConditionChangeInFlight = false;
     private int mDefaultConnectionSequence = 0;
 
     private Object mDnsLock = new Object();
+    private int mNumDnsEntries;
     private boolean mDnsOverridden = false;
 
     private boolean mTestMode;
@@ -507,14 +507,15 @@
             }
         }
 
-        mNetRequestersPids =
-                (List<Integer> [])new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
+        mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
         for (int i : mPriorityList) {
-            mNetRequestersPids[i] = new ArrayList<Integer>();
+            mNetRequestersPids[i] = new ArrayList();
         }
 
         mFeatureUsers = new ArrayList<FeatureUser>();
 
+        mNumDnsEntries = 0;
+
         mTestMode = SystemProperties.get("cm.test.mode").equals("true")
                 && SystemProperties.get("ro.build.type").equals("eng");
 
@@ -1315,7 +1316,6 @@
                 Integer currentPid = new Integer(pid);
                 mNetRequestersPids[usedNetworkType].remove(currentPid);
                 reassessPidDns(pid, true);
-                flushVmDnsCache();
                 if (mNetRequestersPids[usedNetworkType].size() != 0) {
                     if (VDBG) {
                         log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
@@ -1697,8 +1697,9 @@
          * in accordance with network preference policies.
          */
         if (!mNetConfigs[prevNetType].isDefault()) {
-            List<Integer> pids = mNetRequestersPids[prevNetType];
-            for (Integer pid : pids) {
+            List pids = mNetRequestersPids[prevNetType];
+            for (int i = 0; i<pids.size(); i++) {
+                Integer pid = (Integer)pids.get(i);
                 // will remove them because the net's no longer connected
                 // need to do this now as only now do we know the pids and
                 // can properly null things that are no longer referenced.
@@ -1728,6 +1729,10 @@
                 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
             } else {
                 mDefaultInetConditionPublished = 0; // we're not connected anymore
+                if (DBG) {
+                    log("handleDisconnect: net=" + mActiveDefaultNetwork +
+                            ", published condition=" + mDefaultInetConditionPublished);
+                }
                 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
             }
         }
@@ -1918,6 +1923,10 @@
                 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
             } else {
                 mDefaultInetConditionPublished = 0;
+                if (DBG) {
+                    log("handleConnectionFailure: net=" + mActiveDefaultNetwork +
+                            ", published condition=" + mDefaultInetConditionPublished);
+                }
                 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
             }
         }
@@ -2062,6 +2071,10 @@
             mDefaultInetConditionPublished = 0;
             mDefaultConnectionSequence++;
             mInetConditionChangeInFlight = false;
+            if (DBG) {
+                log("handleConnect: net=" + newNetType +
+                        ", published condition=" + mDefaultInetConditionPublished);
+            }
             // Don't do this - if we never sign in stay, grey
             //reportNetworkCondition(mActiveDefaultNetwork, 100);
         }
@@ -2248,7 +2261,6 @@
                         }
                     }
                     if (resetDns) {
-                        flushVmDnsCache();
                         if (VDBG) log("resetting DNS cache for " + iface);
                         try {
                             mNetd.flushInterfaceDnsCache(iface);
@@ -2415,10 +2427,9 @@
      * on the highest priority active net which this process requested.
      * If there aren't any, clear it out
      */
-    private void reassessPidDns(int pid, boolean doBump)
+    private void reassessPidDns(int myPid, boolean doBump)
     {
-        if (VDBG) log("reassessPidDns for pid " + pid);
-        Integer myPid = new Integer(pid);
+        if (VDBG) log("reassessPidDns for pid " + myPid);
         for(int i : mPriorityList) {
             if (mNetConfigs[i].isDefault()) {
                 continue;
@@ -2428,25 +2439,61 @@
                     !nt.isTeardownRequested()) {
                 LinkProperties p = nt.getLinkProperties();
                 if (p == null) continue;
-                if (mNetRequestersPids[i].contains(myPid)) {
-                    try {
-                        mNetd.setDnsIfaceForPid(p.getInterfaceName(), pid);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "exception reasseses pid dns: " + e);
+                List pids = mNetRequestersPids[i];
+                for (int j=0; j<pids.size(); j++) {
+                    Integer pid = (Integer)pids.get(j);
+                    if (pid.intValue() == myPid) {
+                        Collection<InetAddress> dnses = p.getDnses();
+                        writePidDns(dnses, myPid);
+                        if (doBump) {
+                            bumpDns();
+                        }
+                        return;
                     }
-                    return;
                 }
            }
         }
         // nothing found - delete
-        try {
-            mNetd.clearDnsIfaceForPid(pid);
-        } catch (Exception e) {
-            Slog.e(TAG, "exception clear interface from pid: " + e);
+        for (int i = 1; ; i++) {
+            String prop = "net.dns" + i + "." + myPid;
+            if (SystemProperties.get(prop).length() == 0) {
+                if (doBump) {
+                    bumpDns();
+                }
+                return;
+            }
+            SystemProperties.set(prop, "");
         }
     }
 
-    private void flushVmDnsCache() {
+    // return true if results in a change
+    private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
+        int j = 1;
+        boolean changed = false;
+        for (InetAddress dns : dnses) {
+            String dnsString = dns.getHostAddress();
+            if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
+                changed = true;
+                SystemProperties.set("net.dns" + j + "." + pid, dns.getHostAddress());
+            }
+            j++;
+        }
+        return changed;
+    }
+
+    private void bumpDns() {
+        /*
+         * Bump the property that tells the name resolver library to reread
+         * the DNS server list from the properties.
+         */
+        String propVal = SystemProperties.get("net.dnschange");
+        int n = 0;
+        if (propVal.length() != 0) {
+            try {
+                n = Integer.parseInt(propVal);
+            } catch (NumberFormatException e) {}
+        }
+        SystemProperties.set("net.dnschange", "" + (n+1));
         /*
          * Tell the VMs to toss their DNS caches
          */
@@ -2465,23 +2512,56 @@
     }
 
     // Caller must grab mDnsLock.
-    private void updateDns(String network, String iface,
+    private boolean updateDns(String network, String iface,
             Collection<InetAddress> dnses, String domains) {
+        boolean changed = false;
         int last = 0;
         if (dnses.size() == 0 && mDefaultDns != null) {
-            dnses = new ArrayList();
-            dnses.add(mDefaultDns);
-            if (DBG) {
-                loge("no dns provided for " + network + " - using " + mDefaultDns.getHostAddress());
+            ++last;
+            String value = mDefaultDns.getHostAddress();
+            if (!value.equals(SystemProperties.get("net.dns1"))) {
+                if (DBG) {
+                    loge("no dns provided for " + network + " - using " + value);
+                }
+                changed = true;
+                SystemProperties.set("net.dns1", value);
+            }
+        } else {
+            for (InetAddress dns : dnses) {
+                ++last;
+                String key = "net.dns" + last;
+                String value = dns.getHostAddress();
+                if (!changed && value.equals(SystemProperties.get(key))) {
+                    continue;
+                }
+                if (VDBG) {
+                    log("adding dns " + value + " for " + network);
+                }
+                changed = true;
+                SystemProperties.set(key, value);
             }
         }
-
-        try {
-            mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
-            mNetd.setDefaultInterfaceForDns(iface);
-        } catch (Exception e) {
-            if (DBG) loge("exception setting default dns interface: " + e);
+        for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+            String key = "net.dns" + i;
+            if (VDBG) log("erasing " + key);
+            changed = true;
+            SystemProperties.set(key, "");
         }
+        mNumDnsEntries = last;
+        if (SystemProperties.get("net.dns.search").equals(domains) == false) {
+            SystemProperties.set("net.dns.search", domains);
+            changed = true;
+        }
+
+        if (changed) {
+            try {
+                mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
+                mNetd.setDefaultInterfaceForDns(iface);
+            } catch (Exception e) {
+                if (DBG) loge("exception setting default dns interface: " + e);
+            }
+        }
+        return changed;
     }
 
     private void handleDnsConfigurationChange(int netType) {
@@ -2491,11 +2571,12 @@
             LinkProperties p = nt.getLinkProperties();
             if (p == null) return;
             Collection<InetAddress> dnses = p.getDnses();
+            boolean changed = false;
             if (mNetConfigs[netType].isDefault()) {
                 String network = nt.getNetworkInfo().getTypeName();
                 synchronized (mDnsLock) {
                     if (!mDnsOverridden) {
-                        updateDns(network, p.getInterfaceName(), dnses, p.getDomains());
+                        changed = updateDns(network, p.getInterfaceName(), dnses, p.getDomains());
                     }
                 }
             } else {
@@ -2506,16 +2587,13 @@
                     if (DBG) loge("exception setting dns servers: " + e);
                 }
                 // set per-pid dns for attached secondary nets
-                List<Integer> pids = mNetRequestersPids[netType];
-                for (Integer pid : pids) {
-                    try {
-                        mNetd.setDnsIfaceForPid(p.getInterfaceName(), pid);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "exception setting interface for pid: " + e);
-                    }
+                List pids = mNetRequestersPids[netType];
+                for (int y=0; y< pids.size(); y++) {
+                    Integer pid = (Integer)pids.get(y);
+                    changed = writePidDns(dnses, pid.intValue());
                 }
             }
-            flushVmDnsCache();
+            if (changed) bumpDns();
         }
     }
 
@@ -2574,7 +2652,7 @@
         pw.increaseIndent();
         for (int net : mPriorityList) {
             String pidString = net + ": ";
-            for (Integer pid : mNetRequestersPids[net]) {
+            for (Object pid : mNetRequestersPids[net]) {
                 pidString = pidString + pid.toString() + ", ";
             }
             pw.println(pidString);
@@ -2712,7 +2790,8 @@
                 {
                     int netType = msg.arg1;
                     int sequence = msg.arg2;
-                    handleInetConditionHoldEnd(netType, sequence);
+                    int condition = (Integer)msg.obj;
+                    handleInetConditionHoldEnd(netType, sequence, condition);
                     break;
                 }
                 case EVENT_SET_NETWORK_PREFERENCE:
@@ -2925,14 +3004,13 @@
         if (VDBG) {
             log("handleInetConditionChange: net=" +
                     netType + ", condition=" + condition +
-                    ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
+                    " mActiveDefaultNetwork=" + mActiveDefaultNetwork);
         }
-        mDefaultInetCondition = condition;
         int delay;
         if (mInetConditionChangeInFlight == false) {
             if (VDBG) log("handleInetConditionChange: starting a change hold");
             // setup a new hold to debounce this
-            if (mDefaultInetCondition > 50) {
+            if (condition > 50) {
                 delay = Settings.Global.getInt(mContext.getContentResolver(),
                         Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
             } else {
@@ -2941,18 +3019,16 @@
             }
             mInetConditionChangeInFlight = true;
             mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
-                    mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
+                    mActiveDefaultNetwork, mDefaultConnectionSequence, new Integer(condition)), delay);
         } else {
             // we've set the new condition, when this hold ends that will get picked up
             if (VDBG) log("handleInetConditionChange: currently in hold - not setting new end evt");
         }
     }
 
-    private void handleInetConditionHoldEnd(int netType, int sequence) {
+    private void handleInetConditionHoldEnd(int netType, int sequence, int condition) {
         if (DBG) {
-            log("handleInetConditionHoldEnd: net=" + netType +
-                    ", condition=" + mDefaultInetCondition +
-                    ", published condition=" + mDefaultInetConditionPublished);
+            log("handleInetConditionHoldEnd: net=" + netType + ", condition=" + condition);
         }
         mInetConditionChangeInFlight = false;
 
@@ -2964,19 +3040,13 @@
             if (DBG) log("handleInetConditionHoldEnd: event hold for obsolete network - ignoring");
             return;
         }
-        // TODO: Figure out why this optimization sometimes causes a
-        //       change in mDefaultInetCondition to be missed and the
-        //       UI to not be updated.
-        //if (mDefaultInetConditionPublished == mDefaultInetCondition) {
-        //    if (DBG) log("no change in condition - aborting");
-        //    return;
-        //}
+
         NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
         if (networkInfo.isConnected() == false) {
             if (DBG) log("handleInetConditionHoldEnd: default network not connected - ignoring");
             return;
         }
-        mDefaultInetConditionPublished = mDefaultInetCondition;
+        mDefaultInetConditionPublished = condition;
         sendInetConditionBroadcast(networkInfo);
         return;
     }
@@ -3284,10 +3354,14 @@
             String domains = buffer.toString().trim();
 
             // Apply DNS changes.
+            boolean changed = false;
             synchronized (mDnsLock) {
-                updateDns("VPN", "VPN", addresses, domains);
+                changed = updateDns("VPN", "VPN", addresses, domains);
                 mDnsOverridden = true;
             }
+            if (changed) {
+                bumpDns();
+            }
 
             // Temporarily disable the default proxy.
             synchronized (mDefaultProxyLock) {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 2f12112..0f14265 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -382,6 +382,8 @@
     private boolean mInputBoundToKeyguard;
 
     class SettingsObserver extends ContentObserver {
+        String mLastEnabled = "";
+
         SettingsObserver(Handler handler) {
             super(handler);
             ContentResolver resolver = mContext.getContentResolver();
@@ -395,7 +397,13 @@
 
         @Override public void onChange(boolean selfChange) {
             synchronized (mMethodMap) {
-                updateFromSettingsLocked();
+                boolean enabledChanged = false;
+                String newEnabled = mSettings.getEnabledInputMethodsStr();
+                if (!mLastEnabled.equals(newEnabled)) {
+                    mLastEnabled = newEnabled;
+                    enabledChanged = true;
+                }
+                updateFromSettingsLocked(enabledChanged);
             }
         }
     }
@@ -539,7 +547,7 @@
                 }
 
                 if (changed) {
-                    updateFromSettingsLocked();
+                    updateFromSettingsLocked(false);
                 }
             }
         }
@@ -674,7 +682,7 @@
         }
 
         mSettingsObserver = new SettingsObserver(mHandler);
-        updateFromSettingsLocked();
+        updateFromSettingsLocked(true);
 
         // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
         // according to the new system locale.
@@ -748,7 +756,7 @@
                 // If the locale is changed, needs to reset the default ime
                 resetDefaultImeLocked(mContext);
             }
-            updateFromSettingsLocked();
+            updateFromSettingsLocked(true);
             mLastSystemLocale = newLocale;
             if (!updateOnlyWhenLocaleChanged) {
                 try {
@@ -1533,7 +1541,27 @@
         return false;
     }
 
-    void updateFromSettingsLocked() {
+    void updateFromSettingsLocked(boolean enabledMayChange) {
+        if (enabledMayChange) {
+            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
+            for (int i=0; i<enabled.size(); i++) {
+                // We allow the user to select "disabled until used" apps, so if they
+                // are enabling one of those here we now need to make it enabled.
+                InputMethodInfo imm = enabled.get(i);
+                try {
+                    ApplicationInfo ai = mIPackageManager.getApplicationInfo(imm.getPackageName(),
+                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
+                            mSettings.getCurrentUserId());
+                    if (ai.enabledSetting
+                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+                        mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(),
+                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
+                                PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId());
+                    }
+                } catch (RemoteException e) {
+                }
+            }
+        }
         // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
         // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
         // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
@@ -2383,7 +2411,8 @@
 
         final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                 new Intent(InputMethod.SERVICE_INTERFACE),
-                PackageManager.GET_META_DATA, mSettings.getCurrentUserId());
+                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
+                mSettings.getCurrentUserId());
 
         final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
                 mFileManager.getAllAdditionalInputMethodSubtypes();
@@ -2429,7 +2458,7 @@
             if (!map.containsKey(defaultImiId)) {
                 Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
                 if (chooseNewDefaultIMELocked()) {
-                    updateFromSettingsLocked();
+                    updateFromSettingsLocked(true);
                 }
             } else {
                 // Double check that the default IME is certainly enabled.
@@ -2554,6 +2583,9 @@
                         public void onCheckedChanged(
                                 CompoundButton buttonView, boolean isChecked) {
                             mWindowManagerService.setHardKeyboardEnabled(isChecked);
+                            // Ensure that the input method dialog is dismissed when changing
+                            // the hardware keyboard state.
+                            hideInputMethodMenu();
                         }
                     });
 
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index b351fc2..9606cf1 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -529,9 +529,6 @@
         }
 
         public boolean callLocationChangedLocked(Location location) {
-            if (!reportLocationAccessNoThrow(mUid, mPackageName, mAllowedResolutionLevel)) {
-                return true;
-            }
             if (mListener != null) {
                 try {
                     synchronized (this) {
@@ -802,14 +799,20 @@
         }
     }
 
-    boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) {
-        int op;
+    public static int resolutionLevelToOp(int allowedResolutionLevel) {
         if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
             if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
-                op = AppOpsManager.OP_COARSE_LOCATION;
+                return AppOpsManager.OP_COARSE_LOCATION;
             } else {
-                op = AppOpsManager.OP_FINE_LOCATION;
+                return AppOpsManager.OP_FINE_LOCATION;
             }
+        }
+        return -1;
+    }
+
+    boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) {
+        int op = resolutionLevelToOp(allowedResolutionLevel);
+        if (op >= 0) {
             if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
@@ -818,13 +821,8 @@
     }
 
     boolean checkLocationAccess(int uid, String packageName, int allowedResolutionLevel) {
-        int op;
-        if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
-            if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
-                op = AppOpsManager.OP_COARSE_LOCATION;
-            } else {
-                op = AppOpsManager.OP_FINE_LOCATION;
-            }
+        int op = resolutionLevelToOp(allowedResolutionLevel);
+        if (op >= 0) {
             if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
@@ -1019,11 +1017,14 @@
         if (records != null) {
             for (UpdateRecord record : records) {
                 if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
-                    LocationRequest locationRequest = record.mRequest;
-                    providerRequest.locationRequests.add(locationRequest);
-                    if (locationRequest.getInterval() < providerRequest.interval) {
-                        providerRequest.reportLocation = true;
-                        providerRequest.interval = locationRequest.getInterval();
+                    if (checkLocationAccess(record.mReceiver.mUid, record.mReceiver.mPackageName,
+                            record.mReceiver.mAllowedResolutionLevel)) {
+                        LocationRequest locationRequest = record.mRequest;
+                        providerRequest.locationRequests.add(locationRequest);
+                        if (locationRequest.getInterval() < providerRequest.interval) {
+                            providerRequest.reportLocation = true;
+                            providerRequest.interval = locationRequest.getInterval();
+                        }
                     }
                 }
             }
@@ -1144,9 +1145,6 @@
      * and consistency requirements.
      *
      * @param request the LocationRequest from which to create a sanitized version
-     * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution
-     * constraints
-     * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution
      * @return a version of request that meets the given resolution and consistency requirements
      * @hide
      */
@@ -1340,16 +1338,18 @@
         final int uid = Binder.getCallingUid();
         final long identity = Binder.clearCallingIdentity();
         try {
-            if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) {
-                return null;
-            }
-            
             if (mBlacklist.isBlacklisted(packageName)) {
                 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
                         packageName);
                 return null;
             }
 
+            if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) {
+                if (D) Log.d(TAG, "not returning last loc for no op app: " +
+                        packageName);
+                return null;
+            }
+
             synchronized (mLock) {
                 // Figure out the provider. Either its explicitly request (deprecated API's),
                 // or use the fused provider
@@ -1402,7 +1402,8 @@
         }
         long identity = Binder.clearCallingIdentity();
         try {
-            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName);
+            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
+                    uid, packageName);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -1703,6 +1704,13 @@
                 continue;
             }
 
+            if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName,
+                    receiver.mAllowedResolutionLevel)) {
+                if (D) Log.d(TAG, "skipping loc update for no op app: " +
+                        receiver.mPackageName);
+                continue;
+            }
+
             Location notifyLocation = null;
             if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                 notifyLocation = coarseLocation;  // use coarse location
@@ -1784,17 +1792,33 @@
         }
     }
 
+    private boolean isMockProvider(String provider) {
+        synchronized (mLock) {
+            return mMockProviders.containsKey(provider);
+        }
+    }
+
     private void handleLocationChanged(Location location, boolean passive) {
-        String provider = location.getProvider();
+        // create a working copy of the incoming Location so that the service can modify it without
+        // disturbing the caller's copy
+        Location myLocation = new Location(location);
+        String provider = myLocation.getProvider();
+
+        // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
+        // bit if location did not come from a mock provider because passive/fused providers can
+        // forward locations from mock providers, and should not grant them legitimacy in doing so.
+        if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
+            myLocation.setIsFromMockProvider(true);
+        }
 
         if (!passive) {
             // notify passive provider of the new location
-            mPassiveProvider.updateLocation(location);
+            mPassiveProvider.updateLocation(myLocation);
         }
 
         synchronized (mLock) {
             if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
-                handleLocationChangedLocked(location, passive);
+                handleLocationChangedLocked(myLocation, passive);
             }
         }
     }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index de8a44b..0a54593 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -1468,32 +1468,6 @@
     }
 
     @Override
-    public void setDnsIfaceForPid(String iface, int pid) throws IllegalStateException {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            String cmd = "resolver setifaceforpid " + iface + " " + pid;
-
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw new IllegalStateException(
-                    "Error communicating with native deamon to set interface for pid" + iface, e);
-        }
-    }
-
-    @Override
-    public void clearDnsIfaceForPid(int pid) throws IllegalStateException {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            String cmd = "resolver clearifaceforpid " + pid;
-
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw new IllegalStateException(
-                    "Error communicating with native deamon to clear interface for pid " + pid, e);
-        }
-    }
-
-    /** {@inheritDoc} */
     public void monitor() {
         if (mConnector != null) {
             mConnector.monitor();
diff --git a/services/java/com/android/server/RecognitionManagerService.java b/services/java/com/android/server/RecognitionManagerService.java
index 1e0755d..c2e749d 100644
--- a/services/java/com/android/server/RecognitionManagerService.java
+++ b/services/java/com/android/server/RecognitionManagerService.java
@@ -89,17 +89,15 @@
     private void initForUser(int userHandle) {
         if (DEBUG) Slog.i(TAG, "initForUser user=" + userHandle);
         ComponentName comp = getCurRecognizer(userHandle);
+        ServiceInfo info = null;
         if (comp != null) {
-            // See if the current recognizer is no longer available.
+            // See if the current recognizer is still available.
             try {
-                mIPm.getServiceInfo(comp, 0, userHandle);
+                info = mIPm.getServiceInfo(comp, 0, userHandle);
             } catch (RemoteException e) {
-                comp = findAvailRecognizer(null, userHandle);
-                if (comp != null) {
-                    setCurRecognizer(comp, userHandle);
-                }
             }
-        } else {
+        }
+        if (info == null) {
             comp = findAvailRecognizer(null, userHandle);
             if (comp != null) {
                 setCurRecognizer(comp, userHandle);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 5789a53..ad6eb4d 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.app.AlarmManager;
+import android.app.AppOpsManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -127,6 +128,7 @@
     private int mMulticastDisabled;
 
     private final IBatteryStats mBatteryStats;
+    private final AppOpsManager mAppOps;
 
     private boolean mEnableTrafficStatsPoll = false;
     private int mTrafficStatsPollToken = 0;
@@ -381,6 +383,7 @@
         mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
         mWifiStateMachine.enableRssiPolling(true);
         mBatteryStats = BatteryStatsService.getService();
+        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
 
         mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
         Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
@@ -845,10 +848,15 @@
      * a list of {@link ScanResult} objects.
      * @return the list of results
      */
-    public List<ScanResult> getScanResults() {
+    public List<ScanResult> getScanResults(String callingPackage) {
         enforceAccessPermission();
         int userId = UserHandle.getCallingUserId();
+        int uid = Binder.getCallingUid();
         long ident = Binder.clearCallingIdentity();
+        if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
+                != AppOpsManager.MODE_ALLOWED) {
+            return new ArrayList<ScanResult>();
+        }
         try {
             int currentUser = ActivityManager.getCurrentUser();
             if (userId != currentUser) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d8e199b..e0046ad 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -262,6 +262,9 @@
     // Maximum number of users we allow to be running at a time.
     static final int MAX_RUNNING_USERS = 3;
 
+    // How long to wait in getTopActivityExtras for the activity to respond with the result.
+    static final int PENDING_ACTIVITY_RESULT_TIMEOUT = 2*2000;
+
     static final int MY_PID = Process.myPid();
     
     static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -319,11 +322,32 @@
      * Activity we have told the window manager to have key focus.
      */
     ActivityRecord mFocusedActivity = null;
+
     /**
      * List of intents that were used to start the most recent tasks.
      */
     final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
 
+    public class PendingActivityExtras extends Binder implements Runnable {
+        public final ActivityRecord activity;
+        public boolean haveResult = false;
+        public Bundle result = null;
+        public PendingActivityExtras(ActivityRecord _activity) {
+            activity = _activity;
+        }
+        @Override
+        public void run() {
+            Slog.w(TAG, "getTopActivityExtras failed: timeout retrieving from " + activity);
+            synchronized (this) {
+                haveResult = true;
+                notifyAll();
+            }
+        }
+    }
+
+    final ArrayList<PendingActivityExtras> mPendingActivityExtras
+            = new ArrayList<PendingActivityExtras>();
+
     /**
      * Process management.
      */
@@ -7451,6 +7475,63 @@
         return KEY_DISPATCHING_TIMEOUT;
     }
 
+    public Bundle getTopActivityExtras(int requestType) {
+        enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
+                "getTopActivityExtras()");
+        PendingActivityExtras pae;
+        Bundle extras = new Bundle();
+        synchronized (this) {
+            ActivityRecord activity = mMainStack.mResumedActivity;
+            if (activity == null) {
+                Slog.w(TAG, "getTopActivityExtras failed: no resumed activity");
+                return null;
+            }
+            extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
+            if (activity.app == null || activity.app.thread == null) {
+                Slog.w(TAG, "getTopActivityExtras failed: no process for " + activity);
+                return extras;
+            }
+            if (activity.app.pid == Binder.getCallingPid()) {
+                Slog.w(TAG, "getTopActivityExtras failed: request process same as " + activity);
+                return extras;
+            }
+            pae = new PendingActivityExtras(activity);
+            try {
+                activity.app.thread.requestActivityExtras(activity.appToken, pae, requestType);
+                mPendingActivityExtras.add(pae);
+                mHandler.postDelayed(pae, PENDING_ACTIVITY_RESULT_TIMEOUT);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "getTopActivityExtras failed: crash calling " + activity);
+                return extras;
+            }
+        }
+        synchronized (pae) {
+            while (!pae.haveResult) {
+                try {
+                    pae.wait();
+                } catch (InterruptedException e) {
+                }
+            }
+            if (pae.result != null) {
+                extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.result);
+            }
+        }
+        synchronized (this) {
+            mPendingActivityExtras.remove(pae);
+            mHandler.removeCallbacks(pae);
+        }
+        return extras;
+    }
+
+    public void reportTopActivityExtras(IBinder token, Bundle extras) {
+        PendingActivityExtras pae = (PendingActivityExtras)token;
+        synchronized (pae) {
+            pae.result = extras;
+            pae.haveResult = true;
+            pae.notifyAll();
+        }
+    }
+
     public void registerProcessObserver(IProcessObserver observer) {
         enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "registerProcessObserver()");
diff --git a/services/java/com/android/server/location/GeofenceManager.java b/services/java/com/android/server/location/GeofenceManager.java
index f9be719..e24bf76 100644
--- a/services/java/com/android/server/location/GeofenceManager.java
+++ b/services/java/com/android/server/location/GeofenceManager.java
@@ -21,6 +21,7 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -68,6 +69,7 @@
 
     private final Context mContext;
     private final LocationManager mLocationManager;
+    private final AppOpsManager mAppOps;
     private final PowerManager.WakeLock mWakeLock;
     private final GeofenceHandler mHandler;
     private final LocationBlacklist mBlacklist;
@@ -107,6 +109,7 @@
     public GeofenceManager(Context context, LocationBlacklist blacklist) {
         mContext = context;
         mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mHandler = new GeofenceHandler();
@@ -114,14 +117,14 @@
     }
 
     public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
-            int uid, String packageName) {
+            int allowedResolutionLevel, int uid, String packageName) {
         if (D) {
             Slog.d(TAG, "addFence: request=" + request + ", geofence=" + geofence
                     + ", intent=" + intent + ", uid=" + uid + ", packageName=" + packageName);
         }
 
         GeofenceState state = new GeofenceState(geofence,
-                request.getExpireAt(), packageName, intent);
+                request.getExpireAt(), allowedResolutionLevel, uid, packageName, intent);
         synchronized (mLock) {
             // first make sure it doesn't already exist
             for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -261,6 +264,18 @@
                     continue;
                 }
 
+                int op = LocationManagerService.resolutionLevelToOp(state.mAllowedResolutionLevel);
+                if (op >= 0) {
+                    if (mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, state.mUid,
+                            state.mPackageName) != AppOpsManager.MODE_ALLOWED) {
+                        if (D) {
+                            Slog.d(TAG, "skipping geofence processing for no op app: "
+                                    + state.mPackageName);
+                        }
+                        continue;
+                    }
+                }
+
                 needUpdates = true;
                 if (location != null) {
                     int event = state.processLocation(location);
diff --git a/services/java/com/android/server/location/GeofenceState.java b/services/java/com/android/server/location/GeofenceState.java
index 11705ff..3ebe20a 100644
--- a/services/java/com/android/server/location/GeofenceState.java
+++ b/services/java/com/android/server/location/GeofenceState.java
@@ -35,6 +35,8 @@
     public final Geofence mFence;
     private final Location mLocation;
     public final long mExpireAt;
+    public final int mAllowedResolutionLevel;
+    public final int mUid;
     public final String mPackageName;
     public final PendingIntent mIntent;
 
@@ -42,12 +44,14 @@
     double mDistanceToCenter;  // current distance to center of fence
 
     public GeofenceState(Geofence fence, long expireAt,
-            String packageName, PendingIntent intent) {
+            int allowedResolutionLevel, int uid, String packageName, PendingIntent intent) {
         mState = STATE_UNKNOWN;
         mDistanceToCenter = Double.MAX_VALUE;
 
         mFence = fence;
         mExpireAt = expireAt;
+        mAllowedResolutionLevel = allowedResolutionLevel;
+        mUid = uid;
         mPackageName = packageName;
         mIntent = intent;
 
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 12c14bf..da150d9 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -704,17 +704,17 @@
      */
     @Override
     public void enable() {
+        synchronized (mLock) {
+            if (mEnabled) return;
+            mEnabled = true;
+        }
+
         sendMessage(ENABLE, 1, null);
     }
 
     private void handleEnable() {
         if (DEBUG) Log.d(TAG, "handleEnable");
 
-        synchronized (mLock) {
-            if (mEnabled) return;
-            mEnabled = true;
-        }
-
         boolean enabled = native_init();
 
         if (enabled) {
@@ -740,17 +740,17 @@
      */
     @Override
     public void disable() {
+        synchronized (mLock) {
+            if (!mEnabled) return;
+            mEnabled = false;
+        }
+
         sendMessage(ENABLE, 0, null);
     }
 
     private void handleDisable() {
         if (DEBUG) Log.d(TAG, "handleDisable");
 
-        synchronized (mLock) {
-            if (!mEnabled) return;
-            mEnabled = false;
-        }
-
         stopNavigating();
         mAlarmManager.cancel(mWakeupIntent);
         mAlarmManager.cancel(mTimeoutIntent);
diff --git a/services/java/com/android/server/location/LocationBlacklist.java b/services/java/com/android/server/location/LocationBlacklist.java
index 2437a37..6f22689 100644
--- a/services/java/com/android/server/location/LocationBlacklist.java
+++ b/services/java/com/android/server/location/LocationBlacklist.java
@@ -67,9 +67,9 @@
 
     private void reloadBlacklistLocked() {
         mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME);
-        Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist));
+        if (D) Slog.d(TAG, "whitelist: " + Arrays.toString(mWhitelist));
         mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME);
-        Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist));
+        if (D) Slog.d(TAG, "blacklist: " + Arrays.toString(mBlacklist));
     }
 
     private void reloadBlacklist() {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 9b3795a..626002d 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static com.android.internal.util.ArrayUtils.appendInt;
@@ -1347,7 +1348,8 @@
                 continue;
             }
 
-            if (!ps.grantedPermissions
+            final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
+            if (!gp.grantedPermissions
                     .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
                 continue;
             }
@@ -2878,187 +2880,145 @@
         }
     }
 
-    private static final int getContinuationPoint(final String[] keys, final String key) {
-        final int index;
-        if (key == null) {
-            index = 0;
-        } else {
-            final int insertPoint = Arrays.binarySearch(keys, key);
-            if (insertPoint < 0) {
-                index = -insertPoint;
-            } else {
-                index = insertPoint + 1;
-            }
-        }
-        return index;
-    }
-
     @Override
-    public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead,
-            int userId) {
-        final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
+    public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
-        final String[] keys;
 
         enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "get installed packages");
 
         // writer
         synchronized (mPackages) {
+            ArrayList<PackageInfo> list;
             if (listUninstalled) {
-                keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
-            } else {
-                keys = mPackages.keySet().toArray(new String[mPackages.size()]);
-            }
-
-            Arrays.sort(keys);
-            int i = getContinuationPoint(keys, lastRead);
-            final int N = keys.length;
-
-            while (i < N) {
-                final String packageName = keys[i++];
-
-                PackageInfo pi = null;
-                if (listUninstalled) {
-                    final PackageSetting ps = mSettings.mPackages.get(packageName);
-                    if (ps != null) {
+                list = new ArrayList<PackageInfo>(mSettings.mPackages.size());
+                for (PackageSetting ps : mSettings.mPackages.values()) {
+                    PackageInfo pi;
+                    if (ps.pkg != null) {
+                        pi = generatePackageInfo(ps.pkg, flags, userId);
+                    } else {
                         pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
                     }
-                } else {
-                    final PackageParser.Package p = mPackages.get(packageName);
-                    if (p != null) {
-                        pi = generatePackageInfo(p, flags, userId);
+                    if (pi != null) {
+                        list.add(pi);
                     }
                 }
-
-                if (pi != null && list.append(pi)) {
-                    break;
+            } else {
+                list = new ArrayList<PackageInfo>(mPackages.size());
+                for (PackageParser.Package p : mPackages.values()) {
+                    PackageInfo pi = generatePackageInfo(p, flags, userId);
+                    if (pi != null) {
+                        list.add(pi);
+                    }
                 }
             }
 
-            if (i == N) {
-                list.setLastSlice(true);
+            return new ParceledListSlice<PackageInfo>(list);
+        }
+    }
+
+    private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
+            String[] permissions, boolean[] tmp, int flags, int userId) {
+        int numMatch = 0;
+        final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
+        for (int i=0; i<permissions.length; i++) {
+            if (gp.grantedPermissions.contains(permissions[i])) {
+                tmp[i] = true;
+                numMatch++;
+            } else {
+                tmp[i] = false;
             }
         }
-
-        return list;
+        if (numMatch == 0) {
+            return;
+        }
+        PackageInfo pi;
+        if (ps.pkg != null) {
+            pi = generatePackageInfo(ps.pkg, flags, userId);
+        } else {
+            pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
+        }
+        if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
+            if (numMatch == permissions.length) {
+                pi.requestedPermissions = permissions;
+            } else {
+                pi.requestedPermissions = new String[numMatch];
+                numMatch = 0;
+                for (int i=0; i<permissions.length; i++) {
+                    if (tmp[i]) {
+                        pi.requestedPermissions[numMatch] = permissions[i];
+                        numMatch++;
+                    }
+                }
+            }
+        }
+        list.add(pi);
     }
 
     @Override
     public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
-            String[] permissions, int flags, String lastRead, int userId) {
+            String[] permissions, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
 
         // writer
         synchronized (mPackages) {
-            ArrayList<String> keysList = new ArrayList<String>();
+            ArrayList<PackageInfo> list = new ArrayList<PackageInfo>();
+            boolean[] tmpBools = new boolean[permissions.length];
             if (listUninstalled) {
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    for (String perm : permissions) {
-                        if (ps.grantedPermissions.contains(perm)) {
-                            keysList.add(ps.name);
-                            break;
-                        }
-                    }
+                    addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, userId);
                 }
             } else {
                 for (PackageParser.Package pkg : mPackages.values()) {
                     PackageSetting ps = (PackageSetting)pkg.mExtras;
                     if (ps != null) {
-                        for (String perm : permissions) {
-                            if (ps.grantedPermissions.contains(perm)) {
-                                keysList.add(ps.name);
-                                break;
-                            }
+                        addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags,
+                                userId);
+                    }
+                }
+            }
+
+            return new ParceledListSlice<PackageInfo>(list);
+        }
+    }
+
+    @Override
+    public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
+        if (!sUserManager.exists(userId)) return null;
+        final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
+
+        // writer
+        synchronized (mPackages) {
+            ArrayList<ApplicationInfo> list;
+            if (listUninstalled) {
+                list = new ArrayList<ApplicationInfo>(mSettings.mPackages.size());
+                for (PackageSetting ps : mSettings.mPackages.values()) {
+                    ApplicationInfo ai;
+                    if (ps.pkg != null) {
+                        ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
+                                ps.readUserState(userId), userId);
+                    } else {
+                        ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
+                    }
+                    if (ai != null) {
+                        list.add(ai);
+                    }
+                }
+            } else {
+                list = new ArrayList<ApplicationInfo>(mPackages.size());
+                for (PackageParser.Package p : mPackages.values()) {
+                    if (p.mExtras != null) {
+                        ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
+                                ((PackageSetting)p.mExtras).readUserState(userId), userId);
+                        if (ai != null) {
+                            list.add(ai);
                         }
                     }
                 }
             }
 
-            String[] keys = new String[keysList.size()];
-            keysList.toArray(keys);
-            Arrays.sort(keys);
-            int i = getContinuationPoint(keys, lastRead);
-            final int N = keys.length;
-
-            while (i < N) {
-                final String packageName = keys[i++];
-
-                PackageInfo pi = null;
-                if (listUninstalled) {
-                    final PackageSetting ps = mSettings.mPackages.get(packageName);
-                    if (ps != null) {
-                        pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
-                    }
-                } else {
-                    final PackageParser.Package p = mPackages.get(packageName);
-                    if (p != null) {
-                        pi = generatePackageInfo(p, flags, userId);
-                    }
-                }
-
-                if (pi != null && list.append(pi)) {
-                    break;
-                }
-            }
-
-            if (i == N) {
-                list.setLastSlice(true);
-            }
+            return new ParceledListSlice<ApplicationInfo>(list);
         }
-
-        return list;
-    }
-
-    @Override
-    public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
-            String lastRead, int userId) {
-        if (!sUserManager.exists(userId)) return null;
-        final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
-        final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
-        final String[] keys;
-
-        // writer
-        synchronized (mPackages) {
-            if (listUninstalled) {
-                keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
-            } else {
-                keys = mPackages.keySet().toArray(new String[mPackages.size()]);
-            }
-
-            Arrays.sort(keys);
-            int i = getContinuationPoint(keys, lastRead);
-            final int N = keys.length;
-
-            while (i < N) {
-                final String packageName = keys[i++];
-
-                ApplicationInfo ai = null;
-                final PackageSetting ps = mSettings.mPackages.get(packageName);
-                if (listUninstalled) {
-                    if (ps != null) {
-                        ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
-                    }
-                } else {
-                    final PackageParser.Package p = mPackages.get(packageName);
-                    if (p != null && ps != null) {
-                        ai = PackageParser.generateApplicationInfo(p, flags,
-                                ps.readUserState(userId), userId);
-                    }
-                }
-
-                if (ai != null && list.append(ai)) {
-                    break;
-                }
-            }
-
-            if (i == N) {
-                list.setLastSlice(true);
-            }
-        }
-
-        return list;
     }
 
     public List<ApplicationInfo> getPersistentApplications(int flags) {
@@ -3339,6 +3299,13 @@
                     Log.i(TAG, "Package " + ps.name + " at " + scanFile
                             + " ignored: updated version " + ps.versionCode
                             + " better than this " + pkg.mVersionCode);
+                    if (!updatedPkg.codePath.equals(scanFile)) {
+                        Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg : "
+                                + ps.name + " changing from " + updatedPkg.codePathString
+                                + " to " + scanFile);
+                        updatedPkg.codePath = scanFile;
+                        updatedPkg.codePathString = scanFile.toString();                        
+                    }
                     mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
                     return null;
                 } else {
@@ -8949,13 +8916,14 @@
         if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
               || newState == COMPONENT_ENABLED_STATE_ENABLED
               || newState == COMPONENT_ENABLED_STATE_DISABLED
-              || newState == COMPONENT_ENABLED_STATE_DISABLED_USER)) {
+              || newState == COMPONENT_ENABLED_STATE_DISABLED_USER
+              || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
             throw new IllegalArgumentException("Invalid new component state: "
                     + newState);
         }
         PackageSetting pkgSetting;
         final int uid = Binder.getCallingUid();
-        final int permission = mContext.checkCallingPermission(
+        final int permission = mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
         enforceCrossUserPermission(uid, userId, false, "set enabled");
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 06f11bc..e336524 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
@@ -2412,8 +2413,14 @@
             return false;
         }
         PackageUserState ustate = packageSettings.readUserState(userId);
+        if ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0) {
+            if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+                return true;
+            }
+        }
         if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED
                 || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
+                || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
                 || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
                     && ustate.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
             return false;
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java
index 4b2bbfe..f9aaa17 100644
--- a/services/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbSettingsManager.java
@@ -364,8 +364,9 @@
         }
 
         @Override
-        public void onPackageChanged(String packageName, int uid, String[] components) {
+        public boolean onPackageChanged(String packageName, int uid, String[] components) {
             handlePackageUpdate(packageName);
+            return false;
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 167b6c2..47ce130 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -557,6 +557,25 @@
         }
     }
 
+    public void testCycleTodayJanuary() throws Exception {
+        final NetworkPolicy policy = new NetworkPolicy(
+                sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
+
+        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
+                computeNextCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy));
+        assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"),
+                computeNextCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy));
+        assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"),
+                computeNextCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
+
+        assertTimeEquals(parseTime("2012-12-14T00:00:00.000-08:00"),
+                computeLastCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy));
+        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
+                computeLastCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy));
+        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
+                computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
+    }
+
     public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index e2da53e..3ed9cef 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -335,7 +335,7 @@
         mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160;
 
         mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
-        mEvdoEcio = (mEvdoEcio > 0) ? -mEvdoEcio : -1;
+        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -1;
         mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
 
         // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
diff --git a/test-runner/src/android/test/mock/MockContentResolver.java b/test-runner/src/android/test/mock/MockContentResolver.java
index 715da0f..aec6c77 100644
--- a/test-runner/src/android/test/mock/MockContentResolver.java
+++ b/test-runner/src/android/test/mock/MockContentResolver.java
@@ -54,12 +54,20 @@
 public class MockContentResolver extends ContentResolver {
     Map<String, ContentProvider> mProviders;
 
-    /*
-     * Creates a local map of providers. This map is used instead of the global map when an
-     * API call tries to acquire a provider.
+    /**
+     * Creates a local map of providers. This map is used instead of the global
+     * map when an API call tries to acquire a provider.
      */
     public MockContentResolver() {
-        super(null);
+        this(null);
+    }
+
+    /**
+     * Creates a local map of providers. This map is used instead of the global
+     * map when an API call tries to acquire a provider.
+     */
+    public MockContentResolver(Context context) {
+        super(context);
         mProviders = Maps.newHashMap();
     }
 
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 3097811..248fbf1 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -106,6 +106,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public String getBasePackageName() {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         throw new UnsupportedOperationException();
diff --git a/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java
index 1b72486..ab60f21 100644
--- a/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java
+++ b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java
@@ -21,6 +21,7 @@
 import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
 import android.view.ViewGroup;
@@ -180,7 +181,7 @@
     }
 
     private final void validateNotAppThread() {
-        if (ActivityThread.currentActivityThread() != null) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
             throw new RuntimeException(
                 "This method can not be called from the main application thread");
         }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
index 9a4e99e..22b587f 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
@@ -22,6 +22,7 @@
 import android.net.http.SslError;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
 import android.view.ViewGroup;
@@ -184,7 +185,7 @@
     }
 
     private final void validateNotAppThread() {
-        if (ActivityThread.currentActivityThread() != null) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
             throw new RuntimeException(
                 "This method can not be called from the main application thread");
         }
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 7d2ba19..57ce1d6 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -148,7 +148,16 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        
+
+        <activity
+                android:name="ClipRegion2Activity"
+                android:label="_ClipRegion2">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
         <activity
                 android:name="DisplayListLayersActivity"
                 android:label="__DisplayListLayers">
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_5.xml b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
index 36cf8c9..5baf583 100644
--- a/tests/HwAccelerationTest/res/layout/view_layers_5.xml
+++ b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
@@ -48,13 +48,32 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Grow layer" />
+
+        <Button
+            android:onClick="enableClip"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Circle clip" />
+
+        <Button
+            android:onClick="disableClip"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="No clip" />
         
     </LinearLayout>
 
-    <ListView
-        android:id="@+id/list1"
+    <view class="com.android.test.hwui.ViewLayersActivity5$ClipFrameLayout"
+        android:id="@+id/container"
         android:layout_width="0dip"
         android:layout_height="match_parent"
-        android:layout_weight="1" />
+        android:layout_weight="1">
+
+        <ListView
+            android:id="@+id/list1"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+    </view>
 
 </LinearLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion2Activity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion2Activity.java
new file mode 100644
index 0000000..066e35c
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion2Activity.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Region;
+import android.os.Bundle;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ClipRegion2Activity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final RegionView group = new RegionView(this);
+
+        final TextView text = new TextView(this);
+        text.setText(buildText());
+        group.addView(text);
+
+        setContentView(group);
+    }
+
+    private static CharSequence buildText() {
+        StringBuffer buffer = new StringBuffer();
+        for (int i = 0; i < 10; i++) {
+            buffer.append(LOREM_IPSUM);
+        }
+        return buffer;
+    }
+
+    public static class RegionView extends FrameLayout {
+        private final Region mRegion = new Region();
+        private float mClipPosition = 0.0f;
+
+        public RegionView(Context c) {
+            super(c);
+        }
+
+        public float getClipPosition() {
+            return mClipPosition;
+        }
+
+        public void setClipPosition(float clipPosition) {
+            mClipPosition = clipPosition;
+            invalidate();
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+
+            canvas.save();
+
+            mRegion.setEmpty();
+            mRegion.op(0, 0, getWidth(), getHeight(),
+                    Region.Op.REPLACE);
+            mRegion.op(getWidth() / 4, getHeight() / 4, 3 * getWidth() / 4, 3 * getHeight() / 4,
+                    Region.Op.DIFFERENCE);
+
+            canvas.clipRegion(mRegion);
+            super.dispatchDraw(canvas);
+
+            canvas.restore();
+        }
+    }
+
+    private static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis molestie aliquam. Donec metus metus, laoreet nec sagittis vitae, ultricies sit amet eros. Suspendisse sed massa sit amet felis consectetur gravida. In vitae erat mi, in egestas nisl. Phasellus quis ipsum massa, at scelerisque arcu. Nam lectus est, pellentesque eget lacinia non, congue vitae augue. Aliquam erat volutpat. Pellentesque bibendum tincidunt viverra. Aliquam erat volutpat. Maecenas pretium vulputate placerat. Nulla varius elementum rutrum. Aenean mollis blandit imperdiet. Pellentesque interdum fringilla ligula.";
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegionActivity.java
index d5daa5f..3d3d709 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegionActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegionActivity.java
@@ -16,38 +16,77 @@
 
 package com.android.test.hwui;
 
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.Canvas;
-import android.graphics.Region;
+import android.graphics.Path;
 import android.os.Bundle;
-import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.TextView;
 
 @SuppressWarnings({"UnusedDeclaration"})
 public class ClipRegionActivity extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        final RegionView view = new RegionView(this);
-        setContentView(view);
+
+        final RegionView group = new RegionView(this);
+
+        final TextView text = new TextView(this);
+        text.setText(buildText());
+        group.addView(text);
+
+        setContentView(group);
+
+        ObjectAnimator animator = ObjectAnimator.ofFloat(group, "clipPosition", 0.0f, 1.0f);
+        animator.setDuration(3000);
+        animator.setRepeatCount(ValueAnimator.INFINITE);
+        animator.setRepeatMode(ValueAnimator.REVERSE);
+        animator.start();
     }
 
-    public static class RegionView extends View {
+    private static CharSequence buildText() {
+        StringBuffer buffer = new StringBuffer();
+        for (int i = 0; i < 10; i++) {
+            buffer.append(LOREM_IPSUM);
+        }
+        return buffer;
+    }
+
+    public static class RegionView extends FrameLayout {
+        private final Path mClipPath = new Path();
+        private float mClipPosition = 0.0f;
+
         public RegionView(Context c) {
             super(c);
         }
 
-        @Override
-        protected void onDraw(Canvas canvas) {
-            super.onDraw(canvas);
+        public float getClipPosition() {
+            return mClipPosition;
+        }
 
-            canvas.save();
-            canvas.clipRect(100.0f, 100.0f, getWidth() - 100.0f, getHeight() - 100.0f,
-                    Region.Op.DIFFERENCE);
-            canvas.drawARGB(128, 255, 0, 0);
-            canvas.restore();
-
+        public void setClipPosition(float clipPosition) {
+            mClipPosition = clipPosition;
             invalidate();
         }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+
+            canvas.save();
+
+            mClipPath.reset();
+            mClipPath.addCircle(mClipPosition * getWidth(), getHeight() / 2.0f,
+                    getWidth() / 4.0f, Path.Direction.CW);
+
+            canvas.clipPath(mClipPath);
+            super.dispatchDraw(canvas);
+
+            canvas.restore();
+        }
     }
+
+    private static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis molestie aliquam. Donec metus metus, laoreet nec sagittis vitae, ultricies sit amet eros. Suspendisse sed massa sit amet felis consectetur gravida. In vitae erat mi, in egestas nisl. Phasellus quis ipsum massa, at scelerisque arcu. Nam lectus est, pellentesque eget lacinia non, congue vitae augue. Aliquam erat volutpat. Pellentesque bibendum tincidunt viverra. Aliquam erat volutpat. Maecenas pretium vulputate placerat. Nulla varius elementum rutrum. Aenean mollis blandit imperdiet. Pellentesque interdum fringilla ligula.";
 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index 2664977..cbbb7ef 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -19,14 +19,18 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.Path;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.os.Bundle;
+import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
 import android.widget.ListView;
 import android.widget.TextView;
 
@@ -37,30 +41,75 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        
+
+        init();
+
         setContentView(R.layout.view_layers_5);
-
-        mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
-
         setupList(R.id.list1);
     }
 
+    public static class ClipFrameLayout extends FrameLayout {
+        private final Path mClipPath = new Path();
+        private boolean mClipEnabled;
+
+        public ClipFrameLayout(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public ClipFrameLayout(Context context, AttributeSet attrs, int defStyle) {
+            super(context, attrs, defStyle);
+        }
+
+        public boolean isClipEnabled() {
+            return mClipEnabled;
+        }
+
+        public void setClipEnabled(boolean clipEnabled) {
+            mClipEnabled = clipEnabled;
+            invalidate();
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            if (mClipEnabled) {
+                mClipPath.reset();
+                mClipPath.addCircle(getWidth() / 2.0f, getHeight() / 2.0f,
+                        Math.min(getWidth(), getHeight()) / 3.0f, Path.Direction.CW);
+
+                canvas.clipPath(mClipPath);
+            }
+            super.dispatchDraw(canvas);
+        }
+    }
+
+    private void init() {
+        mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
+    }
+
+    public void enableClip(View v) {
+        ((ClipFrameLayout) findViewById(R.id.container)).setClipEnabled(true);
+    }
+
+    public void disableClip(View v) {
+        ((ClipFrameLayout) findViewById(R.id.container)).setClipEnabled(false);
+    }
+
     public void enableLayer(View v) {
-        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
+        findViewById(R.id.container).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
     }
 
     public void disableLayer(View v) {
-        findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_NONE, null);
+        findViewById(R.id.container).setLayerType(View.LAYER_TYPE_NONE, null);
     }
     
     public void growLayer(View v) {
-        findViewById(R.id.list1).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
-        findViewById(R.id.list1).requestLayout();
+        findViewById(R.id.container).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
+        findViewById(R.id.container).requestLayout();
     }
 
     public void shrinkLayer(View v) {
-        findViewById(R.id.list1).getLayoutParams().height = 300;
-        findViewById(R.id.list1).requestLayout();
+        findViewById(R.id.container).getLayoutParams().height = 300;
+        findViewById(R.id.container).requestLayout();
     }
     
     private void setupList(int listId) {
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
index 2818bf5..03e5a79 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
@@ -16,7 +16,7 @@
 
 #pragma version(1)
 #pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+//#pragma rs_fp_relaxed
 
 static float sr = 0.f;
 static float sg = 0.f;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
index 81cb9d0..7ee3405 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
@@ -16,7 +16,7 @@
 
 #pragma version(1)
 #pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+//#pragma rs_fp_relaxed
 
 static double shadowFilterMap[] = {
     -0.00591,  0.0001,
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
index 677e857..fae94a1 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
@@ -16,7 +16,6 @@
 
 #pragma version(1)
 #pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
 
 float vibrance = 0.f;
 
@@ -39,7 +38,7 @@
     int g = in->g;
     int b = in->b;
     float red = (r-max(g, b))/256.f;
-    float sx = (float)(Vib/(1+exp(-red*3)));
+    float sx = (float)(Vib/(1+native_exp(-red*3)));
     S = sx+1;
     MS = 1.0f - S;
     Rt = Rf * MS;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
index 05a5929..5668621 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx.rsh
@@ -50,8 +50,7 @@
     const float2 inCoord = {(float)x, (float)y};
     const float2 coord = mad(inCoord, inv_dimensions, neg_center);
     const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
-    // TODO:  add half_exp once implemented
-    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * native_exp(sloped_dist_ratio));
     float4 fout;
     fout.rgb = fin.rgb * lumen;
     fout.w = fin.w;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
index b9c28fc..8c825f2 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
@@ -16,7 +16,7 @@
 
 #pragma version(1)
 #pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+//#pragma rs_fp_relaxed
 
 static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
 
diff --git a/tests/RenderScriptTests/MathErr/Android.mk b/tests/RenderScriptTests/MathErr/Android.mk
new file mode 100644
index 0000000..b3edd02
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2013 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsMathErr
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/MathErr/AndroidManifest.xml b/tests/RenderScriptTests/MathErr/AndroidManifest.xml
new file mode 100644
index 0000000..6a3db2c
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.rs.matherr">
+
+    <uses-sdk android:minSdkVersion="17" />
+    <application android:label="RS Math Err">
+        <activity android:name="MathErrActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/MathErr/res/layout/main.xml b/tests/RenderScriptTests/MathErr/res/layout/main.xml
new file mode 100644
index 0000000..7b2c76a
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/displayin"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+    <ImageView
+        android:id="@+id/displayout"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErr.java b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErr.java
new file mode 100644
index 0000000..4561267
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErr.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.rs.matherr;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import java.lang.Float;
+import java.lang.Math;
+
+public class MathErr {
+    private RenderScript mRS;
+    private Allocation mAllocationSrc;
+    private Allocation mAllocationRes;
+    private ScriptC_math_err mScript;
+    private java.util.Random mRand = new java.util.Random();
+
+    private final int BUF_SIZE = 4096;
+    float mSrc[] = new float[BUF_SIZE];
+    float mRef[] = new float[BUF_SIZE];
+    float mRes[] = new float[BUF_SIZE];
+
+    MathErr(RenderScript rs) {
+        mRS = rs;
+        mScript = new ScriptC_math_err(mRS);
+
+        mAllocationSrc = Allocation.createSized(rs, Element.F32(rs), BUF_SIZE);
+        mAllocationRes = Allocation.createSized(rs, Element.F32(rs), BUF_SIZE);
+
+        testExp2();
+        testLog2();
+    }
+
+    void buildRand() {
+        for (int i=0; i < BUF_SIZE; i++) {
+            mSrc[i] = (((float)i) / 9) - 200;
+            //mSrc[i] = Float.intBitsToFloat(mRand.nextInt());
+        }
+        mAllocationSrc.copyFrom(mSrc);
+    }
+
+    void logErr() {
+        mAllocationRes.copyTo(mRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            int err = Float.floatToRawIntBits(mRef[i]) - Float.floatToRawIntBits(mRes[i]);
+            err = Math.abs(err);
+            if (err > 8096) {
+                android.util.Log.v("err", "error " + err + " src " + mSrc[i] + " ref " + mRef[i] + " res " + mRes[i]);
+            }
+        }
+    }
+
+    void testExp2() {
+        android.util.Log.v("err", "testing exp2");
+        buildRand();
+        mScript.forEach_testExp2(mAllocationSrc, mAllocationRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            mRef[i] = (float)Math.pow(2.f, mSrc[i]);
+        }
+        logErr();
+    }
+
+    void testLog2() {
+        android.util.Log.v("err", "testing log2");
+        buildRand();
+        mScript.forEach_testLog2(mAllocationSrc, mAllocationRes);
+        for (int i=0; i < BUF_SIZE; i++) {
+            mRef[i] = (float)Math.log(mSrc[i]) * 1.442695041f;
+        }
+        logErr();
+    }
+
+}
diff --git a/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java
new file mode 100644
index 0000000..74d7b71
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/MathErrActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.rs.matherr;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+import android.renderscript.Allocation;
+import android.util.Log;
+
+public class MathErrActivity extends Activity {
+    private MathErr mME;
+    private RenderScript mRS;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mRS = RenderScript.create(this);
+        mME = new MathErr(mRS);
+    }
+}
diff --git a/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/math_err.rs b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/math_err.rs
new file mode 100644
index 0000000..a26770b
--- /dev/null
+++ b/tests/RenderScriptTests/MathErr/src/com/example/android/rs/matherr/math_err.rs
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.matherr)
+
+typedef union
+{
+  float fv;
+  int32_t iv;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float.  */
+
+#define GET_FLOAT_WORD(i,d)         \
+do {                                \
+  ieee_float_shape_type gf_u;       \
+  gf_u.fv = (d);                    \
+  (i) = gf_u.iv;                    \
+} while (0)
+
+/* Set a float from a 32 bit int.  */
+
+#define SET_FLOAT_WORD(d,i)         \
+do {                                \
+  ieee_float_shape_type sf_u;       \
+  sf_u.iv = (i);                    \
+  (d) = sf_u.fv;                    \
+} while (0)
+
+
+static float fast_log2(float v) {
+    int32_t ibits;
+    GET_FLOAT_WORD(ibits, v);
+
+    int32_t e = (ibits >> 23) & 0xff;
+
+    ibits &= 0x7fffff;
+    ibits |= 127 << 23;
+
+    float ir;
+    SET_FLOAT_WORD(ir, ibits);
+
+    ir -= 1.5f;
+    float ir2 = ir*ir;
+    float adj2 = 0.405465108f + // -0.00009f +
+                 (0.666666667f * ir) -
+                 (0.222222222f * ir2) +
+                 (0.098765432f * ir*ir2) -
+                 (0.049382716f * ir2*ir2) +
+                 (0.026337449f * ir*ir2*ir2) -
+                 (0.014631916f * ir2*ir2*ir2);
+    adj2 *= (1.f / 0.693147181f);
+
+    return (float)(e - 127) + adj2;
+}
+
+void testExp2(const float *in, float *out) {
+    float i = *in;
+    if (i > (-125.f) && i < 125.f) {
+        *out = native_exp2(i);
+    } else {
+        *out = exp2(i);
+    }
+    *out = native_exp2(i);
+}
+
+void testLog2(const float *in, float *out) {
+    *out = fast_log2(*in);
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/Android.mk b/tests/RenderScriptTests/RSTest_CompatLib/Android.mk
new file mode 100644
index 0000000..0fd0d96
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/Android.mk
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2013 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RSTest_Compat
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.support.v8.renderscript
+
+LOCAL_SDK_VERSION := 8
+LOCAL_RENDERSCRIPT_TARGET_API := 18
+LOCAL_RENDERSCRIPT_COMPATIBILITY := 18
+
+LOCAL_RENDERSCRIPT_CC := $(LLVM_RS_CC)
+LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := \
+    $(TOPDIR)external/clang/lib/Headers \
+    $(TOPDIR)frameworks/rs/scriptc
+
+LOCAL_RENDERSCRIPT_FLAGS := -rs-package-name=android.support.v8.renderscript
+LOCAL_REQUIRED_MODULES := librsjni
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/AndroidManifest.xml b/tests/RenderScriptTests/RSTest_CompatLib/AndroidManifest.xml
new file mode 100644
index 0000000..53219e7
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.test_compat">
+  <uses-sdk android:minSdkVersion="8" />
+  <uses-sdk android:targetSdkVersion="8" />
+    <application
+        android:label="_RS_Test_Compat"
+        android:icon="@drawable/test_pattern">
+        <activity android:name="RSTest"
+                  android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png b/tests/RenderScriptTests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java
new file mode 100644
index 0000000..b76f21e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.support.v8.renderscript.RenderScript;
+
+import android.app.ListActivity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.ArrayAdapter;
+
+import java.lang.Runtime;
+
+public class RSTest extends ListActivity {
+
+    private static final String LOG_TAG = "RSTest_Compat";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = false;
+
+    private RenderScript mRS;
+    private RSTestCore RSTC;
+
+    String mTestNames[];
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mRS = RenderScript.create(this);
+
+        RSTC = new RSTestCore(this);
+        RSTC.init(mRS, getResources());
+
+
+
+
+    }
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java
new file mode 100644
index 0000000..51f8a4d
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/RSTestCore.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+import android.app.ListActivity;
+import android.widget.ArrayAdapter;
+
+public class RSTestCore {
+    ListActivity mCtx;
+
+    public RSTestCore(ListActivity ctx) {
+        mCtx = ctx;
+    }
+
+    private Resources mRes;
+    private RenderScript mRS;
+
+    private ArrayList<UnitTest> unitTests;
+    private ListIterator<UnitTest> test_iter;
+    private UnitTest activeTest;
+    private boolean stopTesting;
+
+    private ScriptField_ListAllocs_s mListAllocs;
+
+    private ArrayAdapter<UnitTest> testAdapter;
+
+    /* Periodic timer for ensuring future tests get scheduled */
+    private Timer mTimer;
+    public static final int RS_TIMER_PERIOD = 100;
+
+    public void init(RenderScript rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        stopTesting = false;
+
+        unitTests = new ArrayList<UnitTest>();
+
+        unitTests.add(new UT_primitives(this, mRes, mCtx));
+        unitTests.add(new UT_constant(this, mRes, mCtx));
+        unitTests.add(new UT_vector(this, mRes, mCtx));
+        unitTests.add(new UT_unsigned(this, mRes, mCtx));
+        unitTests.add(new UT_array_init(this, mRes, mCtx));
+        unitTests.add(new UT_array_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_kernel(this, mRes, mCtx));
+        unitTests.add(new UT_kernel_struct(this, mRes, mCtx));
+        unitTests.add(new UT_bug_char(this, mRes, mCtx));
+        unitTests.add(new UT_clamp(this, mRes, mCtx));
+        unitTests.add(new UT_clamp_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_convert(this, mRes, mCtx));
+        unitTests.add(new UT_convert_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_copy_test(this, mRes, mCtx));
+        unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstime(this, mRes, mCtx));
+        unitTests.add(new UT_rstypes(this, mRes, mCtx));
+        unitTests.add(new UT_alloc(this, mRes, mCtx));
+        unitTests.add(new UT_refcount(this, mRes, mCtx));
+        unitTests.add(new UT_foreach(this, mRes, mCtx));
+        unitTests.add(new UT_foreach_bounds(this, mRes, mCtx));
+        unitTests.add(new UT_noroot(this, mRes, mCtx));
+        unitTests.add(new UT_atomic(this, mRes, mCtx));
+        unitTests.add(new UT_struct(this, mRes, mCtx));
+        unitTests.add(new UT_math(this, mRes, mCtx));
+        unitTests.add(new UT_math_conformance(this, mRes, mCtx));
+        unitTests.add(new UT_math_agree(this, mRes, mCtx));
+        unitTests.add(new UT_min(this, mRes, mCtx));
+        unitTests.add(new UT_int4(this, mRes, mCtx));
+        unitTests.add(new UT_element(this, mRes, mCtx));
+        unitTests.add(new UT_sampler(this, mRes, mCtx));
+        unitTests.add(new UT_fp_mad(this, mRes, mCtx));
+
+        /*
+        unitTests.add(new UnitTest(null, "<Pass>", 1));
+        unitTests.add(new UnitTest());
+        unitTests.add(new UnitTest(null, "<Fail>", -1));
+
+        for (int i = 0; i < 20; i++) {
+            unitTests.add(new UnitTest(null, "<Pass>", 1));
+        }
+        */
+
+        UnitTest [] uta = new UnitTest[unitTests.size()];
+        uta = unitTests.toArray(uta);
+
+        mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+        for (int i = 0; i < uta.length; i++) {
+
+            ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+            listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
+            listElem.result = uta[i].getResult();
+            mListAllocs.set(listElem, i, false);
+            uta[i].setItem(listElem);
+        }
+
+        mListAllocs.copyAll();
+
+        testAdapter = new ArrayAdapter<UnitTest>(mCtx, android.R.layout.simple_list_item_1, unitTests);
+        mCtx.setListAdapter(testAdapter);
+
+        test_iter = unitTests.listIterator();
+        refreshTestResults(); /* Kick off the first test */
+
+        TimerTask pTask = new TimerTask() {
+            public void run() {
+                refreshTestResults();
+            }
+        };
+
+        mTimer = new Timer();
+        mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD);
+    }
+
+    public void checkAndRunNextTest() {
+        mCtx.runOnUiThread(new Runnable() {
+                public void run() {
+                    if (testAdapter != null)
+                        testAdapter.notifyDataSetChanged();
+                }
+            });
+
+        if (activeTest != null) {
+            if (!activeTest.isAlive()) {
+                /* Properly clean up on our last test */
+                try {
+                    activeTest.join();
+                }
+                catch (InterruptedException e) {
+                }
+                activeTest = null;
+            }
+        }
+
+        if (!stopTesting && activeTest == null) {
+            if (test_iter.hasNext()) {
+                activeTest = test_iter.next();
+                activeTest.start();
+                /* This routine will only get called once when a new test
+                 * should start running. The message handler in UnitTest.java
+                 * ensures this. */
+            }
+            else {
+                if (mTimer != null) {
+                    mTimer.cancel();
+                    mTimer.purge();
+                    mTimer = null;
+                }
+            }
+        }
+    }
+
+    public void refreshTestResults() {
+        checkAndRunNextTest();
+    }
+
+    public void cleanup() {
+        stopTesting = true;
+        UnitTest t = activeTest;
+
+        /* Stop periodic refresh of testing */
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer.purge();
+            mTimer = null;
+        }
+
+        /* Wait to exit until we finish the current test */
+        if (t != null) {
+            try {
+                t.join();
+            }
+            catch (InterruptedException e) {
+            }
+            t = null;
+        }
+
+    }
+
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
new file mode 100644
index 0000000..ddc6a99
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_alloc.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Alloc", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_alloc s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        int Z = 0;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        s.set_dimZ(Z);
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+
+        typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        typeBuilder.setX(X).setY(Y).setFaces(true);
+        Allocation AFaces = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFaces(AFaces);
+        typeBuilder.setFaces(false).setMipmaps(true);
+        Allocation ALOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aLOD(ALOD);
+        typeBuilder.setFaces(true).setMipmaps(true);
+        Allocation AFacesLOD = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_aFacesLOD(AFacesLOD);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_alloc s = new ScriptC_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java
new file mode 100644
index 0000000..751187b
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_alloc.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_array_alloc extends UnitTest {
+    private Resources mRes;
+
+    protected UT_array_alloc(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Array Allocation", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_array_alloc s = new ScriptC_array_alloc(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        int dimX = s.get_dimX();
+        Allocation[] Arr = new Allocation[dimX];
+        Type.Builder typeBuilder = new Type.Builder(pRS, Element.I32(pRS));
+        Type T = typeBuilder.setX(1).create();
+        for (int i = 0; i < dimX; i++) {
+            Allocation A = Allocation.createTyped(pRS, T);
+            Arr[i] = A;
+        }
+        s.set_a(Arr);
+
+        s.invoke_array_alloc_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java
new file mode 100644
index 0000000..f8b2fd3
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_array_init.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_array_init extends UnitTest {
+    private Resources mRes;
+
+    protected UT_array_init(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Array Init", ctx);
+        mRes = res;
+    }
+
+    private void checkInit(ScriptC_array_init s) {
+        float[] fa = s.get_fa();
+        _RS_ASSERT("fa[0] == 1.0", fa[0] == 1.0);
+        _RS_ASSERT("fa[1] == 9.9999f", fa[1] == 9.9999f);
+        _RS_ASSERT("fa[2] == 0", fa[2] == 0);
+        _RS_ASSERT("fa[3] == 0", fa[3] == 0);
+        _RS_ASSERT("fa.length == 4", fa.length == 4);
+
+        double[] da = s.get_da();
+        _RS_ASSERT("da[0] == 7.0", da[0] == 7.0);
+        _RS_ASSERT("da[1] == 8.88888", da[1] == 8.88888);
+        _RS_ASSERT("da.length == 2", da.length == 2);
+
+        byte[] ca = s.get_ca();
+        _RS_ASSERT("ca[0] == 'a'", ca[0] == 'a');
+        _RS_ASSERT("ca[1] == 7", ca[1] == 7);
+        _RS_ASSERT("ca[2] == 'b'", ca[2] == 'b');
+        _RS_ASSERT("ca[3] == 'c'", ca[3] == 'c');
+        _RS_ASSERT("ca.length == 4", ca.length == 4);
+
+        short[] sa = s.get_sa();
+        _RS_ASSERT("sa[0] == 1", sa[0] == 1);
+        _RS_ASSERT("sa[1] == 1", sa[1] == 1);
+        _RS_ASSERT("sa[2] == 2", sa[2] == 2);
+        _RS_ASSERT("sa[3] == 3", sa[3] == 3);
+        _RS_ASSERT("sa.length == 4", sa.length == 4);
+
+        int[] ia = s.get_ia();
+        _RS_ASSERT("ia[0] == 5", ia[0] == 5);
+        _RS_ASSERT("ia[1] == 8", ia[1] == 8);
+        _RS_ASSERT("ia[2] == 0", ia[2] == 0);
+        _RS_ASSERT("ia[3] == 0", ia[3] == 0);
+        _RS_ASSERT("ia.length == 4", ia.length == 4);
+
+        long[] la = s.get_la();
+        _RS_ASSERT("la[0] == 13", la[0] == 13);
+        _RS_ASSERT("la[1] == 21", la[1] == 21);
+        _RS_ASSERT("la.length == 4", la.length == 2);
+
+        long[] lla = s.get_lla();
+        _RS_ASSERT("lla[0] == 34", lla[0] == 34);
+        _RS_ASSERT("lla[1] == 0", lla[1] == 0);
+        _RS_ASSERT("lla[2] == 0", lla[2] == 0);
+        _RS_ASSERT("lla[3] == 0", lla[3] == 0);
+        _RS_ASSERT("lla.length == 4", lla.length == 4);
+
+        boolean[] ba = s.get_ba();
+        _RS_ASSERT("ba[0] == true", ba[0] == true);
+        _RS_ASSERT("ba[1] == false", ba[1] == false);
+        _RS_ASSERT("ba[2] == false", ba[2] == false);
+        _RS_ASSERT("ba.length == 3", ba.length == 3);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_array_init s = new ScriptC_array_init(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        checkInit(s);
+        s.invoke_array_init_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java
new file mode 100644
index 0000000..7fe4b36
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_atomic.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_atomic extends UnitTest {
+    private Resources mRes;
+
+    protected UT_atomic(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Atomics", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_atomic s = new ScriptC_atomic(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_atomic_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java
new file mode 100644
index 0000000..5da5288
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_bug_char.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+
+public class UT_bug_char extends UnitTest {
+    private Resources mRes;
+
+    protected UT_bug_char(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Bug Char", ctx);
+        mRes = res;
+    }
+
+    // packing functions
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        Log.i("bug_char", "pack_b2 " + val[0] + " " + val[1]);
+        return new Byte2(val[0], val[1]);
+    }
+
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_bug_char s) {
+        byte rand_sc1_0 = (byte)7;
+        byte[] rand_sc2_0 = new byte[2];
+        rand_sc2_0[0] = 11;
+        rand_sc2_0[1] = 21;
+        Log.i("bug_char", "Generated sc2_0 to " + Arrays.toString(rand_sc2_0));
+        byte rand_sc1_1 = (byte)10;
+        byte[] rand_sc2_1 = new byte[2];
+        rand_sc2_1[0] = 13;
+        rand_sc2_1[1] = 15;
+        Log.i("bug_char", "Generated sc2_1 to " + Arrays.toString(rand_sc2_1));
+
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        // Set results for min
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        byte[] min_rand_sc2_raw = min(rand_sc2_0, rand_sc2_1);
+        Log.i("bug_char", "Generating min_rand_sc2_sc2 to " +
+              Arrays.toString(min_rand_sc2_raw));
+        Byte2 min_rand_sc2 = pack_b2(min_rand_sc2_raw);
+        Log.i("bug_char", "Setting min_rand_sc2_sc2 to [" + min_rand_sc2.x +
+              ", " + min_rand_sc2.y + "]");
+        s.set_min_rand_sc2_sc2(min_rand_sc2);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_bug_char s = new ScriptC_bug_char(pRS, mRes,
+                R.raw.bug_char);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_bug_char_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java
new file mode 100644
index 0000000..1f28abc
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_clamp extends UnitTest {
+    private Resources mRes;
+
+    protected UT_clamp(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Clamp (Full)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_clamp s = new ScriptC_clamp(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_clamp_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java
new file mode 100644
index 0000000..d880e68
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_clamp_relaxed.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_clamp_relaxed extends UnitTest {
+    private Resources mRes;
+
+    protected UT_clamp_relaxed(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Clamp (Relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_clamp_relaxed s =
+                new ScriptC_clamp_relaxed(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_clamp_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java
new file mode 100644
index 0000000..3085032
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_constant.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_constant extends UnitTest {
+    private Resources mRes;
+
+    protected UT_constant(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Const", ctx);
+        mRes = res;
+    }
+
+    private void Assert(boolean b) {
+        if (!b) {
+            failTest();
+        }
+    }
+
+    public void run() {
+        Assert(ScriptC_constant.const_floatTest == 1.99f);
+        Assert(ScriptC_constant.const_doubleTest == 2.05);
+        Assert(ScriptC_constant.const_charTest == -8);
+        Assert(ScriptC_constant.const_shortTest == -16);
+        Assert(ScriptC_constant.const_intTest == -32);
+        Assert(ScriptC_constant.const_longTest == 17179869184l);
+        Assert(ScriptC_constant.const_longlongTest == 68719476736l);
+
+        Assert(ScriptC_constant.const_ucharTest == 8);
+        Assert(ScriptC_constant.const_ushortTest == 16);
+        Assert(ScriptC_constant.const_uintTest == 32);
+        Assert(ScriptC_constant.const_ulongTest == 4611686018427387904L);
+        Assert(ScriptC_constant.const_int64_tTest == -17179869184l);
+        Assert(ScriptC_constant.const_uint64_tTest == 117179869184l);
+
+        Assert(ScriptC_constant.const_boolTest == true);
+
+        passTest();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java
new file mode 100644
index 0000000..a7cb226
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_convert extends UnitTest {
+    private Resources mRes;
+
+    protected UT_convert(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Convert", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_convert s = new ScriptC_convert(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_convert_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java
new file mode 100644
index 0000000..269bcef
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_convert_relaxed.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_convert_relaxed extends UnitTest {
+    private Resources mRes;
+
+    protected UT_convert_relaxed(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Convert (Relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_convert_relaxed s =
+                new ScriptC_convert_relaxed(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_convert_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java
new file mode 100644
index 0000000..f435dde
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_copy_test.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_copy_test extends UnitTest {
+    private Resources mRes;
+    boolean pass = true;
+
+    protected UT_copy_test(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Copy", ctx);
+        mRes = res;
+    }
+
+    void testFloat2(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+
+        float[] f1 = new float[1024 * 2];
+        float[] f2 = new float[1024 * 2];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat2(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat3(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat3(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if ((f1[ct] != f2[ct]) && ((ct&3) != 3)) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat4(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat4(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_copy_test s = new ScriptC_copy_test(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        testFloat2(pRS, s);
+        testFloat3(pRS, s);
+        testFloat4(pRS, s);
+        s.invoke_sendResult(true);
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java
new file mode 100644
index 0000000..abfa44c
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_element.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_element extends UnitTest {
+    private Resources mRes;
+
+    Element simpleElem;
+    Element complexElem;
+
+    final String subElemNames[] = {
+        "subElem0",
+        "subElem1",
+        "subElem2",
+        "arrayElem0",
+        "arrayElem1",
+        "subElem3",
+        "subElem4",
+        "subElem5",
+        "subElem6",
+        "subElem_7",
+    };
+
+    final int subElemArraySizes[] = {
+        1,
+        1,
+        1,
+        2,
+        5,
+        1,
+        1,
+        1,
+        1,
+        1,
+    };
+
+    final int subElemOffsets[] = {
+        0,
+        4,
+        8,
+        12,
+        20,
+        40,
+        44,
+        48,
+        64,
+        80,
+    };
+
+    protected UT_element(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Element", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_element s) {
+        simpleElem = Element.F32_3(RS);
+        complexElem = ScriptField_ComplexStruct.createElement(RS);
+        s.set_simpleElem(simpleElem);
+        s.set_complexElem(complexElem);
+
+        ScriptField_ComplexStruct data = new ScriptField_ComplexStruct(RS, 1);
+        s.bind_complexStruct(data);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_element s = new ScriptC_element(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_element_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+
+        int subElemCount = simpleElem.getSubElementCount();
+        _RS_ASSERT("subElemCount == 0", subElemCount == 0);
+
+        subElemCount = complexElem.getSubElementCount();
+        _RS_ASSERT("subElemCount == 10", subElemCount == 10);
+        _RS_ASSERT("complexElem.getSizeBytes() == ScriptField_ComplexStruct.Item.sizeof",
+                   complexElem.getBytesSize() == ScriptField_ComplexStruct.Item.sizeof);
+
+        for (int i = 0; i < subElemCount; i ++) {
+            _RS_ASSERT("complexElem.getSubElement(i) != null",
+                       complexElem.getSubElement(i) != null);
+            _RS_ASSERT("complexElem.getSubElementName(i).equals(subElemNames[i])",
+                       complexElem.getSubElementName(i).equals(subElemNames[i]));
+            _RS_ASSERT("complexElem.getSubElementArraySize(i) == subElemArraySizes[i]",
+                       complexElem.getSubElementArraySize(i) == subElemArraySizes[i]);
+            _RS_ASSERT("complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]",
+                       complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]);
+        }
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
new file mode 100644
index 0000000..c3f3ca0
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_foreach extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach s = new ScriptC_foreach(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_root(A);
+        s.invoke_verify_root();
+        s.forEach_foo(A, A);
+        s.invoke_verify_foo();
+        s.invoke_foreach_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
new file mode 100644
index 0000000..653ebd5
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_foreach_bounds.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_foreach_bounds extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_foreach_bounds(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach (bounds)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_foreach_bounds s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+        s.set_s(s);
+        s.set_ain(A);
+        s.set_aout(A);
+        s.set_xStart(2);
+        s.set_xEnd(5);
+        s.set_yStart(3);
+        s.set_yEnd(6);
+        s.forEach_zero(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_foreach_bounds s = new ScriptC_foreach_bounds(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_foreach_bounds_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java
new file mode 100644
index 0000000..960df24
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_fp_mad.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_fp_mad extends UnitTest {
+    private Resources mRes;
+
+    protected UT_fp_mad(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Fp_Mad", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_fp_mad s = new ScriptC_fp_mad(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_fp_mad_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java
new file mode 100644
index 0000000..9592798
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_int4.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_int4 extends UnitTest {
+    private Resources mRes;
+
+    protected UT_int4(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "int4", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_int4 s = new ScriptC_int4(pRS, mRes, R.raw.int4);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_int4_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java
new file mode 100644
index 0000000..ec67665
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        s.set_dimX(X);
+        typeBuilder.setX(X);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_ain(A);
+        B = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_aout(B);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel s = new ScriptC_kernel(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java
new file mode 100644
index 0000000..07538ec
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_kernel_struct.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class UT_kernel_struct extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+    private Allocation B;
+
+    protected UT_kernel_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Kernels (struct pass-by-value)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_kernel_struct s) {
+        int X = 5;
+        s.set_dimX(X);
+        ScriptField_simpleStruct t;
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_ain(t);
+        A = t.getAllocation();
+        t = new ScriptField_simpleStruct(RS, X);
+        s.bind_aout(t);
+        B = t.getAllocation();
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_kernel_struct s = new ScriptC_kernel_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_init_vars(A);
+        s.forEach_root(A, B);
+        s.invoke_verify_root();
+        s.invoke_kernel_struct_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java
new file mode 100644
index 0000000..055c454
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_math extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math s = new ScriptC_math(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_test(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java
new file mode 100644
index 0000000..a7e7429
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_agree.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import java.util.Arrays;
+import java.util.Random;
+
+public class UT_math_agree extends UnitTest {
+    private Resources mRes;
+    private Random rand;
+
+    protected UT_math_agree(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Agreement", ctx);
+        mRes = res;
+        rand = new Random();
+    }
+
+    // packing functions
+    private Float2 pack_f2(float[] val) {
+        assert val.length == 2;
+        return new Float2(val[0], val[1]);
+    }
+    private Float3 pack_f3(float[] val) {
+        assert val.length == 3;
+        return new Float3(val[0], val[1], val[2]);
+    }
+    private Float4 pack_f4(float[] val) {
+        assert val.length == 4;
+        return new Float4(val[0], val[1], val[2], val[3]);
+    }
+    private Byte2 pack_b2(byte[] val) {
+        assert val.length == 2;
+        return new Byte2(val[0], val[1]);
+    }
+    private Byte3 pack_b3(byte[] val) {
+        assert val.length == 3;
+        return new Byte3(val[0], val[1], val[2]);
+    }
+    private Byte4 pack_b4(byte[] val) {
+        assert val.length == 4;
+        return new Byte4(val[0], val[1], val[2], val[3]);
+    }
+    private Short2 pack_s2(short[] val) {
+        assert val.length == 2;
+        return new Short2(val[0], val[1]);
+    }
+    private Short3 pack_s3(short[] val) {
+        assert val.length == 3;
+        return new Short3(val[0], val[1], val[2]);
+    }
+    private Short4 pack_s4(short[] val) {
+        assert val.length == 4;
+        return new Short4(val[0], val[1], val[2], val[3]);
+    }
+    private Int2 pack_i2(int[] val) {
+        assert val.length == 2;
+        return new Int2(val[0], val[1]);
+    }
+    private Int3 pack_i3(int[] val) {
+        assert val.length == 3;
+        return new Int3(val[0], val[1], val[2]);
+    }
+    private Int4 pack_i4(int[] val) {
+        assert val.length == 4;
+        return new Int4(val[0], val[1], val[2], val[3]);
+    }
+    private Long2 pack_l2(long[] val) {
+        assert val.length == 2;
+        return new Long2(val[0], val[1]);
+    }
+    private Long3 pack_l3(long[] val) {
+        assert val.length == 3;
+        return new Long3(val[0], val[1], val[2]);
+    }
+    private Long4 pack_l4(long[] val) {
+        assert val.length == 4;
+        return new Long4(val[0], val[1], val[2], val[3]);
+    }
+
+    // random vector generation functions
+    private float[] randvec_float(int dim) {
+        float[] fv = new float[dim];
+        for (int i = 0; i < dim; ++i)
+            fv[i] = rand.nextFloat();
+        return fv;
+    }
+    private byte[] randvec_char(int dim) {
+        byte[] cv = new byte[dim];
+        rand.nextBytes(cv);
+        return cv;
+    }
+    private short[] randvec_uchar(int dim) {
+       short[] ucv = new short[dim];
+       for (int i = 0; i < dim; ++i)
+           ucv[i] = (short)rand.nextInt(0x1 << 8);
+       return ucv;
+    }
+    private short[] randvec_short(int dim) {
+        short[] sv = new short[dim];
+        for (int i = 0; i < dim; ++i)
+            sv[i] = (short)rand.nextInt(0x1 << 16);
+        return sv;
+    }
+    private int[] randvec_ushort(int dim) {
+        int[] usv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            usv[i] = rand.nextInt(0x1 << 16);
+        return usv;
+    }
+    private int[] randvec_int(int dim) {
+        int[] iv = new int[dim];
+        for (int i = 0; i < dim; ++i)
+            iv[i] = rand.nextInt();
+        return iv;
+    }
+    private long[] randvec_uint(int dim) {
+        long[] uiv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            uiv[i] = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        return uiv;
+    }
+    private long[] randvec_long(int dim) {
+        long[] lv = new long[dim];
+        for (int i = 0; i < dim; ++i)
+            lv[i] = rand.nextLong();
+        return lv;
+    }
+    // TODO:  unsigned long generator
+
+    // min reference functions
+    private float min(float v1, float v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private float[] min(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private byte min(byte v1, byte v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private byte[] min(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private short min(short v1, short v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private short[] min(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private int min(int v1, int v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private int[] min(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    private long min(long v1, long v2) {
+        return v1 < v2 ? v1 : v2;
+    }
+    private long[] min(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of min
+
+    // max reference functions
+    private float max(float v1, float v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private float[] max(float[] v1, float[] v2) {
+        assert v1.length == v2.length;
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private byte max(byte v1, byte v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private byte[] max(byte[] v1, byte[] v2) {
+        assert v1.length == v2.length;
+        byte[] rv = new byte[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private short max(short v1, short v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private short[] max(short[] v1, short[] v2) {
+        assert v1.length == v2.length;
+        short[] rv = new short[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private int max(int v1, int v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private int[] max(int[] v1, int[] v2) {
+        assert v1.length == v2.length;
+        int[] rv = new int[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    private long max(long v1, long v2) {
+        return v1 > v2 ? v1 : v2;
+    }
+    private long[] max(long[] v1, long[] v2) {
+        assert v1.length == v2.length;
+        long[] rv = new long[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2[i]);
+        return rv;
+    }
+    // TODO:  unsigned long version of max
+
+    // fmin reference functions
+    private float fmin(float v1, float v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float[] v2) {
+        return min(v1, v2);
+    }
+    private float[] fmin(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = min(v1[i], v2);
+        return rv;
+    }
+
+    // fmax reference functions
+    private float fmax(float v1, float v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float[] v2) {
+        return max(v1, v2);
+    }
+    private float[] fmax(float[] v1, float v2) {
+        float[] rv = new float[v1.length];
+        for (int i = 0; i < v1.length; ++i)
+            rv[i] = max(v1[i], v2);
+        return rv;
+    }
+
+    private void initializeValues(ScriptC_math_agree s) {
+        float x = rand.nextFloat();
+        float y = rand.nextFloat();
+
+        s.set_x(x);
+        s.set_y(y);
+        s.set_result_add(x + y);
+        s.set_result_sub(x - y);
+        s.set_result_mul(x * y);
+        s.set_result_div(x / y);
+
+        // Generate random vectors of all types
+        float rand_f1_0 = rand.nextFloat();
+        float[] rand_f2_0 = randvec_float(2);
+        float[] rand_f3_0 = randvec_float(3);
+        float[] rand_f4_0 = randvec_float(4);
+        float rand_f1_1 = rand.nextFloat();
+        float[] rand_f2_1 = randvec_float(2);
+        float[] rand_f3_1 = randvec_float(3);
+        float[] rand_f4_1 = randvec_float(4);
+        short rand_uc1_0 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_0 = randvec_uchar(2);
+        short[] rand_uc3_0 = randvec_uchar(3);
+        short[] rand_uc4_0 = randvec_uchar(4);
+        short rand_uc1_1 = (short)rand.nextInt(0x1 << 8);
+        short[] rand_uc2_1 = randvec_uchar(2);
+        short[] rand_uc3_1 = randvec_uchar(3);
+        short[] rand_uc4_1 = randvec_uchar(4);
+        short rand_ss1_0 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_0 = randvec_short(2);
+        short[] rand_ss3_0 = randvec_short(3);
+        short[] rand_ss4_0 = randvec_short(4);
+        short rand_ss1_1 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_1 = randvec_short(2);
+        short[] rand_ss3_1 = randvec_short(3);
+        short[] rand_ss4_1 = randvec_short(4);
+        int rand_us1_0 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_0 = randvec_ushort(2);
+        int[] rand_us3_0 = randvec_ushort(3);
+        int[] rand_us4_0 = randvec_ushort(4);
+        int rand_us1_1 = rand.nextInt(0x1 << 16);
+        int[] rand_us2_1 = randvec_ushort(2);
+        int[] rand_us3_1 = randvec_ushort(3);
+        int[] rand_us4_1 = randvec_ushort(4);
+        int rand_si1_0 = rand.nextInt();
+        int[] rand_si2_0 = randvec_int(2);
+        int[] rand_si3_0 = randvec_int(3);
+        int[] rand_si4_0 = randvec_int(4);
+        int rand_si1_1 = rand.nextInt();
+        int[] rand_si2_1 = randvec_int(2);
+        int[] rand_si3_1 = randvec_int(3);
+        int[] rand_si4_1 = randvec_int(4);
+        long rand_ui1_0 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_0 = randvec_uint(2);
+        long[] rand_ui3_0 = randvec_uint(3);
+        long[] rand_ui4_0 = randvec_uint(4);
+        long rand_ui1_1 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
+        long[] rand_ui2_1 = randvec_uint(2);
+        long[] rand_ui3_1 = randvec_uint(3);
+        long[] rand_ui4_1 = randvec_uint(4);
+        long rand_sl1_0 = rand.nextLong();
+        long[] rand_sl2_0 = randvec_long(2);
+        long[] rand_sl3_0 = randvec_long(3);
+        long[] rand_sl4_0 = randvec_long(4);
+        long rand_sl1_1 = rand.nextLong();
+        long[] rand_sl2_1 = randvec_long(2);
+        long[] rand_sl3_1 = randvec_long(3);
+        long[] rand_sl4_1 = randvec_long(4);
+        byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_0 = randvec_char(2);
+        byte[] rand_sc3_0 = randvec_char(3);
+        byte[] rand_sc4_0 = randvec_char(4);
+        byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_1 = randvec_char(2);
+        byte[] rand_sc3_1 = randvec_char(3);
+        byte[] rand_sc4_1 = randvec_char(4);
+        // TODO:  generate unsigned long vectors
+
+        // Set random vectors in renderscript code
+        s.set_rand_f1_0(rand_f1_0);
+        s.set_rand_f2_0(pack_f2(rand_f2_0));
+        s.set_rand_f3_0(pack_f3(rand_f3_0));
+        s.set_rand_f4_0(pack_f4(rand_f4_0));
+        s.set_rand_f1_1(rand_f1_1);
+        s.set_rand_f2_1(pack_f2(rand_f2_1));
+        s.set_rand_f3_1(pack_f3(rand_f3_1));
+        s.set_rand_f4_1(pack_f4(rand_f4_1));
+        s.set_rand_uc1_1(rand_uc1_1);
+        s.set_rand_uc2_1(pack_s2(rand_uc2_1));
+        s.set_rand_uc3_1(pack_s3(rand_uc3_1));
+        s.set_rand_uc4_1(pack_s4(rand_uc4_1));
+        s.set_rand_ss1_0(rand_ss1_0);
+        s.set_rand_ss2_0(pack_s2(rand_ss2_0));
+        s.set_rand_ss3_0(pack_s3(rand_ss3_0));
+        s.set_rand_ss4_0(pack_s4(rand_ss4_0));
+        s.set_rand_ss1_1(rand_ss1_1);
+        s.set_rand_ss2_1(pack_s2(rand_ss2_1));
+        s.set_rand_ss3_1(pack_s3(rand_ss3_1));
+        s.set_rand_ss4_1(pack_s4(rand_ss4_1));
+        s.set_rand_us1_0(rand_us1_0);
+        s.set_rand_us2_0(pack_i2(rand_us2_0));
+        s.set_rand_us3_0(pack_i3(rand_us3_0));
+        s.set_rand_us4_0(pack_i4(rand_us4_0));
+        s.set_rand_us1_1(rand_us1_1);
+        s.set_rand_us2_1(pack_i2(rand_us2_1));
+        s.set_rand_us3_1(pack_i3(rand_us3_1));
+        s.set_rand_us4_1(pack_i4(rand_us4_1));
+        s.set_rand_si1_0(rand_si1_0);
+        s.set_rand_si2_0(pack_i2(rand_si2_0));
+        s.set_rand_si3_0(pack_i3(rand_si3_0));
+        s.set_rand_si4_0(pack_i4(rand_si4_0));
+        s.set_rand_si1_1(rand_si1_1);
+        s.set_rand_si2_1(pack_i2(rand_si2_1));
+        s.set_rand_si3_1(pack_i3(rand_si3_1));
+        s.set_rand_si4_1(pack_i4(rand_si4_1));
+        s.set_rand_ui1_0(rand_ui1_0);
+        s.set_rand_ui2_0(pack_l2(rand_ui2_0));
+        s.set_rand_ui3_0(pack_l3(rand_ui3_0));
+        s.set_rand_ui4_0(pack_l4(rand_ui4_0));
+        s.set_rand_ui1_1(rand_ui1_1);
+        s.set_rand_ui2_1(pack_l2(rand_ui2_1));
+        s.set_rand_ui3_1(pack_l3(rand_ui3_1));
+        s.set_rand_ui4_1(pack_l4(rand_ui4_1));
+        s.set_rand_sl1_0(rand_sl1_0);
+        s.set_rand_sl2_0(pack_l2(rand_sl2_0));
+        s.set_rand_sl3_0(pack_l3(rand_sl3_0));
+        s.set_rand_sl4_0(pack_l4(rand_sl4_0));
+        s.set_rand_sl1_1(rand_sl1_1);
+        s.set_rand_sl2_1(pack_l2(rand_sl2_1));
+        s.set_rand_sl3_1(pack_l3(rand_sl3_1));
+        s.set_rand_sl4_1(pack_l4(rand_sl4_1));
+        s.set_rand_uc1_0(rand_uc1_0);
+        s.set_rand_uc2_0(pack_s2(rand_uc2_0));
+        s.set_rand_uc3_0(pack_s3(rand_uc3_0));
+        s.set_rand_uc4_0(pack_s4(rand_uc4_0));
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc3_0(pack_b3(rand_sc3_0));
+        s.set_rand_sc4_0(pack_b4(rand_sc4_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        s.set_rand_sc3_1(pack_b3(rand_sc3_1));
+        s.set_rand_sc4_1(pack_b4(rand_sc4_1));
+        // TODO:  set unsigned long vectors
+
+        // Set results for min
+        s.set_min_rand_f1_f1(min(rand_f1_0, rand_f1_1));
+        s.set_min_rand_f2_f2(pack_f2(min(rand_f2_0, rand_f2_1)));
+        s.set_min_rand_f3_f3(pack_f3(min(rand_f3_0, rand_f3_1)));
+        s.set_min_rand_f4_f4(pack_f4(min(rand_f4_0, rand_f4_1)));
+        s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1));
+        s.set_min_rand_uc2_uc2(pack_s2(min(rand_uc2_0, rand_uc2_1)));
+        s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1)));
+        s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1)));
+        s.set_min_rand_ss1_ss1(min(rand_ss1_0, rand_ss1_1));
+        s.set_min_rand_ss2_ss2(pack_s2(min(rand_ss2_0, rand_ss2_1)));
+        s.set_min_rand_ss3_ss3(pack_s3(min(rand_ss3_0, rand_ss3_1)));
+        s.set_min_rand_ss4_ss4(pack_s4(min(rand_ss4_0, rand_ss4_1)));
+        s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1));
+        s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1)));
+        s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1)));
+        s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1)));
+        s.set_min_rand_si1_si1(min(rand_si1_0, rand_si1_1));
+        s.set_min_rand_si2_si2(pack_i2(min(rand_si2_0, rand_si2_1)));
+        s.set_min_rand_si3_si3(pack_i3(min(rand_si3_0, rand_si3_1)));
+        s.set_min_rand_si4_si4(pack_i4(min(rand_si4_0, rand_si4_1)));
+        s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1));
+        s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1)));
+        s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1)));
+        s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1)));
+        s.set_min_rand_sl1_sl1(min(rand_sl1_0, rand_sl1_1));
+        s.set_min_rand_sl2_sl2(pack_l2(min(rand_sl2_0, rand_sl2_1)));
+        s.set_min_rand_sl3_sl3(pack_l3(min(rand_sl3_0, rand_sl3_1)));
+        s.set_min_rand_sl4_sl4(pack_l4(min(rand_sl4_0, rand_sl4_1)));
+        s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
+        s.set_min_rand_sc2_sc2(pack_b2(min(rand_sc2_0, rand_sc2_1)));
+        s.set_min_rand_sc3_sc3(pack_b3(min(rand_sc3_0, rand_sc3_1)));
+        s.set_min_rand_sc4_sc4(pack_b4(min(rand_sc4_0, rand_sc4_1)));
+        // TODO:  set results for unsigned long min
+
+        // Set results for max
+        s.set_max_rand_f1_f1(max(rand_f1_0, rand_f1_1));
+        s.set_max_rand_f2_f2(pack_f2(max(rand_f2_0, rand_f2_1)));
+        s.set_max_rand_f3_f3(pack_f3(max(rand_f3_0, rand_f3_1)));
+        s.set_max_rand_f4_f4(pack_f4(max(rand_f4_0, rand_f4_1)));
+        s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1));
+        s.set_max_rand_uc2_uc2(pack_s2(max(rand_uc2_0, rand_uc2_1)));
+        s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1)));
+        s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1)));
+        s.set_max_rand_ss1_ss1(max(rand_ss1_0, rand_ss1_1));
+        s.set_max_rand_ss2_ss2(pack_s2(max(rand_ss2_0, rand_ss2_1)));
+        s.set_max_rand_ss3_ss3(pack_s3(max(rand_ss3_0, rand_ss3_1)));
+        s.set_max_rand_ss4_ss4(pack_s4(max(rand_ss4_0, rand_ss4_1)));
+        s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1));
+        s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1)));
+        s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1)));
+        s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1)));
+        s.set_max_rand_si1_si1(max(rand_si1_0, rand_si1_1));
+        s.set_max_rand_si2_si2(pack_i2(max(rand_si2_0, rand_si2_1)));
+        s.set_max_rand_si3_si3(pack_i3(max(rand_si3_0, rand_si3_1)));
+        s.set_max_rand_si4_si4(pack_i4(max(rand_si4_0, rand_si4_1)));
+        s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1));
+        s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1)));
+        s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1)));
+        s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1)));
+        s.set_max_rand_sl1_sl1(max(rand_sl1_0, rand_sl1_1));
+        s.set_max_rand_sl2_sl2(pack_l2(max(rand_sl2_0, rand_sl2_1)));
+        s.set_max_rand_sl3_sl3(pack_l3(max(rand_sl3_0, rand_sl3_1)));
+        s.set_max_rand_sl4_sl4(pack_l4(max(rand_sl4_0, rand_sl4_1)));
+        s.set_max_rand_sc1_sc1(max(rand_sc1_0, rand_sc1_1));
+        s.set_max_rand_sc2_sc2(pack_b2(max(rand_sc2_0, rand_sc2_1)));
+        s.set_max_rand_sc3_sc3(pack_b3(max(rand_sc3_0, rand_sc3_1)));
+        s.set_max_rand_sc4_sc4(pack_b4(max(rand_sc4_0, rand_sc4_1)));
+
+        // TODO:  set results for unsigned long max
+
+        // Set results for fmin
+        s.set_fmin_rand_f1_f1(fmin(rand_f1_0, rand_f1_1));
+        s.set_fmin_rand_f2_f2(pack_f2(fmin(rand_f2_0, rand_f2_1)));
+        s.set_fmin_rand_f3_f3(pack_f3(fmin(rand_f3_0, rand_f3_1)));
+        s.set_fmin_rand_f4_f4(pack_f4(fmin(rand_f4_0, rand_f4_1)));
+        s.set_fmin_rand_f2_f1(pack_f2(fmin(rand_f2_0, rand_f1_1)));
+        s.set_fmin_rand_f3_f1(pack_f3(fmin(rand_f3_0, rand_f1_1)));
+        s.set_fmin_rand_f4_f1(pack_f4(fmin(rand_f4_0, rand_f1_1)));
+
+        // Set results for fmax
+        s.set_fmax_rand_f1_f1(fmax(rand_f1_0, rand_f1_1));
+        s.set_fmax_rand_f2_f2(pack_f2(fmax(rand_f2_0, rand_f2_1)));
+        s.set_fmax_rand_f3_f3(pack_f3(fmax(rand_f3_0, rand_f3_1)));
+        s.set_fmax_rand_f4_f4(pack_f4(fmax(rand_f4_0, rand_f4_1)));
+        s.set_fmax_rand_f2_f1(pack_f2(fmax(rand_f2_0, rand_f1_1)));
+        s.set_fmax_rand_f3_f1(pack_f3(fmax(rand_f3_0, rand_f1_1)));
+        s.set_fmax_rand_f4_f1(pack_f4(fmax(rand_f4_0, rand_f1_1)));
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_agree s = new ScriptC_math_agree(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeValues(s);
+        s.invoke_math_agree_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java
new file mode 100644
index 0000000..384cd13
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_math_conformance.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_math_conformance extends UnitTest {
+    private Resources mRes;
+
+    protected UT_math_conformance(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Math Conformance", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_math_conformance s =
+                new ScriptC_math_conformance(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_math_conformance_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+        passTest();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java
new file mode 100644
index 0000000..cea9fe5
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_min.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_min extends UnitTest {
+    private Resources mRes;
+
+    protected UT_min(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Min (relaxed)", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_min s = new ScriptC_min(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_min_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
new file mode 100644
index 0000000..69fc97f
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_noroot.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_noroot extends UnitTest {
+    private Resources mRes;
+    private Allocation A;
+
+    protected UT_noroot(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "ForEach (no root)", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_noroot s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 5;
+        int Y = 7;
+        s.set_dimX(X);
+        s.set_dimY(Y);
+        typeBuilder.setX(X).setY(Y);
+        A = Allocation.createTyped(RS, typeBuilder.create());
+        s.bind_a(A);
+
+        return;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_noroot s = new ScriptC_noroot(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.forEach_foo(A, A);
+        s.invoke_verify_foo();
+        s.invoke_noroot_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java
new file mode 100644
index 0000000..3c663a8
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_primitives.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_primitives extends UnitTest {
+    private Resources mRes;
+
+    protected UT_primitives(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Primitives", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_primitives s) {
+        float pF = s.get_floatTest();
+        if (pF != 1.99f) {
+            return false;
+        }
+        s.set_floatTest(2.99f);
+
+        double pD = s.get_doubleTest();
+        if (pD != 2.05) {
+            return false;
+        }
+        s.set_doubleTest(3.05);
+
+        byte pC = s.get_charTest();
+        if (pC != -8) {
+            return false;
+        }
+        s.set_charTest((byte)-16);
+
+        short pS = s.get_shortTest();
+        if (pS != -16) {
+            return false;
+        }
+        s.set_shortTest((short)-32);
+
+        int pI = s.get_intTest();
+        if (pI != -32) {
+            return false;
+        }
+        s.set_intTest(-64);
+
+        long pL = s.get_longTest();
+        if (pL != 17179869184l) {
+            return false;
+        }
+        s.set_longTest(17179869185l);
+
+        long puL = s.get_ulongTest();
+        if (puL != 4611686018427387904L) {
+            return false;
+        }
+        s.set_ulongTest(4611686018427387903L);
+
+
+        long pLL = s.get_longlongTest();
+        if (pLL != 68719476736L) {
+            return false;
+        }
+        s.set_longlongTest(68719476735L);
+
+        long pu64 = s.get_uint64_tTest();
+        if (pu64 != 117179869184l) {
+            return false;
+        }
+        s.set_uint64_tTest(117179869185l);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_primitives s = new ScriptC_primitives(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_primitives_test(0, 0);
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java
new file mode 100644
index 0000000..e6317d5
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_refcount.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_refcount extends UnitTest {
+    private Resources mRes;
+
+    protected UT_refcount(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Refcount", ctx);
+        mRes = res;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_refcount s) {
+        Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+        int X = 500;
+        int Y = 700;
+        typeBuilder.setX(X).setY(Y);
+        Allocation A = Allocation.createTyped(RS, typeBuilder.create());
+        s.set_globalA(A);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        pRS.setMessageHandler(mRsMessage);
+        ScriptC_refcount s = new ScriptC_refcount(pRS);
+        initializeGlobals(pRS, s);
+        s.invoke_refcount_test();
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java
new file mode 100644
index 0000000..740180e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rsdebug.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rsdebug extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rsdebug(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsDebug", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rsdebug s = new ScriptC_rsdebug(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rsdebug(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..86e35a8
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTime", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstime s = new ScriptC_rstime(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.setTimeZone("America/Los_Angeles");
+        s.invoke_test_rstime(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java
new file mode 100644
index 0000000..3245eca
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_rstypes.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_rstypes extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstypes(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTypes", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstypes s = new ScriptC_rstypes(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstypes(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java
new file mode 100644
index 0000000..d8d5a78
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_sampler.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_sampler extends UnitTest {
+    private Resources mRes;
+
+    Sampler minification;
+    Sampler magnification;
+    Sampler wrapS;
+    Sampler wrapT;
+    Sampler anisotropy;
+
+    protected UT_sampler(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Sampler", ctx);
+        mRes = res;
+    }
+
+    private Sampler.Builder getDefaultBuilder(RenderScript RS) {
+        Sampler.Builder b = new Sampler.Builder(RS);
+        b.setMinification(Sampler.Value.NEAREST);
+        b.setMagnification(Sampler.Value.NEAREST);
+        b.setWrapS(Sampler.Value.CLAMP);
+        b.setWrapT(Sampler.Value.CLAMP);
+        b.setAnisotropy(1.0f);
+        return b;
+    }
+
+    private void initializeGlobals(RenderScript RS, ScriptC_sampler s) {
+        Sampler.Builder b = getDefaultBuilder(RS);
+        b.setMinification(Sampler.Value.LINEAR_MIP_LINEAR);
+        minification = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setMagnification(Sampler.Value.LINEAR);
+        magnification = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setWrapS(Sampler.Value.WRAP);
+        wrapS = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setWrapT(Sampler.Value.WRAP);
+        wrapT = b.create();
+
+        b = getDefaultBuilder(RS);
+        b.setAnisotropy(8.0f);
+        anisotropy = b.create();
+
+        s.set_minification(minification);
+        s.set_magnification(magnification);
+        s.set_wrapS(wrapS);
+        s.set_wrapT(wrapT);
+        s.set_anisotropy(anisotropy);
+    }
+
+    private void testScriptSide(RenderScript pRS) {
+        ScriptC_sampler s = new ScriptC_sampler(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        initializeGlobals(pRS, s);
+        s.invoke_sampler_test();
+        pRS.finish();
+        waitForMessage();
+    }
+
+    private void testJavaSide(RenderScript RS) {
+        _RS_ASSERT("minification.getMagnification() == Sampler.Value.NEAREST",
+                    minification.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR",
+                    minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR);
+        _RS_ASSERT("minification.getWrapS() == Sampler.Value.CLAMP",
+                    minification.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("minification.getWrapT() == Sampler.Value.CLAMP",
+                    minification.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("minification.getAnisotropy() == 1.0f",
+                    minification.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("magnification.getMagnification() == Sampler.Value.LINEAR",
+                    magnification.getMagnification() == Sampler.Value.LINEAR);
+        _RS_ASSERT("magnification.getMinification() == Sampler.Value.NEAREST",
+                    magnification.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("magnification.getWrapS() == Sampler.Value.CLAMP",
+                    magnification.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("magnification.getWrapT() == Sampler.Value.CLAMP",
+                    magnification.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("magnification.getAnisotropy() == 1.0f",
+                    magnification.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("wrapS.getMagnification() == Sampler.Value.NEAREST",
+                    wrapS.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapS.getMinification() == Sampler.Value.NEAREST",
+                    wrapS.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapS.getWrapS() == Sampler.Value.WRAP",
+                    wrapS.getWrapS() == Sampler.Value.WRAP);
+        _RS_ASSERT("wrapS.getWrapT() == Sampler.Value.CLAMP",
+                    wrapS.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("wrapS.getAnisotropy() == 1.0f",
+                    wrapS.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("wrapT.getMagnification() == Sampler.Value.NEAREST",
+                    wrapT.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapT.getMinification() == Sampler.Value.NEAREST",
+                    wrapT.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("wrapT.getWrapS() == Sampler.Value.CLAMP",
+                    wrapT.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("wrapT.getWrapT() == Sampler.Value.WRAP",
+                    wrapT.getWrapT() == Sampler.Value.WRAP);
+        _RS_ASSERT("wrapT.getAnisotropy() == 1.0f",
+                    wrapT.getAnisotropy() == 1.0f);
+
+        _RS_ASSERT("anisotropy.getMagnification() == Sampler.Value.NEAREST",
+                    anisotropy.getMagnification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("anisotropy.getMinification() == Sampler.Value.NEAREST",
+                    anisotropy.getMinification() == Sampler.Value.NEAREST);
+        _RS_ASSERT("anisotropy.getWrapS() == Sampler.Value.CLAMP",
+                    anisotropy.getWrapS() == Sampler.Value.CLAMP);
+        _RS_ASSERT("anisotropy.getWrapT() == Sampler.Value.CLAMP",
+                    anisotropy.getWrapT() == Sampler.Value.CLAMP);
+        _RS_ASSERT("anisotropy.getAnisotropy() == 1.0f",
+                    anisotropy.getAnisotropy() == 8.0f);
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        testScriptSide(pRS);
+        testJavaSide(pRS);
+        passTest();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java
new file mode 100644
index 0000000..43bbaf7
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_struct.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_struct extends UnitTest {
+    private Resources mRes;
+
+    protected UT_struct(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Struct", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_struct s = new ScriptC_struct(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        ScriptField_Point2 p = new ScriptField_Point2(pRS, 1);
+        ScriptField_Point2.Item i = new ScriptField_Point2.Item();
+        int val = 100;
+        i.x = val;
+        i.y = val;
+        p.set(i, 0, true);
+        s.bind_point2(p);
+        s.invoke_struct_test(val);
+        pRS.finish();
+        waitForMessage();
+
+        val = 200;
+        p.set_x(0, val, true);
+        p.set_y(0, val, true);
+        s.invoke_struct_test(val);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java
new file mode 100644
index 0000000..0e16240
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_unsigned.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_unsigned extends UnitTest {
+    private Resources mRes;
+
+    protected UT_unsigned(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Unsigned", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_unsigned s) {
+        short pUC = s.get_uc();
+        if (pUC != 5) {
+            return false;
+        }
+        s.set_uc((short)129);
+
+        long pUI = s.get_ui();
+        if (pUI != 37) {
+            return false;
+        }
+        s.set_ui(0x7fffffff);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_unsigned s = new ScriptC_unsigned(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_unsigned_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java
new file mode 100644
index 0000000..6ba822e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UT_vector.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v8.renderscript.*;
+
+public class UT_vector extends UnitTest {
+    private Resources mRes;
+
+    protected UT_vector(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Vector", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_vector s) {
+        Float2 F2 = s.get_f2();
+        if (F2.x != 1.0f || F2.y != 2.0f) {
+            return false;
+        }
+        F2.x = 2.99f;
+        F2.y = 3.99f;
+        s.set_f2(F2);
+
+        Float3 F3 = s.get_f3();
+        if (F3.x != 1.0f || F3.y != 2.0f || F3.z != 3.0f) {
+            return false;
+        }
+        F3.x = 2.99f;
+        F3.y = 3.99f;
+        F3.z = 4.99f;
+        s.set_f3(F3);
+
+        Float4 F4 = s.get_f4();
+        if (F4.x != 1.0f || F4.y != 2.0f || F4.z != 3.0f || F4.w != 4.0f) {
+            return false;
+        }
+        F4.x = 2.99f;
+        F4.y = 3.99f;
+        F4.z = 4.99f;
+        F4.w = 5.99f;
+        s.set_f4(F4);
+
+        Double2 D2 = s.get_d2();
+        if (D2.x != 1.0 || D2.y != 2.0) {
+            return false;
+        }
+        D2.x = 2.99;
+        D2.y = 3.99;
+        s.set_d2(D2);
+
+        Double3 D3 = s.get_d3();
+        if (D3.x != 1.0 || D3.y != 2.0 || D3.z != 3.0) {
+            return false;
+        }
+        D3.x = 2.99;
+        D3.y = 3.99;
+        D3.z = 4.99;
+        s.set_d3(D3);
+
+        Double4 D4 = s.get_d4();
+        if (D4.x != 1.0 || D4.y != 2.0 || D4.z != 3.0 || D4.w != 4.0) {
+            return false;
+        }
+        D4.x = 2.99;
+        D4.y = 3.99;
+        D4.z = 4.99;
+        D4.w = 5.99;
+        s.set_d4(D4);
+
+        Byte2 B2 = s.get_i8_2();
+        if (B2.x != 1 || B2.y != 2) {
+            return false;
+        }
+        B2.x = 2;
+        B2.y = 3;
+        s.set_i8_2(B2);
+
+        Byte3 B3 = s.get_i8_3();
+        if (B3.x != 1 || B3.y != 2 || B3.z != 3) {
+            return false;
+        }
+        B3.x = 2;
+        B3.y = 3;
+        B3.z = 4;
+        s.set_i8_3(B3);
+
+        Byte4 B4 = s.get_i8_4();
+        if (B4.x != 1 || B4.y != 2 || B4.z != 3 || B4.w != 4) {
+            return false;
+        }
+        B4.x = 2;
+        B4.y = 3;
+        B4.z = 4;
+        B4.w = 5;
+        s.set_i8_4(B4);
+
+        Short2 S2 = s.get_u8_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_u8_2(S2);
+
+        Short3 S3 = s.get_u8_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_u8_3(S3);
+
+        Short4 S4 = s.get_u8_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_u8_4(S4);
+
+        S2 = s.get_i16_2();
+        if (S2.x != 1 || S2.y != 2) {
+            return false;
+        }
+        S2.x = 2;
+        S2.y = 3;
+        s.set_i16_2(S2);
+
+        S3 = s.get_i16_3();
+        if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+            return false;
+        }
+        S3.x = 2;
+        S3.y = 3;
+        S3.z = 4;
+        s.set_i16_3(S3);
+
+        S4 = s.get_i16_4();
+        if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+            return false;
+        }
+        S4.x = 2;
+        S4.y = 3;
+        S4.z = 4;
+        S4.w = 5;
+        s.set_i16_4(S4);
+
+        Int2 I2 = s.get_u16_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_u16_2(I2);
+
+        Int3 I3 = s.get_u16_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_u16_3(I3);
+
+        Int4 I4 = s.get_u16_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_u16_4(I4);
+
+        I2 = s.get_i32_2();
+        if (I2.x != 1 || I2.y != 2) {
+            return false;
+        }
+        I2.x = 2;
+        I2.y = 3;
+        s.set_i32_2(I2);
+
+        I3 = s.get_i32_3();
+        if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+            return false;
+        }
+        I3.x = 2;
+        I3.y = 3;
+        I3.z = 4;
+        s.set_i32_3(I3);
+
+        I4 = s.get_i32_4();
+        if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+            return false;
+        }
+        I4.x = 2;
+        I4.y = 3;
+        I4.z = 4;
+        I4.w = 5;
+        s.set_i32_4(I4);
+
+        Long2 L2 = s.get_u32_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u32_2(L2);
+
+        Long3 L3 = s.get_u32_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u32_3(L3);
+
+        Long4 L4 = s.get_u32_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u32_4(L4);
+
+        L2 = s.get_i64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_i64_2(L2);
+
+        L3 = s.get_i64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_i64_3(L3);
+
+        L4 = s.get_i64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_i64_4(L4);
+
+        L2 = s.get_u64_2();
+        if (L2.x != 1 || L2.y != 2) {
+            return false;
+        }
+        L2.x = 2;
+        L2.y = 3;
+        s.set_u64_2(L2);
+
+        L3 = s.get_u64_3();
+        if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+            return false;
+        }
+        L3.x = 2;
+        L3.y = 3;
+        L3.z = 4;
+        s.set_u64_3(L3);
+
+        L4 = s.get_u64_4();
+        if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+            return false;
+        }
+        L4.x = 2;
+        L4.y = 3;
+        L4.z = 4;
+        L4.w = 5;
+        s.set_u64_4(L4);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_vector s = new ScriptC_vector(pRS);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_vector_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java
new file mode 100644
index 0000000..01abf2f
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/UnitTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test_compat;
+import android.content.Context;
+import android.util.Log;
+import android.support.v8.renderscript.RenderScript.RSMessageHandler;
+
+public class UnitTest extends Thread {
+    public String name;
+    private int result;
+    private ScriptField_ListAllocs_s.Item mItem;
+    private RSTestCore mRSTC;
+    private boolean msgHandled;
+    protected Context mCtx;
+
+    /* These constants must match those in shared.rsh */
+    public static final int RS_MSG_TEST_PASSED = 100;
+    public static final int RS_MSG_TEST_FAILED = 101;
+
+    private static int numTests = 0;
+    public int testID;
+
+    protected UnitTest(RSTestCore rstc, String n, int initResult, Context ctx) {
+        super();
+        mRSTC = rstc;
+        name = n;
+        msgHandled = false;
+        mCtx = ctx;
+        result = initResult;
+        testID = numTests++;
+    }
+
+    protected UnitTest(RSTestCore rstc, String n, Context ctx) {
+        this(rstc, n, 0, ctx);
+    }
+
+    protected UnitTest(RSTestCore rstc, Context ctx) {
+        this (rstc, "<Unknown>", ctx);
+    }
+
+    protected UnitTest(Context ctx) {
+        this (null, ctx);
+    }
+
+    protected void _RS_ASSERT(String message, boolean b) {
+        if(b == false) {
+            Log.e(name, message + " FAILED");
+            failTest();
+        }
+    }
+
+    private void updateUI() {
+        if (mItem != null) {
+            mItem.result = result;
+            msgHandled = true;
+            try {
+                mRSTC.refreshTestResults();
+            }
+            catch (IllegalStateException e) {
+                /* Ignore the case where our message receiver has been
+                   disconnected. This happens when we leave the application
+                   before it finishes running all of the unit tests. */
+            }
+        }
+    }
+
+    protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                        result = 1;
+                        break;
+                    case RS_MSG_TEST_FAILED:
+                        result = -1;
+                        break;
+                    default:
+                        RSTest.log("Unit test got unexpected message");
+                        return;
+                }
+            }
+
+            updateUI();
+        }
+    };
+
+    public void waitForMessage() {
+        while (!msgHandled) {
+            yield();
+        }
+    }
+
+    public int getResult() {
+        return result;
+    }
+
+    public void failTest() {
+        result = -1;
+        updateUI();
+    }
+
+    public void passTest() {
+        if (result != -1) {
+            result = 1;
+        }
+        updateUI();
+    }
+
+    public String toString() {
+        String out = name;
+        if (result == 1) {
+            out += " - PASSED";
+        }
+        else if (result == -1) {
+            out += " - FAILED";
+        }
+        return out;
+    }
+
+    public void setItem(ScriptField_ListAllocs_s.Item item) {
+        mItem = item;
+    }
+
+    public void run() {
+        /* This method needs to be implemented for each subclass */
+        if (mRSTC != null) {
+            mRSTC.refreshTestResults();
+        }
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
new file mode 100644
index 0000000..3116e5a
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/alloc.rs
@@ -0,0 +1,94 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+int dimZ;
+
+rs_allocation aFaces;
+rs_allocation aLOD;
+rs_allocation aFacesLOD;
+
+static bool test_alloc_dims() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            a[i + j * dimX] = i + j * dimX;
+        }
+    }
+
+    rs_allocation alloc = rsGetAllocation(a);
+    _RS_ASSERT(rsAllocationGetDimX(alloc) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(alloc) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(alloc) == dimZ);
+
+    // Test 2D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(alloc, i, j);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    // Test 1D addressing
+    for (i = 0; i < dimX * dimY; i++) {
+        rsDebug("Verifying ", i);
+        const void *p = rsGetElementAt(alloc, i);
+        int val = *(const int *)p;
+        _RS_ASSERT(val == i);
+    }
+
+    // Test 3D addressing
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("Verifying ", i + j * dimX);
+            const void *p = rsGetElementAt(alloc, i, j, 0);
+            int val = *(const int *)p;
+            _RS_ASSERT(val == (i + j * dimX));
+        }
+    }
+
+    _RS_ASSERT(rsAllocationGetDimX(aFaces) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFaces) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFaces) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFaces) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFaces) == 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aLOD) == 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aLOD) != 0);
+
+    _RS_ASSERT(rsAllocationGetDimX(aFacesLOD) == dimX);
+    _RS_ASSERT(rsAllocationGetDimY(aFacesLOD) == dimY);
+    _RS_ASSERT(rsAllocationGetDimZ(aFacesLOD) == dimZ);
+    _RS_ASSERT(rsAllocationGetDimFaces(aFacesLOD) != 0);
+    _RS_ASSERT(rsAllocationGetDimLOD(aFacesLOD) != 0);
+
+    if (failed) {
+        rsDebug("test_alloc_dims FAILED", 0);
+    }
+    else {
+        rsDebug("test_alloc_dims PASSED", 0);
+    }
+
+    return failed;
+}
+
+void alloc_test() {
+    bool failed = false;
+    failed |= test_alloc_dims();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs
new file mode 100644
index 0000000..74ffdb1
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_alloc.rs
@@ -0,0 +1,21 @@
+#include "shared.rsh"
+
+const int dimX = 20;
+rs_allocation a[dimX];
+
+void array_alloc_test() {
+    bool failed = false;
+
+    for (int i = 0; i < dimX; i++) {
+        rsDebug("i: ", i);
+        _RS_ASSERT(rsAllocationGetDimX(a[i]) == 1);
+    }
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs
new file mode 100644
index 0000000..842249a
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/array_init.rs
@@ -0,0 +1,58 @@
+#include "shared.rsh"
+
+// Testing constant array initialization
+float fa[4] = {1.0, 9.9999f};
+double da[2] = {7.0, 8.88888};
+char ca[4] = {'a', 7, 'b', 'c'};
+short sa[4] = {1, 1, 2, 3};
+int ia[4] = {5, 8};
+long la[2] = {13, 21};
+long long lla[4] = {34};
+bool ba[3] = {true, false};
+
+void array_init_test() {
+    bool failed = false;
+
+    _RS_ASSERT(fa[0] == 1.0);
+    _RS_ASSERT(fa[1] == 9.9999f);
+    _RS_ASSERT(fa[2] == 0);
+    _RS_ASSERT(fa[3] == 0);
+
+    _RS_ASSERT(da[0] == 7.0);
+    _RS_ASSERT(da[1] == 8.88888);
+
+    _RS_ASSERT(ca[0] == 'a');
+    _RS_ASSERT(ca[1] == 7);
+    _RS_ASSERT(ca[2] == 'b');
+    _RS_ASSERT(ca[3] == 'c');
+
+    _RS_ASSERT(sa[0] == 1);
+    _RS_ASSERT(sa[1] == 1);
+    _RS_ASSERT(sa[2] == 2);
+    _RS_ASSERT(sa[3] == 3);
+
+    _RS_ASSERT(ia[0] == 5);
+    _RS_ASSERT(ia[1] == 8);
+    _RS_ASSERT(ia[2] == 0);
+    _RS_ASSERT(ia[3] == 0);
+
+    _RS_ASSERT(la[0] == 13);
+    _RS_ASSERT(la[1] == 21);
+
+    _RS_ASSERT(lla[0] == 34);
+    _RS_ASSERT(lla[1] == 0);
+    _RS_ASSERT(lla[2] == 0);
+    _RS_ASSERT(lla[3] == 0);
+
+    _RS_ASSERT(ba[0] == true);
+    _RS_ASSERT(ba[1] == false);
+    _RS_ASSERT(ba[2] == false);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs
new file mode 100644
index 0000000..f0a5041
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/atomic.rs
@@ -0,0 +1,77 @@
+#include "shared.rsh"
+
+// Testing atomic operations
+static bool testUMax(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst > src ? dst : src);
+    uint32_t ret = rsAtomicMax(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUMin(uint32_t dst, uint32_t src) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst < src ? dst : src);
+    uint32_t ret = rsAtomicMin(&dst, src);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool testUCas(uint32_t dst, uint32_t cmp, uint32_t swp) {
+    bool failed = false;
+    uint32_t old = dst;
+    uint32_t expect = (dst == cmp ? swp : dst);
+    uint32_t ret = rsAtomicCas(&dst, cmp, swp);
+    _RS_ASSERT(old == ret);
+    _RS_ASSERT(dst == expect);
+    return failed;
+}
+
+static bool test_atomics() {
+    bool failed = false;
+
+    failed |= testUMax(5, 6);
+    failed |= testUMax(6, 5);
+    failed |= testUMax(5, 0xf0000006);
+    failed |= testUMax(0xf0000006, 5);
+
+    failed |= testUMin(5, 6);
+    failed |= testUMin(6, 5);
+    failed |= testUMin(5, 0xf0000006);
+    failed |= testUMin(0xf0000006, 5);
+
+    failed |= testUCas(4, 4, 5);
+    failed |= testUCas(4, 5, 5);
+    failed |= testUCas(5, 5, 4);
+    failed |= testUCas(5, 4, 4);
+    failed |= testUCas(0xf0000004, 0xf0000004, 0xf0000005);
+    failed |= testUCas(0xf0000004, 0xf0000005, 0xf0000005);
+    failed |= testUCas(0xf0000005, 0xf0000005, 0xf0000004);
+    failed |= testUCas(0xf0000005, 0xf0000004, 0xf0000004);
+
+    if (failed) {
+        rsDebug("test_atomics FAILED", 0);
+    }
+    else {
+        rsDebug("test_atomics PASSED", 0);
+    }
+
+    return failed;
+}
+
+void atomic_test() {
+    bool failed = false;
+    failed |= test_atomics();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs
new file mode 100644
index 0000000..dcd7b72
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/bug_char.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+char rand_sc1_0, rand_sc1_1;
+char2 rand_sc2_0, rand_sc2_1;
+
+char min_rand_sc1_sc1;
+char2 min_rand_sc2_sc2;
+
+static bool test_bug_char() {
+    bool failed = false;
+
+    rsDebug("rand_sc2_0.x: ", rand_sc2_0.x);
+    rsDebug("rand_sc2_0.y: ", rand_sc2_0.y);
+    rsDebug("rand_sc2_1.x: ", rand_sc2_1.x);
+    rsDebug("rand_sc2_1.y: ", rand_sc2_1.y);
+    char temp_sc1;
+    char2 temp_sc2;
+
+    temp_sc1 = min( rand_sc1_0, rand_sc1_1 );
+    if (temp_sc1 != min_rand_sc1_sc1) {
+        rsDebug("temp_sc1", temp_sc1);
+        failed = true;
+    }
+    rsDebug("broken", 'y');
+
+    temp_sc2 = min( rand_sc2_0, rand_sc2_1 );
+    if (temp_sc2.x != min_rand_sc2_sc2.x
+            || temp_sc2.y != min_rand_sc2_sc2.y) {
+        failed = true;
+    }
+
+
+    return failed;
+}
+
+void bug_char_test() {
+    bool failed = false;
+    failed |= test_bug_char();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs
new file mode 100644
index 0000000..28b00bd
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp.rs
@@ -0,0 +1,56 @@
+#include "shared.rsh"
+
+static bool test_clamp_vector() {
+    bool failed = false;
+
+    float2 src2 = { 2.0f, 2.0f};
+    float2 min2 = { 0.5f, -3.0f};
+    float2 max2 = { 1.0f, 9.0f};
+
+    float2 res2 = clamp(src2, min2, max2);
+    _RS_ASSERT(res2.x == 1.0f);
+    _RS_ASSERT(res2.y == 2.0f);
+
+
+    float3 src3 = { 2.0f, 2.0f, 1.0f};
+    float3 min3 = { 0.5f, -3.0f, 3.0f};
+    float3 max3 = { 1.0f, 9.0f, 4.0f};
+
+    float3 res3 = clamp(src3, min3, max3);
+    _RS_ASSERT(res3.x == 1.0f);
+    _RS_ASSERT(res3.y == 2.0f);
+    _RS_ASSERT(res3.z == 3.0f);
+
+
+    float4 src4 = { 2.0f, 2.0f, 1.0f, 4.0f };
+    float4 min4 = { 0.5f, -3.0f, 3.0f, 4.0f };
+    float4 max4 = { 1.0f, 9.0f, 4.0f, 4.0f };
+
+    float4 res4 = clamp(src4, min4, max4);
+    _RS_ASSERT(res4.x == 1.0f);
+    _RS_ASSERT(res4.y == 2.0f);
+    _RS_ASSERT(res4.z == 3.0f);
+    _RS_ASSERT(res4.w == 4.0f);
+
+    if (failed) {
+        rsDebug("test_clamp_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_clamp_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void clamp_test() {
+    bool failed = false;
+    failed |= test_clamp_vector();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs
new file mode 100644
index 0000000..71c65ae
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/clamp_relaxed.rs
@@ -0,0 +1,2 @@
+#include "clamp.rs"
+#pragma rs_fp_relaxed
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/constant.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/constant.rs
new file mode 100644
index 0000000..732eaef
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/constant.rs
@@ -0,0 +1,19 @@
+#include "shared.rsh"
+
+const float floatTest = 1.99f;
+const double doubleTest = 2.05;
+const char charTest = -8;
+const short shortTest = -16;
+const int intTest = -32;
+const long longTest = 17179869184l; // 1 << 34
+const long long longlongTest = 68719476736l; // 1 << 36
+
+const uchar ucharTest = 8;
+const ushort ushortTest = 16;
+const uint uintTest = 32;
+const ulong ulongTest = 4611686018427387904L;
+const int64_t int64_tTest = -17179869184l; // - 1 << 34
+const uint64_t uint64_tTest = 117179869184l;
+
+const bool boolTest = true;
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert.rs
new file mode 100644
index 0000000..e314f2b
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+float4 f4 = { 2.0f, 4.0f, 6.0f, 8.0f };
+
+char4 i8_4 = { -1, -2, -3, 4 };
+
+static bool test_convert() {
+    bool failed = false;
+
+    f4 = convert_float4(i8_4);
+    _RS_ASSERT(f4.x == -1.0f);
+    _RS_ASSERT(f4.y == -2.0f);
+    _RS_ASSERT(f4.z == -3.0f);
+    _RS_ASSERT(f4.w == 4.0f);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void convert_test() {
+    bool failed = false;
+    failed |= test_convert();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs
new file mode 100644
index 0000000..81abb9b
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/convert_relaxed.rs
@@ -0,0 +1,2 @@
+#include "convert.rs"
+#pragma rs_fp_relaxed
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs
new file mode 100644
index 0000000..f4243eb
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/copy_test.rs
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "shared.rsh"
+
+void sendResult(bool pass) {
+    if (pass) {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+}
+
+
+float2 __attribute((kernel)) copyFloat2(float2 i) {
+    return i;
+}
+
+float3 __attribute((kernel)) copyFloat3(float3 i) {
+    return i;
+}
+
+float4 __attribute((kernel)) copyFloat4(float4 i) {
+    return i;
+}
+
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/element.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/element.rs
new file mode 100644
index 0000000..1f24775
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/element.rs
@@ -0,0 +1,156 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element simpleElem;
+rs_element complexElem;
+typedef struct ComplexStruct {
+    float subElem0;
+    float subElem1;
+    int subElem2;
+    float arrayElem0[2];
+    int arrayElem1[5];
+    char subElem3;
+    float subElem4;
+    float2 subElem5;
+    float3 subElem6;
+    float4 subElem_7;
+} ComplexStruct_t;
+
+ComplexStruct_t *complexStruct;
+
+static const char *subElemNames[] = {
+    "subElem0",
+    "subElem1",
+    "subElem2",
+    "arrayElem0",
+    "arrayElem1",
+    "subElem3",
+    "subElem4",
+    "subElem5",
+    "subElem6",
+    "subElem_7",
+};
+
+static uint32_t subElemNamesSizes[] = {
+    8,
+    8,
+    8,
+    10,
+    10,
+    8,
+    8,
+    8,
+    8,
+    9,
+};
+
+static uint32_t subElemArraySizes[] = {
+    1,
+    1,
+    1,
+    2,
+    5,
+    1,
+    1,
+    1,
+    1,
+    1,
+};
+
+static void resetStruct() {
+    uint8_t *bytePtr = (uint8_t*)complexStruct;
+    uint32_t sizeOfStruct = sizeof(*complexStruct);
+    for(uint32_t i = 0; i < sizeOfStruct; i ++) {
+        bytePtr[i] = 0;
+    }
+}
+
+static bool equals(const char *name0, const char * name1, uint32_t len) {
+    for (uint32_t i = 0; i < len; i ++) {
+        if (name0[i] != name1[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool test_element_getters() {
+    bool failed = false;
+
+    uint32_t subElemOffsets[10];
+    uint32_t index = 0;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem0   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem1   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem2   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem0 - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem1 - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem3   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem4   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem5   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem6   - (uint32_t)complexStruct;
+    subElemOffsets[index++] = (uint32_t)&complexStruct->subElem_7  - (uint32_t)complexStruct;
+
+    uint32_t subElemCount = rsElementGetSubElementCount(simpleElem);
+    _RS_ASSERT(subElemCount == 0);
+    _RS_ASSERT(rsElementGetDataType(simpleElem) == RS_TYPE_FLOAT_32);
+    _RS_ASSERT(rsElementGetVectorSize(simpleElem) == 3);
+
+    subElemCount = rsElementGetSubElementCount(complexElem);
+    _RS_ASSERT(subElemCount == 10);
+    _RS_ASSERT(rsElementGetDataType(complexElem) == RS_TYPE_NONE);
+    _RS_ASSERT(rsElementGetVectorSize(complexElem) == 1);
+    _RS_ASSERT(rsElementGetBytesSize(complexElem) == sizeof(*complexStruct));
+
+    char buffer[64];
+    for (uint32_t i = 0; i < subElemCount; i ++) {
+        rs_element subElem = rsElementGetSubElement(complexElem, i);
+        _RS_ASSERT(rsIsObject(subElem));
+
+        _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, i) == subElemNamesSizes[i] + 1);
+
+        uint32_t written = rsElementGetSubElementName(complexElem, i, buffer, 64);
+        _RS_ASSERT(written == subElemNamesSizes[i]);
+        _RS_ASSERT(equals(buffer, subElemNames[i], written));
+
+        _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, i) == subElemArraySizes[i]);
+        _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, i) == subElemOffsets[i]);
+    }
+
+    // Tests error checking
+    rs_element subElem = rsElementGetSubElement(complexElem, subElemCount);
+    _RS_ASSERT(!rsIsObject(subElem));
+
+    _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, subElemCount) == 0);
+
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, subElemCount, buffer, 64) == 0);
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, NULL, 64) == 0);
+    _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, buffer, 0) == 0);
+    uint32_t written = rsElementGetSubElementName(complexElem, 0, buffer, 5);
+    _RS_ASSERT(written == 4);
+    _RS_ASSERT(buffer[4] == '\0');
+
+    _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, subElemCount) == 0);
+    _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, subElemCount) == 0);
+
+    if (failed) {
+        rsDebug("test_element_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_element_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void element_test() {
+    bool failed = false;
+    failed |= test_element_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
new file mode 100644
index 0000000..ac527b5
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach.rs
@@ -0,0 +1,74 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    _RS_ASSERT(*in == (x + y * dimX));
+    *out = 99 + x + y * dimX;
+    _RS_ASSERT(*out == (99 + x + y * dimX));
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            _RS_ASSERT(a[i + j * dimX] == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void foreach_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
new file mode 100644
index 0000000..ddf17f8
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/foreach_bounds.rs
@@ -0,0 +1,71 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+int xStart = 0;
+int xEnd = 0;
+int yStart = 0;
+int yEnd = 0;
+
+rs_script s;
+rs_allocation ain;
+rs_allocation aout;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+int __attribute__((kernel)) zero() {
+    return 0;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            rsDebug("i: ", i);
+            rsDebug("j: ", j);
+            rsDebug("a[j][i]: ", a[i + j * dimX]);
+            if (i < xStart || i >= xEnd || j < yStart || j >= yEnd) {
+                _RS_ASSERT(a[i + j * dimX] == 0);
+            } else {
+                _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+            }
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void foreach_bounds_test() {
+    static bool failed = false;
+
+    rs_script_call_t rssc = {0};
+    rssc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
+    rssc.xStart = xStart;
+    rssc.xEnd = xEnd;
+    rssc.yStart = yStart;
+    rssc.yEnd = yEnd;
+
+    rsForEach(s, ain, aout, NULL, 0, &rssc);
+
+    failed |= test_root_output();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs
new file mode 100644
index 0000000..b6f2b2a6
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/fp_mad.rs
@@ -0,0 +1,174 @@
+#include "shared.rsh"
+
+const int TEST_COUNT = 1;
+
+static float data_f1[1025];
+static float4 data_f4[1025];
+
+static void test_mad4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 80); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = (data_f4[i] * 0.02f +
+                          data_f4[i+1] * 0.04f +
+                          data_f4[i+2] * 0.05f +
+                          data_f4[i+3] * 0.1f +
+                          data_f4[i+4] * 0.2f +
+                          data_f4[i+5] * 0.2f +
+                          data_f4[i+6] * 0.1f +
+                          data_f4[i+7] * 0.05f +
+                          data_f4[i+8] * 0.04f +
+                          data_f4[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad4 M ops", 1000.f / time);
+}
+
+static void test_mad(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~1 billion ops
+    for (int ct=0; ct < 1000 * (1000 / 20); ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = (data_f1[i] * 0.02f +
+                          data_f1[i+1] * 0.04f +
+                          data_f1[i+2] * 0.05f +
+                          data_f1[i+3] * 0.1f +
+                          data_f1[i+4] * 0.2f +
+                          data_f1[i+5] * 0.2f +
+                          data_f1[i+6] * 0.1f +
+                          data_f1[i+7] * 0.05f +
+                          data_f1[i+8] * 0.04f +
+                          data_f1[i+9] * 0.02f + 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_mad M ops", 1000.f / time);
+}
+
+static void test_norm(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = normalize(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_norm M ops", 10.f / time);
+}
+
+static void test_sincos4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10 / 4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = sin(data_f4[i]) * cos(data_f4[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos4 M ops", 10.f / time);
+}
+
+static void test_sincos(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~10 M ops
+    for (int ct=0; ct < 1000 * 10; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = sin(data_f1[i]) * cos(data_f1[i]);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_sincos M ops", 10.f / time);
+}
+
+static void test_clamp(uint32_t index) {
+    start();
+
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f1[i] = clamp(data_f1[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp M ops", 100.f / time);
+
+    start();
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100; ct++) {
+        for (int i=0; i < (1000); i++) {
+            if (data_f1[i] < -1.f) data_f1[i] = -1.f;
+            if (data_f1[i] > -1.f) data_f1[i] = 1.f;
+        }
+    }
+
+    time = end(index);
+    rsDebug("fp_clamp ref M ops", 100.f / time);
+}
+
+static void test_clamp4(uint32_t index) {
+    start();
+
+    float total = 0;
+    // Do ~100 M ops
+    for (int ct=0; ct < 1000 * 100 /4; ct++) {
+        for (int i=0; i < (1000); i++) {
+            data_f4[i] = clamp(data_f4[i], -1.f, 1.f);
+        }
+    }
+
+    float time = end(index);
+    rsDebug("fp_clamp4 M ops", 100.f / time);
+}
+
+void fp_mad_test(uint32_t index, int test_num) {
+    int x;
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f;
+        data_f4[x].x = (x & 0xf) * 0.1f;
+        data_f4[x].y = (x & 0xf0) * 0.1f;
+        data_f4[x].z = (x & 0x33) * 0.1f;
+        data_f4[x].w = (x & 0x77) * 0.1f;
+    }
+
+    test_mad4(index);
+    test_mad(index);
+
+    for (x=0; x < 1025; x++) {
+        data_f1[x] = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].x = (x & 0xf) * 0.1f + 1.f;
+        data_f4[x].y = (x & 0xf0) * 0.1f + 1.f;
+        data_f4[x].z = (x & 0x33) * 0.1f + 1.f;
+        data_f4[x].w = (x & 0x77) * 0.1f + 1.f;
+    }
+
+    test_norm(index);
+    test_sincos4(index);
+    test_sincos(index);
+    test_clamp4(index);
+    test_clamp(index);
+
+    // TODO Actually verify test result accuracy
+    rsDebug("fp_mad_test PASSED", 0);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/int4.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/int4.rs
new file mode 100644
index 0000000..c791cab
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/int4.rs
@@ -0,0 +1,29 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+uchar4 u4 = 4;
+int4 gi4 = {2, 2, 2, 2};
+
+void int4_test() {
+    bool failed = false;
+    int4 i4 = {u4.x, u4.y, u4.z, u4.w};
+    i4 *= gi4;
+
+    rsDebug("i4.x", i4.x);
+    rsDebug("i4.y", i4.y);
+    rsDebug("i4.z", i4.z);
+    rsDebug("i4.w", i4.w);
+
+    _RS_ASSERT(i4.x == 8);
+    _RS_ASSERT(i4.y == 8);
+    _RS_ASSERT(i4.z == 8);
+    _RS_ASSERT(i4.w == 8);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs
new file mode 100644
index 0000000..d6c9df3
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel.rs
@@ -0,0 +1,47 @@
+#include "shared.rsh"
+
+int *ain;
+int *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(int *out) {
+    *out = 7;
+}
+
+
+int __attribute__((kernel)) root(int ain, uint32_t x) {
+    _RS_ASSERT(ain == 7);
+    return ain + x;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i] == (i + ain[i]));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs
new file mode 100644
index 0000000..62c30ae
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/kernel_struct.rs
@@ -0,0 +1,66 @@
+#include "shared.rsh"
+
+struct simpleStruct {
+    int i1;
+    char ignored1;
+    float f1;
+    int i2;
+    char ignored2;
+    float f2;
+};
+
+struct simpleStruct *ain;
+struct simpleStruct *aout;
+int dimX;
+static bool failed = false;
+
+void init_vars(struct simpleStruct *out, uint32_t x) {
+    out->i1 = 0;
+    out->f1 = 0.f;
+    out->i2 = 1;
+    out->f2 = 1.0f;
+}
+
+struct simpleStruct __attribute__((kernel))
+        root(struct simpleStruct in, uint32_t x) {
+    struct simpleStruct s;
+    s.i1 = in.i1 + x;
+    s.f1 = in.f1 + x;
+    s.i2 = in.i2 + x;
+    s.f2 = in.f2 + x;
+    return s;
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i;
+
+    for (i = 0; i < dimX; i++) {
+        _RS_ASSERT(aout[i].i1 == (i + ain[i].i1));
+        _RS_ASSERT(aout[i].f1 == (i + ain[i].f1));
+        _RS_ASSERT(aout[i].i2 == (i + ain[i].i2));
+        _RS_ASSERT(aout[i].f2 == (i + ain[i].f2));
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void kernel_struct_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math.rs
new file mode 100644
index 0000000..aae29a4
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math.rs
@@ -0,0 +1,436 @@
+#include "shared.rsh"
+
+// Testing math library
+
+volatile float f1;
+volatile float2 f2;
+volatile float3 f3;
+volatile float4 f4;
+
+volatile int i1;
+volatile int2 i2;
+volatile int3 i3;
+volatile int4 i4;
+
+volatile uint ui1;
+volatile uint2 ui2;
+volatile uint3 ui3;
+volatile uint4 ui4;
+
+volatile short s1;
+volatile short2 s2;
+volatile short3 s3;
+volatile short4 s4;
+
+volatile ushort us1;
+volatile ushort2 us2;
+volatile ushort3 us3;
+volatile ushort4 us4;
+
+volatile char c1;
+volatile char2 c2;
+volatile char3 c3;
+volatile char4 c4;
+
+volatile uchar uc1;
+volatile uchar2 uc2;
+volatile uchar3 uc3;
+volatile uchar4 uc4;
+
+#define DECL_INT(prefix)            \
+volatile char prefix##_c_1 = 1;     \
+volatile char2 prefix##_c_2 = 1;    \
+volatile char3 prefix##_c_3 = 1;    \
+volatile char4 prefix##_c_4 = 1;    \
+volatile uchar prefix##_uc_1 = 1;   \
+volatile uchar2 prefix##_uc_2 = 1;  \
+volatile uchar3 prefix##_uc_3 = 1;  \
+volatile uchar4 prefix##_uc_4 = 1;  \
+volatile short prefix##_s_1 = 1;    \
+volatile short2 prefix##_s_2 = 1;   \
+volatile short3 prefix##_s_3 = 1;   \
+volatile short4 prefix##_s_4 = 1;   \
+volatile ushort prefix##_us_1 = 1;  \
+volatile ushort2 prefix##_us_2 = 1; \
+volatile ushort3 prefix##_us_3 = 1; \
+volatile ushort4 prefix##_us_4 = 1; \
+volatile int prefix##_i_1 = 1;      \
+volatile int2 prefix##_i_2 = 1;     \
+volatile int3 prefix##_i_3 = 1;     \
+volatile int4 prefix##_i_4 = 1;     \
+volatile uint prefix##_ui_1 = 1;    \
+volatile uint2 prefix##_ui_2 = 1;   \
+volatile uint3 prefix##_ui_3 = 1;   \
+volatile uint4 prefix##_ui_4 = 1;   \
+volatile long prefix##_l_1 = 1;     \
+volatile ulong prefix##_ul_1 = 1;
+
+DECL_INT(res)
+DECL_INT(src1)
+DECL_INT(src2)
+
+#define TEST_INT_OP_TYPE(op, type)                      \
+rsDebug("Testing " #op " for " #type "1", i++);         \
+res_##type##_1 = src1_##type##_1 op src2_##type##_1;    \
+rsDebug("Testing " #op " for " #type "2", i++);         \
+res_##type##_2 = src1_##type##_2 op src2_##type##_2;    \
+rsDebug("Testing " #op " for " #type "3", i++);         \
+res_##type##_3 = src1_##type##_3 op src2_##type##_3;    \
+rsDebug("Testing " #op " for " #type "4", i++);         \
+res_##type##_4 = src1_##type##_4 op src2_##type##_4;
+
+#define TEST_INT_OP(op)                     \
+TEST_INT_OP_TYPE(op, c)                     \
+TEST_INT_OP_TYPE(op, uc)                    \
+TEST_INT_OP_TYPE(op, s)                     \
+TEST_INT_OP_TYPE(op, us)                    \
+TEST_INT_OP_TYPE(op, i)                     \
+TEST_INT_OP_TYPE(op, ui)                    \
+rsDebug("Testing " #op " for l1", i++);     \
+res_l_1 = src1_l_1 op src2_l_1;             \
+rsDebug("Testing " #op " for ul1", i++);    \
+res_ul_1 = src1_ul_1 op src2_ul_1;
+
+#define TEST_XN_FUNC_YN(typeout, fnc, typein)   \
+    res_##typeout##_1 = fnc(src1_##typein##_1); \
+    res_##typeout##_2 = fnc(src1_##typein##_2); \
+    res_##typeout##_3 = fnc(src1_##typein##_3); \
+    res_##typeout##_4 = fnc(src1_##typein##_4);
+
+#define TEST_XN_FUNC_XN_XN(type, fnc)                       \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1); \
+    res_##type##_2 = fnc(src1_##type##_2, src2_##type##_2); \
+    res_##type##_3 = fnc(src1_##type##_3, src2_##type##_3); \
+    res_##type##_4 = fnc(src1_##type##_4, src2_##type##_4);
+
+#define TEST_X_FUNC_X_X_X(type, fnc)    \
+    res_##type##_1 = fnc(src1_##type##_1, src2_##type##_1, src2_##type##_1);
+
+#define TEST_IN_FUNC_IN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, uc)    \
+    TEST_XN_FUNC_YN(c, fnc, c)      \
+    TEST_XN_FUNC_YN(us, fnc, us)    \
+    TEST_XN_FUNC_YN(s, fnc, s)      \
+    TEST_XN_FUNC_YN(ui, fnc, ui)    \
+    TEST_XN_FUNC_YN(i, fnc, i)
+
+#define TEST_UIN_FUNC_IN(fnc)       \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_YN(uc, fnc, c)     \
+    TEST_XN_FUNC_YN(us, fnc, s)     \
+    TEST_XN_FUNC_YN(ui, fnc, i)     \
+
+#define TEST_IN_FUNC_IN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_XN_FUNC_XN_XN(uc, fnc)     \
+    TEST_XN_FUNC_XN_XN(c, fnc)      \
+    TEST_XN_FUNC_XN_XN(us, fnc)     \
+    TEST_XN_FUNC_XN_XN(s, fnc)      \
+    TEST_XN_FUNC_XN_XN(ui, fnc)     \
+    TEST_XN_FUNC_XN_XN(i, fnc)
+
+#define TEST_I_FUNC_I_I_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    TEST_X_FUNC_X_X_X(uc, fnc)      \
+    TEST_X_FUNC_X_X_X(c, fnc)       \
+    TEST_X_FUNC_X_X_X(us, fnc)      \
+    TEST_X_FUNC_X_X_X(s, fnc)       \
+    TEST_X_FUNC_X_X_X(ui, fnc)      \
+    TEST_X_FUNC_X_X_X(i, fnc)
+
+#define TEST_FN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f2 = fnc(f2);                   \
+    f3 = fnc(f3);                   \
+    f4 = fnc(f4);
+
+#define TEST_FN_FUNC_FN_PFN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (float*) &f1);     \
+    f2 = fnc(f2, (float2*) &f2);    \
+    f3 = fnc(f3, (float3*) &f3);    \
+    f4 = fnc(f4, (float4*) &f4);
+
+#define TEST_FN_FUNC_FN_FN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f2);               \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_F34_FUNC_F34_F34(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f3 = fnc(f3, f3);               \
+    f4 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_F(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f2 = fnc(f2, f1);               \
+    f3 = fnc(f3, f1);               \
+    f4 = fnc(f4, f1);
+
+#define TEST_F_FUNC_FN(fnc)         \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1);                   \
+    f1 = fnc(f2);                   \
+    f1 = fnc(f3);                   \
+    f1 = fnc(f4);
+
+#define TEST_F_FUNC_FN_FN(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1);               \
+    f1 = fnc(f2, f2);               \
+    f1 = fnc(f3, f3);               \
+    f1 = fnc(f4, f4);
+
+#define TEST_FN_FUNC_FN_IN(fnc)     \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i2);               \
+    f3 = fnc(f3, i3);               \
+    f4 = fnc(f4, i4);
+
+#define TEST_FN_FUNC_FN_I(fnc)      \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, i1);               \
+    f2 = fnc(f2, i1);               \
+    f3 = fnc(f3, i1);               \
+    f4 = fnc(f4, i1);
+
+#define TEST_FN_FUNC_FN_FN_FN(fnc)  \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f2, f2);           \
+    f3 = fnc(f3, f3, f3);           \
+    f4 = fnc(f4, f4, f4);
+
+#define TEST_FN_FUNC_FN_FN_F(fnc)   \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, f1);           \
+    f2 = fnc(f2, f1, f1);           \
+    f3 = fnc(f3, f1, f1);           \
+    f4 = fnc(f4, f1, f1);
+
+#define TEST_FN_FUNC_FN_PIN(fnc)    \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, (int*) &i1);       \
+    f2 = fnc(f2, (int2*) &i2);      \
+    f3 = fnc(f3, (int3*) &i3);      \
+    f4 = fnc(f4, (int4*) &i4);
+
+#define TEST_FN_FUNC_FN_FN_PIN(fnc) \
+    rsDebug("Testing " #fnc, 0);    \
+    f1 = fnc(f1, f1, (int*) &i1);   \
+    f2 = fnc(f2, f2, (int2*) &i2);  \
+    f3 = fnc(f3, f3, (int3*) &i3);  \
+    f4 = fnc(f4, f4, (int4*) &i4);
+
+#define TEST_IN_FUNC_FN(fnc)        \
+    rsDebug("Testing " #fnc, 0);    \
+    i1 = fnc(f1);                   \
+    i2 = fnc(f2);                   \
+    i3 = fnc(f3);                   \
+    i4 = fnc(f4);
+
+static bool test_fp_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_FN_FUNC_FN(acos);
+    TEST_FN_FUNC_FN(acosh);
+    TEST_FN_FUNC_FN(acospi);
+    TEST_FN_FUNC_FN(asin);
+    TEST_FN_FUNC_FN(asinh);
+    TEST_FN_FUNC_FN(asinpi);
+    TEST_FN_FUNC_FN(atan);
+    TEST_FN_FUNC_FN_FN(atan2);
+    TEST_FN_FUNC_FN(atanh);
+    TEST_FN_FUNC_FN(atanpi);
+    TEST_FN_FUNC_FN_FN(atan2pi);
+    TEST_FN_FUNC_FN(cbrt);
+    TEST_FN_FUNC_FN(ceil);
+    TEST_FN_FUNC_FN_FN_FN(clamp);
+    TEST_FN_FUNC_FN_FN_F(clamp);
+    TEST_FN_FUNC_FN_FN(copysign);
+    TEST_FN_FUNC_FN(cos);
+    TEST_FN_FUNC_FN(cosh);
+    TEST_FN_FUNC_FN(cospi);
+    TEST_F34_FUNC_F34_F34(cross);
+    TEST_FN_FUNC_FN(degrees);
+    TEST_F_FUNC_FN_FN(distance);
+    TEST_F_FUNC_FN_FN(dot);
+    TEST_FN_FUNC_FN(erfc);
+    TEST_FN_FUNC_FN(erf);
+    TEST_FN_FUNC_FN(exp);
+    TEST_FN_FUNC_FN(exp2);
+    TEST_FN_FUNC_FN(exp10);
+    TEST_FN_FUNC_FN(expm1);
+    TEST_FN_FUNC_FN(fabs);
+    TEST_FN_FUNC_FN_FN(fdim);
+    TEST_FN_FUNC_FN(floor);
+    TEST_FN_FUNC_FN_FN_FN(fma);
+    TEST_FN_FUNC_FN_FN(fmax);
+    TEST_FN_FUNC_FN_F(fmax);
+    TEST_FN_FUNC_FN_FN(fmin);
+    TEST_FN_FUNC_FN_F(fmin);
+    TEST_FN_FUNC_FN_FN(fmod);
+    TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN_PIN(frexp);
+    TEST_FN_FUNC_FN_FN(hypot);
+    TEST_IN_FUNC_FN(ilogb);
+    TEST_FN_FUNC_FN_IN(ldexp);
+    TEST_FN_FUNC_FN_I(ldexp);
+    TEST_F_FUNC_FN(length);
+    TEST_FN_FUNC_FN(lgamma);
+    TEST_FN_FUNC_FN_PIN(lgamma);
+    TEST_FN_FUNC_FN(log);
+    TEST_FN_FUNC_FN(log2);
+    TEST_FN_FUNC_FN(log10);
+    TEST_FN_FUNC_FN(log1p);
+    TEST_FN_FUNC_FN(logb);
+    TEST_FN_FUNC_FN_FN_FN(mad);
+    TEST_FN_FUNC_FN_FN(max);
+    TEST_FN_FUNC_FN_F(max);
+    TEST_FN_FUNC_FN_FN(min);
+    TEST_FN_FUNC_FN_F(min);
+    TEST_FN_FUNC_FN_FN_FN(mix);
+    TEST_FN_FUNC_FN_FN_F(mix);
+    TEST_FN_FUNC_FN_PFN(modf);
+    // nan
+    TEST_FN_FUNC_FN_FN(nextafter);
+    TEST_FN_FUNC_FN(normalize);
+    TEST_FN_FUNC_FN_FN(pow);
+    TEST_FN_FUNC_FN_IN(pown);
+    TEST_FN_FUNC_FN_FN(powr);
+    TEST_FN_FUNC_FN(radians);
+    TEST_FN_FUNC_FN_FN(remainder);
+    TEST_FN_FUNC_FN_FN_PIN(remquo);
+    TEST_FN_FUNC_FN(rint);
+    TEST_FN_FUNC_FN_IN(rootn);
+    TEST_FN_FUNC_FN(round);
+    TEST_FN_FUNC_FN(rsqrt);
+    TEST_FN_FUNC_FN(sign);
+    TEST_FN_FUNC_FN(sin);
+    TEST_FN_FUNC_FN_PFN(sincos);
+    TEST_FN_FUNC_FN(sinh);
+    TEST_FN_FUNC_FN(sinpi);
+    TEST_FN_FUNC_FN(sqrt);
+    TEST_FN_FUNC_FN_FN(step);
+    TEST_FN_FUNC_FN_F(step);
+    TEST_FN_FUNC_FN(tan);
+    TEST_FN_FUNC_FN(tanh);
+    TEST_FN_FUNC_FN(tanpi);
+    TEST_FN_FUNC_FN(tgamma);
+    TEST_FN_FUNC_FN(trunc);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_fp_math FAILED", time);
+    }
+    else {
+        rsDebug("test_fp_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_int_math(uint32_t index) {
+    bool failed = false;
+    start();
+
+    TEST_UIN_FUNC_IN(abs);
+    TEST_IN_FUNC_IN(clz);
+    TEST_IN_FUNC_IN_IN(min);
+    TEST_IN_FUNC_IN_IN(max);
+    TEST_I_FUNC_I_I_I(rsClamp);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_int_math FAILED", time);
+    }
+    else {
+        rsDebug("test_int_math PASSED", time);
+    }
+
+    return failed;
+}
+
+static bool test_basic_operators() {
+    bool failed = false;
+    int i = 0;
+
+    TEST_INT_OP(+);
+    TEST_INT_OP(-);
+    TEST_INT_OP(*);
+    TEST_INT_OP(/);
+    TEST_INT_OP(%);
+    TEST_INT_OP(<<);
+    TEST_INT_OP(>>);
+
+    if (failed) {
+        rsDebug("test_basic_operators FAILED", 0);
+    }
+    else {
+        rsDebug("test_basic_operators PASSED", 0);
+    }
+
+    return failed;
+}
+
+#define TEST_CVT(to, from, type)                        \
+rsDebug("Testing convert from " #from " to " #to, 0);   \
+to##1 = from##1;                                        \
+to##2 = convert_##type##2(from##2);                     \
+to##3 = convert_##type##3(from##3);                     \
+to##4 = convert_##type##4(from##4);
+
+#define TEST_CVT_MATRIX(to, type)   \
+TEST_CVT(to, c, type);              \
+TEST_CVT(to, uc, type);             \
+TEST_CVT(to, s, type);              \
+TEST_CVT(to, us, type);             \
+TEST_CVT(to, i, type);              \
+TEST_CVT(to, ui, type);             \
+TEST_CVT(to, f, type);              \
+
+static bool test_convert() {
+    bool failed = false;
+
+    TEST_CVT_MATRIX(c, char);
+    TEST_CVT_MATRIX(uc, uchar);
+    TEST_CVT_MATRIX(s, short);
+    TEST_CVT_MATRIX(us, ushort);
+    TEST_CVT_MATRIX(i, int);
+    TEST_CVT_MATRIX(ui, uint);
+    TEST_CVT_MATRIX(f, float);
+
+    if (failed) {
+        rsDebug("test_convert FAILED", 0);
+    }
+    else {
+        rsDebug("test_convert PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_convert();
+    failed |= test_fp_math(index);
+    failed |= test_int_math(index);
+    failed |= test_basic_operators();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs
new file mode 100644
index 0000000..5bfbb2b
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_agree.rs
@@ -0,0 +1,409 @@
+#include "shared.rsh"
+//#pragma rs_fp_relaxed
+
+volatile float x = 0.0f;
+volatile float y = 0.0f;
+volatile float result_add = 0.0f;
+volatile float result_sub = 0.0f;
+volatile float result_mul = 0.0f;
+volatile float result_div = 0.0f;
+
+#define DECLARE_INPUT_SET(type, abbrev)         \
+volatile type    rand_##abbrev##1_0, rand_##abbrev##1_1; \
+volatile type##2 rand_##abbrev##2_0, rand_##abbrev##2_1; \
+volatile type##3 rand_##abbrev##3_0, rand_##abbrev##3_1; \
+volatile type##4 rand_##abbrev##4_0, rand_##abbrev##4_1;
+
+#define DECLARE_ALL_INPUT_SETS()    \
+DECLARE_INPUT_SET(float, f);        \
+DECLARE_INPUT_SET(char, sc);        \
+DECLARE_INPUT_SET(uchar, uc);       \
+DECLARE_INPUT_SET(short, ss);       \
+DECLARE_INPUT_SET(ushort, us);      \
+DECLARE_INPUT_SET(int, si);         \
+DECLARE_INPUT_SET(uint, ui);        \
+DECLARE_INPUT_SET(long, sl);        \
+DECLARE_INPUT_SET(ulong, ul);
+
+DECLARE_ALL_INPUT_SETS();
+
+#define DECLARE_REFERENCE_SET_VEC_VEC(type, abbrev, func)   \
+volatile type    func##_rand_##abbrev##1_##abbrev##1;                \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##2;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##3;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##4;
+#define DECLARE_REFERENCE_SET_VEC_SCL(type, abbrev, func)   \
+volatile type##2 func##_rand_##abbrev##2_##abbrev##1;                \
+volatile type##3 func##_rand_##abbrev##3_##abbrev##1;                \
+volatile type##4 func##_rand_##abbrev##4_##abbrev##1;
+
+#define DECLARE_ALL_REFERENCE_SETS_VEC_VEC(func)    \
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(char, sc, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(uchar, uc, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(short, ss, func);     \
+DECLARE_REFERENCE_SET_VEC_VEC(ushort, us, func);    \
+DECLARE_REFERENCE_SET_VEC_VEC(int, si, func);       \
+DECLARE_REFERENCE_SET_VEC_VEC(uint, ui, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(long, sl, func);      \
+DECLARE_REFERENCE_SET_VEC_VEC(ulong, ul, func);
+
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(min);
+DECLARE_ALL_REFERENCE_SETS_VEC_VEC(max);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmin);
+DECLARE_REFERENCE_SET_VEC_VEC(float, f, fmax);
+DECLARE_REFERENCE_SET_VEC_SCL(float, f, fmax);
+
+static void fail_f1(float v1, float v2, float actual, float expected, char *op_name) {
+    int dist = float_dist(actual, expected);
+    rsDebug("float operation did not match!", op_name);
+    rsDebug("v1", v1);
+    rsDebug("v2", v2);
+    rsDebug("Dalvik result", expected);
+    rsDebug("Renderscript result", actual);
+    rsDebug("ULP difference", dist);
+}
+
+static void fail_f2(float2 v1, float2 v2, float2 actual, float2 expected, char *op_name) {
+    int2 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    rsDebug("float2 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+}
+
+static void fail_f3(float3 v1, float3 v2, float3 actual, float3 expected, char *op_name) {
+    int3 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    rsDebug("float3 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+}
+
+static void fail_f4(float4 v1, float4 v2, float4 actual, float4 expected, char *op_name) {
+    int4 dist;
+    dist.x = float_dist(actual.x, expected.x);
+    dist.y = float_dist(actual.y, expected.y);
+    dist.z = float_dist(actual.z, expected.z);
+    dist.w = float_dist(actual.w, expected.w);
+    rsDebug("float4 operation did not match!", op_name);
+    rsDebug("v1.x", v1.x);
+    rsDebug("v1.y", v1.y);
+    rsDebug("v1.z", v1.z);
+    rsDebug("v1.w", v1.w);
+    rsDebug("v2.x", v2.x);
+    rsDebug("v2.y", v2.y);
+    rsDebug("v2.z", v2.z);
+    rsDebug("v2.w", v2.w);
+    rsDebug("Dalvik result .x", expected.x);
+    rsDebug("Dalvik result .y", expected.y);
+    rsDebug("Dalvik result .z", expected.z);
+    rsDebug("Dalvik result .w", expected.w);
+    rsDebug("Renderscript result .x", actual.x);
+    rsDebug("Renderscript result .y", actual.y);
+    rsDebug("Renderscript result .z", actual.z);
+    rsDebug("Renderscript result .w", actual.w);
+    rsDebug("ULP difference .x", dist.x);
+    rsDebug("ULP difference .y", dist.y);
+    rsDebug("ULP difference .z", dist.z);
+    rsDebug("ULP difference .w", dist.w);
+}
+
+static bool f1_almost_equal(float a, float b) {
+    return float_almost_equal(a, b);
+}
+
+static bool f2_almost_equal(float2 a, float2 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y);
+}
+
+
+static bool f3_almost_equal(float3 a, float3 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z);
+}
+
+static bool f4_almost_equal(float4 a, float4 b) {
+    return float_almost_equal(a.x, b.x) && float_almost_equal(a.y, b.y)
+            && float_almost_equal(a.z, b.z) && float_almost_equal(a.w, b.w);
+}
+
+#define TEST_BASIC_FLOAT_OP(op, opName)                 \
+temp_f1 = x op y;                                       \
+if (! float_almost_equal(temp_f1, result_##opName)) {   \
+    fail_f1(x, y , temp_f1, result_##opName, #opName);  \
+    failed = true;                                      \
+}
+
+#define TEST_FN_FN(func, size)                                                  \
+temp_f##size = func(rand_f##size##_0, rand_f##size##_1);                        \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f##size)) {   \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f##size, #func);   \
+    failed = true;                                                              \
+}
+#define TEST_FN_F(func, size)                                               \
+temp_f##size = func(rand_f##size##_0, rand_f1_1);                           \
+if (! f##size##_almost_equal(temp_f##size , func##_rand_f##size##_f1)) {    \
+    fail_f##size (x, y , temp_f##size, func##_rand_f##size##_f1 , #func);   \
+    failed = true;                                                          \
+}
+
+#define TEST_FN_FN_ALL(func)    \
+TEST_FN_FN(func, 1)             \
+TEST_FN_FN(func, 2)             \
+TEST_FN_FN(func, 3)             \
+TEST_FN_FN(func, 4)
+#define TEST_FN_F_ALL(func) \
+TEST_FN_F(func, 2)          \
+TEST_FN_F(func, 3)          \
+TEST_FN_F(func, 4)
+
+#define TEST_VEC1_VEC1(func, type)                              \
+temp_##type##1 = func( rand_##type##1_0, rand_##type##1_1 );    \
+if (temp_##type##1 != func##_rand_##type##1_##type##1) {        \
+    rsDebug(#func " " #type "1 operation did not match!", 0);   \
+    rsDebug("v1", rand_##type##1_0);                            \
+    rsDebug("v2", rand_##type##1_1);                            \
+    rsDebug("Dalvik result", func##_rand_##type##1_##type##1);  \
+    rsDebug("Renderscript result", temp_##type##1);             \
+    failed = true;                                              \
+}
+#define TEST_VEC2_VEC2(func, type)                                      \
+temp_##type##2 = func( rand_##type##2_0, rand_##type##2_1 );            \
+if (temp_##type##2 .x != func##_rand_##type##2_##type##2 .x             \
+        || temp_##type##2 .y != func##_rand_##type##2_##type##2 .y) {   \
+    rsDebug(#func " " #type "2 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##2_0 .x);                               \
+    rsDebug("v1.y", rand_##type##2_0 .y);                               \
+    rsDebug("v2.x", rand_##type##2_1 .x);                               \
+    rsDebug("v2.y", rand_##type##2_1 .y);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##2_##type##2 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##2_##type##2 .y);    \
+    rsDebug("Renderscript result .x", temp_##type##2 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##2 .y);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC3_VEC3(func, type)                                      \
+temp_##type##3 = func( rand_##type##3_0, rand_##type##3_1 );            \
+if (temp_##type##3 .x != func##_rand_##type##3_##type##3 .x             \
+        || temp_##type##3 .y != func##_rand_##type##3_##type##3 .y      \
+        || temp_##type##3 .z != func##_rand_##type##3_##type##3 .z) {   \
+    rsDebug(#func " " #type "3 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##3_0 .x);                               \
+    rsDebug("v1.y", rand_##type##3_0 .y);                               \
+    rsDebug("v1.z", rand_##type##3_0 .z);                               \
+    rsDebug("v2.x", rand_##type##3_1 .x);                               \
+    rsDebug("v2.y", rand_##type##3_1 .y);                               \
+    rsDebug("v2.z", rand_##type##3_1 .z);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##3_##type##3 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##3_##type##3 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##3_##type##3 .z);    \
+    rsDebug("Renderscript result .x", temp_##type##3 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##3 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##3 .z);               \
+    failed = true;                                                      \
+}
+#define TEST_VEC4_VEC4(func, type)                                      \
+temp_##type##4 = func( rand_##type##4_0, rand_##type##4_1 );            \
+if (temp_##type##4 .x != func##_rand_##type##4_##type##4 .x             \
+        || temp_##type##4 .y != func##_rand_##type##4_##type##4 .y      \
+        || temp_##type##4 .z != func##_rand_##type##4_##type##4 .z      \
+        || temp_##type##4 .w != func##_rand_##type##4_##type##4 .w) {   \
+    rsDebug(#func " " #type "4 operation did not match!", 0);           \
+    rsDebug("v1.x", rand_##type##4_0 .x);                               \
+    rsDebug("v1.y", rand_##type##4_0 .y);                               \
+    rsDebug("v1.z", rand_##type##4_0 .z);                               \
+    rsDebug("v1.w", rand_##type##4_0 .w);                               \
+    rsDebug("v2.x", rand_##type##4_1 .x);                               \
+    rsDebug("v2.y", rand_##type##4_1 .y);                               \
+    rsDebug("v2.z", rand_##type##4_1 .z);                               \
+    rsDebug("v2.w", rand_##type##4_1 .w);                               \
+    rsDebug("Dalvik result .x", func##_rand_##type##4_##type##4 .x);    \
+    rsDebug("Dalvik result .y", func##_rand_##type##4_##type##4 .y);    \
+    rsDebug("Dalvik result .z", func##_rand_##type##4_##type##4 .z);    \
+    rsDebug("Dalvik result .w", func##_rand_##type##4_##type##4 .w);    \
+    rsDebug("Renderscript result .x", temp_##type##4 .x);               \
+    rsDebug("Renderscript result .y", temp_##type##4 .y);               \
+    rsDebug("Renderscript result .z", temp_##type##4 .z);               \
+    rsDebug("Renderscript result .w", temp_##type##4 .w);               \
+    failed = true;                                                      \
+}
+
+#define TEST_SC1_SC1(func)  TEST_VEC1_VEC1(func, sc)
+#define TEST_SC2_SC2(func)  TEST_VEC2_VEC2(func, sc)
+#define TEST_SC3_SC3(func)  TEST_VEC3_VEC3(func, sc)
+#define TEST_SC4_SC4(func)  TEST_VEC4_VEC4(func, sc)
+
+#define TEST_UC1_UC1(func)  TEST_VEC1_VEC1(func, uc)
+#define TEST_UC2_UC2(func)  TEST_VEC2_VEC2(func, uc)
+#define TEST_UC3_UC3(func)  TEST_VEC3_VEC3(func, uc)
+#define TEST_UC4_UC4(func)  TEST_VEC4_VEC4(func, uc)
+
+#define TEST_SS1_SS1(func)  TEST_VEC1_VEC1(func, ss)
+#define TEST_SS2_SS2(func)  TEST_VEC2_VEC2(func, ss)
+#define TEST_SS3_SS3(func)  TEST_VEC3_VEC3(func, ss)
+#define TEST_SS4_SS4(func)  TEST_VEC4_VEC4(func, ss)
+
+#define TEST_US1_US1(func)  TEST_VEC1_VEC1(func, us)
+#define TEST_US2_US2(func)  TEST_VEC2_VEC2(func, us)
+#define TEST_US3_US3(func)  TEST_VEC3_VEC3(func, us)
+#define TEST_US4_US4(func)  TEST_VEC4_VEC4(func, us)
+
+#define TEST_SI1_SI1(func)  TEST_VEC1_VEC1(func, si)
+#define TEST_SI2_SI2(func)  TEST_VEC2_VEC2(func, si)
+#define TEST_SI3_SI3(func)  TEST_VEC3_VEC3(func, si)
+#define TEST_SI4_SI4(func)  TEST_VEC4_VEC4(func, si)
+
+#define TEST_UI1_UI1(func)  TEST_VEC1_VEC1(func, ui)
+#define TEST_UI2_UI2(func)  TEST_VEC2_VEC2(func, ui)
+#define TEST_UI3_UI3(func)  TEST_VEC3_VEC3(func, ui)
+#define TEST_UI4_UI4(func)  TEST_VEC4_VEC4(func, ui)
+
+#define TEST_SL1_SL1(func)  TEST_VEC1_VEC1(func, sl)
+#define TEST_SL2_SL2(func)  TEST_VEC2_VEC2(func, sl)
+#define TEST_SL3_SL3(func)  TEST_VEC3_VEC3(func, sl)
+#define TEST_SL4_SL4(func)  TEST_VEC4_VEC4(func, sl)
+
+#define TEST_UL1_UL1(func)  TEST_VEC1_VEC1(func, ul)
+#define TEST_UL2_UL2(func)  TEST_VEC2_VEC2(func, ul)
+#define TEST_UL3_UL3(func)  TEST_VEC3_VEC3(func, ul)
+#define TEST_UL4_UL4(func)  TEST_VEC4_VEC4(func, ul)
+
+#define TEST_SC_SC_ALL(func)    \
+TEST_SC1_SC1(func)              \
+TEST_SC2_SC2(func)              \
+TEST_SC3_SC3(func)              \
+TEST_SC4_SC4(func)
+#define TEST_UC_UC_ALL(func)    \
+TEST_UC1_UC1(func)              \
+TEST_UC2_UC2(func)              \
+TEST_UC3_UC3(func)              \
+TEST_UC4_UC4(func)
+
+#define TEST_SS_SS_ALL(func)    \
+TEST_SS1_SS1(func)              \
+TEST_SS2_SS2(func)              \
+TEST_SS3_SS3(func)              \
+TEST_SS4_SS4(func)
+#define TEST_US_US_ALL(func)    \
+TEST_US1_US1(func)              \
+TEST_US2_US2(func)              \
+TEST_US3_US3(func)              \
+TEST_US4_US4(func)
+#define TEST_SI_SI_ALL(func)    \
+TEST_SI1_SI1(func)              \
+TEST_SI2_SI2(func)              \
+TEST_SI3_SI3(func)              \
+TEST_SI4_SI4(func)
+#define TEST_UI_UI_ALL(func)    \
+TEST_UI1_UI1(func)              \
+TEST_UI2_UI2(func)              \
+TEST_UI3_UI3(func)              \
+TEST_UI4_UI4(func)
+#define TEST_SL_SL_ALL(func)    \
+TEST_SL1_SL1(func)              \
+TEST_SL2_SL2(func)              \
+TEST_SL3_SL3(func)              \
+TEST_SL4_SL4(func)
+#define TEST_UL_UL_ALL(func)    \
+TEST_UL1_UL1(func)              \
+TEST_UL2_UL2(func)              \
+TEST_UL3_UL3(func)              \
+TEST_UL4_UL4(func)
+
+#define TEST_VEC_VEC_ALL(func)  \
+TEST_FN_FN_ALL(func)            \
+TEST_SC_SC_ALL(func)            \
+TEST_UC_UC_ALL(func)            \
+TEST_SS_SS_ALL(func)            \
+TEST_US_US_ALL(func)            \
+TEST_SI_SI_ALL(func)            \
+TEST_UI_UI_ALL(func)
+
+// TODO:  add long types to ALL macro
+#if 0
+TEST_SL_SL_ALL(func)            \
+TEST_UL_UL_ALL(func)
+#endif
+
+#define DECLARE_TEMP_SET(type, abbrev)  \
+volatile type    temp_##abbrev##1;               \
+volatile type##2 temp_##abbrev##2;               \
+volatile type##3 temp_##abbrev##3;               \
+volatile type##4 temp_##abbrev##4;
+
+#define DECLARE_ALL_TEMP_SETS() \
+DECLARE_TEMP_SET(float, f);     \
+DECLARE_TEMP_SET(char, sc);     \
+DECLARE_TEMP_SET(uchar, uc);    \
+DECLARE_TEMP_SET(short, ss);    \
+DECLARE_TEMP_SET(ushort, us);   \
+DECLARE_TEMP_SET(int, si);      \
+DECLARE_TEMP_SET(uint, ui);     \
+DECLARE_TEMP_SET(long, sl);     \
+DECLARE_TEMP_SET(ulong, ul);
+
+static bool test_math_agree() {
+    bool failed = false;
+
+    DECLARE_ALL_TEMP_SETS();
+
+    TEST_BASIC_FLOAT_OP(+, add);
+    TEST_BASIC_FLOAT_OP(-, sub);
+    TEST_BASIC_FLOAT_OP(*, mul);
+    TEST_BASIC_FLOAT_OP(/, div);
+
+    TEST_VEC_VEC_ALL(min);
+    TEST_VEC_VEC_ALL(max);
+    TEST_FN_FN_ALL(fmin);
+    TEST_FN_F_ALL(fmin);
+    TEST_FN_FN_ALL(fmax);
+    TEST_FN_F_ALL(fmax);
+
+    if (failed) {
+        rsDebug("test_math_agree FAILED", 0);
+    }
+    else {
+        rsDebug("test_math_agree PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_agree_test() {
+    bool failed = false;
+    failed |= test_math_agree();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs
new file mode 100644
index 0000000..2d62f34
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/math_conformance.rs
@@ -0,0 +1,57 @@
+#include "shared.rsh"
+
+// Testing math conformance
+
+static bool test_rootn() {
+    bool failed = false;
+
+    // rootn(x, 0) -> NaN
+    _RS_ASSERT(isnan(rootn(1.0f, 0)));
+
+    // rootn(+/-0, n) -> +/-inf for odd n < 0
+    _RS_ASSERT(isposinf(rootn(0.f, -3)));
+    _RS_ASSERT(isneginf(rootn(-0.f, -3)));
+
+    // rootn(+/-0, n) -> +inf for even n < 0
+    _RS_ASSERT(isposinf(rootn(0.f, -8)));
+    _RS_ASSERT(isposinf(rootn(-0.f, -8)));
+
+    // rootn(+/-0, n) -> +/-0 for odd n > 0
+    _RS_ASSERT(isposzero(rootn(0.f, 3)));
+    _RS_ASSERT(isnegzero(rootn(-0.f, 3)));
+
+    // rootn(+/-0, n) -> +0 for even n > 0
+    _RS_ASSERT(isposzero(rootn(0.f, 8)));
+    _RS_ASSERT(isposzero(rootn(-0.f, 8)));
+
+    // rootn(x, n) -> NaN for x < 0 and even n
+    _RS_ASSERT(isnan(rootn(-10000.f, -4)));
+    _RS_ASSERT(isnan(rootn(-10000.f, 4)));
+
+    // rootn(x, n) -> value for x < 0 and odd n
+    _RS_ASSERT(!isnan(rootn(-10000.f, -3)));
+    _RS_ASSERT(!isnan(rootn(-10000.f, 3)));
+
+    if (failed) {
+        rsDebug("test_rootn FAILED", -1);
+    }
+    else {
+        rsDebug("test_rootn PASSED", 0);
+    }
+
+    return failed;
+}
+
+void math_conformance_test() {
+    bool failed = false;
+    failed |= test_rootn();
+
+    if (failed) {
+        rsDebug("math_conformance_test FAILED", -1);
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsDebug("math_conformance_test PASSED", 0);
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/min.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/min.rs
new file mode 100644
index 0000000..4b92763
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/min.rs
@@ -0,0 +1,20 @@
+#include "shared.rsh"
+#pragma rs_fp_relaxed
+
+volatile uchar2 res_uc_2 = 1;
+volatile uchar2 src1_uc_2 = 1;
+volatile uchar2 src2_uc_2 = 1;
+
+void min_test() {
+    bool failed = false;
+
+    res_uc_2 = min(src1_uc_2, src2_uc_2);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
new file mode 100644
index 0000000..33944aa
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/noroot.rs
@@ -0,0 +1,44 @@
+#include "shared.rsh"
+
+int *a;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    *out = 99 + x + y * dimX;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            _RS_ASSERT(a[i + j * dimX] == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void noroot_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs
new file mode 100644
index 0000000..ce451da
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/primitives.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool test_primitive_types(uint32_t index) {
+    bool failed = false;
+    start();
+
+    _RS_ASSERT(floatTest == 2.99f);
+    _RS_ASSERT(doubleTest == 3.05);
+    _RS_ASSERT(charTest == -16);
+    _RS_ASSERT(shortTest == -32);
+    _RS_ASSERT(intTest == -64);
+    _RS_ASSERT(longTest == 17179869185l);
+    _RS_ASSERT(longlongTest == 68719476735l);
+
+    _RS_ASSERT(ucharTest == 8);
+    _RS_ASSERT(ushortTest == 16);
+    _RS_ASSERT(uintTest == 32);
+    _RS_ASSERT(ulongTest == 4611686018427387903L);
+    _RS_ASSERT(int64_tTest == -17179869184l);
+    _RS_ASSERT(uint64_tTest == 117179869185l);
+
+    float time = end(index);
+
+    if (failed) {
+        rsDebug("test_primitives FAILED", time);
+    }
+    else {
+        rsDebug("test_primitives PASSED", time);
+    }
+
+    return failed;
+}
+
+void primitives_test(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= test_primitive_types(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs
new file mode 100644
index 0000000..4ea70e2
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/refcount.rs
@@ -0,0 +1,13 @@
+#include "shared.rsh"
+
+// Testing reference counting of RS object types
+
+rs_allocation globalA;
+static rs_allocation staticGlobalA;
+
+void refcount_test() {
+    staticGlobalA = globalA;
+    rsClearObject(&globalA);
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs
new file mode 100644
index 0000000..68ac168
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rsdebug.rs
@@ -0,0 +1,62 @@
+#include "shared.rsh"
+
+// Testing primitive types
+float floatTest = 1.99f;
+float2 float2Test = {2.99f, 12.99f};
+float3 float3Test = {3.99f, 13.99f, 23.99f};
+float4 float4Test = {4.99f, 14.99f, 24.99f, 34.99f};
+double doubleTest = 2.05;
+char charTest = -8;
+short shortTest = -16;
+int intTest = -32;
+long longTest = 17179869184l; // 1 << 34
+long long longlongTest = 68719476736l; // 1 << 36
+
+uchar ucharTest = 8;
+ushort ushortTest = 16;
+uint uintTest = 32;
+ulong ulongTest = 4611686018427387904L;
+int64_t int64_tTest = -17179869184l; // - 1 << 34
+uint64_t uint64_tTest = 117179869184l;
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    // For this reason, none of the outputs are actually checked.
+
+    rsDebug("floatTest", floatTest);
+    rsDebug("float2Test", float2Test);
+    rsDebug("float3Test", float3Test);
+    rsDebug("float4Test", float4Test);
+    rsDebug("doubleTest", doubleTest);
+    rsDebug("charTest", charTest);
+    rsDebug("shortTest", shortTest);
+    rsDebug("intTest", intTest);
+    rsDebug("longTest", longTest);
+    rsDebug("longlongTest", longlongTest);
+
+    rsDebug("ucharTest", ucharTest);
+    rsDebug("ushortTest", ushortTest);
+    rsDebug("uintTest", uintTest);
+    rsDebug("ulongTest", ulongTest);
+    rsDebug("int64_tTest", int64_tTest);
+    rsDebug("uint64_tTest", uint64_tTest);
+
+    return failed;
+}
+
+void test_rsdebug(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rsdebug_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rsdebug_test PASSED", 0);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs
new file mode 100644
index 0000000..650243e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rslist.rs
@@ -0,0 +1,25 @@
+// Copyright (C) 2013 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+typedef struct ListAllocs_s {
+    rs_allocation text;
+    int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..7be955d
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_time_t curTime = rsTime(0);
+    rs_tm tm;
+    rsDebug("curTime", curTime);
+
+    rsLocaltime(&tm, &curTime);
+
+    rsDebug("tm.tm_sec", tm.tm_sec);
+    rsDebug("tm.tm_min", tm.tm_min);
+    rsDebug("tm.tm_hour", tm.tm_hour);
+    rsDebug("tm.tm_mday", tm.tm_mday);
+    rsDebug("tm.tm_mon", tm.tm_mon);
+    rsDebug("tm.tm_year", tm.tm_year);
+    rsDebug("tm.tm_wday", tm.tm_wday);
+    rsDebug("tm.tm_yday", tm.tm_yday);
+    rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+    // Test a specific time (since we set America/Los_Angeles localtime)
+    curTime = 1294438893;
+    rsLocaltime(&tm, &curTime);
+
+    _RS_ASSERT(tm.tm_sec == 33);
+    _RS_ASSERT(tm.tm_min == 21);
+    _RS_ASSERT(tm.tm_hour == 14);
+    _RS_ASSERT(tm.tm_mday == 7);
+    _RS_ASSERT(tm.tm_mon == 0);
+    _RS_ASSERT(tm.tm_year == 111);
+    _RS_ASSERT(tm.tm_wday == 5);
+    _RS_ASSERT(tm.tm_yday == 6);
+    _RS_ASSERT(tm.tm_isdst == 0);
+
+    return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstime_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstime_test PASSED", 0);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs
new file mode 100644
index 0000000..bec124d
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/rstypes.rs
@@ -0,0 +1,61 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element elementTest;
+rs_type typeTest;
+rs_allocation allocationTest;
+rs_sampler samplerTest;
+rs_script scriptTest;
+
+rs_matrix4x4 matrix4x4Test;
+rs_matrix3x3 matrix3x3Test;
+rs_matrix2x2 matrix2x2Test;
+
+struct my_struct {
+    int i;
+    rs_allocation banana;
+};
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_matrix4x4 matrix4x4TestLocal;
+    rs_matrix3x3 matrix3x3TestLocal;
+    rs_matrix2x2 matrix2x2TestLocal;
+
+    // This test focuses primarily on compilation-time, not run-time.
+    rs_element elementTestLocal;
+    rs_type typeTestLocal;
+    rs_allocation allocationTestLocal;
+    rs_sampler samplerTestLocal;
+    rs_script scriptTestLocal;
+
+    struct my_struct structTest;
+
+    //allocationTestLocal = allocationTest;
+
+    //allocationTest = allocationTestLocal;
+
+    /*for (int i = 0; i < 4; i++) {
+        fontTestLocalArray[i] = fontTestLocal;
+    }*/
+
+    /*fontTest = fontTestLocalArray[3];*/
+
+    return failed;
+}
+
+void test_rstypes(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstypes_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstypes_test PASSED", 0);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs
new file mode 100644
index 0000000..ff1c0a7
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/sampler.rs
@@ -0,0 +1,63 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+rs_sampler minification;
+rs_sampler magnification;
+rs_sampler wrapS;
+rs_sampler wrapT;
+rs_sampler anisotropy;
+
+static bool test_sampler_getters() {
+    bool failed = false;
+
+    _RS_ASSERT(rsSamplerGetMagnification(minification) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(minification) == RS_SAMPLER_LINEAR_MIP_LINEAR);
+    _RS_ASSERT(rsSamplerGetWrapS(minification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(minification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(minification) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(magnification) == RS_SAMPLER_LINEAR);
+    _RS_ASSERT(rsSamplerGetMinification(magnification) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(magnification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(magnification) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(magnification) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(wrapS) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(wrapS) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(wrapS) == RS_SAMPLER_WRAP);
+    _RS_ASSERT(rsSamplerGetWrapT(wrapS) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(wrapS) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(wrapT) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(wrapT) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(wrapT) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(wrapT) == RS_SAMPLER_WRAP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(wrapT) == 1.0f);
+
+    _RS_ASSERT(rsSamplerGetMagnification(anisotropy) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetMinification(anisotropy) == RS_SAMPLER_NEAREST);
+    _RS_ASSERT(rsSamplerGetWrapS(anisotropy) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetWrapT(anisotropy) == RS_SAMPLER_CLAMP);
+    _RS_ASSERT(rsSamplerGetAnisotropy(anisotropy) == 8.0f);
+
+    if (failed) {
+        rsDebug("test_sampler_getters FAILED", 0);
+    }
+    else {
+        rsDebug("test_sampler_getters PASSED", 0);
+    }
+
+    return failed;
+}
+
+void sampler_test() {
+    bool failed = false;
+    failed |= test_sampler_getters();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh
new file mode 100644
index 0000000..b05a354
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/shared.rsh
@@ -0,0 +1,114 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+typedef struct TestResult_s {
+    rs_allocation name;
+    bool pass;
+    float score;
+    int64_t time;
+} TestResult;
+//TestResult *g_results;
+
+static int64_t g_time;
+
+static void start(void) {
+    g_time = rsUptimeMillis();
+}
+
+static float end(uint32_t idx) {
+    int64_t t = rsUptimeMillis() - g_time;
+    //g_results[idx].time = t;
+    //rsDebug("test time", (int)t);
+    return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+    if (!(b)) { \
+        failed = true; \
+        rsDebug(#b " FAILED", 0); \
+    } \
+\
+} while (0)
+
+static const int iposinf = 0x7f800000;
+static const int ineginf = 0xff800000;
+
+static const float posinf() {
+    float f = *((float*)&iposinf);
+    return f;
+}
+
+static const float neginf() {
+    float f = *((float*)&ineginf);
+    return f;
+}
+
+static bool isposinf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == iposinf);
+}
+
+static bool isneginf(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == ineginf);
+}
+
+static bool isnan(float f) {
+    int i = *((int*)(void*)&f);
+    return (((i & 0x7f800000) == 0x7f800000) && (i & 0x007fffff));
+}
+
+static bool isposzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x00000000);
+}
+
+static bool isnegzero(float f) {
+    int i = *((int*)(void*)&f);
+    return (i == 0x80000000);
+}
+
+static bool iszero(float f) {
+    return isposzero(f) || isnegzero(f);
+}
+
+/* Absolute epsilon used for floats.  Value is similar to float.h. */
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19e7f
+#endif
+/* Max ULPs while still being considered "equal".  Only used when this number
+   of ULPs is of a greater size than FLT_EPSILON. */
+#define FLT_MAX_ULP 1
+
+/* Calculate the difference in ULPs between the two values.  (Return zero on
+   perfect equality.) */
+static int float_dist(float f1, float f2) {
+    return *((int *)(&f1)) - *((int *)(&f2));
+}
+
+/* Check if two floats are essentially equal.  Will fail with some values
+   due to design.  (Validate using FLT_EPSILON or similar if necessary.) */
+static bool float_almost_equal(float f1, float f2) {
+    int *i1 = (int*)(&f1);
+    int *i2 = (int*)(&f2);
+
+    // Check for sign equality
+    if ( ((*i1 >> 31) == 0) != ((*i2 >> 31) == 0) ) {
+        // Handle signed zeroes
+        if (f1 == f2)
+            return true;
+        return false;
+    }
+
+    // Check with ULP distance
+    if (float_dist(f1, f2) > FLT_MAX_ULP)
+        return false;
+    return true;
+}
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/struct.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/struct.rs
new file mode 100644
index 0000000..1cd728e
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/struct.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+typedef struct Point2 {
+   int x;
+   int y;
+} Point_2;
+Point_2 *point2;
+
+static bool test_Point_2(int expected) {
+    bool failed = false;
+
+    rsDebug("Point: ", point2[0].x, point2[0].y);
+    _RS_ASSERT(point2[0].x == expected);
+    _RS_ASSERT(point2[0].y == expected);
+
+    if (failed) {
+        rsDebug("test_Point_2 FAILED", 0);
+    }
+    else {
+        rsDebug("test_Point_2 PASSED", 0);
+    }
+
+    return failed;
+}
+
+void struct_test(int expected) {
+    bool failed = false;
+    failed |= test_Point_2(expected);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs
new file mode 100644
index 0000000..89e7de7
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/test_root.rs
@@ -0,0 +1,23 @@
+// Fountain test script
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test_compat)
+
+#pragma stateFragment(parent)
+
+#include "rs_graphics.rsh"
+
+
+typedef struct TestResult {
+    rs_allocation name;
+    bool pass;
+    float score;
+} TestResult_t;
+TestResult_t *results;
+
+int root() {
+
+    return 0;
+}
+
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs
new file mode 100644
index 0000000..2c056f4
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/unsigned.rs
@@ -0,0 +1,36 @@
+#include "shared.rsh"
+
+// Testing unsigned types for Bug 6764163
+unsigned int ui = 37;
+unsigned char uc = 5;
+
+static bool test_unsigned() {
+    bool failed = false;
+
+    rsDebug("ui", ui);
+    rsDebug("uc", uc);
+    _RS_ASSERT(ui == 0x7fffffff);
+    _RS_ASSERT(uc == 129);
+
+    if (failed) {
+        rsDebug("test_unsigned FAILED", -1);
+    }
+    else {
+        rsDebug("test_unsigned PASSED", 0);
+    }
+
+    return failed;
+}
+
+void unsigned_test() {
+    bool failed = false;
+    failed |= test_unsigned();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/vector.rs b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/vector.rs
new file mode 100644
index 0000000..0430a2f
--- /dev/null
+++ b/tests/RenderScriptTests/RSTest_CompatLib/src/com/android/rs/test/vector.rs
@@ -0,0 +1,198 @@
+#include "shared.rsh"
+
+// Testing vector types
+float2 f2 = { 1.0f, 2.0f };
+float3 f3 = { 1.0f, 2.0f, 3.0f };
+float4 f4 = { 1.0f, 2.0f, 3.0f, 4.0f };
+
+double2 d2 = { 1.0, 2.0 };
+double3 d3 = { 1.0, 2.0, 3.0 };
+double4 d4 = { 1.0, 2.0, 3.0, 4.0 };
+
+char2 i8_2 = { 1, 2 };
+char3 i8_3 = { 1, 2, 3 };
+char4 i8_4 = { 1, 2, 3, 4 };
+
+uchar2 u8_2 = { 1, 2 };
+uchar3 u8_3 = { 1, 2, 3 };
+uchar4 u8_4 = { 1, 2, 3, 4 };
+
+short2 i16_2 = { 1, 2 };
+short3 i16_3 = { 1, 2, 3 };
+short4 i16_4 = { 1, 2, 3, 4 };
+
+ushort2 u16_2 = { 1, 2 };
+ushort3 u16_3 = { 1, 2, 3 };
+ushort4 u16_4 = { 1, 2, 3, 4 };
+
+int2 i32_2 = { 1, 2 };
+int3 i32_3 = { 1, 2, 3 };
+int4 i32_4 = { 1, 2, 3, 4 };
+
+uint2 u32_2 = { 1, 2 };
+uint3 u32_3 = { 1, 2, 3 };
+uint4 u32_4 = { 1, 2, 3, 4 };
+
+long2 i64_2 = { 1, 2 };
+long3 i64_3 = { 1, 2, 3 };
+long4 i64_4 = { 1, 2, 3, 4 };
+
+ulong2 u64_2 = { 1, 2 };
+ulong3 u64_3 = { 1, 2, 3 };
+ulong4 u64_4 = { 1, 2, 3, 4 };
+
+static bool test_vector_types() {
+    bool failed = false;
+
+    rsDebug("Testing F32", 0);
+    _RS_ASSERT(f2.x == 2.99f);
+    _RS_ASSERT(f2.y == 3.99f);
+
+    _RS_ASSERT(f3.x == 2.99f);
+    _RS_ASSERT(f3.y == 3.99f);
+    _RS_ASSERT(f3.z == 4.99f);
+
+    _RS_ASSERT(f4.x == 2.99f);
+    _RS_ASSERT(f4.y == 3.99f);
+    _RS_ASSERT(f4.z == 4.99f);
+    _RS_ASSERT(f4.w == 5.99f);
+
+    rsDebug("Testing F64", 0);
+    _RS_ASSERT(d2.x == 2.99);
+    _RS_ASSERT(d2.y == 3.99);
+
+    _RS_ASSERT(d3.x == 2.99);
+    _RS_ASSERT(d3.y == 3.99);
+    _RS_ASSERT(d3.z == 4.99);
+
+    _RS_ASSERT(d4.x == 2.99);
+    _RS_ASSERT(d4.y == 3.99);
+    _RS_ASSERT(d4.z == 4.99);
+    _RS_ASSERT(d4.w == 5.99);
+
+    rsDebug("Testing I8", 0);
+    _RS_ASSERT(i8_2.x == 2);
+    _RS_ASSERT(i8_2.y == 3);
+
+    _RS_ASSERT(i8_3.x == 2);
+    _RS_ASSERT(i8_3.y == 3);
+    _RS_ASSERT(i8_3.z == 4);
+
+    _RS_ASSERT(i8_4.x == 2);
+    _RS_ASSERT(i8_4.y == 3);
+    _RS_ASSERT(i8_4.z == 4);
+    _RS_ASSERT(i8_4.w == 5);
+
+    rsDebug("Testing U8", 0);
+    _RS_ASSERT(u8_2.x == 2);
+    _RS_ASSERT(u8_2.y == 3);
+
+    _RS_ASSERT(u8_3.x == 2);
+    _RS_ASSERT(u8_3.y == 3);
+    _RS_ASSERT(u8_3.z == 4);
+
+    _RS_ASSERT(u8_4.x == 2);
+    _RS_ASSERT(u8_4.y == 3);
+    _RS_ASSERT(u8_4.z == 4);
+    _RS_ASSERT(u8_4.w == 5);
+
+    rsDebug("Testing I16", 0);
+    _RS_ASSERT(i16_2.x == 2);
+    _RS_ASSERT(i16_2.y == 3);
+
+    _RS_ASSERT(i16_3.x == 2);
+    _RS_ASSERT(i16_3.y == 3);
+    _RS_ASSERT(i16_3.z == 4);
+
+    _RS_ASSERT(i16_4.x == 2);
+    _RS_ASSERT(i16_4.y == 3);
+    _RS_ASSERT(i16_4.z == 4);
+    _RS_ASSERT(i16_4.w == 5);
+
+    rsDebug("Testing U16", 0);
+    _RS_ASSERT(u16_2.x == 2);
+    _RS_ASSERT(u16_2.y == 3);
+
+    _RS_ASSERT(u16_3.x == 2);
+    _RS_ASSERT(u16_3.y == 3);
+    _RS_ASSERT(u16_3.z == 4);
+
+    _RS_ASSERT(u16_4.x == 2);
+    _RS_ASSERT(u16_4.y == 3);
+    _RS_ASSERT(u16_4.z == 4);
+    _RS_ASSERT(u16_4.w == 5);
+
+    rsDebug("Testing I32", 0);
+    _RS_ASSERT(i32_2.x == 2);
+    _RS_ASSERT(i32_2.y == 3);
+
+    _RS_ASSERT(i32_3.x == 2);
+    _RS_ASSERT(i32_3.y == 3);
+    _RS_ASSERT(i32_3.z == 4);
+
+    _RS_ASSERT(i32_4.x == 2);
+    _RS_ASSERT(i32_4.y == 3);
+    _RS_ASSERT(i32_4.z == 4);
+    _RS_ASSERT(i32_4.w == 5);
+
+    rsDebug("Testing U32", 0);
+    _RS_ASSERT(u32_2.x == 2);
+    _RS_ASSERT(u32_2.y == 3);
+
+    _RS_ASSERT(u32_3.x == 2);
+    _RS_ASSERT(u32_3.y == 3);
+    _RS_ASSERT(u32_3.z == 4);
+
+    _RS_ASSERT(u32_4.x == 2);
+    _RS_ASSERT(u32_4.y == 3);
+    _RS_ASSERT(u32_4.z == 4);
+    _RS_ASSERT(u32_4.w == 5);
+
+    rsDebug("Testing I64", 0);
+    _RS_ASSERT(i64_2.x == 2);
+    _RS_ASSERT(i64_2.y == 3);
+
+    _RS_ASSERT(i64_3.x == 2);
+    _RS_ASSERT(i64_3.y == 3);
+    _RS_ASSERT(i64_3.z == 4);
+
+    _RS_ASSERT(i64_4.x == 2);
+    _RS_ASSERT(i64_4.y == 3);
+    _RS_ASSERT(i64_4.z == 4);
+    _RS_ASSERT(i64_4.w == 5);
+
+    rsDebug("Testing U64", 0);
+    _RS_ASSERT(u64_2.x == 2);
+    _RS_ASSERT(u64_2.y == 3);
+
+    _RS_ASSERT(u64_3.x == 2);
+    _RS_ASSERT(u64_3.y == 3);
+    _RS_ASSERT(u64_3.z == 4);
+
+    _RS_ASSERT(u64_4.x == 2);
+    _RS_ASSERT(u64_4.y == 3);
+    _RS_ASSERT(u64_4.z == 4);
+    _RS_ASSERT(u64_4.w == 5);
+
+    if (failed) {
+        rsDebug("test_vector FAILED", 0);
+    }
+    else {
+        rsDebug("test_vector PASSED", 0);
+    }
+
+    return failed;
+}
+
+void vector_test() {
+    bool failed = false;
+    failed |= test_vector_types();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/math.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/math.rs
index aae29a4..edde9d8 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/math.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/math.rs
@@ -278,6 +278,7 @@
     TEST_FN_FUNC_FN_F(fmin);
     TEST_FN_FUNC_FN_FN(fmod);
     TEST_FN_FUNC_FN_PFN(fract);
+    TEST_FN_FUNC_FN(fract);
     TEST_FN_FUNC_FN_PIN(frexp);
     TEST_FN_FUNC_FN_FN(hypot);
     TEST_IN_FUNC_FN(ilogb);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index e2fced6..e682da7 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1080,6 +1080,12 @@
     }
 
     @Override
+    public String getBasePackageName() {
+        // pass
+        return null;
+    }
+
+    @Override
     public ApplicationInfo getApplicationInfo() {
         return mApplicationInfo;
     }
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index 1d67055..ea943e9 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -25,17 +25,11 @@
 import android.net.sip.SimpleSessionDescription.Media;
 import android.net.wifi.WifiManager;
 import android.os.Message;
-import android.os.RemoteException;
+import android.telephony.Rlog;
 import android.text.TextUtils;
-import android.util.Log;
-
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 
 /**
  * Handles an Internet audio call over SIP. You can instantiate this class with {@link SipManager},
@@ -60,7 +54,8 @@
  * </div>
  */
 public class SipAudioCall {
-    private static final String TAG = SipAudioCall.class.getSimpleName();
+    private static final String LOG_TAG = SipAudioCall.class.getSimpleName();
+    private static final boolean DBG = true;
     private static final boolean RELEASE_SOCKET = true;
     private static final boolean DONT_RELEASE_SOCKET = false;
     private static final int SESSION_TIMEOUT = 5; // in seconds
@@ -191,7 +186,6 @@
     private boolean mMuted = false;
     private boolean mHold = false;
 
-    private SipProfile mPendingCallRequest;
     private WifiManager mWm;
     private WifiManager.WifiLock mWifiHighPerfLock;
 
@@ -261,7 +255,7 @@
                 }
             }
         } catch (Throwable t) {
-            Log.e(TAG, "setListener()", t);
+            loge("setListener()", t);
         }
     }
 
@@ -371,7 +365,7 @@
                 mAudioStream = new AudioStream(InetAddress.getByName(
                         getLocalIp()));
             } catch (Throwable t) {
-                Log.i(TAG, "transferToNewSession(): " + t);
+                loge("transferToNewSession():", t);
             }
         }
         if (origin != null) origin.endCall();
@@ -382,26 +376,26 @@
         return new SipSession.Listener() {
             @Override
             public void onCalling(SipSession session) {
-                Log.d(TAG, "calling... " + session);
+                if (DBG) log("onCalling: session=" + session);
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
                         listener.onCalling(SipAudioCall.this);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCalling(): " + t);
+                        loge("onCalling():", t);
                     }
                 }
             }
 
             @Override
             public void onRingingBack(SipSession session) {
-                Log.d(TAG, "sip call ringing back: " + session);
+                if (DBG) log("onRingingBackk: " + session);
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
                         listener.onRingingBack(SipAudioCall.this);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onRingingBack(): " + t);
+                        loge("onRingingBack():", t);
                     }
                 }
             }
@@ -424,7 +418,7 @@
                         String answer = createAnswer(sessionDescription).encode();
                         mSipSession.answerCall(answer, SESSION_TIMEOUT);
                     } catch (Throwable e) {
-                        Log.e(TAG, "onRinging()", e);
+                        loge("onRinging():", e);
                         session.endCall();
                     }
                 }
@@ -434,7 +428,7 @@
             public void onCallEstablished(SipSession session,
                     String sessionDescription) {
                 mPeerSd = sessionDescription;
-                Log.v(TAG, "onCallEstablished()" + mPeerSd);
+                if (DBG) log("onCallEstablished(): " + mPeerSd);
 
                 // TODO: how to notify the UI that the remote party is changed
                 if ((mTransferringSession != null)
@@ -452,14 +446,14 @@
                             listener.onCallEstablished(SipAudioCall.this);
                         }
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCallEstablished(): " + t);
+                        loge("onCallEstablished(): ", t);
                     }
                 }
             }
 
             @Override
             public void onCallEnded(SipSession session) {
-                Log.d(TAG, "sip call ended: " + session + " mSipSession:" + mSipSession);
+                if (DBG) log("onCallEnded: " + session + " mSipSession:" + mSipSession);
                 // reset the trasnferring session if it is the one.
                 if (session == mTransferringSession) {
                     mTransferringSession = null;
@@ -475,7 +469,7 @@
                     try {
                         listener.onCallEnded(SipAudioCall.this);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCallEnded(): " + t);
+                        loge("onCallEnded(): ", t);
                     }
                 }
                 close();
@@ -483,13 +477,13 @@
 
             @Override
             public void onCallBusy(SipSession session) {
-                Log.d(TAG, "sip call busy: " + session);
+                if (DBG) log("onCallBusy: " + session);
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
                         listener.onCallBusy(SipAudioCall.this);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCallBusy(): " + t);
+                        loge("onCallBusy(): ", t);
                     }
                 }
                 close(false);
@@ -498,7 +492,7 @@
             @Override
             public void onCallChangeFailed(SipSession session, int errorCode,
                     String message) {
-                Log.d(TAG, "sip call change failed: " + message);
+                if (DBG) log("onCallChangedFailed: " + message);
                 mErrorCode = errorCode;
                 mErrorMessage = message;
                 Listener listener = mListener;
@@ -507,7 +501,7 @@
                         listener.onError(SipAudioCall.this, mErrorCode,
                                 message);
                     } catch (Throwable t) {
-                        Log.i(TAG, "onCallBusy(): " + t);
+                        loge("onCallBusy():", t);
                     }
                 }
             }
@@ -542,8 +536,8 @@
             @Override
             public void onCallTransferring(SipSession newSession,
                     String sessionDescription) {
-                Log.v(TAG, "onCallTransferring mSipSession:"
-                        + mSipSession + " newSession:" + newSession);
+                if (DBG) log("onCallTransferring: mSipSession="
+                        + mSipSession + " newSession=" + newSession);
                 mTransferringSession = newSession;
                 try {
                     if (sessionDescription == null) {
@@ -554,7 +548,7 @@
                         newSession.answerCall(answer, SESSION_TIMEOUT);
                     }
                 } catch (Throwable e) {
-                    Log.e(TAG, "onCallTransferring()", e);
+                    loge("onCallTransferring()", e);
                     newSession.endCall();
                 }
             }
@@ -562,7 +556,7 @@
     }
 
     private void onError(int errorCode, String message) {
-        Log.d(TAG, "sip session error: "
+        if (DBG) log("onError: "
                 + SipErrorCode.toString(errorCode) + ": " + message);
         mErrorCode = errorCode;
         mErrorMessage = message;
@@ -571,7 +565,7 @@
             try {
                 listener.onError(this, errorCode, message);
             } catch (Throwable t) {
-                Log.i(TAG, "onError(): " + t);
+                loge("onError():", t);
             }
         }
         synchronized (this) {
@@ -600,11 +594,11 @@
         synchronized (this) {
             mSipSession = session;
             mPeerSd = sessionDescription;
-            Log.v(TAG, "attachCall()" + mPeerSd);
+            if (DBG) log("attachCall(): " + mPeerSd);
             try {
                 session.setListener(createListener());
             } catch (Throwable e) {
-                Log.e(TAG, "attachCall()", e);
+                loge("attachCall()", e);
                 throwSipException(e);
             }
         }
@@ -627,6 +621,7 @@
      */
     public void makeCall(SipProfile peerProfile, SipSession sipSession,
             int timeout) throws SipException {
+        if (DBG) log("makeCall: " + peerProfile + " session=" + sipSession + " timeout=" + timeout);
         if (!SipManager.isVoipSupported(mContext)) {
             throw new SipException("VOIP API is not supported");
         }
@@ -640,6 +635,7 @@
                 sipSession.makeCall(peerProfile, createOffer().encode(),
                         timeout);
             } catch (IOException e) {
+                loge("makeCall:", e);
                 throw new SipException("makeCall()", e);
             }
         }
@@ -650,6 +646,7 @@
      * @throws SipException if the SIP service fails to end the call
      */
     public void endCall() throws SipException {
+        if (DBG) log("endCall: mSipSession" + mSipSession);
         synchronized (this) {
             stopCall(RELEASE_SOCKET);
             mInCall = false;
@@ -672,9 +669,11 @@
      * @throws SipException if the SIP service fails to hold the call
      */
     public void holdCall(int timeout) throws SipException {
+        if (DBG) log("holdCall: mSipSession" + mSipSession + " timeout=" + timeout);
         synchronized (this) {
             if (mHold) return;
             if (mSipSession == null) {
+                loge("holdCall:");
                 throw new SipException("Not in a call to hold call");
             }
             mSipSession.changeCall(createHoldOffer().encode(), timeout);
@@ -695,6 +694,7 @@
      * @throws SipException if the SIP service fails to answer the call
      */
     public void answerCall(int timeout) throws SipException {
+        if (DBG) log("answerCall: mSipSession" + mSipSession + " timeout=" + timeout);
         synchronized (this) {
             if (mSipSession == null) {
                 throw new SipException("No call to answer");
@@ -704,6 +704,7 @@
                         getLocalIp()));
                 mSipSession.answerCall(createAnswer(mPeerSd).encode(), timeout);
             } catch (IOException e) {
+                loge("answerCall:", e);
                 throw new SipException("answerCall()", e);
             }
         }
@@ -722,6 +723,7 @@
      * @throws SipException if the SIP service fails to unhold the call
      */
     public void continueCall(int timeout) throws SipException {
+        if (DBG) log("continueCall: mSipSession" + mSipSession + " timeout=" + timeout);
         synchronized (this) {
             if (!mHold) return;
             mSipSession.changeCall(createContinueOffer().encode(), timeout);
@@ -740,6 +742,7 @@
             media.setRtpPayload(codec.type, codec.rtpmap, codec.fmtp);
         }
         media.setRtpPayload(127, "telephone-event/8000", "0-15");
+        if (DBG) log("createOffer: offer=" + offer);
         return offer;
     }
 
@@ -798,18 +801,22 @@
             }
         }
         if (codec == null) {
+            loge("createAnswer: no suitable codes");
             throw new IllegalStateException("Reject SDP: no suitable codecs");
         }
+        if (DBG) log("createAnswer: answer=" + answer);
         return answer;
     }
 
     private SimpleSessionDescription createHoldOffer() {
         SimpleSessionDescription offer = createContinueOffer();
         offer.setAttribute("sendonly", "");
+        if (DBG) log("createHoldOffer: offer=" + offer);
         return offer;
     }
 
     private SimpleSessionDescription createContinueOffer() {
+        if (DBG) log("createContinueOffer");
         SimpleSessionDescription offer =
                 new SimpleSessionDescription(mSessionId, getLocalIp());
         Media media = offer.newMedia(
@@ -825,17 +832,17 @@
 
     private void grabWifiHighPerfLock() {
         if (mWifiHighPerfLock == null) {
-            Log.v(TAG, "acquire wifi high perf lock");
+            if (DBG) log("grabWifiHighPerfLock:");
             mWifiHighPerfLock = ((WifiManager)
                     mContext.getSystemService(Context.WIFI_SERVICE))
-                    .createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TAG);
+                    .createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, LOG_TAG);
             mWifiHighPerfLock.acquire();
         }
     }
 
     private void releaseWifiHighPerfLock() {
         if (mWifiHighPerfLock != null) {
-            Log.v(TAG, "release wifi high perf lock");
+            if (DBG) log("releaseWifiHighPerfLock:");
             mWifiHighPerfLock.release();
             mWifiHighPerfLock = null;
         }
@@ -912,7 +919,7 @@
             AudioGroup audioGroup = getAudioGroup();
             if ((audioGroup != null) && (mSipSession != null)
                     && (SipSession.State.IN_CALL == getState())) {
-                Log.v(TAG, "send DTMF: " + code);
+                if (DBG) log("sendDtmf: code=" + code + " result=" + result);
                 audioGroup.sendDtmf(code);
             }
             if (result != null) result.sendToTarget();
@@ -971,6 +978,7 @@
      */
     public void setAudioGroup(AudioGroup group) {
         synchronized (this) {
+            if (DBG) log("setAudioGroup: group=" + group);
             if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
                 mAudioStream.join(group);
             }
@@ -997,8 +1005,8 @@
     }
 
     private synchronized void startAudioInternal() throws UnknownHostException {
+        if (DBG) loge("startAudioInternal: mPeerSd=" + mPeerSd);
         if (mPeerSd == null) {
-            Log.v(TAG, "startAudioInternal() mPeerSd = null");
             throw new IllegalStateException("mPeerSd = null");
         }
 
@@ -1082,6 +1090,7 @@
     // set audio group mode based on current audio configuration
     private void setAudioGroupMode() {
         AudioGroup audioGroup = getAudioGroup();
+        if (DBG) log("setAudioGroupMode: audioGroup=" + audioGroup);
         if (audioGroup != null) {
             if (mHold) {
                 audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
@@ -1096,7 +1105,7 @@
     }
 
     private void stopCall(boolean releaseSocket) {
-        Log.d(TAG, "stop audiocall");
+        if (DBG) log("stopCall: releaseSocket=" + releaseSocket);
         releaseWifiHighPerfLock();
         if (mAudioStream != null) {
             mAudioStream.join(null);
@@ -1120,7 +1129,15 @@
         }
     }
 
-    private SipProfile getPeerProfile(SipSession session) {
-        return session.getPeerProfile();
+    private void log(String s) {
+        Rlog.d(LOG_TAG, s);
+    }
+
+    private void loge(String s) {
+        Rlog.e(LOG_TAG, s);
+    }
+
+    private void loge(String s, Throwable t) {
+        Rlog.e(LOG_TAG, s, t);
     }
 }
diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java
index 74c3672..a94232a 100644
--- a/voip/java/android/net/sip/SipManager.java
+++ b/voip/java/android/net/sip/SipManager.java
@@ -21,10 +21,9 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.text.ParseException;
 
@@ -591,7 +590,7 @@
                         : session.getLocalProfile().getUriString());
             } catch (Throwable e) {
                 // SipService died? SIP stack died?
-                Log.w(TAG, "getUri(): " + e);
+                Rlog.e(TAG, "getUri(): ", e);
                 return null;
             }
         }
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index e03cf9f..edbc66f 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -17,7 +17,7 @@
 package android.net.sip;
 
 import android.os.RemoteException;
-import android.util.Log;
+import android.telephony.Rlog;
 
 /**
  * Represents a SIP session that is associated with a SIP dialog or a standalone
@@ -242,7 +242,7 @@
             try {
                 realSession.setListener(createListener());
             } catch (RemoteException e) {
-                Log.e(TAG, "SipSession.setListener(): " + e);
+                loge("SipSession.setListener:", e);
             }
         }
     }
@@ -261,7 +261,7 @@
         try {
             return mSession.getLocalIp();
         } catch (RemoteException e) {
-            Log.e(TAG, "getLocalIp(): " + e);
+            loge("getLocalIp:", e);
             return "127.0.0.1";
         }
     }
@@ -275,7 +275,7 @@
         try {
             return mSession.getLocalProfile();
         } catch (RemoteException e) {
-            Log.e(TAG, "getLocalProfile(): " + e);
+            loge("getLocalProfile:", e);
             return null;
         }
     }
@@ -290,7 +290,7 @@
         try {
             return mSession.getPeerProfile();
         } catch (RemoteException e) {
-            Log.e(TAG, "getPeerProfile(): " + e);
+            loge("getPeerProfile:", e);
             return null;
         }
     }
@@ -305,7 +305,7 @@
         try {
             return mSession.getState();
         } catch (RemoteException e) {
-            Log.e(TAG, "getState(): " + e);
+            loge("getState:", e);
             return State.NOT_DEFINED;
         }
     }
@@ -319,7 +319,7 @@
         try {
             return mSession.isInCall();
         } catch (RemoteException e) {
-            Log.e(TAG, "isInCall(): " + e);
+            loge("isInCall:", e);
             return false;
         }
     }
@@ -333,7 +333,7 @@
         try {
             return mSession.getCallId();
         } catch (RemoteException e) {
-            Log.e(TAG, "getCallId(): " + e);
+            loge("getCallId:", e);
             return null;
         }
     }
@@ -364,7 +364,7 @@
         try {
             mSession.register(duration);
         } catch (RemoteException e) {
-            Log.e(TAG, "register(): " + e);
+            loge("register:", e);
         }
     }
 
@@ -381,7 +381,7 @@
         try {
             mSession.unregister();
         } catch (RemoteException e) {
-            Log.e(TAG, "unregister(): " + e);
+            loge("unregister:", e);
         }
     }
 
@@ -402,7 +402,7 @@
         try {
             mSession.makeCall(callee, sessionDescription, timeout);
         } catch (RemoteException e) {
-            Log.e(TAG, "makeCall(): " + e);
+            loge("makeCall:", e);
         }
     }
 
@@ -420,7 +420,7 @@
         try {
             mSession.answerCall(sessionDescription, timeout);
         } catch (RemoteException e) {
-            Log.e(TAG, "answerCall(): " + e);
+            loge("answerCall:", e);
         }
     }
 
@@ -436,7 +436,7 @@
         try {
             mSession.endCall();
         } catch (RemoteException e) {
-            Log.e(TAG, "endCall(): " + e);
+            loge("endCall:", e);
         }
     }
 
@@ -453,7 +453,7 @@
         try {
             mSession.changeCall(sessionDescription, timeout);
         } catch (RemoteException e) {
-            Log.e(TAG, "changeCall(): " + e);
+            loge("changeCall:", e);
         }
     }
 
@@ -463,12 +463,14 @@
 
     private ISipSessionListener createListener() {
         return new ISipSessionListener.Stub() {
+            @Override
             public void onCalling(ISipSession session) {
                 if (mListener != null) {
                     mListener.onCalling(SipSession.this);
                 }
             }
 
+            @Override
             public void onRinging(ISipSession session, SipProfile caller,
                     String sessionDescription) {
                 if (mListener != null) {
@@ -477,12 +479,14 @@
                 }
             }
 
+            @Override
             public void onRingingBack(ISipSession session) {
                 if (mListener != null) {
                     mListener.onRingingBack(SipSession.this);
                 }
             }
 
+            @Override
             public void onCallEstablished(ISipSession session,
                     String sessionDescription) {
                 if (mListener != null) {
@@ -491,18 +495,21 @@
                 }
             }
 
+            @Override
             public void onCallEnded(ISipSession session) {
                 if (mListener != null) {
                     mListener.onCallEnded(SipSession.this);
                 }
             }
 
+            @Override
             public void onCallBusy(ISipSession session) {
                 if (mListener != null) {
                     mListener.onCallBusy(SipSession.this);
                 }
             }
 
+            @Override
             public void onCallTransferring(ISipSession session,
                     String sessionDescription) {
                 if (mListener != null) {
@@ -513,6 +520,7 @@
                 }
             }
 
+            @Override
             public void onCallChangeFailed(ISipSession session, int errorCode,
                     String message) {
                 if (mListener != null) {
@@ -521,24 +529,28 @@
                 }
             }
 
+            @Override
             public void onError(ISipSession session, int errorCode, String message) {
                 if (mListener != null) {
                     mListener.onError(SipSession.this, errorCode, message);
                 }
             }
 
+            @Override
             public void onRegistering(ISipSession session) {
                 if (mListener != null) {
                     mListener.onRegistering(SipSession.this);
                 }
             }
 
+            @Override
             public void onRegistrationDone(ISipSession session, int duration) {
                 if (mListener != null) {
                     mListener.onRegistrationDone(SipSession.this, duration);
                 }
             }
 
+            @Override
             public void onRegistrationFailed(ISipSession session, int errorCode,
                     String message) {
                 if (mListener != null) {
@@ -547,6 +559,7 @@
                 }
             }
 
+            @Override
             public void onRegistrationTimeout(ISipSession session) {
                 if (mListener != null) {
                     mListener.onRegistrationTimeout(SipSession.this);
@@ -554,4 +567,8 @@
             }
         };
     }
+
+    private void loge(String s, Throwable t) {
+        Rlog.e(TAG, s, t);
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 113f007..c708be8 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -24,7 +24,7 @@
 import gov.nist.javax.sip.header.extensions.ReplacesHeader;
 
 import android.net.sip.SipProfile;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.text.ParseException;
 import java.util.ArrayList;
@@ -46,9 +46,7 @@
 import javax.sip.SipProvider;
 import javax.sip.SipStack;
 import javax.sip.Transaction;
-import javax.sip.TransactionAlreadyExistsException;
 import javax.sip.TransactionTerminatedEvent;
-import javax.sip.TransactionUnavailableException;
 import javax.sip.TransactionState;
 import javax.sip.address.Address;
 import javax.sip.address.AddressFactory;
@@ -73,8 +71,8 @@
  */
 class SipHelper {
     private static final String TAG = SipHelper.class.getSimpleName();
-    private static final boolean DEBUG = false;
-    private static final boolean DEBUG_PING = false;
+    private static final boolean DBG = false;
+    private static final boolean DBG_PING = false;
 
     private SipStack mSipStack;
     private SipProvider mSipProvider;
@@ -262,7 +260,7 @@
         ClientTransaction tid = responseEvent.getClientTransaction();
         ClientTransaction ct = authenticationHelper.handleChallenge(
                 responseEvent.getResponse(), tid, mSipProvider, 5);
-        if (DEBUG) Log.d(TAG, "send request with challenge response: "
+        if (DBG) log("send request with challenge response: "
                 + ct.getRequest());
         ct.sendRequest();
         return ct;
@@ -301,7 +299,7 @@
                             "application", "sdp"));
             ClientTransaction clientTransaction =
                     mSipProvider.getNewClientTransaction(request);
-            if (DEBUG) Log.d(TAG, "send INVITE: " + request);
+            if (DBG) log("send INVITE: " + request);
             clientTransaction.sendRequest();
             return clientTransaction;
         } catch (ParseException e) {
@@ -326,7 +324,7 @@
 
             ClientTransaction clientTransaction =
                     mSipProvider.getNewClientTransaction(request);
-            if (DEBUG) Log.d(TAG, "send RE-INVITE: " + request);
+            if (DBG) log("send RE-INVITE: " + request);
             dialog.sendRequest(clientTransaction);
             return clientTransaction;
         } catch (ParseException e) {
@@ -360,7 +358,7 @@
             ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
             toHeader.setTag(tag);
             response.addHeader(toHeader);
-            if (DEBUG) Log.d(TAG, "send RINGING: " + response);
+            if (DBG) log("send RINGING: " + response);
             transaction.sendResponse(response);
             return transaction;
         } catch (ParseException e) {
@@ -390,7 +388,7 @@
             }
 
             if (inviteTransaction.getState() != TransactionState.COMPLETED) {
-                if (DEBUG) Log.d(TAG, "send OK: " + response);
+                if (DBG) log("send OK: " + response);
                 inviteTransaction.sendResponse(response);
             }
 
@@ -412,7 +410,7 @@
             }
 
             if (inviteTransaction.getState() != TransactionState.COMPLETED) {
-                if (DEBUG) Log.d(TAG, "send BUSY HERE: " + response);
+                if (DBG) log("send BUSY HERE: " + response);
                 inviteTransaction.sendResponse(response);
             }
         } catch (ParseException e) {
@@ -429,20 +427,20 @@
         long cseq = ((CSeqHeader) response.getHeader(CSeqHeader.NAME))
                 .getSeqNumber();
         Request ack = dialog.createAck(cseq);
-        if (DEBUG) Log.d(TAG, "send ACK: " + ack);
+        if (DBG) log("send ACK: " + ack);
         dialog.sendAck(ack);
     }
 
     public void sendBye(Dialog dialog) throws SipException {
         Request byeRequest = dialog.createRequest(Request.BYE);
-        if (DEBUG) Log.d(TAG, "send BYE: " + byeRequest);
+        if (DBG) log("send BYE: " + byeRequest);
         dialog.sendRequest(mSipProvider.getNewClientTransaction(byeRequest));
     }
 
     public void sendCancel(ClientTransaction inviteTransaction)
             throws SipException {
         Request cancelRequest = inviteTransaction.createCancel();
-        if (DEBUG) Log.d(TAG, "send CANCEL: " + cancelRequest);
+        if (DBG) log("send CANCEL: " + cancelRequest);
         mSipProvider.getNewClientTransaction(cancelRequest).sendRequest();
     }
 
@@ -452,9 +450,9 @@
             Request request = event.getRequest();
             Response response = mMessageFactory.createResponse(
                     responseCode, request);
-            if (DEBUG && (!Request.OPTIONS.equals(request.getMethod())
-                    || DEBUG_PING)) {
-                Log.d(TAG, "send response: " + response);
+            if (DBG && (!Request.OPTIONS.equals(request.getMethod())
+                    || DBG_PING)) {
+                log("send response: " + response);
             }
             getServerTransaction(event).sendResponse(response);
         } catch (ParseException e) {
@@ -474,7 +472,7 @@
                             "message", "sipfrag"));
             request.addHeader(mHeaderFactory.createEventHeader(
                     ReferencesHeader.REFER));
-            if (DEBUG) Log.d(TAG, "send NOTIFY: " + request);
+            if (DBG) log("send NOTIFY: " + request);
             dialog.sendRequest(mSipProvider.getNewClientTransaction(request));
         } catch (ParseException e) {
             throw new SipException("sendReferNotify()", e);
@@ -486,7 +484,7 @@
         try {
             Response response = mMessageFactory.createResponse(
                     Response.REQUEST_TERMINATED, inviteRequest);
-            if (DEBUG) Log.d(TAG, "send response: " + response);
+            if (DBG) log("send response: " + response);
             inviteTransaction.sendResponse(response);
         } catch (ParseException e) {
             throw new SipException("sendInviteRequestTerminated()", e);
@@ -532,4 +530,8 @@
     private static String getCallId(Dialog dialog) {
         return dialog.getCallId().getCallId();
     }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index a477fd1..80fe68c 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -16,7 +16,6 @@
 
 package com.android.server.sip;
 
-import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -44,22 +43,15 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.io.IOException;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Comparator;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.TreeSet;
 import java.util.concurrent.Executor;
 import javax.sip.SipException;
 
@@ -68,7 +60,7 @@
  */
 public final class SipService extends ISipService.Stub {
     static final String TAG = "SipService";
-    static final boolean DEBUG = false;
+    static final boolean DBG = true;
     private static final int EXPIRY_TIME = 3600;
     private static final int SHORT_EXPIRY_TIME = 10;
     private static final int MIN_EXPIRY_TIME = 60;
@@ -82,7 +74,7 @@
     private WifiManager.WifiLock mWifiLock;
     private boolean mSipOnWifiOnly;
 
-    private IntervalMeasurementProcess mIntervalMeasurementProcess;
+    private SipKeepAliveProcessCallback mSipKeepAliveProcessCallback;
 
     private MyExecutor mExecutor = new MyExecutor();
 
@@ -107,12 +99,12 @@
         if (SipManager.isApiSupported(context)) {
             ServiceManager.addService("sip", new SipService(context));
             context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP));
-            if (DEBUG) Log.d(TAG, "SIP service started");
+            if (DBG) slog("start:");
         }
     }
 
     private SipService(Context context) {
-        if (DEBUG) Log.d(TAG, " service started!");
+        if (DBG) log("SipService: started!");
         mContext = context;
         mConnectivityReceiver = new ConnectivityReceiver();
 
@@ -128,6 +120,7 @@
         mTimer = new SipWakeupTimer(context, mExecutor);
     }
 
+    @Override
     public synchronized SipProfile[] getListOfProfiles() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -141,6 +134,7 @@
         return profiles.toArray(new SipProfile[profiles.size()]);
     }
 
+    @Override
     public synchronized void open(SipProfile localProfile) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -148,11 +142,12 @@
         try {
             createGroup(localProfile);
         } catch (SipException e) {
-            Log.e(TAG, "openToMakeCalls()", e);
+            loge("openToMakeCalls()", e);
             // TODO: how to send the exception back
         }
     }
 
+    @Override
     public synchronized void open3(SipProfile localProfile,
             PendingIntent incomingCallPendingIntent,
             ISipSessionListener listener) {
@@ -160,11 +155,11 @@
                 android.Manifest.permission.USE_SIP, null);
         localProfile.setCallingUid(Binder.getCallingUid());
         if (incomingCallPendingIntent == null) {
-            Log.w(TAG, "incomingCallPendingIntent cannot be null; "
+            if (DBG) log("open3: incomingCallPendingIntent cannot be null; "
                     + "the profile is not opened");
             return;
         }
-        if (DEBUG) Log.d(TAG, "open3: " + localProfile.getUriString() + ": "
+        if (DBG) log("open3: " + localProfile.getUriString() + ": "
                 + incomingCallPendingIntent + ": " + listener);
         try {
             SipSessionGroupExt group = createGroup(localProfile,
@@ -174,7 +169,7 @@
                 updateWakeLocks();
             }
         } catch (SipException e) {
-            Log.e(TAG, "openToReceiveCalls()", e);
+            loge("open3:", e);
             // TODO: how to send the exception back
         }
     }
@@ -192,13 +187,14 @@
         return (Binder.getCallingUid() == Process.PHONE_UID);
     }
 
+    @Override
     public synchronized void close(String localProfileUri) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
         SipSessionGroupExt group = mSipGroups.get(localProfileUri);
         if (group == null) return;
         if (!isCallerCreatorOrRadio(group)) {
-            Log.w(TAG, "only creator or radio can close this profile");
+            if (DBG) log("only creator or radio can close this profile");
             return;
         }
 
@@ -209,6 +205,7 @@
         updateWakeLocks();
     }
 
+    @Override
     public synchronized boolean isOpened(String localProfileUri) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -217,11 +214,12 @@
         if (isCallerCreatorOrRadio(group)) {
             return true;
         } else {
-            Log.w(TAG, "only creator or radio can query on the profile");
+            if (DBG) log("only creator or radio can query on the profile");
             return false;
         }
     }
 
+    @Override
     public synchronized boolean isRegistered(String localProfileUri) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -230,11 +228,12 @@
         if (isCallerCreatorOrRadio(group)) {
             return group.isRegistered();
         } else {
-            Log.w(TAG, "only creator or radio can query on the profile");
+            if (DBG) log("only creator or radio can query on the profile");
             return false;
         }
     }
 
+    @Override
     public synchronized void setRegistrationListener(String localProfileUri,
             ISipSessionListener listener) {
         mContext.enforceCallingOrSelfPermission(
@@ -244,25 +243,31 @@
         if (isCallerCreator(group)) {
             group.setListener(listener);
         } else {
-            Log.w(TAG, "only creator can set listener on the profile");
+            if (DBG) log("only creator can set listener on the profile");
         }
     }
 
+    @Override
     public synchronized ISipSession createSession(SipProfile localProfile,
             ISipSessionListener listener) {
+        if (DBG) log("createSession: profile" + localProfile);
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
         localProfile.setCallingUid(Binder.getCallingUid());
-        if (mNetworkType == -1) return null;
+        if (mNetworkType == -1) {
+            if (DBG) log("createSession: mNetworkType==-1 ret=null");
+            return null;
+        }
         try {
             SipSessionGroupExt group = createGroup(localProfile);
             return group.createSession(listener);
         } catch (SipException e) {
-            if (DEBUG) Log.d(TAG, "createSession()", e);
+            if (DBG) loge("createSession;", e);
             return null;
         }
     }
 
+    @Override
     public synchronized ISipSession getPendingSession(String callId) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.USE_SIP, null);
@@ -276,7 +281,7 @@
             s.connect(InetAddress.getByName("192.168.1.1"), 80);
             return s.getLocalAddress().getHostAddress();
         } catch (IOException e) {
-            if (DEBUG) Log.d(TAG, "determineLocalIp()", e);
+            if (DBG) loge("determineLocalIp()", e);
             // dont do anything; there should be a connectivity change going
             return null;
         }
@@ -317,7 +322,7 @@
     }
 
     private void notifyProfileAdded(SipProfile localProfile) {
-        if (DEBUG) Log.d(TAG, "notify: profile added: " + localProfile);
+        if (DBG) log("notify: profile added: " + localProfile);
         Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE);
         intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
         mContext.sendBroadcast(intent);
@@ -327,7 +332,7 @@
     }
 
     private void notifyProfileRemoved(SipProfile localProfile) {
-        if (DEBUG) Log.d(TAG, "notify: profile removed: " + localProfile);
+        if (DBG) log("notify: profile removed: " + localProfile);
         Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE);
         intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
         mContext.sendBroadcast(intent);
@@ -337,9 +342,9 @@
     }
 
     private void stopPortMappingMeasurement() {
-        if (mIntervalMeasurementProcess != null) {
-            mIntervalMeasurementProcess.stop();
-            mIntervalMeasurementProcess = null;
+        if (mSipKeepAliveProcessCallback != null) {
+            mSipKeepAliveProcessCallback.stop();
+            mSipKeepAliveProcessCallback = null;
         }
     }
 
@@ -351,10 +356,10 @@
 
     private void startPortMappingLifetimeMeasurement(
             SipProfile localProfile, int maxInterval) {
-        if ((mIntervalMeasurementProcess == null)
+        if ((mSipKeepAliveProcessCallback == null)
                 && (mKeepAliveInterval == -1)
                 && isBehindNAT(mLocalIp)) {
-            Log.d(TAG, "start NAT port mapping timeout measurement on "
+            if (DBG) log("startPortMappingLifetimeMeasurement: profile="
                     + localProfile.getUriString());
 
             int minInterval = mLastGoodKeepAliveInterval;
@@ -363,11 +368,11 @@
                 // to the default min
                 minInterval = mLastGoodKeepAliveInterval
                         = DEFAULT_KEEPALIVE_INTERVAL;
-                Log.d(TAG, "  reset min interval to " + minInterval);
+                log("  reset min interval to " + minInterval);
             }
-            mIntervalMeasurementProcess = new IntervalMeasurementProcess(
+            mSipKeepAliveProcessCallback = new SipKeepAliveProcessCallback(
                     localProfile, minInterval, maxInterval);
-            mIntervalMeasurementProcess.start();
+            mSipKeepAliveProcessCallback.start();
         }
     }
 
@@ -382,10 +387,10 @@
         try {
             cleanUpPendingSessions();
             mPendingSessions.put(session.getCallId(), session);
-            if (DEBUG) Log.d(TAG, "#pending sess=" + mPendingSessions.size());
+            if (DBG) log("#pending sess=" + mPendingSessions.size());
         } catch (RemoteException e) {
             // should not happen with a local call
-            Log.e(TAG, "addPendingSession()", e);
+            loge("addPendingSession()", e);
         }
     }
 
@@ -405,7 +410,7 @@
         String callId = ringingSession.getCallId();
         for (SipSessionGroupExt group : mSipGroups.values()) {
             if ((group != ringingGroup) && group.containsSession(callId)) {
-                if (DEBUG) Log.d(TAG, "call self: "
+                if (DBG) log("call self: "
                         + ringingSession.getLocalProfile().getUriString()
                         + " -> " + group.getLocalProfile().getUriString());
                 return true;
@@ -428,31 +433,36 @@
 
     private boolean isBehindNAT(String address) {
         try {
+            // TODO: How is isBehindNAT used and why these constanst address:
+            //       10.x.x.x | 192.168.x.x | 172.16.x.x .. 172.19.x.x
             byte[] d = InetAddress.getByName(address).getAddress();
             if ((d[0] == 10) ||
-                    (((0x000000FF & ((int)d[0])) == 172) &&
-                    ((0x000000F0 & ((int)d[1])) == 16)) ||
-                    (((0x000000FF & ((int)d[0])) == 192) &&
-                    ((0x000000FF & ((int)d[1])) == 168))) {
+                    (((0x000000FF & d[0]) == 172) &&
+                    ((0x000000F0 & d[1]) == 16)) ||
+                    (((0x000000FF & d[0]) == 192) &&
+                    ((0x000000FF & d[1]) == 168))) {
                 return true;
             }
         } catch (UnknownHostException e) {
-            Log.e(TAG, "isBehindAT()" + address, e);
+            loge("isBehindAT()" + address, e);
         }
         return false;
     }
 
     private class SipSessionGroupExt extends SipSessionAdapter {
+        private static final String SSGE_TAG = "SipSessionGroupExt";
+        private static final boolean SSGE_DBG = true;
         private SipSessionGroup mSipGroup;
         private PendingIntent mIncomingCallPendingIntent;
         private boolean mOpenedToReceiveCalls;
 
-        private AutoRegistrationProcess mAutoRegistration =
-                new AutoRegistrationProcess();
+        private SipAutoReg mAutoRegistration =
+                new SipAutoReg();
 
         public SipSessionGroupExt(SipProfile localProfile,
                 PendingIntent incomingCallPendingIntent,
                 ISipSessionListener listener) throws SipException {
+            if (SSGE_DBG) log("SipSessionGroupExt: profile=" + localProfile);
             mSipGroup = new SipSessionGroup(duplicate(localProfile),
                     localProfile.getPassword(), mTimer, mMyWakeLock);
             mIncomingCallPendingIntent = incomingCallPendingIntent;
@@ -481,7 +491,7 @@
             try {
                 return new SipProfile.Builder(p).setPassword("*").build();
             } catch (Exception e) {
-                Log.wtf(TAG, "duplicate()", e);
+                loge("duplicate()", e);
                 throw new RuntimeException("duplicate profile", e);
             }
         }
@@ -500,20 +510,21 @@
                 mSipGroup.openToReceiveCalls(this);
                 mAutoRegistration.start(mSipGroup);
             }
-            if (DEBUG) Log.d(TAG, "  openToReceiveCalls: " + getUri() + ": "
+            if (SSGE_DBG) log("openToReceiveCalls: " + getUri() + ": "
                     + mIncomingCallPendingIntent);
         }
 
         public void onConnectivityChanged(boolean connected)
                 throws SipException {
+            if (SSGE_DBG) {
+                log("onConnectivityChanged: connected=" + connected + " uri="
+                    + getUri() + ": " + mIncomingCallPendingIntent);
+            }
             mSipGroup.onConnectivityChanged();
             if (connected) {
                 mSipGroup.reset();
                 if (mOpenedToReceiveCalls) openToReceiveCalls();
             } else {
-                // close mSipGroup but remember mOpenedToReceiveCalls
-                if (DEBUG) Log.d(TAG, "  close auto reg temporarily: "
-                        + getUri() + ": " + mIncomingCallPendingIntent);
                 mSipGroup.close();
                 mAutoRegistration.stop();
             }
@@ -523,23 +534,23 @@
             mOpenedToReceiveCalls = false;
             mSipGroup.close();
             mAutoRegistration.stop();
-            if (DEBUG) Log.d(TAG, "   close: " + getUri() + ": "
-                    + mIncomingCallPendingIntent);
+            if (SSGE_DBG) log("close: " + getUri() + ": " + mIncomingCallPendingIntent);
         }
 
         public ISipSession createSession(ISipSessionListener listener) {
+            if (SSGE_DBG) log("createSession");
             return mSipGroup.createSession(listener);
         }
 
         @Override
         public void onRinging(ISipSession s, SipProfile caller,
                 String sessionDescription) {
-            if (DEBUG) Log.d(TAG, "<<<<< onRinging()");
             SipSessionGroup.SipSessionImpl session =
                     (SipSessionGroup.SipSessionImpl) s;
             synchronized (SipService.this) {
                 try {
                     if (!isRegistered() || callingSelf(this, session)) {
+                        if (SSGE_DBG) log("onRinging: end notReg or self");
                         session.endCall();
                         return;
                     }
@@ -548,13 +559,13 @@
                     addPendingSession(session);
                     Intent intent = SipManager.createIncomingCallBroadcast(
                             session.getCallId(), sessionDescription);
-                    if (DEBUG) Log.d(TAG, " ringing~~ " + getUri() + ": "
+                    if (SSGE_DBG) log("onRinging: uri=" + getUri() + ": "
                             + caller.getUri() + ": " + session.getCallId()
                             + " " + mIncomingCallPendingIntent);
                     mIncomingCallPendingIntent.send(mContext,
                             SipManager.INCOMING_CALL_RESULT_CODE, intent);
                 } catch (PendingIntent.CanceledException e) {
-                    Log.w(TAG, "pendingIntent is canceled, drop incoming call");
+                    loge("onRinging: pendingIntent is canceled, drop incoming call", e);
                     session.endCall();
                 }
             }
@@ -563,7 +574,7 @@
         @Override
         public void onError(ISipSession session, int errorCode,
                 String message) {
-            if (DEBUG) Log.d(TAG, "sip session error: "
+            if (SSGE_DBG) log("onError: errorCode=" + errorCode + " desc="
                     + SipErrorCode.toString(errorCode) + ": " + message);
         }
 
@@ -578,14 +589,23 @@
         private String getUri() {
             return mSipGroup.getLocalProfileUri();
         }
+
+        private void log(String s) {
+            Rlog.d(SSGE_TAG, s);
+        }
+
+        private void loge(String s, Throwable t) {
+            Rlog.e(SSGE_TAG, s, t);
+        }
+
     }
 
-    private class IntervalMeasurementProcess implements Runnable,
+    private class SipKeepAliveProcessCallback implements Runnable,
             SipSessionGroup.KeepAliveProcessCallback {
-        private static final String TAG = "SipKeepAliveInterval";
+        private static final String SKAI_TAG = "SipKeepAliveProcessCallback";
+        private static final boolean SKAI_DBG = true;
         private static final int MIN_INTERVAL = 5; // in seconds
         private static final int PASS_THRESHOLD = 10;
-        private static final int MAX_RETRY_COUNT = 5;
         private static final int NAT_MEASUREMENT_RETRY_INTERVAL = 120; // in seconds
         private SipProfile mLocalProfile;
         private SipSessionGroupExt mGroup;
@@ -595,7 +615,7 @@
         private int mInterval;
         private int mPassCount;
 
-        public IntervalMeasurementProcess(SipProfile localProfile,
+        public SipKeepAliveProcessCallback(SipProfile localProfile,
                 int minInterval, int maxInterval) {
             mMaxInterval = maxInterval;
             mMinInterval = minInterval;
@@ -613,13 +633,13 @@
 
                 // Don't start measurement if the interval is too small
                 if (mInterval < DEFAULT_KEEPALIVE_INTERVAL || checkTermination()) {
-                    Log.w(TAG, "measurement aborted; interval=[" +
+                    if (SKAI_DBG) log("start: measurement aborted; interval=[" +
                             mMinInterval + "," + mMaxInterval + "]");
                     return;
                 }
 
                 try {
-                    Log.d(TAG, "start measurement w interval=" + mInterval);
+                    if (SKAI_DBG) log("start: interval=" + mInterval);
 
                     mGroup = new SipSessionGroupExt(mLocalProfile, null, null);
                     // TODO: remove this line once SipWakeupTimer can better handle
@@ -646,6 +666,7 @@
                     mGroup = null;
                 }
                 mTimer.cancel(this);
+                if (SKAI_DBG) log("stop");
             }
         }
 
@@ -654,13 +675,13 @@
                 // Return immediately if the measurement process is stopped
                 if (mSession == null) return;
 
-                Log.d(TAG, "restart measurement w interval=" + mInterval);
+                if (SKAI_DBG) log("restart: interval=" + mInterval);
                 try {
                     mSession.stopKeepAliveProcess();
                     mPassCount = 0;
                     mSession.startKeepAliveProcess(mInterval, this);
                 } catch (SipException e) {
-                    Log.e(TAG, "restart()", e);
+                    loge("restart", e);
                 }
             }
         }
@@ -681,8 +702,8 @@
                         mLastGoodKeepAliveInterval = mKeepAliveInterval;
                     }
                     mKeepAliveInterval = mMinInterval = mInterval;
-                    if (DEBUG) {
-                        Log.d(TAG, "measured good keepalive interval: "
+                    if (SKAI_DBG) {
+                        log("onResponse: portChanged=" + portChanged + " mKeepAliveInterval="
                                 + mKeepAliveInterval);
                     }
                     onKeepAliveIntervalChanged();
@@ -698,16 +719,16 @@
                     // measurement with min interval=DEFAULT_KEEPALIVE_INTERVAL
                     // will be conducted.
                     mKeepAliveInterval = mMinInterval;
-                    if (DEBUG) {
-                        Log.d(TAG, "measured keepalive interval: "
+                    if (SKAI_DBG) {
+                        log("onResponse: checkTermination mKeepAliveInterval="
                                 + mKeepAliveInterval);
                     }
                 } else {
                     // calculate the new interval and continue.
                     mInterval = (mMaxInterval + mMinInterval) / 2;
-                    if (DEBUG) {
-                        Log.d(TAG, "current interval: " + mKeepAliveInterval
-                                + ", test new interval: " + mInterval);
+                    if (SKAI_DBG) {
+                        log("onResponse: mKeepAliveInterval=" + mKeepAliveInterval
+                                + ", new mInterval=" + mInterval);
                     }
                     restart();
                 }
@@ -717,7 +738,7 @@
         // SipSessionGroup.KeepAliveProcessCallback
         @Override
         public void onError(int errorCode, String description) {
-            Log.w(TAG, "interval measurement error: " + description);
+            if (SKAI_DBG) loge("onError: errorCode=" + errorCode + " desc=" + description);
             restartLater();
         }
 
@@ -735,12 +756,25 @@
                 mTimer.set(interval * 1000, this);
             }
         }
+
+        private void log(String s) {
+            Rlog.d(SKAI_TAG, s);
+        }
+
+        private void loge(String s) {
+            Rlog.d(SKAI_TAG, s);
+        }
+
+        private void loge(String s, Throwable t) {
+            Rlog.d(SKAI_TAG, s, t);
+        }
     }
 
-    private class AutoRegistrationProcess extends SipSessionAdapter
+    private class SipAutoReg extends SipSessionAdapter
             implements Runnable, SipSessionGroup.KeepAliveProcessCallback {
+        private String SAR_TAG;
+        private static final boolean SAR_DBG = true;
         private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10;
-        private String TAG = "SipAutoReg";
 
         private SipSessionGroup.SipSessionImpl mSession;
         private SipSessionGroup.SipSessionImpl mKeepAliveSession;
@@ -754,10 +788,6 @@
 
         private int mKeepAliveSuccessCount = 0;
 
-        private String getAction() {
-            return toString();
-        }
-
         public void start(SipSessionGroup group) {
             if (!mRunning) {
                 mRunning = true;
@@ -772,12 +802,13 @@
                 // in registration to avoid adding duplicate entries to server
                 mMyWakeLock.acquire(mSession);
                 mSession.unregister();
-                TAG = "SipAutoReg:" + mSession.getLocalProfile().getUriString();
+                SAR_TAG = "SipAutoReg:" + mSession.getLocalProfile().getUriString();
+                if (SAR_DBG) log("start: group=" + group);
             }
         }
 
         private void startKeepAliveProcess(int interval) {
-            if (DEBUG) Log.d(TAG, "start keepalive w interval=" + interval);
+            if (SAR_DBG) log("startKeepAliveProcess: interval=" + interval);
             if (mKeepAliveSession == null) {
                 mKeepAliveSession = mSession.duplicate();
             } else {
@@ -786,8 +817,7 @@
             try {
                 mKeepAliveSession.startKeepAliveProcess(interval, this);
             } catch (SipException e) {
-                Log.e(TAG, "failed to start keepalive w interval=" + interval,
-                        e);
+                loge("startKeepAliveProcess: interval=" + interval, e);
             }
         }
 
@@ -806,17 +836,19 @@
                 if (portChanged) {
                     int interval = getKeepAliveInterval();
                     if (mKeepAliveSuccessCount < MIN_KEEPALIVE_SUCCESS_COUNT) {
-                        Log.i(TAG, "keepalive doesn't work with interval "
-                                + interval + ", past success count="
-                                + mKeepAliveSuccessCount);
+                        if (SAR_DBG) {
+                            log("onResponse: keepalive doesn't work with interval "
+                                    + interval + ", past success count="
+                                    + mKeepAliveSuccessCount);
+                        }
                         if (interval > DEFAULT_KEEPALIVE_INTERVAL) {
                             restartPortMappingLifetimeMeasurement(
                                     mSession.getLocalProfile(), interval);
                             mKeepAliveSuccessCount = 0;
                         }
                     } else {
-                        if (DEBUG) {
-                            Log.i(TAG, "keep keepalive going with interval "
+                        if (SAR_DBG) {
+                            log("keep keepalive going with interval "
                                     + interval + ", past success count="
                                     + mKeepAliveSuccessCount);
                         }
@@ -847,8 +879,8 @@
         // SipSessionGroup.KeepAliveProcessCallback
         @Override
         public void onError(int errorCode, String description) {
-            if (DEBUG) {
-                Log.e(TAG, "keepalive error: " + description);
+            if (SAR_DBG) {
+                loge("onError: errorCode=" + errorCode + " desc=" + description);
             }
             onResponse(true); // re-register immediately
         }
@@ -872,8 +904,8 @@
         public void onKeepAliveIntervalChanged() {
             if (mKeepAliveSession != null) {
                 int newInterval = getKeepAliveInterval();
-                if (DEBUG) {
-                    Log.v(TAG, "restart keepalive w interval=" + newInterval);
+                if (SAR_DBG) {
+                    log("onKeepAliveIntervalChanged: interval=" + newInterval);
                 }
                 mKeepAliveSuccessCount = 0;
                 startKeepAliveProcess(newInterval);
@@ -916,7 +948,7 @@
                                 String.valueOf(state));
                     }
                 } catch (Throwable t) {
-                    Log.w(TAG, "setListener(): " + t);
+                    loge("setListener: ", t);
                 }
             }
         }
@@ -933,7 +965,7 @@
 
                 mErrorCode = SipErrorCode.NO_ERROR;
                 mErrorMessage = null;
-                if (DEBUG) Log.d(TAG, "registering");
+                if (SAR_DBG) log("run: registering");
                 if (mNetworkType != -1) {
                     mMyWakeLock.acquire(mSession);
                     mSession.register(EXPIRY_TIME);
@@ -942,7 +974,7 @@
         }
 
         private void restart(int duration) {
-            Log.d(TAG, "Refresh registration " + duration + "s later.");
+            if (SAR_DBG) log("restart: duration=" + duration + "s later.");
             mTimer.cancel(this);
             mTimer.set(duration * 1000, this);
         }
@@ -959,7 +991,7 @@
 
         @Override
         public void onRegistering(ISipSession session) {
-            if (DEBUG) Log.d(TAG, "onRegistering(): " + session);
+            if (SAR_DBG) log("onRegistering: " + session);
             synchronized (SipService.this) {
                 if (notCurrentSession(session)) return;
 
@@ -979,7 +1011,7 @@
 
         @Override
         public void onRegistrationDone(ISipSession session, int duration) {
-            if (DEBUG) Log.d(TAG, "onRegistrationDone(): " + session);
+            if (SAR_DBG) log("onRegistrationDone: " + session);
             synchronized (SipService.this) {
                 if (notCurrentSession(session)) return;
 
@@ -1008,7 +1040,7 @@
                 } else {
                     mRegistered = false;
                     mExpiryTime = -1L;
-                    if (DEBUG) Log.d(TAG, "Refresh registration immediately");
+                    if (SAR_DBG) log("Refresh registration immediately");
                     run();
                 }
             }
@@ -1017,7 +1049,7 @@
         @Override
         public void onRegistrationFailed(ISipSession session, int errorCode,
                 String message) {
-            if (DEBUG) Log.d(TAG, "onRegistrationFailed(): " + session + ": "
+            if (SAR_DBG) log("onRegistrationFailed: " + session + ": "
                     + SipErrorCode.toString(errorCode) + ": " + message);
             synchronized (SipService.this) {
                 if (notCurrentSession(session)) return;
@@ -1025,7 +1057,7 @@
                 switch (errorCode) {
                     case SipErrorCode.INVALID_CREDENTIALS:
                     case SipErrorCode.SERVER_UNREACHABLE:
-                        if (DEBUG) Log.d(TAG, "   pause auto-registration");
+                        if (SAR_DBG) log("   pause auto-registration");
                         stop();
                         break;
                     default:
@@ -1041,7 +1073,7 @@
 
         @Override
         public void onRegistrationTimeout(ISipSession session) {
-            if (DEBUG) Log.d(TAG, "onRegistrationTimeout(): " + session);
+            if (SAR_DBG) log("onRegistrationTimeout: " + session);
             synchronized (SipService.this) {
                 if (notCurrentSession(session)) return;
 
@@ -1053,9 +1085,22 @@
         }
 
         private void restartLater() {
+            if (SAR_DBG) loge("restartLater");
             mRegistered = false;
             restart(backoffDuration());
         }
+
+        private void log(String s) {
+            Rlog.d(SAR_TAG, s);
+        }
+
+        private void loge(String s) {
+            Rlog.e(SAR_TAG, s);
+        }
+
+        private void loge(String s, Throwable e) {
+            Rlog.e(SAR_TAG, s, e);
+        }
     }
 
     private class ConnectivityReceiver extends BroadcastReceiver {
@@ -1068,6 +1113,7 @@
 
                 // Run the handler in MyExecutor to be protected by wake lock
                 mExecutor.execute(new Runnable() {
+                    @Override
                     public void run() {
                         onConnectivityChanged(info);
                     }
@@ -1079,12 +1125,12 @@
     private void registerReceivers() {
         mContext.registerReceiver(mConnectivityReceiver,
                 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
-        if (DEBUG) Log.d(TAG, " +++ register receivers");
+        if (DBG) log("registerReceivers:");
     }
 
     private void unregisterReceivers() {
         mContext.unregisterReceiver(mConnectivityReceiver);
-        if (DEBUG) Log.d(TAG, " --- unregister receivers");
+        if (DBG) log("unregisterReceivers:");
 
         // Reset variables maintained by ConnectivityReceiver.
         mWifiLock.release();
@@ -1131,10 +1177,11 @@
 
         // Ignore the event if the current active network is not changed.
         if (mNetworkType == networkType) {
+            // TODO: Maybe we need to send seq/generation number
             return;
         }
-        if (DEBUG) {
-            Log.d(TAG, "onConnectivityChanged(): " + mNetworkType +
+        if (DBG) {
+            log("onConnectivityChanged: " + mNetworkType +
                     " -> " + networkType);
         }
 
@@ -1158,7 +1205,7 @@
             }
             updateWakeLocks();
         } catch (SipException e) {
-            Log.e(TAG, "onConnectivityChanged()", e);
+            loge("onConnectivityChanged()", e);
         }
     }
 
@@ -1186,7 +1233,7 @@
             if (msg.obj instanceof Runnable) {
                 executeInternal((Runnable) msg.obj);
             } else {
-                Log.w(TAG, "can't handle msg: " + msg);
+                if (DBG) log("handleMessage: not Runnable ignore msg=" + msg);
             }
         }
 
@@ -1194,10 +1241,22 @@
             try {
                 task.run();
             } catch (Throwable t) {
-                Log.e(TAG, "run task: " + task, t);
+                loge("run task: " + task, t);
             } finally {
                 mMyWakeLock.release(task);
             }
         }
     }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private static void slog(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private void loge(String s, Throwable e) {
+        Rlog.e(TAG, s, e);
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 6acd456..e820f35 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -35,7 +35,7 @@
 import android.net.sip.SipSession;
 import android.net.sip.SipSessionAdapter;
 import android.text.TextUtils;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
@@ -43,7 +43,6 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.text.ParseException;
-import java.util.Collection;
 import java.util.EventObject;
 import java.util.HashMap;
 import java.util.Map;
@@ -53,7 +52,6 @@
 import javax.sip.Dialog;
 import javax.sip.DialogTerminatedEvent;
 import javax.sip.IOExceptionEvent;
-import javax.sip.ListeningPoint;
 import javax.sip.ObjectInUseException;
 import javax.sip.RequestEvent;
 import javax.sip.ResponseEvent;
@@ -65,9 +63,7 @@
 import javax.sip.SipStack;
 import javax.sip.TimeoutEvent;
 import javax.sip.Transaction;
-import javax.sip.TransactionState;
 import javax.sip.TransactionTerminatedEvent;
-import javax.sip.TransactionUnavailableException;
 import javax.sip.address.Address;
 import javax.sip.address.SipURI;
 import javax.sip.header.CSeqHeader;
@@ -88,8 +84,8 @@
  */
 class SipSessionGroup implements SipListener {
     private static final String TAG = "SipSession";
-    private static final boolean DEBUG = false;
-    private static final boolean DEBUG_PING = false;
+    private static final boolean DBG = false;
+    private static final boolean DBG_PING = false;
     private static final String ANONYMOUS = "anonymous";
     // Limit the size of thread pool to 1 for the order issue when the phone is
     // waken up from sleep and there are many packets to be processed in the SIP
@@ -105,9 +101,6 @@
 
     private static final EventObject DEREGISTER = new EventObject("Deregister");
     private static final EventObject END_CALL = new EventObject("End call");
-    private static final EventObject HOLD_CALL = new EventObject("Hold call");
-    private static final EventObject CONTINUE_CALL
-            = new EventObject("Continue call");
 
     private final SipProfile mLocalProfile;
     private final String mPassword;
@@ -133,7 +126,7 @@
     /**
      * @param profile the local profile with password crossed out
      * @param password the password of the profile
-     * @throws IOException if cannot assign requested address
+     * @throws SipException if cannot assign requested address
      */
     public SipSessionGroup(SipProfile profile, String password,
             SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException {
@@ -206,7 +199,7 @@
             throw new SipException("failed to initialize SIP stack", e);
         }
 
-        Log.d(TAG, " start stack for " + mLocalProfile.getUriString());
+        if (DBG) log("reset: start stack for " + mLocalProfile.getUriString());
         mSipStack.start();
     }
 
@@ -224,8 +217,8 @@
     }
 
     synchronized void resetExternalAddress() {
-        if (DEBUG) {
-            Log.d(TAG, " reset external addr on " + mSipStack);
+        if (DBG) {
+            log("resetExternalAddress: " + mSipStack);
         }
         mExternalIp = null;
         mExternalPort = 0;
@@ -244,7 +237,7 @@
     }
 
     public synchronized void close() {
-        Log.d(TAG, " close stack for " + mLocalProfile.getUriString());
+        if (DBG) log("close: " + mLocalProfile.getUriString());
         onConnectivityChanged();
         mSessionMap.clear();
         closeToNotReceiveCalls();
@@ -285,10 +278,10 @@
         String key = SipHelper.getCallId(event);
         SipSessionImpl session = mSessionMap.get(key);
         if ((session != null) && isLoggable(session)) {
-            Log.d(TAG, "session key from event: " + key);
-            Log.d(TAG, "active sessions:");
+            if (DBG) log("getSipSession: event=" + key);
+            if (DBG) log("getSipSession: active sessions:");
             for (String k : mSessionMap.keySet()) {
-                Log.d(TAG, " ..." + k + ": " + mSessionMap.get(k));
+                if (DBG) log("getSipSession: ..." + k + ": " + mSessionMap.get(k));
             }
         }
         return ((session != null) ? session : mCallReceiverSession);
@@ -299,9 +292,9 @@
         String key = newSession.getCallId();
         mSessionMap.put(key, newSession);
         if (isLoggable(newSession)) {
-            Log.d(TAG, "+++  add a session with key:  '" + key + "'");
+            if (DBG) log("addSipSession: key='" + key + "'");
             for (String k : mSessionMap.keySet()) {
-                Log.d(TAG, "  " + k + ": " + mSessionMap.get(k));
+                if (DBG) log("addSipSession:  " + k + ": " + mSessionMap.get(k));
             }
         }
     }
@@ -312,7 +305,7 @@
         SipSessionImpl s = mSessionMap.remove(key);
         // sanity check
         if ((s != null) && (s != session)) {
-            Log.w(TAG, "session " + session + " is not associated with key '"
+            if (DBG) log("removeSession: " + session + " is not associated with key '"
                     + key + "'");
             mSessionMap.put(key, s);
             for (Map.Entry<String, SipSessionImpl> entry
@@ -325,16 +318,17 @@
         }
 
         if ((s != null) && isLoggable(s)) {
-            Log.d(TAG, "remove session " + session + " @key '" + key + "'");
+            if (DBG) log("removeSession: " + session + " @key '" + key + "'");
             for (String k : mSessionMap.keySet()) {
-                Log.d(TAG, "  " + k + ": " + mSessionMap.get(k));
+                if (DBG) log("removeSession:  " + k + ": " + mSessionMap.get(k));
             }
         }
     }
 
+    @Override
     public void processRequest(final RequestEvent event) {
         if (isRequestEvent(Request.INVITE, event)) {
-            if (DEBUG) Log.d(TAG, "<<<<< got INVITE, thread:"
+            if (DBG) log("processRequest: mWakeLock.acquire got INVITE, thread:"
                     + Thread.currentThread());
             // Acquire a wake lock and keep it for WAKE_LOCK_HOLDING_TIME;
             // should be large enough to bring up the app.
@@ -343,22 +337,27 @@
         process(event);
     }
 
+    @Override
     public void processResponse(ResponseEvent event) {
         process(event);
     }
 
+    @Override
     public void processIOException(IOExceptionEvent event) {
         process(event);
     }
 
+    @Override
     public void processTimeout(TimeoutEvent event) {
         process(event);
     }
 
+    @Override
     public void processTransactionTerminated(TransactionTerminatedEvent event) {
         process(event);
     }
 
+    @Override
     public void processDialogTerminated(DialogTerminatedEvent event) {
         process(event);
     }
@@ -369,11 +368,11 @@
             boolean isLoggable = isLoggable(session, event);
             boolean processed = (session != null) && session.process(event);
             if (isLoggable && processed) {
-                Log.d(TAG, "new state after: "
+                log("process: event new state after: "
                         + SipSession.State.toString(session.mState));
             }
         } catch (Throwable e) {
-            Log.w(TAG, "event process error: " + event, getRootCause(e));
+            loge("process: error event=" + event, getRootCause(e));
             session.onError(e);
         }
     }
@@ -404,8 +403,8 @@
         if ((rport > 0) && (externalIp != null)) {
             mExternalIp = externalIp;
             mExternalPort = rport;
-            if (DEBUG) {
-                Log.d(TAG, " got external addr " + externalIp + ":" + rport
+            if (DBG) {
+                log("extractExternalAddress: external addr " + externalIp + ":" + rport
                         + " on " + mSipStack);
             }
         }
@@ -436,6 +435,9 @@
     }
 
     private class SipSessionCallReceiverImpl extends SipSessionImpl {
+        private static final String SSCRI_TAG = "SipSessionCallReceiverImpl";
+        private static final boolean SSCRI_DBG = true;
+
         public SipSessionCallReceiverImpl(ISipSessionListener listener) {
             super(listener);
         }
@@ -473,8 +475,8 @@
             SipSessionImpl newSession = null;
             if (replaces != null) {
                 int response = processInviteWithReplaces(event, replaces);
-                if (DEBUG) {
-                    Log.v(TAG, "ReplacesHeader: " + replaces
+                if (SSCRI_DBG) {
+                    log("processNewInviteRequest: " + replaces
                             + " response=" + response);
                 }
                 if (response == Response.OK) {
@@ -501,10 +503,11 @@
             if (newSession != null) addSipSession(newSession);
         }
 
+        @Override
         public boolean process(EventObject evt) throws SipException {
-            if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~   " + this + ": "
+            if (isLoggable(this, evt)) log("process: " + this + ": "
                     + SipSession.State.toString(mState) + ": processing "
-                    + log(evt));
+                    + logEvt(evt));
             if (isRequestEvent(Request.INVITE, evt)) {
                 processNewInviteRequest((RequestEvent) evt);
                 return true;
@@ -515,6 +518,10 @@
                 return false;
             }
         }
+
+        private void log(String s) {
+            Rlog.d(SSCRI_TAG, s);
+        }
     }
 
     static interface KeepAliveProcessCallback {
@@ -524,6 +531,9 @@
     }
 
     class SipSessionImpl extends ISipSession.Stub {
+        private static final String SSI_TAG = "SipSessionImpl";
+        private static final boolean SSI_DBG = true;
+
         SipProfile mPeerProfile;
         SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
         int mState = SipSession.State.READY_TO_CALL;
@@ -536,9 +546,9 @@
         SessionTimer mSessionTimer;
         int mAuthenticationRetryCount;
 
-        private KeepAliveProcess mKeepAliveProcess;
+        private SipKeepAlive mSipKeepAlive;
 
-        private SipSessionImpl mKeepAliveSession;
+        private SipSessionImpl mSipSessionImpl;
 
         // the following three members are used for handling refer request.
         SipSessionImpl mReferSession;
@@ -551,6 +561,7 @@
 
             void start(final int timeout) {
                 new Thread(new Runnable() {
+                    @Override
                     public void run() {
                         sleep(timeout);
                         if (mRunning) timeout();
@@ -573,7 +584,7 @@
                 try {
                     this.wait(timeout * 1000);
                 } catch (InterruptedException e) {
-                    Log.e(TAG, "session timer interrupted!");
+                    loge("session timer interrupted!", e);
                 }
             }
         }
@@ -617,28 +628,33 @@
 
             cancelSessionTimer();
 
-            if (mKeepAliveSession != null) {
-                mKeepAliveSession.stopKeepAliveProcess();
-                mKeepAliveSession = null;
+            if (mSipSessionImpl != null) {
+                mSipSessionImpl.stopKeepAliveProcess();
+                mSipSessionImpl = null;
             }
         }
 
+        @Override
         public boolean isInCall() {
             return mInCall;
         }
 
+        @Override
         public String getLocalIp() {
             return mLocalIp;
         }
 
+        @Override
         public SipProfile getLocalProfile() {
             return mLocalProfile;
         }
 
+        @Override
         public SipProfile getPeerProfile() {
             return mPeerProfile;
         }
 
+        @Override
         public String getCallId() {
             return SipHelper.getCallId(getTransaction());
         }
@@ -649,10 +665,12 @@
             return null;
         }
 
+        @Override
         public int getState() {
             return mState;
         }
 
+        @Override
         public void setListener(ISipSessionListener listener) {
             mProxy.setListener((listener instanceof SipSessionListenerProxy)
                     ? ((SipSessionListenerProxy) listener).getListener()
@@ -662,11 +680,12 @@
         // process the command in a new thread
         private void doCommandAsync(final EventObject command) {
             new Thread(new Runnable() {
+                    @Override
                     public void run() {
                         try {
                             processCommand(command);
                         } catch (Throwable e) {
-                            Log.w(TAG, "command error: " + command + ": "
+                            loge("command error: " + command + ": "
                                     + mLocalProfile.getUriString(),
                                     getRootCause(e));
                             onError(e);
@@ -675,12 +694,14 @@
             }, "SipSessionAsyncCmdThread").start();
         }
 
+        @Override
         public void makeCall(SipProfile peerProfile, String sessionDescription,
                 int timeout) {
             doCommandAsync(new MakeCallCommand(peerProfile, sessionDescription,
                     timeout));
         }
 
+        @Override
         public void answerCall(String sessionDescription, int timeout) {
             synchronized (SipSessionGroup.this) {
                 if (mPeerProfile == null) return;
@@ -689,10 +710,12 @@
             }
         }
 
+        @Override
         public void endCall() {
             doCommandAsync(END_CALL);
         }
 
+        @Override
         public void changeCall(String sessionDescription, int timeout) {
             synchronized (SipSessionGroup.this) {
                 if (mPeerProfile == null) return;
@@ -701,16 +724,18 @@
             }
         }
 
+        @Override
         public void register(int duration) {
             doCommandAsync(new RegisterCommand(duration));
         }
 
+        @Override
         public void unregister() {
             doCommandAsync(DEREGISTER);
         }
 
         private void processCommand(EventObject command) throws SipException {
-            if (isLoggable(command)) Log.d(TAG, "process cmd: " + command);
+            if (isLoggable(command)) log("process cmd: " + command);
             if (!process(command)) {
                 onError(SipErrorCode.IN_PROGRESS,
                         "cannot initiate a new transaction to execute: "
@@ -723,6 +748,7 @@
             return String.valueOf((long) (Math.random() * 0x100000000L));
         }
 
+        @Override
         public String toString() {
             try {
                 String s = super.toString();
@@ -734,15 +760,15 @@
         }
 
         public boolean process(EventObject evt) throws SipException {
-            if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~   " + this + ": "
+            if (isLoggable(this, evt)) log(" ~~~~~   " + this + ": "
                     + SipSession.State.toString(mState) + ": processing "
-                    + log(evt));
+                    + logEvt(evt));
             synchronized (SipSessionGroup.this) {
                 if (isClosed()) return false;
 
-                if (mKeepAliveProcess != null) {
+                if (mSipKeepAlive != null) {
                     // event consumed by keepalive process
-                    if (mKeepAliveProcess.process(evt)) return true;
+                    if (mSipKeepAlive.process(evt)) return true;
                 }
 
                 Dialog dialog = null;
@@ -824,7 +850,7 @@
             if (mDialog == event.getDialog()) {
                 onError(new SipException("dialog terminated"));
             } else {
-                Log.d(TAG, "not the current dialog; current=" + mDialog
+                if (SSI_DBG) log("not the current dialog; current=" + mDialog
                         + ", terminated=" + event.getDialog());
             }
         }
@@ -838,11 +864,11 @@
                     : event.getClientTransaction();
 
             if ((current != target) && (mState != SipSession.State.PINGING)) {
-                Log.d(TAG, "not the current transaction; current="
+                if (SSI_DBG) log("not the current transaction; current="
                         + toString(current) + ", target=" + toString(target));
                 return false;
             } else if (current != null) {
-                Log.d(TAG, "transaction terminated: " + toString(current));
+                if (SSI_DBG) log("transaction terminated: " + toString(current));
                 return true;
             } else {
                 // no transaction; shouldn't be here; ignored
@@ -865,17 +891,17 @@
             switch (mState) {
                 case SipSession.State.IN_CALL:
                 case SipSession.State.READY_TO_CALL:
-                    Log.d(TAG, "Transaction terminated; do nothing");
+                    if (SSI_DBG) log("Transaction terminated; do nothing");
                     break;
                 default:
-                    Log.d(TAG, "Transaction terminated early: " + this);
+                    if (SSI_DBG) log("Transaction terminated early: " + this);
                     onError(SipErrorCode.TRANSACTION_TERMINTED,
                             "transaction terminated");
             }
         }
 
         private void processTimeout(TimeoutEvent event) {
-            Log.d(TAG, "processing Timeout...");
+            if (SSI_DBG) log("processing Timeout...");
             switch (mState) {
                 case SipSession.State.REGISTERING:
                 case SipSession.State.DEREGISTERING:
@@ -890,7 +916,7 @@
                     break;
 
                 default:
-                    Log.d(TAG, "   do nothing");
+                    if (SSI_DBG) log("   do nothing");
                     break;
             }
         }
@@ -912,8 +938,8 @@
             if (expires != null && time < expires.getExpires()) {
                 time = expires.getExpires();
             }
-            if (DEBUG) {
-                Log.v(TAG, "Expiry time = " + time);
+            if (SSI_DBG) {
+                log("Expiry time = " + time);
             }
             return time;
         }
@@ -960,7 +986,7 @@
                 mDialog = mClientTransaction.getDialog();
                 mAuthenticationRetryCount++;
                 if (isLoggable(this, event)) {
-                    Log.d(TAG, "   authentication retry count="
+                    if (SSI_DBG) log("   authentication retry count="
                             + mAuthenticationRetryCount);
                 }
                 return true;
@@ -984,19 +1010,23 @@
 
         private AccountManager getAccountManager() {
             return new AccountManager() {
+                @Override
                 public UserCredentials getCredentials(ClientTransaction
                         challengedTransaction, String realm) {
                     return new UserCredentials() {
+                        @Override
                         public String getUserName() {
                             String username = mLocalProfile.getAuthUserName();
                             return (!TextUtils.isEmpty(username) ? username :
                                     mLocalProfile.getUserName());
                         }
 
+                        @Override
                         public String getPassword() {
                             return mPassword;
                         }
 
+                        @Override
                         public String getSipDomain() {
                             return mLocalProfile.getSipDomain();
                         }
@@ -1097,8 +1127,7 @@
             return false;
         }
 
-        private boolean incomingCallToInCall(EventObject evt)
-                throws SipException {
+        private boolean incomingCallToInCall(EventObject evt) {
             // expect ACK, CANCEL request
             if (isRequestEvent(Request.ACK, evt)) {
                 String sdp = extractContent(((RequestEvent) evt).getRequest());
@@ -1154,8 +1183,7 @@
                     }
                     return true;
                 case Response.REQUEST_PENDING:
-                    // TODO:
-                    // rfc3261#section-14.1; re-schedule invite
+                    // TODO: rfc3261#section-14.1; re-schedule invite
                     return true;
                 default:
                     if (mReferSession != null) {
@@ -1342,17 +1370,17 @@
         }
 
         private void enableKeepAlive() {
-            if (mKeepAliveSession != null) {
-                mKeepAliveSession.stopKeepAliveProcess();
+            if (mSipSessionImpl != null) {
+                mSipSessionImpl.stopKeepAliveProcess();
             } else {
-                mKeepAliveSession = duplicate();
+                mSipSessionImpl = duplicate();
             }
             try {
-                mKeepAliveSession.startKeepAliveProcess(
+                mSipSessionImpl.startKeepAliveProcess(
                         INCALL_KEEPALIVE_INTERVAL, mPeerProfile, null);
             } catch (SipException e) {
-                Log.w(TAG, "keepalive cannot be enabled; ignored", e);
-                mKeepAliveSession.stopKeepAliveProcess();
+                loge("keepalive cannot be enabled; ignored", e);
+                mSipSessionImpl.stopKeepAliveProcess();
             }
         }
 
@@ -1454,12 +1482,6 @@
             mProxy.onRegistrationFailed(this, errorCode, message);
         }
 
-        private void onRegistrationFailed(Throwable exception) {
-            exception = getRootCause(exception);
-            onRegistrationFailed(getErrorCode(exception),
-                    exception.toString());
-        }
-
         private void onRegistrationFailed(Response response) {
             int statusCode = response.getStatusCode();
             onRegistrationFailed(getErrorCode(statusCode),
@@ -1480,28 +1502,30 @@
         public void startKeepAliveProcess(int interval, SipProfile peerProfile,
                 KeepAliveProcessCallback callback) throws SipException {
             synchronized (SipSessionGroup.this) {
-                if (mKeepAliveProcess != null) {
+                if (mSipKeepAlive != null) {
                     throw new SipException("Cannot create more than one "
                             + "keepalive process in a SipSession");
                 }
                 mPeerProfile = peerProfile;
-                mKeepAliveProcess = new KeepAliveProcess();
-                mProxy.setListener(mKeepAliveProcess);
-                mKeepAliveProcess.start(interval, callback);
+                mSipKeepAlive = new SipKeepAlive();
+                mProxy.setListener(mSipKeepAlive);
+                mSipKeepAlive.start(interval, callback);
             }
         }
 
         public void stopKeepAliveProcess() {
             synchronized (SipSessionGroup.this) {
-                if (mKeepAliveProcess != null) {
-                    mKeepAliveProcess.stop();
-                    mKeepAliveProcess = null;
+                if (mSipKeepAlive != null) {
+                    mSipKeepAlive.stop();
+                    mSipKeepAlive = null;
                 }
             }
         }
 
-        class KeepAliveProcess extends SipSessionAdapter implements Runnable {
-            private static final String TAG = "SipKeepAlive";
+        class SipKeepAlive extends SipSessionAdapter implements Runnable {
+            private static final String SKA_TAG = "SipKeepAlive";
+            private static final boolean SKA_DBG = true;
+
             private boolean mRunning = false;
             private KeepAliveProcessCallback mCallback;
 
@@ -1516,8 +1540,8 @@
                 mInterval = interval;
                 mCallback = new KeepAliveProcessCallbackProxy(callback);
                 mWakeupTimer.set(interval * 1000, this);
-                if (DEBUG) {
-                    Log.d(TAG, "start keepalive:"
+                if (SKA_DBG) {
+                    log("start keepalive:"
                             + mLocalProfile.getUriString());
                 }
 
@@ -1526,7 +1550,7 @@
             }
 
             // return true if the event is consumed
-            boolean process(EventObject evt) throws SipException {
+            boolean process(EventObject evt) {
                 if (mRunning && (mState == SipSession.State.PINGING)) {
                     if (evt instanceof ResponseEvent) {
                         if (parseOptionsResult(evt)) {
@@ -1560,18 +1584,18 @@
                 synchronized (SipSessionGroup.this) {
                     if (!mRunning) return;
 
-                    if (DEBUG_PING) {
+                    if (DBG_PING) {
                         String peerUri = (mPeerProfile == null)
                                 ? "null"
                                 : mPeerProfile.getUriString();
-                        Log.d(TAG, "keepalive: " + mLocalProfile.getUriString()
+                        log("keepalive: " + mLocalProfile.getUriString()
                                 + " --> " + peerUri + ", interval=" + mInterval);
                     }
                     try {
                         sendKeepAlive();
                     } catch (Throwable t) {
-                        if (DEBUG) {
-                            Log.w(TAG, "keepalive error: "
+                        if (SKA_DBG) {
+                            loge("keepalive error: "
                                     + mLocalProfile.getUriString(), getRootCause(t));
                         }
                         // It's possible that the keepalive process is being stopped
@@ -1584,8 +1608,8 @@
 
             void stop() {
                 synchronized (SipSessionGroup.this) {
-                    if (DEBUG) {
-                        Log.d(TAG, "stop keepalive:" + mLocalProfile.getUriString()
+                    if (SKA_DBG) {
+                        log("stop keepalive:" + mLocalProfile.getUriString()
                                 + ",RPort=" + mRPort);
                     }
                     mRunning = false;
@@ -1594,7 +1618,7 @@
                 }
             }
 
-            private void sendKeepAlive() throws SipException, InterruptedException {
+            private void sendKeepAlive() throws SipException {
                 synchronized (SipSessionGroup.this) {
                     mState = SipSession.State.PINGING;
                     mClientTransaction = mSipHelper.sendOptions(
@@ -1615,14 +1639,14 @@
                         if (mRPort == 0) mRPort = rPort;
                         if (mRPort != rPort) {
                             mPortChanged = true;
-                            if (DEBUG) Log.d(TAG, String.format(
+                            if (SKA_DBG) log(String.format(
                                     "rport is changed: %d <> %d", mRPort, rPort));
                             mRPort = rPort;
                         } else {
-                            if (DEBUG) Log.d(TAG, "rport is the same: " + rPort);
+                            if (SKA_DBG) log("rport is the same: " + rPort);
                         }
                     } else {
-                        if (DEBUG) Log.w(TAG, "peer did not respond rport");
+                        if (SKA_DBG) log("peer did not respond rport");
                     }
                     return true;
                 }
@@ -1634,6 +1658,14 @@
                         SIPHeaderNames.VIA));
                 return (viaHeader == null) ? -1 : viaHeader.getRPort();
             }
+
+            private void log(String s) {
+                Rlog.d(SKA_TAG, s);
+            }
+        }
+
+        private void log(String s) {
+            Rlog.d(SSI_TAG, s);
         }
     }
 
@@ -1670,22 +1702,6 @@
         return false;
     }
 
-    /**
-     * @return true if the event is a response event and the response code and
-     *      CSeqHeader method match the given arguments; false otherwise
-     */
-    private static boolean expectResponse(
-            int responseCode, String expectedMethod, EventObject evt) {
-        if (evt instanceof ResponseEvent) {
-            ResponseEvent event = (ResponseEvent) evt;
-            Response response = event.getResponse();
-            if (response.getStatusCode() == responseCode) {
-                return expectedMethod.equalsIgnoreCase(getCseqMethod(response));
-            }
-        }
-        return false;
-    }
-
     private static SipProfile createPeerProfile(HeaderAddress header)
             throws SipException {
         try {
@@ -1710,10 +1726,10 @@
         if (s != null) {
             switch (s.mState) {
                 case SipSession.State.PINGING:
-                    return DEBUG_PING;
+                    return DBG_PING;
             }
         }
-        return DEBUG;
+        return DBG;
     }
 
     private static boolean isLoggable(EventObject evt) {
@@ -1727,19 +1743,19 @@
         if (evt instanceof ResponseEvent) {
             Response response = ((ResponseEvent) evt).getResponse();
             if (Request.OPTIONS.equals(response.getHeader(CSeqHeader.NAME))) {
-                return DEBUG_PING;
+                return DBG_PING;
             }
-            return DEBUG;
+            return DBG;
         } else if (evt instanceof RequestEvent) {
             if (isRequestEvent(Request.OPTIONS, evt)) {
-                return DEBUG_PING;
+                return DBG_PING;
             }
-            return DEBUG;
+            return DBG;
         }
         return false;
     }
 
-    private static String log(EventObject evt) {
+    private static String logEvt(EventObject evt) {
         if (evt instanceof RequestEvent) {
             return ((RequestEvent) evt).getRequest().toString();
         } else if (evt instanceof ResponseEvent) {
@@ -1767,11 +1783,6 @@
         private int mTimeout; // in seconds
 
         public MakeCallCommand(SipProfile peerProfile,
-                String sessionDescription) {
-            this(peerProfile, sessionDescription, -1);
-        }
-
-        public MakeCallCommand(SipProfile peerProfile,
                 String sessionDescription, int timeout) {
             super(peerProfile);
             mSessionDescription = sessionDescription;
@@ -1793,6 +1804,7 @@
 
     /** Class to help safely run KeepAliveProcessCallback in a different thread. */
     static class KeepAliveProcessCallbackProxy implements KeepAliveProcessCallback {
+        private static final String KAPCP_TAG = "KeepAliveProcessCallbackProxy";
         private KeepAliveProcessCallback mCallback;
 
         KeepAliveProcessCallbackProxy(KeepAliveProcessCallback callback) {
@@ -1806,30 +1818,46 @@
             new Thread(runnable, "SIP-KeepAliveProcessCallbackThread").start();
         }
 
+        @Override
         public void onResponse(final boolean portChanged) {
             if (mCallback == null) return;
             proxy(new Runnable() {
+                @Override
                 public void run() {
                     try {
                         mCallback.onResponse(portChanged);
                     } catch (Throwable t) {
-                        Log.w(TAG, "onResponse", t);
+                        loge("onResponse", t);
                     }
                 }
             });
         }
 
+        @Override
         public void onError(final int errorCode, final String description) {
             if (mCallback == null) return;
             proxy(new Runnable() {
+                @Override
                 public void run() {
                     try {
                         mCallback.onError(errorCode, description);
                     } catch (Throwable t) {
-                        Log.w(TAG, "onError", t);
+                        loge("onError", t);
                     }
                 }
             });
         }
+
+        private void loge(String s, Throwable t) {
+            Rlog.e(KAPCP_TAG, s, t);
+        }
+    }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private void loge(String s, Throwable t) {
+        Rlog.e(TAG, s, t);
     }
 }
diff --git a/voip/java/com/android/server/sip/SipSessionListenerProxy.java b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
index 8655a3a..7a4ae8d 100644
--- a/voip/java/com/android/server/sip/SipSessionListenerProxy.java
+++ b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
@@ -20,11 +20,11 @@
 import android.net.sip.ISipSessionListener;
 import android.net.sip.SipProfile;
 import android.os.DeadObjectException;
-import android.util.Log;
+import android.telephony.Rlog;
 
 /** Class to help safely run a callback in a different thread. */
 class SipSessionListenerProxy extends ISipSessionListener.Stub {
-    private static final String TAG = "SipSession";
+    private static final String TAG = "SipSessionListnerProxy";
 
     private ISipSessionListener mListener;
 
@@ -43,9 +43,11 @@
         new Thread(runnable, "SipSessionCallbackThread").start();
     }
 
+    @Override
     public void onCalling(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCalling(session);
@@ -56,10 +58,12 @@
         });
     }
 
+    @Override
     public void onRinging(final ISipSession session, final SipProfile caller,
             final String sessionDescription) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRinging(session, caller, sessionDescription);
@@ -70,9 +74,11 @@
         });
     }
 
+    @Override
     public void onRingingBack(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRingingBack(session);
@@ -83,10 +89,12 @@
         });
     }
 
+    @Override
     public void onCallEstablished(final ISipSession session,
             final String sessionDescription) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallEstablished(session, sessionDescription);
@@ -97,9 +105,11 @@
         });
     }
 
+    @Override
     public void onCallEnded(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallEnded(session);
@@ -110,10 +120,12 @@
         });
     }
 
+    @Override
     public void onCallTransferring(final ISipSession newSession,
             final String sessionDescription) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallTransferring(newSession, sessionDescription);
@@ -124,9 +136,11 @@
         });
     }
 
+    @Override
     public void onCallBusy(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallBusy(session);
@@ -137,10 +151,12 @@
         });
     }
 
+    @Override
     public void onCallChangeFailed(final ISipSession session,
             final int errorCode, final String message) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onCallChangeFailed(session, errorCode, message);
@@ -151,10 +167,12 @@
         });
     }
 
+    @Override
     public void onError(final ISipSession session, final int errorCode,
             final String message) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onError(session, errorCode, message);
@@ -165,9 +183,11 @@
         });
     }
 
+    @Override
     public void onRegistering(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRegistering(session);
@@ -178,10 +198,12 @@
         });
     }
 
+    @Override
     public void onRegistrationDone(final ISipSession session,
             final int duration) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRegistrationDone(session, duration);
@@ -192,10 +214,12 @@
         });
     }
 
+    @Override
     public void onRegistrationFailed(final ISipSession session,
             final int errorCode, final String message) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRegistrationFailed(session, errorCode, message);
@@ -206,9 +230,11 @@
         });
     }
 
+    @Override
     public void onRegistrationTimeout(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
+            @Override
             public void run() {
                 try {
                     mListener.onRegistrationTimeout(session);
@@ -225,7 +251,15 @@
             // This creates race but it's harmless. Just don't log the error
             // when it happens.
         } else if (mListener != null) {
-            Log.w(TAG, message, t);
+            loge(message, t);
         }
     }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private void loge(String s, Throwable t) {
+        Rlog.e(TAG, s, t);
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipWakeLock.java b/voip/java/com/android/server/sip/SipWakeLock.java
index 0c4d14c..b3fbb56 100644
--- a/voip/java/com/android/server/sip/SipWakeLock.java
+++ b/voip/java/com/android/server/sip/SipWakeLock.java
@@ -17,13 +17,13 @@
 package com.android.server.sip;
 
 import android.os.PowerManager;
-import android.util.Log;
+import android.telephony.Rlog;
 
 import java.util.HashSet;
 
 class SipWakeLock {
-    private static final boolean DEBUG = false;
     private static final String TAG = "SipWakeLock";
+    private static final boolean DBG = false;
     private PowerManager mPowerManager;
     private PowerManager.WakeLock mWakeLock;
     private PowerManager.WakeLock mTimerWakeLock;
@@ -34,7 +34,7 @@
     }
 
     synchronized void reset() {
-        if (DEBUG) Log.v(TAG, "reset count=" + mHolders.size());
+        if (DBG) log("reset count=" + mHolders.size());
         mHolders.clear();
         release(null);
     }
@@ -55,7 +55,7 @@
                     PowerManager.PARTIAL_WAKE_LOCK, "SipWakeLock");
         }
         if (!mWakeLock.isHeld()) mWakeLock.acquire();
-        if (DEBUG) Log.v(TAG, "acquire count=" + mHolders.size());
+        if (DBG) log("acquire count=" + mHolders.size());
     }
 
     synchronized void release(Object holder) {
@@ -64,6 +64,10 @@
                 && mWakeLock.isHeld()) {
             mWakeLock.release();
         }
-        if (DEBUG) Log.v(TAG, "release count=" + mHolders.size());
+        if (DBG) log("release count=" + mHolders.size());
+    }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
     }
 }
diff --git a/voip/java/com/android/server/sip/SipWakeupTimer.java b/voip/java/com/android/server/sip/SipWakeupTimer.java
index 00d47ac..3ba43312 100644
--- a/voip/java/com/android/server/sip/SipWakeupTimer.java
+++ b/voip/java/com/android/server/sip/SipWakeupTimer.java
@@ -23,31 +23,20 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.SystemClock;
-import android.util.Log;
+import android.telephony.Rlog;
 
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
 import java.util.TreeSet;
 import java.util.concurrent.Executor;
-import javax.sip.SipException;
 
 /**
  * Timer that can schedule events to occur even when the device is in sleep.
  */
 class SipWakeupTimer extends BroadcastReceiver {
-    private static final String TAG = "_SIP.WkTimer_";
+    private static final String TAG = "SipWakeupTimer";
+    private static final boolean DBG = SipService.DBG && true; // STOPSHIP if true
     private static final String TRIGGER_TIME = "TriggerTime";
-    private static final boolean DEBUG_TIMER = SipService.DEBUG && false;
 
     private Context mContext;
     private AlarmManager mAlarmManager;
@@ -85,7 +74,7 @@
 
     private boolean stopped() {
         if (mEventQueue == null) {
-            Log.w(TAG, "Timer stopped");
+            if (DBG) log("Timer stopped");
             return true;
         } else {
             return false;
@@ -112,11 +101,11 @@
         }
         TreeSet<MyEvent> newQueue = new TreeSet<MyEvent>(
                 mEventQueue.comparator());
-        newQueue.addAll((Collection<MyEvent>) mEventQueue);
+        newQueue.addAll(mEventQueue);
         mEventQueue.clear();
         mEventQueue = newQueue;
-        if (DEBUG_TIMER) {
-            Log.d(TAG, "queue re-calculated");
+        if (DBG) {
+            log("queue re-calculated");
             printQueue();
         }
     }
@@ -172,8 +161,8 @@
         }
 
         long triggerTime = event.mTriggerTime;
-        if (DEBUG_TIMER) {
-            Log.d(TAG, " add event " + event + " scheduled on "
+        if (DBG) {
+            log("set: add event " + event + " scheduled on "
                     + showTime(triggerTime) + " at " + showTime(now)
                     + ", #events=" + mEventQueue.size());
             printQueue();
@@ -187,7 +176,7 @@
      */
     public synchronized void cancel(Runnable callback) {
         if (stopped() || mEventQueue.isEmpty()) return;
-        if (DEBUG_TIMER) Log.d(TAG, "cancel:" + callback);
+        if (DBG) log("cancel:" + callback);
 
         MyEvent firstEvent = mEventQueue.first();
         for (Iterator<MyEvent> iter = mEventQueue.iterator();
@@ -195,7 +184,7 @@
             MyEvent event = iter.next();
             if (event.mCallback == callback) {
                 iter.remove();
-                if (DEBUG_TIMER) Log.d(TAG, "    cancel found:" + event);
+                if (DBG) log("    cancel found:" + event);
             }
         }
         if (mEventQueue.isEmpty()) {
@@ -209,8 +198,8 @@
             recalculatePeriods();
             scheduleNext();
         }
-        if (DEBUG_TIMER) {
-            Log.d(TAG, "after cancel:");
+        if (DBG) {
+            log("cancel: X");
             printQueue();
         }
     }
@@ -242,33 +231,33 @@
             long triggerTime = intent.getLongExtra(TRIGGER_TIME, -1L);
             execute(triggerTime);
         } else {
-            Log.d(TAG, "unrecognized intent: " + intent);
+            log("onReceive: unrecognized intent: " + intent);
         }
     }
 
     private void printQueue() {
         int count = 0;
         for (MyEvent event : mEventQueue) {
-            Log.d(TAG, "     " + event + ": scheduled at "
+            log("     " + event + ": scheduled at "
                     + showTime(event.mTriggerTime) + ": last at "
                     + showTime(event.mLastTriggerTime));
             if (++count >= 5) break;
         }
         if (mEventQueue.size() > count) {
-            Log.d(TAG, "     .....");
+            log("     .....");
         } else if (count == 0) {
-            Log.d(TAG, "     <empty>");
+            log("     <empty>");
         }
     }
 
     private void execute(long triggerTime) {
-        if (DEBUG_TIMER) Log.d(TAG, "time's up, triggerTime = "
+        if (DBG) log("time's up, triggerTime = "
                 + showTime(triggerTime) + ": " + mEventQueue.size());
         if (stopped() || mEventQueue.isEmpty()) return;
 
         for (MyEvent event : mEventQueue) {
             if (event.mTriggerTime != triggerTime) continue;
-            if (DEBUG_TIMER) Log.d(TAG, "execute " + event);
+            if (DBG) log("execute " + event);
 
             event.mLastTriggerTime = triggerTime;
             event.mTriggerTime += event.mPeriod;
@@ -276,8 +265,8 @@
             // run the callback in the handler thread to prevent deadlock
             mExecutor.execute(event.mCallback);
         }
-        if (DEBUG_TIMER) {
-            Log.d(TAG, "after timeout execution");
+        if (DBG) {
+            log("after timeout execution");
             printQueue();
         }
         scheduleNext();
@@ -327,6 +316,7 @@
     // Sort the events by mMaxPeriod so that the first event can be used to
     // align events with larger periods
     private static class MyEventComparator implements Comparator<MyEvent> {
+        @Override
         public int compare(MyEvent e1, MyEvent e2) {
             if (e1 == e2) return 0;
             int diff = e1.mMaxPeriod - e2.mMaxPeriod;
@@ -334,8 +324,13 @@
             return diff;
         }
 
+        @Override
         public boolean equals(Object that) {
             return (this == that);
         }
     }
+
+    private void log(String s) {
+        Rlog.d(TAG, s);
+    }
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 55de065..0be453c 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -45,7 +45,7 @@
 
     void startScan(boolean forceActive);
 
-    List<ScanResult> getScanResults();
+    List<ScanResult> getScanResults(String callingPackage);
 
     void disconnect();
 
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index ac53eb2..66c2f3f 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -1089,17 +1089,19 @@
                 break setVariables;
             }
 
-            HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
-            for (String key : enterpriseFields.keySet()) {
-                    String value = enterpriseFields.get(key);
-                    if (!mWifiNative.setNetworkVariable(
-                                netId,
-                                key,
-                                value)) {
-                        loge(config.SSID + ": failed to set " + key +
-                                ": " + value);
-                        break setVariables;
-                    }
+            if (config.enterpriseConfig != null) {
+                HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
+                for (String key : enterpriseFields.keySet()) {
+                        String value = enterpriseFields.get(key);
+                        if (!mWifiNative.setNetworkVariable(
+                                    netId,
+                                    key,
+                                    value)) {
+                            loge(config.SSID + ": failed to set " + key +
+                                    ": " + value);
+                            break setVariables;
+                        }
+                }
             }
             updateFailed = false;
         }
@@ -1398,11 +1400,16 @@
             }
         }
 
-        HashMap<String, String> entepriseFields = config.enterpriseConfig.getFields();
-        for (String key : entepriseFields.keySet()) {
+        if (config.enterpriseConfig == null) {
+            config.enterpriseConfig = new WifiEnterpriseConfig();
+        }
+        HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
+        for (String key : WifiEnterpriseConfig.getSupplicantKeys()) {
             value = mWifiNative.getNetworkVariable(netId, key);
             if (!TextUtils.isEmpty(value)) {
-                entepriseFields.put(key, removeDoubleQuotes(value));
+                enterpriseFields.put(key, removeDoubleQuotes(value));
+            } else {
+                enterpriseFields.put(key, WifiEnterpriseConfig.EMPTY_VALUE);
             }
         }
 
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 46e446e..4dca7ac 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -74,18 +74,14 @@
     /** This represents an empty value of an enterprise field.
      * NULL is used at wpa_supplicant to indicate an empty value
      */
-    private static final String EMPTY_VALUE = "NULL";
+    static final String EMPTY_VALUE = "NULL";
 
     public WifiEnterpriseConfig() {
-        // Set the required defaults
-        mFields.put(EAP_KEY, Eap.strings[Eap.PEAP]);
-        mFields.put(ENGINE_KEY, ENGINE_DISABLE);
+        // Do not set defaults so that the enterprise fields that are not changed
+        // by API are not changed underneath
+        // This is essential because an app may not have all fields like password
+        // available. It allows modification of subset of fields.
 
-        for (String key : new String[] {PHASE2_KEY, IDENTITY_KEY, ANON_IDENTITY_KEY,
-                PASSWORD_KEY, CLIENT_CERT_KEY, ENGINE_ID_KEY, PRIVATE_KEY_ID_KEY,
-                CA_CERT_KEY, SUBJECT_MATCH_KEY}) {
-            mFields.put(key, EMPTY_VALUE);
-        }
     }
 
     /** Copy constructor */
@@ -128,6 +124,8 @@
             };
 
     public static final class Eap {
+        /* NONE represents an empty enterprise config */
+        public static final int NONE    = -1;
         public static final int PEAP    = 0;
         public static final int TLS     = 1;
         public static final int TTLS    = 2;
@@ -152,6 +150,13 @@
         return mFields;
     }
 
+    /** Internal use only @hide */
+    public static String[] getSupplicantKeys() {
+        return new String[] { EAP_KEY, PHASE2_KEY, IDENTITY_KEY, ANON_IDENTITY_KEY, PASSWORD_KEY,
+                CLIENT_CERT_KEY, CA_CERT_KEY, SUBJECT_MATCH_KEY, ENGINE_KEY, ENGINE_ID_KEY,
+                PRIVATE_KEY_ID_KEY };
+    }
+
     /**
      * Set the EAP authentication method.
      * @param  eapMethod is one {@link Eap#PEAP}, {@link Eap#TLS}, {@link Eap#TTLS} or
@@ -177,7 +182,7 @@
      */
     public int getEapMethod() {
         String eapMethod  = mFields.get(EAP_KEY);
-        return getStringIndex(Eap.strings, eapMethod, Eap.PEAP);
+        return getStringIndex(Eap.strings, eapMethod, Eap.NONE);
     }
 
     /**
@@ -211,7 +216,11 @@
      * @return a phase 2 method defined at {@link Phase2}
      * */
     public int getPhase2Method() {
-        String phase2Method = mFields.get(PHASE2_KEY);
+        String phase2Method = removeDoubleQuotes(mFields.get(PHASE2_KEY));
+        // Remove auth= prefix
+        if (phase2Method.startsWith(Phase2.PREFIX)) {
+            phase2Method = phase2Method.substring(Phase2.PREFIX.length());
+        }
         return getStringIndex(Phase2.strings, phase2Method, Phase2.NONE);
     }
 
@@ -387,9 +396,7 @@
      */
     private int getStringIndex(String arr[], String toBeFound, int defaultIndex) {
         for (int i = 0; i < arr.length; i++) {
-            // toBeFound can be formatted with a prefix. For example, phase2
-            // string has "auth=" as the prefix.
-            if (toBeFound.contains(arr[i])) return i;
+            if (toBeFound.equals(arr[i])) return i;
         }
         return defaultIndex;
     }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4861759..c08db07 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -777,7 +777,7 @@
      */
     public List<ScanResult> getScanResults() {
         try {
-            return mService.getScanResults();
+            return mService.getScanResults(mContext.getBasePackageName());
         } catch (RemoteException e) {
             return null;
         }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 0a61972..476ebbc 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -2315,7 +2315,7 @@
             if (!mWifiNative.setSerialNumber(detail)) {
                 loge("Failed to set serial number " + detail);
             }
-            if (!mWifiNative.setConfigMethods("physical_display virtual_push_button keypad")) {
+            if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) {
                 loge("Failed to set WPS config methods");
             }
             if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) {