Merge "Declare ownership of native_handle_t object"
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 12e8cd1..669f403 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -1235,31 +1235,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/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index 170f20d..aa415d5 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -34,7 +34,8 @@
 class MemoryDealer : public RefBase
 {
 public:
-    MemoryDealer(size_t size, const char* name = 0);
+    MemoryDealer(size_t size, const char* name = 0,
+            uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */ );
 
     virtual sp<IMemory> allocate(size_t size);
     virtual void        deallocate(size_t offset);
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
index 95bdf77..fc6b49c 100644
--- a/include/media/drm/DrmAPI.h
+++ b/include/media/drm/DrmAPI.h
@@ -178,12 +178,16 @@
         // provisioning server.
         //
         // If successful, the opaque provision request blob is returned to the caller.
-        virtual status_t getProvisionRequest(Vector<uint8_t> &request,
+        virtual status_t getProvisionRequest(String8 const &cert_type,
+                                             String8 const &cert_authority,
+                                             Vector<uint8_t> &request,
                                              String8 &defaultUrl) = 0;
 
         // After a provision response is received by the app, it is provided to the
         // Drm plugin using provideProvisionResponse.
-        virtual status_t provideProvisionResponse(Vector<uint8_t> const &response) = 0;
+        virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+                                                  Vector<uint8_t> &certificate,
+                                                  Vector<uint8_t> &wrapped_key) = 0;
 
         // A means of enforcing the contractual requirement for a concurrent stream
         // limit per subscriber across devices is provided via SecureStop.  SecureStop
@@ -290,6 +294,15 @@
                                 bool &match) = 0;
 
 
+        // Compute an RSA signature on the provided message using the algorithm
+        // specified by algorithm.
+        virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+                                 String8 const &algorithm,
+                                 Vector<uint8_t> const &message,
+                                 Vector<uint8_t> const &wrapped_key,
+                                 Vector<uint8_t> &signature) = 0;
+
+
         status_t setListener(const sp<DrmPluginListener>& listener) {
             Mutex::Autolock lock(mEventLock);
             mListener = listener;
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index a14c100..8739625 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -225,8 +225,8 @@
 
 // ----------------------------------------------------------------------------
 
-MemoryDealer::MemoryDealer(size_t size, const char* name)
-    : mHeap(new MemoryHeapBase(size, 0, name)),
+MemoryDealer::MemoryDealer(size_t size, const char* name, uint32_t flags)
+    : mHeap(new MemoryHeapBase(size, flags, name)),
     mAllocator(new SimpleBestFitAllocator(size))
 {    
 }
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 7db344a..9dd90ba 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -432,6 +432,7 @@
     mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
     mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
     mSlots[*outSlot].mFence = Fence::NO_FENCE;
+    mSlots[*outSlot].mRequestBufferCalled = true;
 
     return returnFlags;
 }
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index d3dffdd..1b19626 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -71,11 +71,11 @@
     size_t c = 0;
     if (mGraphicBuffer != 0) {
         c += mGraphicBuffer->getFlattenedSize();
-        FlattenableUtils::align<4>(c);
+        c = FlattenableUtils::align<4>(c);
     }
     if (mFence != 0) {
         c += mFence->getFlattenedSize();
-        FlattenableUtils::align<4>(c);
+        c = FlattenableUtils::align<4>(c);
     }
     return sizeof(int32_t) + c + getPodSize();
 }
@@ -91,11 +91,21 @@
     return c;
 }
 
+static void writeBoolAsInt(void*& buffer, size_t& size, bool b) {
+    FlattenableUtils::write(buffer, size, static_cast<int32_t>(b));
+}
+
+static bool readBoolFromInt(void const*& buffer, size_t& size) {
+    int32_t i;
+    FlattenableUtils::read(buffer, size, i);
+    return static_cast<bool>(i);
+}
+
 status_t IGraphicBufferConsumer::BufferItem::flatten(
         void*& buffer, size_t& size, int*& fds, size_t& count) const {
 
     // make sure we have enough space
-    if (count < BufferItem::getFlattenedSize()) {
+    if (size < BufferItem::getFlattenedSize()) {
         return NO_MEMORY;
     }
 
@@ -128,12 +138,12 @@
     FlattenableUtils::write(buffer, size, mTransform);
     FlattenableUtils::write(buffer, size, mScalingMode);
     FlattenableUtils::write(buffer, size, mTimestamp);
-    FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
+    writeBoolAsInt(buffer, size, mIsAutoTimestamp);
     FlattenableUtils::write(buffer, size, mFrameNumber);
     FlattenableUtils::write(buffer, size, mBuf);
-    FlattenableUtils::write(buffer, size, mIsDroppable);
-    FlattenableUtils::write(buffer, size, mAcquireCalled);
-    FlattenableUtils::write(buffer, size, mTransformToDisplayInverse);
+    writeBoolAsInt(buffer, size, mIsDroppable);
+    writeBoolAsInt(buffer, size, mAcquireCalled);
+    writeBoolAsInt(buffer, size, mTransformToDisplayInverse);
 
     return NO_ERROR;
 }
@@ -170,12 +180,12 @@
     FlattenableUtils::read(buffer, size, mTransform);
     FlattenableUtils::read(buffer, size, mScalingMode);
     FlattenableUtils::read(buffer, size, mTimestamp);
-    FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
+    mIsAutoTimestamp = readBoolFromInt(buffer, size);
     FlattenableUtils::read(buffer, size, mFrameNumber);
     FlattenableUtils::read(buffer, size, mBuf);
-    FlattenableUtils::read(buffer, size, mIsDroppable);
-    FlattenableUtils::read(buffer, size, mAcquireCalled);
-    FlattenableUtils::read(buffer, size, mTransformToDisplayInverse);
+    mIsDroppable = readBoolFromInt(buffer, size);
+    mAcquireCalled = readBoolFromInt(buffer, size);
+    mTransformToDisplayInverse = readBoolFromInt(buffer, size);
 
     return NO_ERROR;
 }
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 5aa34a5..7943476 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -24,7 +24,9 @@
 
 #include <ui/GraphicBuffer.h>
 
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
 #include <gui/BufferQueue.h>
 
 namespace android {
@@ -32,20 +34,12 @@
 class BufferQueueTest : public ::testing::Test {
 
 public:
-    static const String16 PRODUCER_NAME;
-    static const String16 CONSUMER_NAME;
-
 protected:
     BufferQueueTest() {
         const ::testing::TestInfo* const testInfo =
             ::testing::UnitTest::GetInstance()->current_test_info();
         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
                 testInfo->name());
-
-        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
-        sp<IServiceManager> serviceManager = defaultServiceManager();
-        serviceManager->addService(PRODUCER_NAME, mProducer.get());
-        serviceManager->addService(CONSUMER_NAME, mConsumer.get());
     }
 
     ~BufferQueueTest() {
@@ -62,12 +56,13 @@
         ASSERT_GE(*bufferCount, 0);
     }
 
-    sp<BnGraphicBufferProducer> mProducer;
-    sp<BnGraphicBufferConsumer> mConsumer;
-};
+    void createBufferQueue() {
+        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+    }
 
-const String16 BufferQueueTest::PRODUCER_NAME = String16("BQTestProducer");
-const String16 BufferQueueTest::CONSUMER_NAME = String16("BQTestConsumer");
+    sp<IGraphicBufferProducer> mProducer;
+    sp<IGraphicBufferConsumer> mConsumer;
+};
 
 struct DummyConsumer : public BnConsumerListener {
     virtual void onFrameAvailable() {}
@@ -75,7 +70,74 @@
     virtual void onSidebandStreamChanged() {}
 };
 
+// XXX: Tests that fork a process to hold the BufferQueue must run before tests
+// that use a local BufferQueue, or else Binder will get unhappy
+TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) {
+    const String16 PRODUCER_NAME = String16("BQTestProducer");
+    const String16 CONSUMER_NAME = String16("BQTestConsumer");
+
+    pid_t forkPid = fork();
+    ASSERT_NE(forkPid, -1);
+
+    if (forkPid == 0) {
+        // Child process
+        sp<BnGraphicBufferProducer> producer;
+        sp<BnGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+        sp<IServiceManager> serviceManager = defaultServiceManager();
+        serviceManager->addService(PRODUCER_NAME, producer.get());
+        serviceManager->addService(CONSUMER_NAME, consumer.get());
+        ProcessState::self()->startThreadPool();
+        IPCThreadState::self()->joinThreadPool();
+        LOG_ALWAYS_FATAL("Shouldn't be here");
+    }
+
+    sp<IServiceManager> serviceManager = defaultServiceManager();
+    sp<IBinder> binderProducer =
+        serviceManager->getService(PRODUCER_NAME);
+    mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
+    EXPECT_TRUE(mProducer != NULL);
+    sp<IBinder> binderConsumer =
+        serviceManager->getService(CONSUMER_NAME);
+    mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
+    EXPECT_TRUE(mConsumer != NULL);
+
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK,
+            mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output));
+
+    int slot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+                    GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+
+    uint32_t* dataIn;
+    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
+            reinterpret_cast<void**>(&dataIn)));
+    *dataIn = 0x12345678;
+    ASSERT_EQ(OK, buffer->unlock());
+
+    IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+    IGraphicBufferConsumer::BufferItem item;
+    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+
+    uint32_t* dataOut;
+    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
+            reinterpret_cast<void**>(&dataOut)));
+    ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
+}
+
 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
     IGraphicBufferProducer::QueueBufferOutput qbo;
@@ -109,6 +171,7 @@
 }
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
 
@@ -125,6 +188,7 @@
 }
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
 
@@ -139,6 +203,7 @@
 }
 
 TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -187,9 +252,11 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
 TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -243,9 +310,11 @@
     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, buffer->unlock());
 }
 
 TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -283,6 +352,7 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
 } // namespace android
diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp
index ff91260..1428945 100644
--- a/opengl/tests/lib/WindowSurface.cpp
+++ b/opengl/tests/lib/WindowSurface.cpp
@@ -56,7 +56,7 @@
 
     sp<SurfaceControl> sc = surfaceComposerClient->createSurface(
             String8("Benchmark"), width, height,
-            PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eOpaque);
+            PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
     if (sc == NULL || !sc->isValid()) {
         fprintf(stderr, "Failed to create SurfaceControl\n");
         return;
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 94fc0af..b70ea76 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -813,7 +813,7 @@
                 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                     // Device was removed before INotify noticed.
                     ALOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d "
-                            "capacity: %d errno: %d)\n",
+                            "capacity: %zu errno: %d)\n",
                             device->fd, readSize, bufferSize, capacity, errno);
                     deviceChanged = true;
                     closeDeviceLocked(device);
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 95eee06..dbfc957 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -148,7 +148,7 @@
         return false;
     }
     if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
-        ALOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
+        ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
                 pointerCount, MAX_POINTERS);
         return false;
     }
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 66f907a..f27ba96 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -6174,8 +6174,8 @@
             && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
         size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
         if (slotCount > MAX_SLOTS) {
-            ALOGW("MultiTouch Device %s reported %d slots but the framework "
-                    "only supports a maximum of %d slots at this time.",
+            ALOGW("MultiTouch Device %s reported %zu slots but the framework "
+                    "only supports a maximum of %zu slots at this time.",
                     getDeviceName().string(), slotCount, MAX_SLOTS);
             slotCount = MAX_SLOTS;
         }
@@ -6347,7 +6347,7 @@
         // If there are too many axes, start dropping them.
         // Prefer to keep explicitly mapped axes.
         if (mAxes.size() > PointerCoords::MAX_AXES) {
-            ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
+            ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
                     getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
             pruneAxes(true);
             pruneAxes(false);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0650d97..d084bf5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2687,7 +2687,7 @@
             looper->sendMessage(this, Message(MSG_API_CALL));
             barrier.wait();
         }
-        return NO_ERROR;
+        return result;
     }
 
     /*
@@ -2697,7 +2697,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;