Merge commit '6d05ef2310bdc84811d5b0385b009ad11447a749' into HEAD
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 12e8cd1..a86abe1 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -685,9 +685,13 @@
     /* Before anything else: is there a .odex file?  If so, we have
      * precompiled the apk and there is nothing to do here.
      */
-    sprintf(out_path, "%s%s", apk_path, ".odex");
-    if (stat(out_path, &dex_stat) == 0) {
-        return 0;
+    strcpy(out_path, apk_path);
+    end = strrchr(out_path, '.');
+    if (end != NULL) {
+        strcpy(end, ".odex");
+        if (stat(out_path, &dex_stat) == 0) {
+            return 0;
+        }
     }
 
     if (create_cache_path(out_path, apk_path)) {
@@ -1235,31 +1239,82 @@
     return -1;
 }
 
-int restorecon_data()
+int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid)
 {
-    char *data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
-    char *user_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
-
-    unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE |
-            SELINUX_ANDROID_RESTORECON_DATADATA;
-
+    struct dirent *entry;
+    DIR *d;
+    struct stat s;
+    char *userdir;
+    char *primarydir;
+    char *pkgdir;
     int ret = 0;
 
-    if (!data_dir || !user_dir) {
+    // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
+    unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
+
+    if (!pkgName || !seinfo) {
+        ALOGE("Package name or seinfo tag is null when trying to restorecon.");
         return -1;
     }
 
-    if (selinux_android_restorecon(data_dir, flags) < 0) {
-        ALOGE("restorecon failed for %s: %s\n", data_dir, strerror(errno));
+    if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) {
+        return -1;
+    }
+
+    // Relabel for primary user.
+    if (selinux_android_restorecon_pkgdir(primarydir, seinfo, uid, flags) < 0) {
+        ALOGE("restorecon failed for %s: %s\n", primarydir, strerror(errno));
         ret |= -1;
     }
 
-    if (selinux_android_restorecon(user_dir, flags) < 0) {
-        ALOGE("restorecon failed for %s: %s\n", user_dir, strerror(errno));
-        ret |= -1;
+    if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) {
+        free(primarydir);
+        return -1;
     }
 
-    free(data_dir);
-    free(user_dir);
+    // Relabel package directory for all secondary users.
+    d = opendir(userdir);
+    if (d == NULL) {
+        free(primarydir);
+        free(userdir);
+        return -1;
+    }
+
+    while ((entry = readdir(d))) {
+        if (entry->d_type != DT_DIR) {
+            continue;
+        }
+
+        const char *user = entry->d_name;
+        // Ignore "." and ".."
+        if (!strcmp(user, ".") || !strcmp(user, "..")) {
+            continue;
+        }
+
+        // user directories start with a number
+        if (user[0] < '0' || user[0] > '9') {
+            ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user);
+            continue;
+        }
+
+        if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) {
+            continue;
+        }
+
+        if (stat(pkgdir, &s) < 0) {
+            free(pkgdir);
+            continue;
+        }
+
+        if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, uid, flags) < 0) {
+            ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno));
+            ret |= -1;
+        }
+        free(pkgdir);
+    }
+
+    closedir(d);
+    free(primarydir);
+    free(userdir);
     return ret;
 }
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 40fc13f..a078e1c 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -129,10 +129,10 @@
     return idmap(arg[0], arg[1], atoi(arg[2]));
 }
 
-static int do_restorecon_data(char **arg __attribute__((unused)),
-    char reply[REPLY_MAX] __attribute__((unused)))
+static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused)))
 {
-    return restorecon_data();
+    return restorecon_data(arg[0], arg[1], atoi(arg[2]));
+                             /* pkgName, seinfo, uid*/
 }
 
 struct cmdinfo {
@@ -159,7 +159,7 @@
     { "mkuserdata",           4, do_mk_user_data },
     { "rmuser",               1, do_rm_user },
     { "idmap",                3, do_idmap },
-    { "restorecondata",       0, do_restorecon_data },
+    { "restorecondata",       3, do_restorecon_data },
 };
 
 static int readx(int s, void *_buf, int count)
@@ -541,6 +541,27 @@
     }
 }
 
+static int log_callback(int type, const char *fmt, ...) {
+    va_list ap;
+    int priority;
+
+    switch (type) {
+    case SELINUX_WARNING:
+        priority = ANDROID_LOG_WARN;
+        break;
+    case SELINUX_INFO:
+        priority = ANDROID_LOG_INFO;
+        break;
+    default:
+        priority = ANDROID_LOG_ERROR;
+        break;
+    }
+    va_start(ap, fmt);
+    LOG_PRI_VA(priority, "SELinux", fmt, ap);
+    va_end(ap);
+    return 0;
+}
+
 int main(const int argc, const char *argv[]) {
     char buf[BUFFER_MAX];
     struct sockaddr addr;
@@ -550,6 +571,10 @@
 
     ALOGI("installd firing up\n");
 
+    union selinux_callback cb;
+    cb.func_log = log_callback;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
     if (initialize_globals() < 0) {
         ALOGE("Could not initialize globals; exiting.\n");
         exit(1);
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 8f4da65..671d031 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -1022,7 +1022,13 @@
         // Make the profile directory write-only for group and other. Owner can rwx it.
         if (chmod(profile_dir, 0711) < 0) {
             ALOGE("cannot chown profile dir '%s': %s\n", profile_dir, strerror(errno));
-            unlink(profile_dir);
+            rmdir(profile_dir);
+            return -1;
+        }
+
+        if (selinux_android_restorecon(profile_dir, 0) < 0) {
+            ALOGE("cannot restorecon profile dir '%s': %s\n", profile_dir, strerror(errno));
+            rmdir(profile_dir);
             return -1;
         }
     }
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index e63a0d0..3bc978d 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -27,11 +27,6 @@
 // ---------------------------------------------------------------------------
 namespace android {
 
-// Global variables
-extern int                 mArgC;
-extern const char* const*  mArgV;
-extern int                 mArgLen;
-
 class IPCThreadState;
 
 class ProcessState : public virtual RefBase
@@ -62,12 +57,6 @@
             wp<IBinder>         getWeakProxyForHandle(int32_t handle);
             void                expungeHandle(int32_t handle, IBinder* binder);
 
-            void                setArgs(int argc, const char* const argv[]);
-            int                 getArgC() const;
-            const char* const*  getArgV() const;
-
-            void                setArgV0(const char* txt);
-
             void                spawnPooledThread(bool isMain);
             
             status_t            setThreadPoolMaxThreadCount(size_t maxThreads);
diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h
index f8267bf..a4718b9 100644
--- a/include/gui/DisplayEventReceiver.h
+++ b/include/gui/DisplayEventReceiver.h
@@ -49,7 +49,7 @@
         struct Header {
             uint32_t type;
             uint32_t id;
-            nsecs_t timestamp;
+            nsecs_t timestamp __attribute__((aligned(8)));
         };
 
         struct VSync {
diff --git a/include/media/openmax/OMX_Types.h b/include/media/openmax/OMX_Types.h
index 03fd4bc..9dec372 100644
--- a/include/media/openmax/OMX_Types.h
+++ b/include/media/openmax/OMX_Types.h
@@ -48,6 +48,8 @@
 #ifndef OMX_Types_h
 #define OMX_Types_h
 
+#include <stdint.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -160,10 +162,10 @@
 typedef signed short OMX_S16;
 
 /** OMX_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */
-typedef unsigned long OMX_U32;
+typedef uint32_t OMX_U32;
 
 /** OMX_S32 is a 32 bit signed quantity that is 32 bit word aligned */
-typedef signed long OMX_S32;
+typedef int32_t OMX_S32;
 
 
 /* Users with compilers that cannot accept the "long long" designation should
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 19ed047..303d6cf 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -48,11 +48,6 @@
 
 namespace android {
  
-// Global variables
-int                 mArgC;
-const char* const*  mArgV;
-int                 mArgLen;
-
 class PoolThread : public Thread
 {
 public:
@@ -280,36 +275,6 @@
     if (e && e->binder == binder) e->binder = NULL;
 }
 
-void ProcessState::setArgs(int argc, const char* const argv[])
-{
-    mArgC = argc;
-    mArgV = (const char **)argv;
-
-    mArgLen = 0;
-    for (int i=0; i<argc; i++) {
-        mArgLen += strlen(argv[i]) + 1;
-    }
-    mArgLen--;
-}
-
-int ProcessState::getArgC() const
-{
-    return mArgC;
-}
-
-const char* const* ProcessState::getArgV() const
-{
-    return mArgV;
-}
-
-void ProcessState::setArgV0(const char* txt)
-{
-    if (mArgV != NULL) {
-        strncpy((char*)mArgV[0], txt, mArgLen);
-        set_process_name(txt);
-    }
-}
-
 String8 ProcessState::makeBinderThreadName() {
     int32_t s = android_atomic_add(1, &mThreadPoolSeq);
     String8 name;
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index 93ec0ce..3c0306c 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -138,7 +138,7 @@
     if (size < getFlattenedSize() || count < getFdCount()) {
         return NO_MEMORY;
     }
-    FlattenableUtils::write(buffer, size, getFdCount());
+    FlattenableUtils::write(buffer, size, (uint32_t)getFdCount());
     if (isValid()) {
         *fds++ = mFenceFd;
         count--;
@@ -156,7 +156,7 @@
         return NO_MEMORY;
     }
 
-    size_t numFds;
+    uint32_t numFds;
     FlattenableUtils::read(buffer, size, numFds);
 
     if (numFds > 1) {
diff --git a/opengl/libagl/fixed_asm.S b/opengl/libagl/fixed_asm.S
index 05044f2..5e08856 100644
--- a/opengl/libagl/fixed_asm.S
+++ b/opengl/libagl/fixed_asm.S
@@ -17,7 +17,7 @@
 
 
     .text
-    .align
+    .align 2
     
     .global gglFloatToFixed
     .type gglFloatToFixed, %function
diff --git a/opengl/libagl/iterators.S b/opengl/libagl/iterators.S
index 8c86482..8fe9039 100644
--- a/opengl/libagl/iterators.S
+++ b/opengl/libagl/iterators.S
@@ -17,7 +17,7 @@
 
 
     .text
-    .align
+    .align 2
     .arm
     
     .global iterators0032
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index e528831..1fcc048 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -188,12 +188,17 @@
     LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
 
 #if defined(__LP64__)
+    cnx->libEgl   = load_wrapper("/system/lib64/libEGL.so");
     cnx->libGles2 = load_wrapper("/system/lib64/libGLESv2.so");
     cnx->libGles1 = load_wrapper("/system/lib64/libGLESv1_CM.so");
 #else
+    cnx->libEgl   = load_wrapper("/system/lib/libEGL.so");
     cnx->libGles2 = load_wrapper("/system/lib/libGLESv2.so");
     cnx->libGles1 = load_wrapper("/system/lib/libGLESv1_CM.so");
 #endif
+    LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
+            "couldn't load system EGL wrapper libraries");
+
     LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
             "couldn't load system OpenGL ES wrapper libraries");
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index d96b54f..22990f3 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -877,11 +877,14 @@
     return err;
 }
 
-static __eglMustCastToProperFunctionPointerType findBuiltinGLWrapper(
+static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
         const char* procname) {
     const egl_connection_t* cnx = &gEGLImpl;
     void* proc = NULL;
 
+    proc = dlsym(cnx->libEgl, procname);
+    if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
+
     proc = dlsym(cnx->libGles2, procname);
     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
 
@@ -912,7 +915,7 @@
     addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
     if (addr) return addr;
 
-    addr = findBuiltinGLWrapper(procname);
+    addr = findBuiltinWrapper(procname);
     if (addr) return addr;
 
     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index b905ea0..9858276 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -44,6 +44,7 @@
     EGLint              minor;
     egl_t               egl;
 
+    void*               libEgl;
     void*               libGles1;
     void*               libGles2;
 };
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bc559cc..943ed02 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2639,7 +2639,7 @@
             looper->sendMessage(this, Message(MSG_API_CALL));
             barrier.wait();
         }
-        return NO_ERROR;
+        return result;
     }
 
     /*
@@ -2649,7 +2649,7 @@
     virtual void handleMessage(const Message& message) {
         android_atomic_release_load(&memoryBarrier);
         if (message.what == MSG_API_CALL) {
-            impl->asBinder()->transact(code, data[0], reply);
+            result = impl->asBinder()->transact(code, data[0], reply);
             barrier.open();
         } else if (message.what == MSG_EXIT) {
             exitRequested = true;