Add a native class to interact with DropBoxManager.

Test: Not written yet
Change-Id: I63ed888bd76f75c78a244a1bffae2d26f3b5f055
diff --git a/core/java/android/os/DropBoxManager.aidl b/core/java/android/os/DropBoxManager.aidl
index 6474ec2..241e93b 100644
--- a/core/java/android/os/DropBoxManager.aidl
+++ b/core/java/android/os/DropBoxManager.aidl
@@ -16,4 +16,4 @@
 
 package android.os;
 
-parcelable DropBoxManager.Entry;
+parcelable DropBoxManager.Entry cpp_header "android/os/DropBoxManager.h";
diff --git a/core/java/com/android/internal/os/IDropBoxManagerService.aidl b/core/java/com/android/internal/os/IDropBoxManagerService.aidl
index d067926..d16579c 100644
--- a/core/java/com/android/internal/os/IDropBoxManagerService.aidl
+++ b/core/java/com/android/internal/os/IDropBoxManagerService.aidl
@@ -17,7 +17,6 @@
 package com.android.internal.os;
 
 import android.os.DropBoxManager;
-import android.os.ParcelFileDescriptor;
 
 /**
  * "Backend" interface used by {@link android.os.DropBoxManager} to talk to the
diff --git a/libs/services/Android.mk b/libs/services/Android.mk
new file mode 100644
index 0000000..cbfd4b3
--- /dev/null
+++ b/libs/services/Android.mk
@@ -0,0 +1,43 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+# Provides C++ wrappers for system services.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libservices
+LOCAL_SRC_FILES := \
+    ../../core/java/com/android/internal/os/IDropBoxManagerService.aidl \
+    src/os/DropBoxManager.cpp
+
+LOCAL_AIDL_INCLUDES := \
+    $(LOCAL_PATH)/../../core/java
+LOCAL_C_INCLUDES := \
+    system/core/include
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    liblog \
+    libcutils \
+    libutils
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
+
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+
+include $(BUILD_SHARED_LIBRARY)
+
+
diff --git a/libs/services/include/android/os/DropBoxManager.h b/libs/services/include/android/os/DropBoxManager.h
new file mode 100644
index 0000000..8717178
--- /dev/null
+++ b/libs/services/include/android/os/DropBoxManager.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef _ANDROID_OS_DROPBOXMANAGER_H
+#define _ANDROID_OS_DROPBOXMANAGER_H
+
+#include <android-base/unique_fd.h>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <binder/Status.h>
+#include <utils/RefBase.h>
+
+#include <vector>
+
+namespace android {
+namespace os {
+
+using namespace android;
+using namespace android::base;
+using namespace android::binder;
+using namespace std;
+
+class DropBoxManager : public virtual RefBase
+{
+public:
+    enum {
+        IS_EMPTY = 1,
+        IS_TEXT = 2,
+        IS_GZIPPED = 4
+    };
+
+    DropBoxManager();
+    virtual ~DropBoxManager();
+
+    static sp<DropBoxManager> create();
+
+    // Create a new entry with plain text contents.
+    Status addText(const String16& tag, const string& text);
+
+    // Create a new Entry with byte array contents. Makes a copy of the data.
+    Status addData(const String16& tag, uint8_t const* data, size_t size, int flags);
+
+    // Create a new Entry from a file. The file will be opened in this process
+    // and a handle will be passed to the system process, so no additional permissions
+    // are required from the system process.  Returns NULL if the file can't be opened.
+    Status addFile(const String16& tag, const string& filename, int flags);
+    
+    class Entry : public virtual RefBase, public Parcelable {
+    public:
+        Entry();
+        virtual ~Entry();
+
+        virtual status_t writeToParcel(Parcel* out) const;
+        virtual status_t readFromParcel(const Parcel* in);
+        
+    private:
+        Entry(const String16& tag, int32_t flags);
+        Entry(const String16& tag, int32_t flags, int fd);
+
+        String16 mTag;
+        int64_t mTimeMillis;
+        int32_t mFlags;
+
+        vector<uint8_t> mData;
+        unique_fd mFd;
+
+        friend class DropBoxManager;
+    };
+
+private:
+    enum {
+        HAS_BYTE_ARRAY = 8
+    };
+
+    Status add(const Entry& entry);
+};
+
+}} // namespace android::os
+
+#endif // _ANDROID_OS_DROPBOXMANAGER_H
+
diff --git a/libs/services/src/os/DropBoxManager.cpp b/libs/services/src/os/DropBoxManager.cpp
new file mode 100644
index 0000000..bbb45f0
--- /dev/null
+++ b/libs/services/src/os/DropBoxManager.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#define LOG_TAG "DropBoxManager"
+
+#include <android/os/DropBoxManager.h>
+
+#include <binder/IServiceManager.h>
+#include <com/android/internal/os/IDropBoxManagerService.h>
+#include <cutils/log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace android {
+namespace os {
+
+using namespace ::com::android::internal::os;
+
+DropBoxManager::Entry::Entry()
+    :mTag(),
+     mTimeMillis(0),
+     mFlags(IS_EMPTY),
+     mData(),
+     mFd()
+{
+    mFlags = IS_EMPTY;
+}
+
+DropBoxManager::Entry::Entry(const String16& tag, int32_t flags)
+    :mTag(tag),
+     mTimeMillis(0),
+     mFlags(flags),
+     mData(),
+     mFd()
+{
+}
+
+DropBoxManager::Entry::Entry(const String16& tag, int32_t flags, int fd)
+    :mTag(tag),
+     mTimeMillis(0),
+     mFlags(flags),
+     mData(),
+     mFd(fd)
+{
+}
+
+DropBoxManager::Entry::~Entry()
+{
+}
+
+status_t
+DropBoxManager::Entry::writeToParcel(Parcel* out) const
+{
+    status_t err;
+
+    err = out->writeString16(mTag);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    err = out->writeInt64(mTimeMillis);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    if (mFd.get() != -1) {
+        err = out->writeInt32(mFlags & ~HAS_BYTE_ARRAY);  // Clear bit just to be safe
+        if (err != NO_ERROR) {
+            return err;
+        }
+        ALOGD("writing fd %d\n", mFd.get());
+        err = out->writeParcelFileDescriptor(mFd);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    } else {
+        err = out->writeInt32(mFlags | HAS_BYTE_ARRAY);
+        if (err != NO_ERROR) {
+            return err;
+        }
+        err = out->writeByteVector(mData);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t
+DropBoxManager::Entry::readFromParcel(const Parcel* in)
+{
+    status_t err;
+
+    err = in->readString16(&mTag);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    err = in->readInt64(&mTimeMillis);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    err = in->readInt32(&mFlags);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    if ((mFlags & HAS_BYTE_ARRAY) != 0) {
+        err = in->readByteVector(&mData);
+        if (err != NO_ERROR) {
+            return err;
+        }
+        mFlags &= ~HAS_BYTE_ARRAY;
+    } else {
+        int fd;
+        fd = in->readParcelFileDescriptor();
+        if (fd == -1) {
+            return EBADF;
+        }
+        fd = dup(fd);
+        if (fd == -1) {
+            return errno;
+        }
+        mFd.reset(fd);
+    }
+
+    return NO_ERROR;
+}
+
+
+DropBoxManager::DropBoxManager()
+{
+}
+
+DropBoxManager::~DropBoxManager()
+{
+}
+
+Status
+DropBoxManager::addText(const String16& tag, const string& text)
+{
+    Entry entry(tag, IS_TEXT);
+    entry.mData.assign(text.c_str(), text.c_str() + text.size());
+    return add(entry);
+}
+
+Status
+DropBoxManager::addData(const String16& tag, uint8_t const* data,
+        size_t size, int flags)
+{
+    Entry entry(tag, flags);
+    entry.mData.assign(data, data+size);
+    return add(entry);
+}
+
+Status
+DropBoxManager::addFile(const String16& tag, const string& filename, int flags)
+{
+    int fd = open(filename.c_str(), O_RDONLY);
+    if (fd == -1) {
+        string message("addFile can't open file: ");
+        message += filename;
+        ALOGW("DropboxManager: %s", message.c_str());
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, message.c_str());
+    }
+
+    Entry entry(tag, flags, fd);
+    return add(entry);
+}
+
+Status
+DropBoxManager::add(const Entry& entry)
+{
+    sp<IDropBoxManagerService> service = interface_cast<IDropBoxManagerService>(
+        defaultServiceManager()->getService(android::String16("dropbox")));
+    if (service == NULL) {
+        return Status::fromExceptionCode(Status::EX_NULL_POINTER, "can't find dropbox service");
+    }
+    return service->add(entry);
+}
+
+}} // namespace android::os
+