Merge "Parcel compRequired flag correctly."
diff --git a/api/current.txt b/api/current.txt
index d270ae0..b06a51d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19290,6 +19290,7 @@
   public class CdmaCellLocation extends android.telephony.CellLocation {
     ctor public CdmaCellLocation();
     ctor public CdmaCellLocation(android.os.Bundle);
+    method public static double convertQuartSecToDecDegrees(int);
     method public void fillInNotifierBundle(android.os.Bundle);
     method public int getBaseStationId();
     method public int getBaseStationLatitude();
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index f277339..3e722ea 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -34,6 +34,12 @@
 LOCAL_STATIC_LIBRARIES := \
     libdiskusage
 
+ifeq ($(HAVE_SELINUX),true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_CFLAGS := -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
 LOCAL_MODULE := installd
 
 LOCAL_MODULE_TAGS := optional
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index dd92bbe..0dd8156 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -17,6 +17,10 @@
 #include "installd.h"
 #include <diskusage/dirsize.h>
 
+#ifdef HAVE_SELINUX
+#include <selinux/android.h>
+#endif
+
 /* Directory records that are used in execution of commands. */
 dir_rec_t android_data_dir;
 dir_rec_t android_asec_dir;
@@ -58,6 +62,15 @@
         unlink(pkgdir);
         return -errno;
     }
+
+#ifdef HAVE_SELINUX
+    if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
+        LOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(pkgdir);
+        return -errno;
+    }
+#endif
+
     if (mkdir(libdir, 0755) < 0) {
         ALOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
         unlink(pkgdir);
@@ -75,6 +88,16 @@
         unlink(pkgdir);
         return -errno;
     }
+
+#ifdef HAVE_SELINUX
+    if (selinux_android_setfilecon(libdir, pkgname, AID_SYSTEM) < 0) {
+        LOGE("cannot setfilecon dir '%s': %s\n", libdir, strerror(errno));
+        unlink(libdir);
+        unlink(pkgdir);
+        return -errno;
+    }
+#endif
+
     return 0;
 }
 
@@ -135,6 +158,15 @@
         unlink(pkgdir);
         return -errno;
     }
+
+#ifdef HAVE_SELINUX
+    if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
+        LOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(pkgdir);
+        return -errno;
+    }
+#endif
+
     return 0;
 }
 
@@ -284,12 +316,18 @@
         ALOGE("failed to chgrp '%s': %s\n", pkgpath, strerror(errno));
         return -1;
     }
-
     if (chmod(pkgpath, S_IRUSR|S_IWUSR|S_IRGRP) < 0) {
         ALOGE("failed to chmod '%s': %s\n", pkgpath, strerror(errno));
         return -1;
     }
 
+#ifdef HAVE_SELINUX
+    if (selinux_android_setfilecon(pkgpath, pkgname, s.st_uid) < 0) {
+        LOGE("cannot setfilecon dir '%s': %s\n", pkgpath, strerror(errno));
+        return -1;
+    }
+#endif
+
     return 0;
 }
 
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index dd9ea26..3a67cec 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -64,11 +64,12 @@
     }
 
     /**
-     * Called when the application is starting, before any other application
-     * objects have been created.  Implementations should be as quick as
-     * possible (for example using lazy initialization of state) since the time
-     * spent in this function directly impacts the performance of starting the
-     * first activity, service, or receiver in a process.
+     * Called when the application is starting, before any activity, service,
+     * or receiver objects (excluding content providers) have been created.
+     * Implementations should be as quick as possible (for example using 
+     * lazy initialization of state) since the time spent in this function
+     * directly impacts the performance of starting the first activity,
+     * service, or receiver in a process.
      * If you override this method, be sure to call super.onCreate().
      */
     public void onCreate() {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index c4a4fea..310d033 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -369,6 +369,7 @@
 
         case SCHEDULE_LOW_MEMORY_TRANSACTION:
         {
+            data.enforceInterface(IApplicationThread.descriptor);
             scheduleLowMemory();
             return true;
         }
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
new file mode 100644
index 0000000..90cfa37
--- /dev/null
+++ b/core/java/android/os/SELinux.java
@@ -0,0 +1,105 @@
+package android.os;
+
+import java.io.FileDescriptor;
+
+/**
+ * This class provides access to the centralized jni bindings for
+ * SELinux interaction.
+ * {@hide}
+ */
+public class SELinux {
+
+    /**
+     * Determine whether SELinux is disabled or enabled.
+     * @return a boolean indicating whether SELinux is enabled.
+     */
+    public static final native boolean isSELinuxEnabled();
+
+    /**
+     * Determine whether SELinux is permissive or enforcing.
+     * @return a boolean indicating whether SELinux is enforcing.
+     */
+    public static final native boolean isSELinuxEnforced();
+
+    /**
+     * Set whether SELinux is permissive or enforcing.
+     * @param boolean representing whether to set SELinux to enforcing
+     * @return a boolean representing whether the desired mode was set
+     */
+    public static final native boolean setSELinuxEnforce(boolean value);
+
+    /**
+     * Sets the security context for newly created file objects.
+     * @param context a security context given as a String.
+     * @return a boolean indicating whether the operation succeeded.
+     */
+    public static final native boolean setFSCreateContext(String context);
+
+    /**
+     * Change the security context of an existing file object.
+     * @param path representing the path of file object to relabel.
+     * @param con new security context given as a String.
+     * @return a boolean indicating whether the operation succeeded.
+     */
+    public static final native boolean setFileContext(String path, String context);
+
+    /**
+     * Get the security context of a file object.
+     * @param path the pathname of the file object.
+     * @return a security context given as a String.
+     */
+    public static final native String getFileContext(String path);
+
+    /**
+     * Get the security context of a peer socket.
+     * @param fd FileDescriptor class of the peer socket.
+     * @return a String representing the peer socket security context.
+     */
+    public static final native String getPeerContext(FileDescriptor fd);
+
+    /**
+     * Gets the security context of the current process.
+     * @return a String representing the security context of the current process.
+     */
+    public static final native String getContext();
+
+    /**
+     * Gets the security context of a given process id.
+     * Use of this function is discouraged for Binder transactions.
+     * Use Binder.getCallingSecctx() instead.
+     * @param pid an int representing the process id to check.
+     * @return a String representing the security context of the given pid.
+     */
+    public static final native String getPidContext(int pid);
+
+    /**
+     * Gets a list of the SELinux boolean names.
+     * @return an array of strings containing the SELinux boolean names.
+     */
+    public static final native String[] getBooleanNames();
+
+    /**
+     * Gets the value for the given SELinux boolean name.
+     * @param String The name of the SELinux boolean.
+     * @return a boolean indicating whether the SELinux boolean is set.
+     */
+    public static final native boolean getBooleanValue(String name);
+
+    /**
+     * Sets the value for the given SELinux boolean name.
+     * @param String The name of the SELinux boolean.
+     * @param Boolean The new value of the SELinux boolean.
+     * @return a boolean indicating whether or not the operation succeeded.
+     */
+    public static final native boolean setBooleanValue(String name, boolean value);
+
+    /**
+     * Check permissions between two security contexts.
+     * @param scon The source or subject security context.
+     * @param tcon The target or object security context.
+     * @param tclass The object security class name.
+     * @param perm The permission name.
+     * @return a boolean indicating whether permission was granted.
+     */
+    public static final native boolean checkSELinuxAccess(String scon, String tcon, String tclass, String perm);
+}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index f947f95..e2074ec 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -181,6 +181,8 @@
     private boolean         mBlockNetworkImage = false;
     private boolean         mBlockNetworkLoads;
     private boolean         mJavaScriptEnabled = false;
+    private boolean         mAllowUniversalAccessFromFileURLs = true;
+    private boolean         mAllowFileAccessFromFileURLs = true;
     private boolean         mHardwareAccelSkia = false;
     private boolean         mShowVisualIndicator = false;
     private PluginState     mPluginState = PluginState.OFF;
@@ -1264,6 +1266,47 @@
     }
 
     /**
+     * Sets whether JavaScript running in the context of a file scheme URL
+     * should be allowed to access content from any origin. This includes
+     * access to content from other file scheme URLs. See
+     * {@link #setAllowFileAccessFromFileURLs}. To enable the most restrictive,
+     * and therefore secure policy, this setting should be disabled.
+     * <p>
+     * The default value is true.
+     *
+     * @param flag whether JavaScript running in the context of a file scheme
+     *             URL should be allowed to access content from any origin
+     * @hide
+     */
+    public synchronized void setAllowUniversalAccessFromFileURLs(boolean flag) {
+        if (mAllowUniversalAccessFromFileURLs != flag) {
+            mAllowUniversalAccessFromFileURLs = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * Sets whether JavaScript running in the context of a file scheme URL
+     * should be allowed to access content from other file scheme URLs. To
+     * enable the most restrictive, and therefore secure policy, this setting
+     * should be disabled. Note that the value of this setting is ignored if
+     * the value of {@link #getAllowUniversalAccessFromFileURLs} is true.
+     * <p>
+     * The default value is true.
+     *
+     * @param flag whether JavaScript running in the context of a file scheme
+     *             URL should be allowed to access content from other file
+     *             scheme URLs
+     * @hide
+     */
+    public synchronized void setAllowFileAccessFromFileURLs(boolean flag) {
+        if (mAllowFileAccessFromFileURLs != flag) {
+            mAllowFileAccessFromFileURLs = flag;
+            postSync();
+        }
+    }
+
+    /**
      * Tell the WebView to use Skia's hardware accelerated rendering path
      * @param flag True if the WebView should use Skia's hw-accel path
      * @hide
@@ -1500,6 +1543,33 @@
     }
 
     /**
+     * Gets whether JavaScript running in the context of a file scheme URL can
+     * access content from any origin. This includes access to content from
+     * other file scheme URLs.
+     *
+     * @return whether JavaScript running in the context of a file scheme URL
+     *         can access content from any origin
+     * @see #setAllowUniversalAccessFromFileURLs
+     * @hide
+     */
+    public synchronized boolean getAllowUniversalAccessFromFileURLs() {
+        return mAllowUniversalAccessFromFileURLs;
+    }
+
+    /**
+     * Gets whether JavaScript running in the context of a file scheme URL can
+     * access content from other file scheme URLs.
+     *
+     * @return whether JavaScript running in the context of a file scheme URL
+     *         can access content from other file scheme URLs
+     * @see #setAllowFileAccessFromFileURLs
+     * @hide
+     */
+    public synchronized boolean getAllowFileAccessFromFileURLs() {
+        return mAllowFileAccessFromFileURLs;
+    }
+
+    /**
      * Return true if plugins are enabled.
      * @return True if plugins are enabled.
      * @deprecated This method has been replaced by {@link #getPluginState}
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index 77d0c97..96a6428 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -76,6 +76,8 @@
     private PowerManager.WakeLock mCpuWakeLock;
     private PowerManager.WakeLock mScreenWakeLock;
     private Handler mHandler;
+
+    private static AlertDialog sConfirmDialog;
     
     private ShutdownThread() {
     }
@@ -108,7 +110,10 @@
 
         if (confirm) {
             final CloseDialogReceiver closer = new CloseDialogReceiver(context);
-            final AlertDialog dialog = new AlertDialog.Builder(context)
+            if (sConfirmDialog != null) {
+                sConfirmDialog.dismiss();
+            }
+            sConfirmDialog = new AlertDialog.Builder(context)
                     .setTitle(com.android.internal.R.string.power_off)
                     .setMessage(resourceId)
                     .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
@@ -118,10 +123,10 @@
                     })
                     .setNegativeButton(com.android.internal.R.string.no, null)
                     .create();
-            closer.dialog = dialog;
-            dialog.setOnDismissListener(closer);
-            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-            dialog.show();
+            closer.dialog = sConfirmDialog;
+            sConfirmDialog.setOnDismissListener(closer);
+            sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+            sConfirmDialog.show();
         } else {
             beginShutdownSequence(context);
         }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 71c5d26..0b6a3a6 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -66,6 +66,7 @@
 	android_os_MessageQueue.cpp \
 	android_os_ParcelFileDescriptor.cpp \
 	android_os_Power.cpp \
+	android_os_SELinux.cpp \
 	android_os_StatFs.cpp \
 	android_os_SystemClock.cpp \
 	android_os_SystemProperties.cpp \
@@ -216,7 +217,13 @@
 	libnfc_ndef \
 	libusbhost \
 	libharfbuzz \
-	libz \
+	libz
+
+ifeq ($(HAVE_SELINUX),true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
 
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 1c0d7cf..31c1120 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -135,6 +135,7 @@
 extern int register_android_os_MessageQueue(JNIEnv* env);
 extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
 extern int register_android_os_Power(JNIEnv *env);
+extern int register_android_os_SELinux(JNIEnv* env);
 extern int register_android_os_StatFs(JNIEnv *env);
 extern int register_android_os_SystemProperties(JNIEnv *env);
 extern int register_android_os_SystemClock(JNIEnv* env);
@@ -1153,6 +1154,7 @@
     REG_JNI(register_android_os_MessageQueue),
     REG_JNI(register_android_os_ParcelFileDescriptor),
     REG_JNI(register_android_os_Power),
+    REG_JNI(register_android_os_SELinux),
     REG_JNI(register_android_os_StatFs),
     REG_JNI(register_android_os_UEventObserver),
     REG_JNI(register_android_net_LocalSocketImpl),
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
new file mode 100644
index 0000000..eb99d2b
--- /dev/null
+++ b/core/jni/android_os_SELinux.cpp
@@ -0,0 +1,502 @@
+#define LOG_TAG "SELinuxJNI"
+#include <utils/Log.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include "android_runtime/AndroidRuntime.h"
+#ifdef HAVE_SELINUX
+#include "selinux/selinux.h"
+#endif
+#include <errno.h>
+
+namespace android {
+
+  static jboolean isSELinuxDisabled = true;
+
+  static void throw_NullPointerException(JNIEnv *env, const char* msg) {
+    jclass clazz;
+    clazz = env->FindClass("java/lang/NullPointerException");
+    env->ThrowNew(clazz, msg);
+  }
+
+  /*
+   * Function: isSELinuxEnabled
+   * Purpose:  checks whether SELinux is enabled/disbaled
+   * Parameters: none
+   * Return value : true (enabled) or false (disabled)
+   * Exceptions: none
+   */
+  static jboolean isSELinuxEnabled(JNIEnv *env, jobject classz) {
+
+    return !isSELinuxDisabled;
+  }
+
+  /*
+   * Function: isSELinuxEnforced
+   * Purpose: return the current SELinux enforce mode
+   * Parameters: none
+   * Return value: true (enforcing) or false (permissive)
+   * Exceptions: none
+   */
+  static jboolean isSELinuxEnforced(JNIEnv *env, jobject clazz) {
+#ifdef HAVE_SELINUX
+    return (security_getenforce() == 1) ? true : false;
+#else
+    return false;
+#endif
+  }
+
+  /*
+   * Function: setSELinuxEnforce
+   * Purpose: set the SE Linux enforcing mode
+   * Parameters: true (enforcing) or false (permissive)
+   * Return value: true (success) or false (fail)
+   * Exceptions: none
+   */
+  static jboolean setSELinuxEnforce(JNIEnv *env, jobject clazz, jboolean value) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return false;
+
+    int enforce = (value) ? 1 : 0;
+
+    return (security_setenforce(enforce) != -1) ? true : false;
+#else
+    return false;
+#endif
+  }
+
+  /*
+   * Function: getPeerCon
+   * Purpose: retrieves security context of peer socket
+   * Parameters:
+   *        fileDescriptor: peer socket file as a FileDescriptor object
+   * Returns: jstring representing the security_context of socket or NULL if error
+   * Exceptions: NullPointerException if fileDescriptor object is NULL
+   */
+  static jstring getPeerCon(JNIEnv *env, jobject clazz, jobject fileDescriptor) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return NULL;
+
+    if (fileDescriptor == NULL) {
+      throw_NullPointerException(env, "Trying to check security context of a null peer socket.");
+      return NULL;
+    }
+
+    security_context_t context = NULL;
+    jstring securityString = NULL;
+
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+
+    if (env->ExceptionOccurred() != NULL) {
+      LOGE("There was an issue with retrieving the file descriptor");
+      goto bail;
+    }
+
+    if (getpeercon(fd, &context) == -1)
+      goto bail;
+
+    LOGV("getPeerCon: Successfully retrived context of peer socket '%s'", context);
+
+    securityString = env->NewStringUTF(context);
+
+  bail:
+    if (context != NULL)
+      freecon(context);
+
+    return securityString;
+#else
+    return NULL;
+#endif
+  }
+
+  /*
+   * Function: setFSCreateCon
+   * Purpose: set security context used for creating a new file system object
+   * Parameters:
+   *       context: security_context_t representing the new context of a file system object,
+   *                set to NULL to return to the default policy behavior
+   * Returns: true on success, false on error
+   * Exception: none
+   */
+  static jboolean setFSCreateCon(JNIEnv *env, jobject clazz, jstring context) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return false;
+
+    char * securityContext = NULL;
+    const char *constant_securityContext = NULL;
+
+    if (context != NULL) {
+      constant_securityContext = env->GetStringUTFChars(context, NULL);
+
+      // GetStringUTFChars returns const char * yet setfscreatecon needs char *
+      securityContext = const_cast<char *>(constant_securityContext);
+    }
+
+    int ret;
+    if ((ret = setfscreatecon(securityContext)) == -1)
+      goto bail;
+
+    LOGV("setFSCreateCon: set new security context to '%s' ", context == NULL ? "default", context);
+
+  bail:
+    if (constant_securityContext != NULL)
+      env->ReleaseStringUTFChars(context, constant_securityContext);
+
+    return (ret == 0) ? true : false;
+#else
+    return false;
+#endif
+  }
+
+  /*
+   * Function: setFileCon
+   * Purpose:  set the security context of a file object
+   * Parameters:
+   *       path: the location of the file system object
+   *       con: the new security context of the file system object
+   * Returns: true on success, false on error
+   * Exception: NullPointerException is thrown if either path or context strign are NULL
+   */
+  static jboolean setFileCon(JNIEnv *env, jobject clazz, jstring path, jstring con) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return false;
+
+    if (path == NULL) {
+      throw_NullPointerException(env, "Trying to change the security context of a NULL file object.");
+      return false;
+    }
+
+    if (con == NULL) {
+      throw_NullPointerException(env, "Trying to set the security context of a file object with NULL.");
+      return false;
+    }
+
+    const char *objectPath = env->GetStringUTFChars(path, NULL);
+    const char *constant_con = env->GetStringUTFChars(con, NULL);
+
+    // GetStringUTFChars returns const char * yet setfilecon needs char *
+    char *newCon = const_cast<char *>(constant_con);
+
+    int ret;
+    if ((ret = setfilecon(objectPath, newCon)) == -1)
+      goto bail;
+
+    LOGV("setFileCon: Succesfully set security context '%s' for '%s'", newCon, objectPath);
+
+  bail:
+    env->ReleaseStringUTFChars(path, objectPath);
+    env->ReleaseStringUTFChars(con, constant_con);
+    return (ret == 0) ? true : false;
+#else
+    return false;
+#endif
+  }
+
+  /*
+   * Function: getFileCon
+   * Purpose: retrieves the context associated with the given path in the file system
+   * Parameters:
+   *        path: given path in the file system
+   * Returns:
+   *        string representing the security context string of the file object
+   *        the string may be NULL if an error occured
+   * Exceptions: NullPointerException if the path object is null
+   */
+  static jstring getFileCon(JNIEnv *env, jobject clazz, jstring path) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return NULL;
+
+    if (path == NULL) {
+      throw_NullPointerException(env, "Trying to check security context of a null path.");
+      return NULL;
+    }
+
+    const char *objectPath = env->GetStringUTFChars(path, NULL);
+
+    security_context_t context = NULL;
+    jstring securityString = NULL;
+
+    if (getfilecon(objectPath, &context) == -1)
+      goto bail;
+
+    LOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath);
+
+    securityString = env->NewStringUTF(context);
+
+  bail:
+    if (context != NULL)
+      freecon(context);
+
+    env->ReleaseStringUTFChars(path, objectPath);
+
+    return securityString;
+#else
+    return NULL;
+#endif
+  }
+
+  /*
+   * Function: getCon
+   * Purpose: Get the context of the current process.
+   * Parameters: none
+   * Returns: a jstring representing the security context of the process,
+   *          the jstring may be NULL if there was an error
+   * Exceptions: none
+   */
+  static jstring getCon(JNIEnv *env, jobject clazz) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return NULL;
+
+    security_context_t context = NULL;
+    jstring securityString = NULL;
+
+    if (getcon(&context) == -1)
+      goto bail;
+
+    LOGV("getCon: Successfully retrieved context '%s'", context);
+
+    securityString = env->NewStringUTF(context);
+
+  bail:
+    if (context != NULL)
+      freecon(context);
+
+    return securityString;
+#else
+    return NULL;
+#endif
+  }
+
+  /*
+   * Function: getPidCon
+   * Purpose: Get the context of a process identified by its pid
+   * Parameters:
+   *            pid: a jint representing the process
+   * Returns: a jstring representing the security context of the pid,
+   *          the jstring may be NULL if there was an error
+   * Exceptions: none
+   */
+  static jstring getPidCon(JNIEnv *env, jobject clazz, jint pid) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return NULL;
+
+    security_context_t context = NULL;
+    jstring securityString = NULL;
+
+    pid_t checkPid = (pid_t)pid;
+
+    if (getpidcon(checkPid, &context) == -1)
+      goto bail;
+
+    LOGV("getPidCon: Successfully retrived context '%s' for pid '%d'", context, checkPid);
+
+    securityString = env->NewStringUTF(context);
+
+  bail:
+    if (context != NULL)
+      freecon(context);
+
+    return securityString;
+#else
+    return NULL;
+#endif
+  }
+
+  /*
+   * Function: getBooleanNames
+   * Purpose: Gets a list of the SELinux boolean names.
+   * Parameters: None
+   * Returns: an array of strings  containing the SELinux boolean names.
+   *          returns NULL string on error
+   * Exceptions: None
+   */
+  static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv clazz) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return NULL;
+
+    char **list;
+    int i, len, ret;
+    jclass stringClass;
+    jobjectArray stringArray = NULL;
+
+    if (security_get_boolean_names(&list, &len) == -1)
+      return NULL;
+
+    stringClass = env->FindClass("java/lang/String");
+    stringArray = env->NewObjectArray(len, stringClass, env->NewStringUTF(""));
+    for (i = 0; i < len; i++) {
+      jstring obj;
+      obj = env->NewStringUTF(list[i]);
+      env->SetObjectArrayElement(stringArray, i, obj);
+      env->DeleteLocalRef(obj);
+      free(list[i]);
+    }
+    free(list);
+
+    return stringArray;
+#else
+    return NULL;
+#endif
+  }
+
+  /*
+   * Function: getBooleanValue
+   * Purpose: Gets the value for the given SELinux boolean name.
+   * Parameters:
+   *            String: The name of the SELinux boolean.
+   * Returns: a boolean: (true) boolean is set or (false) it is not.
+   * Exceptions: None
+   */
+  static jboolean getBooleanValue(JNIEnv *env, jobject clazz, jstring name) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return false;
+
+    const char *boolean_name;
+    int ret;
+
+    if (name == NULL)
+      return false;
+    boolean_name = env->GetStringUTFChars(name, NULL);
+    ret = security_get_boolean_active(boolean_name);
+    env->ReleaseStringUTFChars(name, boolean_name);
+    return (ret == 1) ? true : false;
+#else
+    return false;
+#endif
+  }
+
+  /*
+   * Function: setBooleanNames
+   * Purpose: Sets the value for the given SELinux boolean name.
+   * Parameters:
+   *            String: The name of the SELinux boolean.
+   *            Boolean: The new value of the SELinux boolean.
+   * Returns: a boolean indicating whether or not the operation succeeded.
+   * Exceptions: None
+   */
+  static jboolean setBooleanValue(JNIEnv *env, jobject clazz, jstring name, jboolean value) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return false;
+
+    const char *boolean_name = NULL;
+    int ret;
+
+    if (name == NULL)
+      return false;
+    boolean_name = env->GetStringUTFChars(name, NULL);
+    ret = security_set_boolean(boolean_name, (value) ? 1 : 0);
+    env->ReleaseStringUTFChars(name, boolean_name);
+    if (ret)
+      return false;
+
+    if (security_commit_booleans() == -1)
+      return false;
+
+    return true;
+#else
+    return false;
+#endif
+  }
+
+  /*
+   * Function: checkSELinuxAccess
+   * Purpose: Check permissions between two security contexts.
+   * Parameters: scon: subject security context as a string
+   *             tcon: object security context as a string
+   *             tclass: object's security class name as a string
+   *             perm: permission name as a string
+   * Returns: boolean: (true) if permission was granted, (false) otherwise
+   * Exceptions: None
+   */
+  static jboolean checkSELinuxAccess(JNIEnv *env, jobject clazz, jstring scon, jstring tcon, jstring tclass, jstring perm) {
+#ifdef HAVE_SELINUX
+    if (isSELinuxDisabled)
+      return true;
+
+    int accessGranted = -1;
+
+    const char *const_scon, *const_tcon, *mytclass, *myperm;
+    char *myscon, *mytcon;
+
+    if (scon == NULL || tcon == NULL || tclass == NULL || perm == NULL)
+      goto bail;
+
+    const_scon = env->GetStringUTFChars(scon, NULL);
+    const_tcon = env->GetStringUTFChars(tcon, NULL);
+    mytclass   = env->GetStringUTFChars(tclass, NULL);
+    myperm     = env->GetStringUTFChars(perm, NULL);
+
+    // selinux_check_access needs char* for some
+    myscon = const_cast<char *>(const_scon);
+    mytcon = const_cast<char *>(const_tcon);
+
+    accessGranted = selinux_check_access(myscon, mytcon, mytclass, myperm, NULL);
+
+    LOGV("selinux_check_access returned %d", accessGranted);
+
+    env->ReleaseStringUTFChars(scon, const_scon);
+    env->ReleaseStringUTFChars(tcon, const_tcon);
+    env->ReleaseStringUTFChars(tclass, mytclass);
+    env->ReleaseStringUTFChars(perm, myperm);
+
+  bail:
+    return (accessGranted == 0) ? true : false;
+
+#else
+    return true;
+#endif
+  }
+
+  /*
+   * JNI registration.
+   */
+  static JNINativeMethod method_table[] = {
+
+    /* name,                     signature,                    funcPtr */
+    { "checkSELinuxAccess"       , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess },
+    { "getBooleanNames"          , "()[Ljava/lang/String;"                        , (void*)getBooleanNames  },
+    { "getBooleanValue"          , "(Ljava/lang/String;)Z"                        , (void*)getBooleanValue  },
+    { "getContext"               , "()Ljava/lang/String;"                         , (void*)getCon           },
+    { "getFileContext"           , "(Ljava/lang/String;)Ljava/lang/String;"       , (void*)getFileCon       },
+    { "getPeerContext"           , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getPeerCon       },
+    { "getPidContext"            , "(I)Ljava/lang/String;"                        , (void*)getPidCon        },
+    { "isSELinuxEnforced"        , "()Z"                                          , (void*)isSELinuxEnforced},
+    { "isSELinuxEnabled"         , "()Z"                                          , (void*)isSELinuxEnabled },
+    { "setBooleanValue"          , "(Ljava/lang/String;Z)Z"                       , (void*)setBooleanValue  },
+    { "setFileContext"           , "(Ljava/lang/String;Ljava/lang/String;)Z"      , (void*)setFileCon       },
+    { "setFSCreateContext"       , "(Ljava/lang/String;)Z"                        , (void*)setFSCreateCon   },
+    { "setSELinuxEnforce"        , "(Z)Z"                                         , (void*)setSELinuxEnforce},
+  };
+
+  static int log_callback(int type, const char *fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    LOG_PRI_VA(ANDROID_LOG_ERROR, "SELinux", fmt, ap);
+    va_end(ap);
+    return 0;
+  }
+
+  int register_android_os_SELinux(JNIEnv *env) {
+#ifdef HAVE_SELINUX
+    union selinux_callback cb;
+    cb.func_log = log_callback;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
+    isSELinuxDisabled = (is_selinux_enabled() != 1) ? true : false;
+
+#endif
+    return AndroidRuntime::registerNativeMethods(
+         env, "android/os/SELinux",
+         method_table, NELEM(method_table));
+  }
+}
diff --git a/core/tests/coretests/src/android/os/SELinuxTest.java b/core/tests/coretests/src/android/os/SELinuxTest.java
new file mode 100644
index 0000000..9b63a6b
--- /dev/null
+++ b/core/tests/coretests/src/android/os/SELinuxTest.java
@@ -0,0 +1,45 @@
+package android.os;
+
+import android.os.Process;
+import android.os.SELinux;
+import android.test.AndroidTestCase;
+import static junit.framework.Assert.assertEquals;
+
+public class SELinuxTest extends AndroidTestCase {
+
+    public void testgetFileCon() {
+        if(SELinux.isSELinuxEnabled() == false)
+            return;
+
+        String ctx = SELinux.getFileContext("/system/bin/toolbox");
+        assertEquals(ctx, "u:object_r:system_file:s0");
+    }
+
+    public void testgetCon() {
+        if(SELinux.isSELinuxEnabled() == false)
+            return;
+
+        String mycon = SELinux.getContext();
+        assertEquals(mycon, "u:r:untrusted_app:s0:c33");
+    }
+
+    public void testgetPidCon() {
+        if(SELinux.isSELinuxEnabled() == false)
+            return;
+
+        String mycon = SELinux.getPidContext(Process.myPid());
+        assertEquals(mycon, "u:r:untrusted_app:s0:c33");
+    }
+
+    public void testcheckSELinuxAccess() {
+        if(SELinux.isSELinuxEnabled() == false)
+            return;
+
+        String mycon = SELinux.getContext();
+        boolean ret;
+        ret = SELinux.checkSELinuxAccess(mycon, mycon, "process", "fork");
+        assertEquals(ret,"true");
+        ret = SELinux.checkSELinuxAccess(mycon, mycon, "memprotect", "mmap_zero");
+        assertEquals(ret,"true");
+    }
+}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 3400e97..2480dec 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1047,10 +1047,11 @@
 {
   int32_t exception_code = readAligned<int32_t>();
   if (exception_code == EX_HAS_REPLY_HEADER) {
+    int32_t header_start = dataPosition();
     int32_t header_size = readAligned<int32_t>();
     // Skip over fat responses headers.  Not used (or propagated) in
     // native code
-    setDataPosition(dataPosition() + header_size);
+    setDataPosition(header_start + header_size);
     // And fat response headers are currently only used when there are no
     // exceptions, so return no error:
     return 0;
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index e275aa6..d674374 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -172,6 +172,7 @@
 
     static {
         addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg", MtpConstants.FORMAT_MP3);
+        addFileType("MPGA", FILE_TYPE_MP3, "audio/mpeg", MtpConstants.FORMAT_MP3);
         addFileType("M4A", FILE_TYPE_M4A, "audio/mp4", MtpConstants.FORMAT_MPEG);
         addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav", MtpConstants.FORMAT_WAV);
         addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index df00581..ba54dcb 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -95,11 +95,11 @@
 # currently must follow the same logic to determine how webkit was built and
 # if it's safe to link against libchromium.net
 
-# V8 also requires an ARMv7 & x86 CPU, and since we must use jsc, we cannot
+# On ARM, V8 also requires an ARMv7 CPU, and since we must use jsc, we cannot
 # use the Chrome http stack either.
-ifneq ($(strip $(ARCH_ARM_HAVE_ARMV7A)),true)
-  ifneq ($(TARGET_ARCH),x86)
-      USE_ALT_HTTP := true
+ifeq ($(TARGET_ARCH),arm)
+  ifneq ($(strip $(ARCH_ARM_HAVE_ARMV7A)),true)
+    USE_ALT_HTTP := true
   endif
 endif
 
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc.c b/media/libstagefright/codecs/aacenc/src/aacenc.c
index ad2f29a..d1c8621 100644
--- a/media/libstagefright/codecs/aacenc/src/aacenc.c
+++ b/media/libstagefright/codecs/aacenc/src/aacenc.c
@@ -357,9 +357,9 @@
 		if(config.sampleRate%8000 == 0)
 			tmp =480;
 		/* check the bitrate */
-		if(config.bitRate!=0 && (config.bitRate/config.nChannelsOut < 4000) ||
+		if(config.bitRate!=0 && ((config.bitRate/config.nChannelsOut < 4000) ||
            (config.bitRate/config.nChannelsOut > 160000) ||
-		   (config.bitRate > config.sampleRate*6*config.nChannelsOut))
+		   (config.bitRate > config.sampleRate*6*config.nChannelsOut)))
 		{
 			config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
 
diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c
index 07b33b7..ccfe883 100644
--- a/media/libstagefright/codecs/aacenc/src/adj_thr.c
+++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c
@@ -20,13 +20,16 @@
 
 *******************************************************************************/
 
+/* Include system headers before local headers - the local headers
+ * redefine __inline, which can mess up definitions in libc headers if
+ * they happen to use __inline. */
+#include <string.h>
 #include "basic_op.h"
 #include "oper_32b.h"
 #include "adj_thr_data.h"
 #include "adj_thr.h"
 #include "qc_data.h"
 #include "line_pe.h"
-#include <string.h>
 
 
 #define  minSnrLimit    0x6666 /* 1 dB */
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index a5e3483..56fe106 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1460,7 +1460,13 @@
                     "true".equalsIgnoreCase(
                             SystemProperties.get("ro.com.android.dataroaming",
                                     "false")) ? 1 : 0);
-    
+
+            // Mobile Data default, based on build
+            loadSetting(stmt, Settings.Secure.MOBILE_DATA,
+                    "true".equalsIgnoreCase(
+                            SystemProperties.get("ro.com.android.mobiledata",
+                                    "true")) ? 1 : 0);
+
             loadBooleanSetting(stmt, Settings.Secure.INSTALL_NON_MARKET_APPS,
                     R.bool.def_install_non_market_apps);
     
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 5425813..540dda4 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1218,6 +1218,7 @@
             for(MountServiceBinderListener bl : mListeners) {
                 if (bl.mListener == listener) {
                     mListeners.remove(mListeners.indexOf(bl));
+                    listener.asBinder().unlinkToDeath(bl, 0);
                     return;
                 }
             }
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 2a0d2a0..5848cc9 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1103,6 +1103,8 @@
                         ? "SCREEN_BRIGHT_BIT " : "")
                 + (((state & SCREEN_ON_BIT) != 0)
                         ? "SCREEN_ON_BIT " : "")
+                + (((state & BUTTON_BRIGHT_BIT) != 0)
+                        ? "BUTTON_BRIGHT_BIT " : "")
                 + (((state & BATTERY_LOW_BIT) != 0)
                         ? "BATTERY_LOW_BIT " : "");
     }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3ae62ad..ce133f0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -79,7 +79,7 @@
         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
             SystemClock.uptimeMillis());
 
-        Looper.prepare();
+        Looper.prepareMainLooper();
 
         android.os.Process.setThreadPriority(
                 android.os.Process.THREAD_PRIORITY_FOREGROUND);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index cffb391..6190a63 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1757,7 +1757,7 @@
                 if (cr.binding != null && cr.binding.service != null
                         && cr.binding.service.app != null
                         && cr.binding.service.app.lruSeq != mLruSeq) {
-                    updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
+                    updateLruProcessInternalLocked(cr.binding.service.app, false,
                             updateActivityTime, i+1);
                 }
             }
@@ -1765,7 +1765,7 @@
         if (app.conProviders.size() > 0) {
             for (ContentProviderRecord cpr : app.conProviders.keySet()) {
                 if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
-                    updateLruProcessInternalLocked(cpr.proc, oomAdj,
+                    updateLruProcessInternalLocked(cpr.proc, false,
                             updateActivityTime, i+1);
                 }
             }
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index e3347cb..c5b1c7b 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -59,11 +59,11 @@
         if ((modeFlagsToClear&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
             globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
             modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-            if (readOwners.size() > 0) {
+            if (writeOwners.size() > 0) {
                 for (UriPermissionOwner r : writeOwners) {
                     r.removeWritePermission(this);
                 }
-                readOwners.clear();
+                writeOwners.clear();
             }
         }
     }
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 84db830..6cfae6a 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -81,14 +81,26 @@
     }
 
     /**
-     * @return cdma base station latitude, Integer.MAX_VALUE if unknown
+     * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
+     * (http://www.3gpp2.org/public_html/specs/C.S0005-A_v6.0.pdf)
+     * It is represented in units of 0.25 seconds and ranges from -1296000
+     * to 1296000, both values inclusive (corresponding to a range of -90
+     * to +90 degrees). Integer.MAX_VALUE is considered invalid value.
+     *
+     * @return cdma base station latitude in units of 0.25 seconds, Integer.MAX_VALUE if unknown
      */
     public int getBaseStationLatitude() {
         return this.mBaseStationLatitude;
     }
 
     /**
-     * @return cdma base station longitude, Integer.MAX_VALUE if unknown
+     * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
+     * (http://www.3gpp2.org/public_html/specs/C.S0005-A_v6.0.pdf)
+     * It is represented in units of 0.25 seconds and ranges from -2592000
+     * to 2592000, both values inclusive (corresponding to a range of -180
+     * to +180 degrees). Integer.MAX_VALUE is considered invalid value.
+     *
+     * @return cdma base station longitude in units of 0.25 seconds, Integer.MAX_VALUE if unknown
      */
     public int getBaseStationLongitude() {
         return this.mBaseStationLongitude;
@@ -215,6 +227,22 @@
                 this.mNetworkId == -1);
     }
 
+    /**
+     * Converts latitude or longitude from 0.25 seconds (as defined in the
+     * 3GPP2 C.S0005-A v6.0 standard) to decimal degrees
+     *
+     * @param quartSec latitude or longitude in 0.25 seconds units
+     * @return latitude or longitude in decimal degrees units
+     * @throws IllegalArgumentException if value is less than -2592000,
+     *                                  greater than 2592000, or is not a number.
+     */
+    public static double convertQuartSecToDecDegrees(int quartSec) {
+        if(Double.isNaN(quartSec) || quartSec < -2592000 || quartSec > 2592000){
+            // Invalid value
+            throw new IllegalArgumentException("Invalid coordiante value:" + quartSec);
+        }
+        return ((double)quartSec) / (3600 * 4);
+    }
 
 }
 
diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java
index 07f90cd..021602f 100644
--- a/telephony/java/com/android/internal/telephony/Connection.java
+++ b/telephony/java/com/android/internal/telephony/Connection.java
@@ -28,6 +28,10 @@
     public static int PRESENTATION_UNKNOWN = 3;    // no specified or unknown by network
     public static int PRESENTATION_PAYPHONE = 4;   // show pay phone info
 
+    //Caller Name Display
+    protected String cnapName;
+    protected int cnapNamePresentation  = PRESENTATION_ALLOWED;
+
     private static String LOG_TAG = "TelephonyConnection";
 
     public enum DisconnectCause {
@@ -84,11 +88,11 @@
     public abstract String getAddress();
 
     /**
-     * Gets CDMA CNAP name associated with connection.
+     * Gets CNAP name associated with connection.
      * @return cnap name or null if unavailable
      */
     public String getCnapName() {
-        return null;
+        return cnapName;
     }
 
     /**
@@ -100,12 +104,12 @@
     }
 
     /**
-     * Gets CDMA CNAP presentation associated with connection.
+     * Gets CNAP presentation associated with connection.
      * @return cnap name or null if unavailable
      */
 
     public int getCnapNamePresentation() {
-       return 0;
+       return cnapNamePresentation;
     };
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 8fb136e..e013d84 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -50,7 +50,6 @@
     String postDialString;      // outgoing calls only
     boolean isIncoming;
     boolean disconnected;
-    String cnapName;
     int index;          // index in CdmaCallTracker.connections[], -1 if unassigned
 
     /*
@@ -76,7 +75,6 @@
     DisconnectCause cause = DisconnectCause.NOT_DISCONNECTED;
     PostDialState postDialState = PostDialState.NOT_STARTED;
     int numberPresentation = Connection.PRESENTATION_ALLOWED;
-    int cnapNamePresentation  = Connection.PRESENTATION_ALLOWED;
 
 
     Handler h;
@@ -229,14 +227,6 @@
         return address;
     }
 
-    public String getCnapName() {
-        return cnapName;
-    }
-
-    public int getCnapNamePresentation() {
-        return cnapNamePresentation;
-    }
-
     public CdmaCall getCall() {
         return parent;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index e1f4c4b..5c95e7d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -1240,7 +1240,7 @@
                 // If the radio shuts off or resets while one of these
                 // is pending, we need to clean up.
 
-                for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
+                for (int i = mPendingMMIs.size() - 1; i >= 0; i--) {
                     if (mPendingMMIs.get(i).isPendingUSSD()) {
                         mPendingMMIs.get(i).onUssdFinishedError();
                     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
index c1ad7b3..a879dac 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -26,6 +26,7 @@
 import android.util.Log;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
+import android.text.TextUtils;
 
 import com.android.internal.telephony.*;
 
@@ -125,6 +126,8 @@
 
         isIncoming = dc.isMT;
         createTime = System.currentTimeMillis();
+        cnapName = dc.name;
+        cnapNamePresentation = dc.namePresentation;
         numberPresentation = dc.numberPresentation;
         uusInfo = dc.uusInfo;
 
@@ -151,6 +154,9 @@
         index = -1;
 
         isIncoming = false;
+        cnapName = null;
+        cnapNamePresentation = Connection.PRESENTATION_ALLOWED;
+        numberPresentation = Connection.PRESENTATION_ALLOWED;
         createTime = System.currentTimeMillis();
 
         this.parent = parent;
@@ -437,6 +443,21 @@
             changed = true;
         }
 
+        // A null cnapName should be the same as ""
+        if (TextUtils.isEmpty(dc.name)) {
+            if (!TextUtils.isEmpty(cnapName)) {
+                changed = true;
+                cnapName = "";
+            }
+        } else if (!dc.name.equals(cnapName)) {
+            changed = true;
+            cnapName = dc.name;
+        }
+
+        if (Phone.DEBUG_PHONE) log("--dssds----"+cnapName);
+        cnapNamePresentation = dc.namePresentation;
+        numberPresentation = dc.numberPresentation;
+
         if (newParent != parent) {
             if (parent != null) {
                 parent.detach(this);
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 7d735ad..22f495a 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -58,7 +58,7 @@
 
 // The default to use if no other ignore pattern is defined.
 const char * const gDefaultIgnoreAssets =
-    "!.svn:!.git:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~";
+    "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~";
 // The ignore pattern that can be passed via --ignore-assets in Main.cpp
 const char * gUserIgnoreAssets = NULL;
 
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index cb55a9c..eeddd4b 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -29,6 +29,10 @@
 
 
 LOCAL_CFLAGS += -Wno-format-y2k
+ifeq (darwin,$(HOST_OS))
+LOCAL_CFLAGS += -D_DARWIN_UNLIMITED_STREAMS
+endif
+
 
 LOCAL_C_INCLUDES += external/expat/lib
 LOCAL_C_INCLUDES += external/libpng
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 770b027..d051c29 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2253,7 +2253,6 @@
         bool failed = false;
         while (pos < end && !failed) {
             const char16_t* start = pos;
-            end++;
             while (pos < end && *pos != '|') {
                 pos++;
             }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
index b197ea7..1549cf4 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
@@ -45,7 +45,7 @@
 public class AsmAnalyzer {
 
     // Note: a bunch of stuff has package-level access for unit tests. Consider it private.
-    
+
     /** Output logger. */
     private final Log mLog;
     /** The input source JAR to parse. */
@@ -59,11 +59,11 @@
 
     /**
      * Creates a new analyzer.
-     * 
+     *
      * @param log The log output.
      * @param osJarPath The input source JARs to parse.
      * @param gen The generator to fill with the class list and dependency list.
-     * @param deriveFrom Keep all classes that derive from these one (these included). 
+     * @param deriveFrom Keep all classes that derive from these one (these included).
      * @param includeGlobs Glob patterns of classes to keep, e.g. "com.foo.*"
      *        ("*" does not matches dots whilst "**" does, "." and "$" are interpreted as-is)
      */
@@ -81,16 +81,13 @@
      * Fills the generator with classes & dependencies found.
      */
     public void analyze() throws IOException, LogAbortException {
-
-        AsmAnalyzer visitor = this;
-        
         Map<String, ClassReader> zipClasses = parseZip(mOsSourceJar);
         mLog.info("Found %d classes in input JAR%s.", zipClasses.size(),
                 mOsSourceJar.size() > 1 ? "s" : "");
-        
+
         Map<String, ClassReader> found = findIncludes(zipClasses);
         Map<String, ClassReader> deps = findDeps(zipClasses, found);
-        
+
         if (mGen != null) {
             mGen.setKeep(found);
             mGen.setDeps(deps);
@@ -117,10 +114,10 @@
                 }
             }
         }
-        
+
         return classes;
     }
-    
+
     /**
      * Utility that returns the fully qualified binary class name for a ClassReader.
      * E.g. it returns something like android.view.View.
@@ -132,7 +129,7 @@
             return classReader.getClassName().replace('/', '.');
         }
     }
-    
+
     /**
      * Utility that returns the fully qualified binary class name from a path-like FQCN.
      * E.g. it returns android.view.View from android/view/View.
@@ -144,7 +141,7 @@
             return className.replace('/', '.');
         }
     }
-    
+
     /**
      * Process the "includes" arrays.
      * <p/>
@@ -162,11 +159,11 @@
         for (String s : mDeriveFrom) {
             findClassesDerivingFrom(s, zipClasses, found);
         }
-        
+
         return found;
     }
 
-    
+
     /**
      * Uses ASM to find the class reader for the given FQCN class name.
      * If found, insert it in the in_out_found map.
@@ -215,7 +212,7 @@
         globPattern += "$";
 
         Pattern regexp = Pattern.compile(globPattern);
-        
+
         for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
             String class_name = entry.getKey();
             if (regexp.matcher(class_name).matches()) {
@@ -229,10 +226,9 @@
      * determine if they are derived from the given FQCN super class name.
      * Inserts the super class and all the class objects found in the map.
      */
-    void findClassesDerivingFrom(String super_name, Map<String, ClassReader> zipClasses,
-            Map<String, ClassReader> inOutFound) throws LogAbortException {
-        ClassReader super_clazz = findClass(super_name, zipClasses, inOutFound);
-
+    void findClassesDerivingFrom(String super_name,
+            Map<String, ClassReader> zipClasses,
+            Map<String, ClassReader> inOutFound) {
         for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
             String className = entry.getKey();
             if (super_name.equals(className)) {
@@ -284,7 +280,7 @@
         for (ClassReader cr : inOutKeepClasses.values()) {
             cr.accept(visitor, 0 /* flags */);
         }
-        
+
         while (new_deps.size() > 0 || new_keep.size() > 0) {
             deps.putAll(new_deps);
             inOutKeepClasses.putAll(new_keep);
@@ -308,12 +304,12 @@
         return deps;
     }
 
-    
+
 
     // ----------------------------------
-    
+
     /**
-     * Visitor to collect all the type dependencies from a class. 
+     * Visitor to collect all the type dependencies from a class.
      */
     public class DependencyVisitor
         implements ClassVisitor, FieldVisitor, MethodVisitor, SignatureVisitor, AnnotationVisitor {
@@ -333,7 +329,7 @@
          * Creates a new visitor that will find all the dependencies for the visited class.
          * Types which are already in the zipClasses, keepClasses or inDeps are not marked.
          * New dependencies are marked in outDeps.
-         * 
+         *
          * @param zipClasses All classes found in the source JAR.
          * @param inKeep Classes from which dependencies are to be found.
          * @param inDeps Dependencies already known.
@@ -350,7 +346,7 @@
             mInDeps = inDeps;
             mOutDeps = outDeps;
         }
-        
+
         /**
          * Considers the given class name as a dependency.
          * If it does, add to the mOutDeps map.
@@ -361,7 +357,7 @@
             }
 
             className = internalToBinaryClassName(className);
-            
+
             // exclude classes that have already been found
             if (mInKeep.containsKey(className) ||
                     mOutKeep.containsKey(className) ||
@@ -384,7 +380,7 @@
             } catch (ClassNotFoundException e) {
                 // ignore
             }
-            
+
             // accept this class:
             // - android classes are added to dependencies
             // - non-android classes are added to the list of classes to keep as-is (they don't need
@@ -395,7 +391,7 @@
                 mOutKeep.put(className, cr);
             }
         }
-        
+
         /**
          * Considers this array of names using considerName().
          */
@@ -450,7 +446,7 @@
             }
         }
 
-        
+
         // ---------------------------------------------------
         // --- ClassVisitor, FieldVisitor
         // ---------------------------------------------------
@@ -460,7 +456,7 @@
                 String signature, String superName, String[] interfaces) {
             // signature is the signature of this class. May be null if the class is not a generic
             // one, and does not extend or implement generic classes or interfaces.
-            
+
             if (signature != null) {
                 considerSignature(signature);
             }
@@ -468,7 +464,7 @@
             // superName is the internal of name of the super class (see getInternalName).
             // For interfaces, the super class is Object. May be null but only for the Object class.
             considerName(superName);
-            
+
             // interfaces is the internal names of the class's interfaces (see getInternalName).
             // May be null.
             considerNames(interfaces);
@@ -513,7 +509,7 @@
             // signature is the method's signature. May be null if the method parameters, return
             // type and exceptions do not use generic types.
             considerSignature(signature);
-            
+
             return this; // returns this to visit the method
         }
 
@@ -525,7 +521,7 @@
             // pass
         }
 
-        
+
         // ---------------------------------------------------
         // --- MethodVisitor
         // ---------------------------------------------------
@@ -601,7 +597,7 @@
 
         // instruction that invokes a method
         public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-            
+
             // owner is the internal name of the method's owner class
             considerName(owner);
             // desc is the method's descriptor (see Type).
@@ -610,7 +606,7 @@
 
         // instruction multianewarray, whatever that is
         public void visitMultiANewArrayInsn(String desc, int dims) {
-            
+
             // desc an array type descriptor.
             considerDesc(desc);
         }
@@ -624,7 +620,7 @@
 
         public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
             // pass -- table switch instruction
-            
+
         }
 
         public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
@@ -641,10 +637,10 @@
         }
 
         public void visitVarInsn(int opcode, int var) {
-            // pass -- local variable instruction 
+            // pass -- local variable instruction
         }
 
-        
+
         // ---------------------------------------------------
         // --- SignatureVisitor
         // ---------------------------------------------------
@@ -716,8 +712,8 @@
         public void visitTypeArgument() {
             // pass
         }
-        
-        
+
+
         // ---------------------------------------------------
         // --- AnnotationVisitor
         // ---------------------------------------------------
@@ -746,6 +742,6 @@
             // desc is the class descriptor of the enumeration class.
             considerDesc(desc);
         }
-        
+
     }
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
new file mode 100755
index 0000000..2956958
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
@@ -0,0 +1,694 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.layoutlib.create;
+
+import com.android.tools.layoutlib.annotations.VisibleForTesting;
+import com.android.tools.layoutlib.annotations.VisibleForTesting.Visibility;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * Analyzes the input JAR using the ASM java bytecode manipulation library
+ * to list the classes and their dependencies. A "dependency" is a class
+ * used by another class.
+ */
+public class DependencyFinder {
+
+    // Note: a bunch of stuff has package-level access for unit tests. Consider it private.
+
+    /** Output logger. */
+    private final Log mLog;
+
+    /**
+     * Creates a new analyzer.
+     *
+     * @param log The log output.
+     */
+    public DependencyFinder(Log log) {
+        mLog = log;
+    }
+
+    /**
+     * Starts the analysis using parameters from the constructor.
+     *
+     * @param osJarPath The input source JARs to parse.
+     * @return A pair: [0]: map { class FQCN => set of FQCN class dependencies }.
+     *                 [1]: map { missing class FQCN => set of FQCN class that uses it. }
+     */
+    public List<Map<String, Set<String>>> findDeps(List<String> osJarPath) throws IOException {
+
+        Map<String, ClassReader> zipClasses = parseZip(osJarPath);
+        mLog.info("Found %d classes in input JAR%s.",
+                zipClasses.size(),
+                osJarPath.size() > 1 ? "s" : "");
+
+        Map<String, Set<String>> deps = findClassesDeps(zipClasses);
+
+        Map<String, Set<String>> missing = findMissingClasses(deps, zipClasses.keySet());
+
+        List<Map<String, Set<String>>> result = new ArrayList<Map<String,Set<String>>>(2);
+        result.add(deps);
+        result.add(missing);
+        return result;
+    }
+
+    /**
+     * Prints dependencies to the current logger, found stuff and missing stuff.
+     */
+    public void printAllDeps(List<Map<String, Set<String>>> result) {
+        assert result.size() == 2;
+        Map<String, Set<String>> deps = result.get(0);
+        Map<String, Set<String>> missing = result.get(1);
+
+        // Print all dependences found in the format:
+        // +Found: <FQCN from zip>
+        //     uses: FQCN
+
+        mLog.info("++++++ %d Entries found in source JARs", deps.size());
+        mLog.info("");
+
+        for (Entry<String, Set<String>> entry : deps.entrySet()) {
+            mLog.info(    "+Found  : %s", entry.getKey());
+            for (String dep : entry.getValue()) {
+                mLog.info("    uses: %s", dep);
+            }
+
+            mLog.info("");
+        }
+
+
+        // Now print all missing dependences in the format:
+        // -Missing <FQCN>:
+        //     used by: <FQCN>
+
+        mLog.info("");
+        mLog.info("------ %d Entries missing from source JARs", missing.size());
+        mLog.info("");
+
+        for (Entry<String, Set<String>> entry : missing.entrySet()) {
+            mLog.info(    "-Missing  : %s", entry.getKey());
+            for (String dep : entry.getValue()) {
+                mLog.info("   used by: %s", dep);
+            }
+
+            mLog.info("");
+        }
+    }
+
+    /**
+     * Prints only a summary of the missing dependencies to the current logger.
+     */
+    public void printMissingDeps(List<Map<String, Set<String>>> result) {
+        assert result.size() == 2;
+        @SuppressWarnings("unused") Map<String, Set<String>> deps = result.get(0);
+        Map<String, Set<String>> missing = result.get(1);
+
+        for (String fqcn : missing.keySet()) {
+            mLog.info("%s", fqcn);
+        }
+    }
+
+    // ----------------
+
+    /**
+     * Parses a JAR file and returns a list of all classes founds using a map
+     * class name => ASM ClassReader. Class names are in the form "android.view.View".
+     */
+    Map<String,ClassReader> parseZip(List<String> jarPathList) throws IOException {
+        TreeMap<String, ClassReader> classes = new TreeMap<String, ClassReader>();
+
+        for (String jarPath : jarPathList) {
+            ZipFile zip = new ZipFile(jarPath);
+            Enumeration<? extends ZipEntry> entries = zip.entries();
+            ZipEntry entry;
+            while (entries.hasMoreElements()) {
+                entry = entries.nextElement();
+                if (entry.getName().endsWith(".class")) {
+                    ClassReader cr = new ClassReader(zip.getInputStream(entry));
+                    String className = classReaderToClassName(cr);
+                    classes.put(className, cr);
+                }
+            }
+        }
+
+        return classes;
+    }
+
+    /**
+     * Utility that returns the fully qualified binary class name for a ClassReader.
+     * E.g. it returns something like android.view.View.
+     */
+    static String classReaderToClassName(ClassReader classReader) {
+        if (classReader == null) {
+            return null;
+        } else {
+            return classReader.getClassName().replace('/', '.');
+        }
+    }
+
+    /**
+     * Utility that returns the fully qualified binary class name from a path-like FQCN.
+     * E.g. it returns android.view.View from android/view/View.
+     */
+    static String internalToBinaryClassName(String className) {
+        if (className == null) {
+            return null;
+        } else {
+            return className.replace('/', '.');
+        }
+    }
+
+    /**
+     * Finds all dependencies for all classes in keepClasses which are also
+     * listed in zipClasses. Returns a map of all the dependencies found.
+     */
+    Map<String, Set<String>> findClassesDeps(Map<String, ClassReader> zipClasses) {
+
+        // The dependencies that we'll collect.
+        // It's a map Class name => uses class names.
+        Map<String, Set<String>> dependencyMap = new TreeMap<String, Set<String>>();
+
+        DependencyVisitor visitor = getVisitor();
+
+        int count = 0;
+        try {
+            for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
+                String name = entry.getKey();
+
+                TreeSet<String> set = new TreeSet<String>();
+                dependencyMap.put(name, set);
+                visitor.setDependencySet(set);
+
+                ClassReader cr = entry.getValue();
+                cr.accept(visitor, 0 /* flags */);
+
+                visitor.setDependencySet(null);
+
+                mLog.debugNoln("Visited %d classes\r", ++count);
+            }
+        } finally {
+            mLog.debugNoln("\n");
+        }
+
+        return dependencyMap;
+    }
+
+    /**
+     * Computes which classes FQCN were found as dependencies that are NOT listed
+     * in the original JAR classes.
+     *
+     * @param deps The map { FQCN => dependencies[] } returned by {@link #findClassesDeps(Map)}.
+     * @param zipClasses The set of all classes FQCN found in the JAR files.
+     * @return A map { FQCN not found in the zipClasses => classes using it }
+     */
+    private Map<String, Set<String>> findMissingClasses(
+            Map<String, Set<String>> deps,
+            Set<String> zipClasses) {
+        Map<String, Set<String>> missing = new TreeMap<String, Set<String>>();
+
+        for (Entry<String, Set<String>> entry : deps.entrySet()) {
+            String name = entry.getKey();
+
+            for (String dep : entry.getValue()) {
+                if (!zipClasses.contains(dep)) {
+                    // This dependency doesn't exist in the zip classes.
+                    Set<String> set = missing.get(dep);
+                    if (set == null) {
+                        set = new TreeSet<String>();
+                        missing.put(dep, set);
+                    }
+                    set.add(name);
+                }
+            }
+
+        }
+
+        return missing;
+    }
+
+
+    // ----------------------------------
+
+    /**
+     * Instantiates a new DependencyVisitor. Useful for unit tests.
+     */
+    @VisibleForTesting(visibility=Visibility.PRIVATE)
+    DependencyVisitor getVisitor() {
+        return new DependencyVisitor();
+    }
+
+    /**
+     * Visitor to collect all the type dependencies from a class.
+     */
+    public class DependencyVisitor
+        implements ClassVisitor, FieldVisitor, MethodVisitor, SignatureVisitor, AnnotationVisitor {
+
+        private Set<String> mCurrentDepSet;
+
+        /**
+         * Creates a new visitor that will find all the dependencies for the visited class.
+         */
+        public DependencyVisitor() {
+        }
+
+        /**
+         * Sets the {@link Set} where to record direct dependencies for this class.
+         * This will change before each {@link ClassReader#accept(ClassVisitor, int)} call.
+         */
+        public void setDependencySet(Set<String> set) {
+            mCurrentDepSet = set;
+        }
+
+        /**
+         * Considers the given class name as a dependency.
+         */
+        public void considerName(String className) {
+            if (className == null) {
+                return;
+            }
+
+            className = internalToBinaryClassName(className);
+
+            try {
+                // exclude classes that are part of the default JRE (the one executing this program)
+                if (getClass().getClassLoader().loadClass(className) != null) {
+                    return;
+                }
+            } catch (ClassNotFoundException e) {
+                // ignore
+            }
+
+            // Add it to the dependency set for the currently visited class, as needed.
+            assert mCurrentDepSet != null;
+            if (mCurrentDepSet != null) {
+                mCurrentDepSet.add(className);
+            }
+        }
+
+        /**
+         * Considers this array of names using considerName().
+         */
+        public void considerNames(String[] classNames) {
+            if (classNames != null) {
+                for (String className : classNames) {
+                    considerName(className);
+                }
+            }
+        }
+
+        /**
+         * Considers this signature or type signature by invoking the {@link SignatureVisitor}
+         * on it.
+         */
+        public void considerSignature(String signature) {
+            if (signature != null) {
+                SignatureReader sr = new SignatureReader(signature);
+                // SignatureReader.accept will call accessType so we don't really have
+                // to differentiate where the signature comes from.
+                sr.accept(this);
+            }
+        }
+
+        /**
+         * Considers this {@link Type}. For arrays, the element type is considered.
+         * If the type is an object, it's internal name is considered.
+         */
+        public void considerType(Type t) {
+            if (t != null) {
+                if (t.getSort() == Type.ARRAY) {
+                    t = t.getElementType();
+                }
+                if (t.getSort() == Type.OBJECT) {
+                    considerName(t.getInternalName());
+                }
+            }
+        }
+
+        /**
+         * Considers a descriptor string. The descriptor is converted to a {@link Type}
+         * and then considerType() is invoked.
+         */
+        public boolean considerDesc(String desc) {
+            if (desc != null) {
+                try {
+                    if (desc.length() > 0 && desc.charAt(0) == '(') {
+                        // This is a method descriptor with arguments and a return type.
+                        Type t = Type.getReturnType(desc);
+                        considerType(t);
+
+                        for (Type arg : Type.getArgumentTypes(desc)) {
+                            considerType(arg);
+                        }
+
+                    } else {
+                        Type t = Type.getType(desc);
+                        considerType(t);
+                    }
+                    return true;
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    // ignore, not a valid type.
+                }
+            }
+            return false;
+        }
+
+
+        // ---------------------------------------------------
+        // --- ClassVisitor, FieldVisitor
+        // ---------------------------------------------------
+
+        // Visits a class header
+        public void visit(int version, int access, String name,
+                String signature, String superName, String[] interfaces) {
+            // signature is the signature of this class. May be null if the class is not a generic
+            // one, and does not extend or implement generic classes or interfaces.
+
+            if (signature != null) {
+                considerSignature(signature);
+            }
+
+            // superName is the internal of name of the super class (see getInternalName).
+            // For interfaces, the super class is Object. May be null but only for the Object class.
+            considerName(superName);
+
+            // interfaces is the internal names of the class's interfaces (see getInternalName).
+            // May be null.
+            considerNames(interfaces);
+        }
+
+        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+            // desc is the class descriptor of the annotation class.
+            considerDesc(desc);
+            return this; // return this to visit annotion values
+        }
+
+        public void visitAttribute(Attribute attr) {
+            // pass
+        }
+
+        // Visits the end of a class
+        public void visitEnd() {
+            // pass
+        }
+
+        public FieldVisitor visitField(int access, String name, String desc,
+                String signature, Object value) {
+            // desc is the field's descriptor (see Type).
+            considerDesc(desc);
+
+            // signature is the field's signature. May be null if the field's type does not use
+            // generic types.
+            considerSignature(signature);
+
+            return this; // a visitor to visit field annotations and attributes
+        }
+
+        public void visitInnerClass(String name, String outerName, String innerName, int access) {
+            // name is the internal name of an inner class (see getInternalName).
+            // Note: outerName/innerName seems to be null when we're reading the
+            // _Original_ClassName classes generated by layoutlib_create.
+            if (outerName != null) {
+                considerName(name);
+            }
+        }
+
+        public MethodVisitor visitMethod(int access, String name, String desc,
+                String signature, String[] exceptions) {
+            // desc is the method's descriptor (see Type).
+            considerDesc(desc);
+            // signature is the method's signature. May be null if the method parameters, return
+            // type and exceptions do not use generic types.
+            considerSignature(signature);
+
+            return this; // returns this to visit the method
+        }
+
+        public void visitOuterClass(String owner, String name, String desc) {
+            // pass
+        }
+
+        public void visitSource(String source, String debug) {
+            // pass
+        }
+
+
+        // ---------------------------------------------------
+        // --- MethodVisitor
+        // ---------------------------------------------------
+
+        public AnnotationVisitor visitAnnotationDefault() {
+            return this; // returns this to visit the default value
+        }
+
+
+        public void visitCode() {
+            // pass
+        }
+
+        // field instruction
+        public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+            // name is the field's name, not a type.
+            // desc is the field's descriptor (see Type).
+            considerDesc(desc);
+        }
+
+        public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) {
+            // pass
+        }
+
+        public void visitIincInsn(int var, int increment) {
+            // pass -- an IINC instruction
+        }
+
+        public void visitInsn(int opcode) {
+            // pass -- a zero operand instruction
+        }
+
+        public void visitIntInsn(int opcode, int operand) {
+            // pass -- a single int operand instruction
+        }
+
+        public void visitJumpInsn(int opcode, Label label) {
+            // pass -- a jump instruction
+        }
+
+        public void visitLabel(Label label) {
+            // pass -- a label target
+        }
+
+        // instruction to load a constant from the stack
+        public void visitLdcInsn(Object cst) {
+            if (cst instanceof Type) {
+                considerType((Type) cst);
+            }
+        }
+
+        public void visitLineNumber(int line, Label start) {
+            // pass
+        }
+
+        public void visitLocalVariable(String name, String desc,
+                String signature, Label start, Label end, int index) {
+            // desc is the type descriptor of this local variable.
+            considerDesc(desc);
+            // signature is the type signature of this local variable. May be null if the local
+            // variable type does not use generic types.
+            considerSignature(signature);
+        }
+
+        public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+            // pass -- a lookup switch instruction
+        }
+
+        public void visitMaxs(int maxStack, int maxLocals) {
+            // pass
+        }
+
+        // instruction that invokes a method
+        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+
+            // owner is the internal name of the method's owner class
+            if (!considerDesc(owner) && owner.indexOf('/') != -1) {
+                considerName(owner);
+            }
+            // desc is the method's descriptor (see Type).
+            considerDesc(desc);
+        }
+
+        // instruction multianewarray, whatever that is
+        public void visitMultiANewArrayInsn(String desc, int dims) {
+
+            // desc an array type descriptor.
+            considerDesc(desc);
+        }
+
+        public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
+                boolean visible) {
+            // desc is the class descriptor of the annotation class.
+            considerDesc(desc);
+            return this; // return this to visit annotation values
+        }
+
+        public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
+            // pass -- table switch instruction
+
+        }
+
+        public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+            // type is the internal name of the type of exceptions handled by the handler,
+            // or null to catch any exceptions (for "finally" blocks).
+            considerName(type);
+        }
+
+        // type instruction
+        public void visitTypeInsn(int opcode, String type) {
+            // type is the operand of the instruction to be visited. This operand must be the
+            // internal name of an object or array class.
+            if (!considerDesc(type) && type.indexOf('/') != -1) {
+                considerName(type);
+            }
+        }
+
+        public void visitVarInsn(int opcode, int var) {
+            // pass -- local variable instruction
+        }
+
+
+        // ---------------------------------------------------
+        // --- SignatureVisitor
+        // ---------------------------------------------------
+
+        private String mCurrentSignatureClass = null;
+
+        // Starts the visit of a signature corresponding to a class or interface type
+        public void visitClassType(String name) {
+            mCurrentSignatureClass = name;
+            considerName(name);
+        }
+
+        // Visits an inner class
+        public void visitInnerClassType(String name) {
+            if (mCurrentSignatureClass != null) {
+                mCurrentSignatureClass += "$" + name;
+                considerName(mCurrentSignatureClass);
+            }
+        }
+
+        public SignatureVisitor visitArrayType() {
+            return this; // returns this to visit the signature of the array element type
+        }
+
+        public void visitBaseType(char descriptor) {
+            // pass -- a primitive type, ignored
+        }
+
+        public SignatureVisitor visitClassBound() {
+            return this; // returns this to visit the signature of the class bound
+        }
+
+        public SignatureVisitor visitExceptionType() {
+            return this; // return this to visit the signature of the exception type.
+        }
+
+        public void visitFormalTypeParameter(String name) {
+            // pass
+        }
+
+        public SignatureVisitor visitInterface() {
+            return this; // returns this to visit the signature of the interface type
+        }
+
+        public SignatureVisitor visitInterfaceBound() {
+            return this; // returns this to visit the signature of the interface bound
+        }
+
+        public SignatureVisitor visitParameterType() {
+            return this; // returns this to visit the signature of the parameter type
+        }
+
+        public SignatureVisitor visitReturnType() {
+            return this; // returns this to visit the signature of the return type
+        }
+
+        public SignatureVisitor visitSuperclass() {
+            return this; // returns this to visit the signature of the super class type
+        }
+
+        public SignatureVisitor visitTypeArgument(char wildcard) {
+            return this; // returns this to visit the signature of the type argument
+        }
+
+        public void visitTypeVariable(String name) {
+            // pass
+        }
+
+        public void visitTypeArgument() {
+            // pass
+        }
+
+
+        // ---------------------------------------------------
+        // --- AnnotationVisitor
+        // ---------------------------------------------------
+
+
+        // Visits a primitive value of an annotation
+        public void visit(String name, Object value) {
+            // value is the actual value, whose type must be Byte, Boolean, Character, Short,
+            // Integer, Long, Float, Double, String or Type
+            if (value instanceof Type) {
+                considerType((Type) value);
+            }
+        }
+
+        public AnnotationVisitor visitAnnotation(String name, String desc) {
+            // desc is the class descriptor of the nested annotation class.
+            considerDesc(desc);
+            return this; // returns this to visit the actual nested annotation value
+        }
+
+        public AnnotationVisitor visitArray(String name) {
+            return this; // returns this to visit the actual array value elements
+        }
+
+        public void visitEnum(String name, String desc, String value) {
+            // desc is the class descriptor of the enumeration class.
+            considerDesc(desc);
+        }
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Log.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Log.java
index 8efd871..c3ba591 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Log.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Log.java
@@ -33,11 +33,19 @@
         }
     }
 
+    /** Similar to debug() but doesn't do a \n automatically. */
+    public void debugNoln(String format, Object... args) {
+        if (mVerbose) {
+            String s = String.format(format, args);
+            System.out.print(s);
+        }
+    }
+
     public void info(String format, Object... args) {
         String s = String.format(format, args);
         outPrintln(s);
     }
-    
+
     public void error(String format, Object... args) {
         String s = String.format(format, args);
         errPrintln(s);
@@ -50,15 +58,15 @@
         pw.flush();
         error(format + "\n" + sw.toString(), args);
     }
-    
+
     /** for unit testing */
     protected void errPrintln(String msg) {
         System.err.println(msg);
     }
-    
+
     /** for unit testing */
     protected void outPrintln(String msg) {
         System.out.println(msg);
     }
-    
+
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 4b7a348..9cd74db 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -18,6 +18,8 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 
@@ -47,6 +49,8 @@
 
     public static class Options {
         public boolean generatePublicAccess = true;
+        public boolean listAllDeps = false;
+        public boolean listOnlyMissingDeps = false;
     }
 
     public static final Options sOptions = new Options();
@@ -60,16 +64,29 @@
 
         if (!processArgs(log, args, osJarPath, osDestJar)) {
             log.error("Usage: layoutlib_create [-v] [-p] output.jar input.jar ...");
+            log.error("Usage: layoutlib_create [-v] [--list-deps|--missing-deps] input.jar ...");
             System.exit(1);
         }
 
-        log.info("Output: %1$s", osDestJar[0]);
+        if (sOptions.listAllDeps || sOptions.listOnlyMissingDeps) {
+            System.exit(listDeps(osJarPath, log));
+
+        } else {
+            System.exit(createLayoutLib(osDestJar[0], osJarPath, log));
+        }
+
+
+        System.exit(1);
+    }
+
+    private static int createLayoutLib(String osDestJar, ArrayList<String> osJarPath, Log log) {
+        log.info("Output: %1$s", osDestJar);
         for (String path : osJarPath) {
             log.info("Input :      %1$s", path);
         }
 
         try {
-            AsmGenerator agen = new AsmGenerator(log, osDestJar[0], new CreateInfo());
+            AsmGenerator agen = new AsmGenerator(log, osDestJar, new CreateInfo());
 
             AsmAnalyzer aa = new AsmAnalyzer(log, osJarPath, agen,
                     new String[] {                          // derived from
@@ -116,17 +133,33 @@
                 for (String path : osJarPath) {
                     log.info("- Input JAR : %1$s", path);
                 }
-                System.exit(1);
+                return 1;
             }
 
-            System.exit(0);
+            return 0;
         } catch (IOException e) {
             log.exception(e, "Failed to load jar");
         } catch (LogAbortException e) {
             e.error(log);
         }
 
-        System.exit(1);
+        return 1;
+    }
+
+    private static int listDeps(ArrayList<String> osJarPath, Log log) {
+        DependencyFinder df = new DependencyFinder(log);
+        try {
+            List<Map<String, Set<String>>> result = df.findDeps(osJarPath);
+            if (sOptions.listAllDeps) {
+                df.printAllDeps(result);
+            } else if (sOptions.listOnlyMissingDeps) {
+                df.printMissingDeps(result);
+            }
+        } catch (IOException e) {
+            log.exception(e, "Failed to load jar");
+        }
+
+        return 0;
     }
 
     /**
@@ -138,14 +171,21 @@
      */
     private static boolean processArgs(Log log, String[] args,
             ArrayList<String> osJarPath, String[] osDestJar) {
+        boolean needs_dest = true;
         for (int i = 0; i < args.length; i++) {
             String s = args[i];
             if (s.equals("-v")) {
                 log.setVerbose(true);
             } else if (s.equals("-p")) {
                 sOptions.generatePublicAccess = false;
+            } else if (s.equals("--list-deps")) {
+                sOptions.listAllDeps = true;
+                needs_dest = false;
+            } else if (s.equals("--missing-deps")) {
+                sOptions.listOnlyMissingDeps = true;
+                needs_dest = false;
             } else if (!s.startsWith("-")) {
-                if (osDestJar[0] == null) {
+                if (needs_dest && osDestJar[0] == null) {
                     osDestJar[0] = s;
                 } else {
                     osJarPath.add(s);
@@ -160,7 +200,7 @@
             log.error("Missing parameter: path to input jar");
             return false;
         }
-        if (osDestJar[0] == null) {
+        if (needs_dest && osDestJar[0] == null) {
             log.error("Missing parameter: path to output jar");
             return false;
         }