storaged: use AIDL to generate storaged binder calls.

Split binder calls into two separate services.

"storaged" service will be used by external clients, e.g. vold.
- Added stub onUserStarted/onUserStopped to prepare for moving
storaged.proto into ce area.

"storaged_pri" private service will be used by storaged cmdline,
e.g. adb shell storaged -u
- Added parcelable UidInfo for private service.
- Change format of perf history to one vector with first 3 elements
showing size of recent/daily/weekly perf history.

Test: adb shell storaged -u -p
Bug: 63740245
Change-Id: Ib0367282a95b6cb0a38f064f0456e849ecccc210
diff --git a/storaged/Android.bp b/storaged/Android.bp
index 6aef8c8..e902712 100644
--- a/storaged/Android.bp
+++ b/storaged/Android.bp
@@ -42,6 +42,12 @@
 
     defaults: ["storaged_defaults"],
 
+    aidl: {
+        export_aidl_headers: true,
+        local_include_dirs: ["binder"],
+        include_dirs: ["frameworks/native/aidl/binder"],
+    },
+
     srcs: [
         "storaged.cpp",
         "storaged_diskstats.cpp",
@@ -49,7 +55,10 @@
         "storaged_service.cpp",
         "storaged_utils.cpp",
         "storaged_uid_monitor.cpp",
+        "uid_info.cpp",
         "storaged.proto",
+        "binder/android/os/IStoraged.aidl",
+        "binder/android/os/storaged/IStoragedPrivate.aidl",
     ],
 
     logtags: ["EventLogTags.logtags"],
diff --git a/storaged/binder/android/os/IStoraged.aidl b/storaged/binder/android/os/IStoraged.aidl
new file mode 100644
index 0000000..f81e904
--- /dev/null
+++ b/storaged/binder/android/os/IStoraged.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/** {@hide} */
+interface IStoraged {
+    void onUserStarted(int userId);
+    void onUserStopped(int userId);
+}
\ No newline at end of file
diff --git a/storaged/binder/android/os/storaged/IStoragedPrivate.aidl b/storaged/binder/android/os/storaged/IStoragedPrivate.aidl
new file mode 100644
index 0000000..9c888e3
--- /dev/null
+++ b/storaged/binder/android/os/storaged/IStoragedPrivate.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storaged;
+
+import android.os.storaged.UidInfo;
+
+/** {@hide} */
+interface IStoragedPrivate {
+    UidInfo[] dumpUids();
+    int[] dumpPerfHistory();
+}
\ No newline at end of file
diff --git a/storaged/binder/android/os/storaged/UidInfo.aidl b/storaged/binder/android/os/storaged/UidInfo.aidl
new file mode 100644
index 0000000..440f386
--- /dev/null
+++ b/storaged/binder/android/os/storaged/UidInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storaged;
+
+parcelable UidInfo cpp_header "include/uid_info.h";
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index f5c78f9..dead656 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -48,6 +48,7 @@
 #include "storaged_info.h"
 #include "storaged_uid_monitor.h"
 #include "storaged.pb.h"
+#include "uid_info.h"
 
 using namespace std;
 using namespace android;
@@ -56,8 +57,8 @@
 #define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 )
 #define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 )
 #define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 )
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT (300)
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_FLUSH_PROTO (3600)
+#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT ( 300 )
+#define DEFAULT_PERIODIC_CHORES_INTERVAL_FLUSH_PROTO ( 3600 )
 
 // UID IO threshold in bytes
 #define DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD ( 1024 * 1024 * 1024ULL )
@@ -96,11 +97,11 @@
         return mStarttime;
     }
 
-    unordered_map<uint32_t, struct uid_info> get_uids(void) {
+    unordered_map<uint32_t, uid_info> get_uids(void) {
         return mUidm.get_uid_io_stats();
     }
 
-    vector<vector<uint32_t>> get_perf_history(void) {
+    vector<int> get_perf_history(void) {
         return storage_info->get_perf_history();
     }
 
diff --git a/storaged/include/storaged_info.h b/storaged/include/storaged_info.h
index 8b07862..125b5a8 100644
--- a/storaged/include/storaged_info.h
+++ b/storaged/include/storaged_info.h
@@ -72,7 +72,7 @@
     void refresh(IOPerfHistory* perf_history);
     void update_perf_history(uint32_t bw,
                              const time_point<system_clock>& tp);
-    vector<vector<uint32_t>> get_perf_history(void);
+    vector<int> get_perf_history();
 };
 
 class emmc_info_t : public storage_info_t {
diff --git a/storaged/include/storaged_service.h b/storaged/include/storaged_service.h
index b7fe5b8..3246caf 100644
--- a/storaged/include/storaged_service.h
+++ b/storaged/include/storaged_service.h
@@ -19,47 +19,34 @@
 
 #include <vector>
 
-#include <binder/IInterface.h>
-#include <binder/IBinder.h>
+#include <binder/BinderService.h>
 
-#include "storaged.h"
+#include "android/os/BnStoraged.h"
+#include "android/os/storaged/BnStoragedPrivate.h"
 
 using namespace std;
-using namespace android;
+using namespace android::os;
+using namespace android::os::storaged;
 
-// Interface
-class IStoraged : public IInterface {
+class StoragedService : public BinderService<StoragedService>, public BnStoraged {
 public:
-    enum {
-        DUMPUIDS = IBinder::FIRST_CALL_TRANSACTION,
-        DUMPPERF,
-    };
-    // Request the service to run the test function
-    virtual vector<struct uid_info> dump_uids(const char* option) = 0;
-    virtual vector<vector<uint32_t>> dump_perf_history(const char* option) = 0;
+    static status_t start();
+    static char const* getServiceName() { return "storaged"; }
+    virtual status_t dump(int fd, const Vector<String16> &args) override;
 
-    DECLARE_META_INTERFACE(Storaged);
+    binder::Status onUserStarted(int32_t userId);
+    binder::Status onUserStopped(int32_t userId);
 };
 
-// Client
-class BpStoraged : public BpInterface<IStoraged> {
+class StoragedPrivateService : public BinderService<StoragedPrivateService>, public BnStoragedPrivate {
 public:
-    BpStoraged(const sp<IBinder>& impl) : BpInterface<IStoraged>(impl){};
-    virtual vector<struct uid_info> dump_uids(const char* option);
-    virtual vector<vector<uint32_t>> dump_perf_history(const char* option);
+    static status_t start();
+    static char const* getServiceName() { return "storaged_pri"; }
+
+    binder::Status dumpUids(vector<UidInfo>* _aidl_return);
+    binder::Status dumpPerfHistory(vector<int32_t>* _aidl_return);
 };
 
-// Server
-class BnStoraged : public BnInterface<IStoraged> {
-    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
-};
-
-class Storaged : public BnStoraged {
-    virtual vector<struct uid_info> dump_uids(const char* option);
-    virtual vector<vector<uint32_t>> dump_perf_history(const char* option);
-    virtual status_t dump(int fd, const Vector<String16>& args);
-};
-
-sp<IStoraged> get_storaged_service();
+sp<IStoragedPrivate> get_storaged_pri_service();
 
 #endif /* _STORAGED_SERVICE_H_ */
\ No newline at end of file
diff --git a/storaged/include/storaged_uid_monitor.h b/storaged/include/storaged_uid_monitor.h
index d2c7105..abf2475 100644
--- a/storaged/include/storaged_uid_monitor.h
+++ b/storaged/include/storaged_uid_monitor.h
@@ -24,47 +24,13 @@
 #include <vector>
 
 #include "storaged.pb.h"
+#include "uid_info.h"
 
 using namespace storaged_proto;
+using namespace android::os::storaged;
 
-enum uid_stat_t {
-    FOREGROUND = 0,
-    BACKGROUND = 1,
-    UID_STATS = 2
-};
-
-enum charger_stat_t {
-    CHARGER_OFF = 0,
-    CHARGER_ON = 1,
-    CHARGER_STATS = 2
-};
-
-enum io_type_t {
-    READ = 0,
-    WRITE = 1,
-    IO_TYPES = 2
-};
-
-struct io_stats {
-    uint64_t rchar;                 // characters read
-    uint64_t wchar;                 // characters written
-    uint64_t read_bytes;            // bytes read (from storage layer)
-    uint64_t write_bytes;           // bytes written (to storage layer)
-    uint64_t fsync;                 // number of fsync syscalls
-};
-
-struct task_info {
-    std::string comm;
-    pid_t pid;
-    struct io_stats io[UID_STATS];
-    bool parse_task_io_stats(std::string&& s);
-};
-
-struct uid_info {
-    uint32_t uid;                   // user id
-    std::string name;               // package name
-    struct io_stats io[UID_STATS];    // [0]:foreground [1]:background
-    std::unordered_map<uint32_t, task_info> tasks; // mapped from pid
+class uid_info : public UidInfo {
+public:
     bool parse_uid_io_stats(std::string&& s);
 };
 
@@ -104,7 +70,7 @@
 class uid_monitor {
 private:
     // last dump from /proc/uid_io/stats, uid -> uid_info
-    std::unordered_map<uint32_t, struct uid_info> last_uid_io_stats;
+    std::unordered_map<uint32_t, uid_info> last_uid_io_stats;
     // current io usage for next report, app name -> uid_io_usage
     std::unordered_map<std::string, struct uid_io_usage> curr_io_stats;
     // io usage records, end timestamp -> {start timestamp, vector of records}
@@ -119,7 +85,7 @@
     const bool enable;
 
     // reads from /proc/uid_io/stats
-    std::unordered_map<uint32_t, struct uid_info> get_uid_io_stats_locked();
+    std::unordered_map<uint32_t, uid_info> get_uid_io_stats_locked();
     // flushes curr_io_stats to records
     void add_records_locked(uint64_t curr_ts);
     // updates curr_io_stats and set last_uid_io_stats
@@ -135,7 +101,7 @@
     // called by storaged main thread
     void init(charger_stat_t stat, const UidIOUsage& proto);
     // called by storaged -u
-    std::unordered_map<uint32_t, struct uid_info> get_uid_io_stats();
+    std::unordered_map<uint32_t, uid_info> get_uid_io_stats();
     // called by dumpsys
     std::map<uint64_t, struct uid_records> dump(
         double hours, uint64_t threshold, bool force_report,
diff --git a/storaged/include/storaged_utils.h b/storaged/include/storaged_utils.h
index 3b595b7..b866d20 100644
--- a/storaged/include/storaged_utils.h
+++ b/storaged/include/storaged_utils.h
@@ -24,6 +24,8 @@
 
 #include "storaged.h"
 
+using namespace android::os::storaged;
+
 // Diskstats
 bool parse_disk_stats(const char* disk_stats_path, struct disk_stats* stats);
 struct disk_perf get_disk_perf(struct disk_stats* stats);
@@ -31,10 +33,10 @@
 void add_disk_stats(struct disk_stats* src, struct disk_stats* dst);
 
 // UID I/O
-void sort_running_uids_info(std::vector<struct uid_info> &uids);
+void sort_running_uids_info(std::vector<UidInfo> &uids);
 
 // Logging
-void log_console_running_uids_info(const std::vector<struct uid_info>& uids, bool flag_dump_task);
-void log_console_perf_history(const vector<vector<uint32_t>>& perf_history);
+void log_console_running_uids_info(const std::vector<UidInfo>& uids, bool flag_dump_task);
+void log_console_perf_history(const vector<int>& perf_history);
 
 #endif /* _STORAGED_UTILS_H_ */
diff --git a/storaged/include/uid_info.h b/storaged/include/uid_info.h
new file mode 100644
index 0000000..4398a0d
--- /dev/null
+++ b/storaged/include/uid_info.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 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 _UID_INFO_H_
+#define _UID_INFO_H_
+
+#include <string>
+#include <unordered_map>
+
+namespace android {
+namespace os {
+namespace storaged {
+
+enum uid_stat_t {
+    FOREGROUND = 0,
+    BACKGROUND = 1,
+    UID_STATS = 2
+};
+
+enum charger_stat_t {
+    CHARGER_OFF = 0,
+    CHARGER_ON = 1,
+    CHARGER_STATS = 2
+};
+
+enum io_type_t {
+    READ = 0,
+    WRITE = 1,
+    IO_TYPES = 2
+};
+
+struct io_stats {
+    uint64_t rchar;                 // characters read
+    uint64_t wchar;                 // characters written
+    uint64_t read_bytes;            // bytes read (from storage layer)
+    uint64_t write_bytes;           // bytes written (to storage layer)
+    uint64_t fsync;                 // number of fsync syscalls
+};
+
+class task_info {
+public:
+    std::string comm;
+    pid_t pid;
+    io_stats io[UID_STATS];
+    bool parse_task_io_stats(std::string&& s);
+};
+
+class UidInfo : public Parcelable {
+public:
+    uint32_t uid;                     // user id
+    std::string name;                 // package name
+    io_stats io[UID_STATS];           // [0]:foreground [1]:background
+    std::unordered_map<uint32_t, task_info> tasks; // mapped from pid
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+};
+
+} // namespace storaged
+} // namespace os
+} // namespace android
+
+#endif /*  _UID_INFO_H_ */
\ No newline at end of file
diff --git a/storaged/main.cpp b/storaged/main.cpp
index adc550a..0bc36e5 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -43,22 +43,23 @@
 #include <storaged_utils.h>
 
 using namespace std;
+using namespace android;
 
-sp<storaged_t> storaged;
+sp<storaged_t> storaged_sp;
 
 // Function of storaged's main thread
 void* storaged_main(void* /* unused */) {
-    storaged = new storaged_t();
+    storaged_sp = new storaged_t();
 
-    storaged->load_proto();
-    storaged->init_battery_service();
-    storaged->report_storage_info();
+    storaged_sp->load_proto();
+    storaged_sp->init_battery_service();
+    storaged_sp->report_storage_info();
 
     LOG_TO(SYSTEM, INFO) << "storaged: Start";
 
     for (;;) {
-        storaged->event_checked();
-        storaged->pause();
+        storaged_sp->event_checked();
+        storaged_sp->pause();
     }
     return NULL;
 }
@@ -82,39 +83,33 @@
     for (;;) {
         int opt_idx = 0;
         static struct option long_options[] = {
-            {"start",       no_argument,        0, 's'},
-            {"kill",        no_argument,        0, 'k'},
-            {"uid",         no_argument,        0, 'u'},
-            {"task",        no_argument,        0, 't'},
-            {"perf",        no_argument,        0, 'p'},
-            {"help",        no_argument,        0, 'h'}
+            {"perf",        no_argument,    nullptr, 'p'},
+            {"start",       no_argument,    nullptr, 's'},
+            {"task",        no_argument,    nullptr, 't'},
+            {"uid",         no_argument,    nullptr, 'u'},
+            {nullptr,       0,              nullptr,  0}
         };
-        opt = getopt_long(argc, argv, ":skhutp", long_options, &opt_idx);
+        opt = getopt_long(argc, argv, ":pstu", long_options, &opt_idx);
         if (opt == -1) {
             break;
         }
 
         switch (opt) {
+        case 'p':
+            flag_dump_perf = true;
+            break;
         case 's':
             flag_main_service = true;
             break;
-        case 'u':
-            flag_dump_uid = true;
-            break;
         case 't':
             flag_dump_task = true;
             break;
-        case 'p':
-            flag_dump_perf = true;
+        case 'u':
+            flag_dump_uid = true;
             break;
-        case 'h':
+        default:
             help_message();
             return 0;
-        case '?':
-        default:
-            fprintf(stderr, "no supported option\n");
-            help_message();
-            return -1;
         }
     }
 
@@ -137,7 +132,12 @@
             return -1;
         }
 
-        defaultServiceManager()->addService(String16("storaged"), new Storaged());
+        if (StoragedService::start() != android::OK ||
+            StoragedPrivateService::start() != android::OK) {
+            PLOG_TO(SYSTEM, ERROR) << "Failed to start storaged service";
+            return -1;
+        }
+
         android::ProcessState::self()->startThreadPool();
         IPCThreadState::self()->joinThreadPool();
         pthread_join(storaged_main_thread, NULL);
@@ -145,31 +145,33 @@
         return 0;
     }
 
-    sp<IStoraged> storaged_service = get_storaged_service();
+    sp<IStoragedPrivate> storaged_service = get_storaged_pri_service();
     if (storaged_service == NULL) {
         fprintf(stderr, "Cannot find storaged service.\nMaybe run storaged --start first?\n");
         return -1;
     }
 
     if (flag_dump_uid || flag_dump_task) {
-        vector<struct uid_info> res = storaged_service->dump_uids(NULL);
-        if (res.size() == 0) {
-            fprintf(stderr, "UID I/O is not readable in this version of kernel.\n");
+        vector<UidInfo> uid_io;
+        binder::Status status = storaged_service->dumpUids(&uid_io);
+        if (!status.isOk() || uid_io.size() == 0) {
+            fprintf(stderr, "UID I/O info is not available.\n");
             return 0;
         }
 
-        sort_running_uids_info(res);
-        log_console_running_uids_info(res, flag_dump_task);
+        sort_running_uids_info(uid_io);
+        log_console_running_uids_info(uid_io, flag_dump_task);
     }
 
     if (flag_dump_perf) {
-        vector<vector<uint32_t>> res = storaged_service->dump_perf_history(NULL);
-        if (res.size() == 0) {
-            fprintf(stderr, "I/O perf history is empty.\n");
+        vector<int> perf_history;
+        binder::Status status = storaged_service->dumpPerfHistory(&perf_history);
+        if (!status.isOk() || perf_history.size() == 0) {
+            fprintf(stderr, "I/O perf history is not available.\n");
             return 0;
         }
 
-        log_console_perf_history(res);
+        log_console_perf_history(perf_history);
     }
 
     return 0;
diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp
index c5552f6..4243bd7 100644
--- a/storaged/storaged_info.cpp
+++ b/storaged/storaged_info.cpp
@@ -180,28 +180,32 @@
     weekly_perf[nr_weeks++] = week_avg_bw;
 }
 
-vector<vector<uint32_t>> storage_info_t::get_perf_history()
+vector<int> storage_info_t::get_perf_history()
 {
     unique_ptr<lock_t> lock(new lock_t(&si_lock));
 
-    vector<vector<uint32_t>> ret(3);
+    vector<int> ret(3 + recent_perf.size() + daily_perf.size() + weekly_perf.size());
 
-    ret[0].resize(recent_perf.size());
+    ret[0] = recent_perf.size();
+    ret[1] = daily_perf.size();
+    ret[2] = weekly_perf.size();
+
+    int start = 3;
     for (size_t i = 0; i < recent_perf.size(); i++) {
         int idx = (recent_perf.size() + nr_samples - 1 - i) % recent_perf.size();
-        ret[0][i] = recent_perf[idx];
+        ret[start + i] = recent_perf[idx];
     }
 
-    ret[1].resize(daily_perf.size());
+    start += recent_perf.size();
     for (size_t i = 0; i < daily_perf.size(); i++) {
         int idx = (daily_perf.size() + nr_days - 1 - i) % daily_perf.size();
-        ret[1][i] = daily_perf[idx];
+        ret[start + i] = daily_perf[idx];
     }
 
-    ret[2].resize(weekly_perf.size());
+    start += daily_perf.size();
     for (size_t i = 0; i < weekly_perf.size(); i++) {
         int idx = (weekly_perf.size() + nr_weeks - 1 - i) % weekly_perf.size();
-        ret[2][i] = weekly_perf[idx];
+        ret[start + i] = weekly_perf[idx];
     }
 
     return ret;
diff --git a/storaged/storaged_service.cpp b/storaged/storaged_service.cpp
index e4ba380..abfecff 100644
--- a/storaged/storaged_service.cpp
+++ b/storaged/storaged_service.cpp
@@ -35,121 +35,13 @@
 using namespace std;
 using namespace android::base;
 
-extern sp<storaged_t> storaged;
+extern sp<storaged_t> storaged_sp;
 
-vector<struct uid_info> BpStoraged::dump_uids(const char* /*option*/) {
-    Parcel data, reply;
-    data.writeInterfaceToken(IStoraged::getInterfaceDescriptor());
-
-    remote()->transact(DUMPUIDS, data, &reply);
-
-    uint32_t res_size = reply.readInt32();
-    vector<struct uid_info> res(res_size);
-    for (auto&& uid : res) {
-        uid.uid = reply.readInt32();
-        uid.name = reply.readCString();
-        reply.read(&uid.io, sizeof(uid.io));
-
-        uint32_t tasks_size = reply.readInt32();
-        for (uint32_t i = 0; i < tasks_size; i++) {
-            struct task_info task;
-            task.pid = reply.readInt32();
-            task.comm = reply.readCString();
-            reply.read(&task.io, sizeof(task.io));
-            uid.tasks[task.pid] = task;
-        }
-    }
-    return res;
+status_t StoragedService::start() {
+    return BinderService<StoragedService>::publish();
 }
 
-vector<vector<uint32_t>> BpStoraged::dump_perf_history(const char* /*option*/) {
-    Parcel data, reply;
-    data.writeInterfaceToken(IStoraged::getInterfaceDescriptor());
-
-    remote()->transact(DUMPPERF, data, &reply);
-
-    vector<vector<uint32_t>> res(3);
-    uint32_t size = reply.readUint32();
-    res[0].resize(size);
-    for (uint32_t i = 0; i < size; i++) {
-        res[0][i] = reply.readUint32();
-    }
-    size = reply.readUint32();
-    res[1].resize(size);
-    for (uint32_t i = 0; i < size; i++) {
-        res[1][i] = reply.readUint32();
-    }
-    size = reply.readUint32();
-    res[2].resize(size);
-    for (uint32_t i = 0; i < size; i++) {
-        res[2][i] = reply.readUint32();
-    }
-    return res;
-}
-
-IMPLEMENT_META_INTERFACE(Storaged, "Storaged");
-
-status_t BnStoraged::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
-    switch(code) {
-        case DUMPUIDS: {
-                if (!data.checkInterface(this))
-                    return BAD_TYPE;
-                vector<struct uid_info> res = dump_uids(NULL);
-                reply->writeInt32(res.size());
-                for (const auto& uid : res) {
-                    reply->writeInt32(uid.uid);
-                    reply->writeCString(uid.name.c_str());
-                    reply->write(&uid.io, sizeof(uid.io));
-
-                    reply->writeInt32(uid.tasks.size());
-                    for (const auto& task_it : uid.tasks) {
-                        reply->writeInt32(task_it.first);
-                        reply->writeCString(task_it.second.comm.c_str());
-                        reply->write(&task_it.second.io, sizeof(task_it.second.io));
-                    }
-                }
-                return NO_ERROR;
-            }
-            break;
-        case DUMPPERF: {
-            if (!data.checkInterface(this))
-                return BAD_TYPE;
-            vector<vector<uint32_t>> res = dump_perf_history(NULL);
-            reply->writeUint32(res[0].size());
-            for (const auto& item : res[0]) {
-                reply->writeUint32(item);
-            }
-            reply->writeUint32(res[1].size());
-            for (const auto& item : res[1]) {
-                reply->writeUint32(item);
-            }
-            reply->writeUint32(res[2].size());
-            for (const auto& item : res[2]) {
-                reply->writeUint32(item);
-            }
-            return NO_ERROR;
-        }
-        break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-vector<struct uid_info> Storaged::dump_uids(const char* /* option */) {
-    vector<struct uid_info> uids_v;
-    unordered_map<uint32_t, struct uid_info> uids_m = storaged->get_uids();
-
-    for (const auto& it : uids_m) {
-        uids_v.push_back(it.second);
-    }
-    return uids_v;
-}
-
-vector<vector<uint32_t>> Storaged::dump_perf_history(const char* /* option */) {
-    return storaged->get_perf_history();
-}
-
-status_t Storaged::dump(int fd, const Vector<String16>& args) {
+status_t StoragedService::dump(int fd, const Vector<String16>& args) {
     IPCThreadState* self = IPCThreadState::self();
     const int pid = self->getCallingPid();
     const int uid = self->getCallingUid();
@@ -199,7 +91,7 @@
 
     uint64_t last_ts = 0;
     const map<uint64_t, struct uid_records>& records =
-                storaged->get_uid_records(hours, threshold, force_report);
+                storaged_sp->get_uid_records(hours, threshold, force_report);
     for (const auto& it : records) {
         if (last_ts != it.second.start_ts) {
             dprintf(fd, "%" PRIu64, it.second.start_ts);
@@ -241,20 +133,51 @@
     }
 
     if (time_window) {
-        storaged->update_uid_io_interval(time_window);
+        storaged_sp->update_uid_io_interval(time_window);
     }
 
     return NO_ERROR;
 }
 
-sp<IStoraged> get_storaged_service() {
+binder::Status StoragedService::onUserStarted(int32_t userId) {
+    return binder::Status::ok();
+}
+
+binder::Status StoragedService::onUserStopped(int32_t userId) {
+    return binder::Status::ok();
+}
+
+status_t StoragedPrivateService::start() {
+    return BinderService<StoragedPrivateService>::publish();
+}
+
+binder::Status StoragedPrivateService::dumpUids(
+        vector<::android::os::storaged::UidInfo>* _aidl_return) {
+    unordered_map<uint32_t, uid_info> uids_m = storaged_sp->get_uids();
+
+    for (const auto& it : uids_m) {
+        UidInfo uinfo;
+        uinfo.uid = it.second.uid;
+        uinfo.name = it.second.name;
+        uinfo.tasks = it.second.tasks;
+        memcpy(&uinfo.io, &it.second.io, sizeof(uinfo.io));
+        _aidl_return->push_back(uinfo);
+    }
+    return binder::Status::ok();
+}
+
+binder::Status StoragedPrivateService::dumpPerfHistory(
+        vector<int32_t>* _aidl_return) {
+    *_aidl_return = storaged_sp->get_perf_history();
+    return binder::Status::ok();
+}
+
+sp<IStoragedPrivate> get_storaged_pri_service() {
     sp<IServiceManager> sm = defaultServiceManager();
     if (sm == NULL) return NULL;
 
-    sp<IBinder> binder = sm->getService(String16("storaged"));
+    sp<IBinder> binder = sm->getService(String16("storaged_pri"));
     if (binder == NULL) return NULL;
 
-    sp<IStoraged> storaged = interface_cast<IStoraged>(binder);
-
-    return storaged;
+    return interface_cast<IStoragedPrivate>(binder);
 }
diff --git a/storaged/storaged_uid_monitor.cpp b/storaged/storaged_uid_monitor.cpp
index 9295ff2..06a0632 100644
--- a/storaged/storaged_uid_monitor.cpp
+++ b/storaged/storaged_uid_monitor.cpp
@@ -38,6 +38,7 @@
 using namespace android;
 using namespace android::base;
 using namespace android::content::pm;
+using namespace android::os::storaged;
 using namespace storaged_proto;
 
 namespace {
@@ -47,7 +48,7 @@
 
 } // namepsace
 
-std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uid_io_stats()
+std::unordered_map<uint32_t, uid_info> uid_monitor::get_uid_io_stats()
 {
     std::unique_ptr<lock_t> lock(new lock_t(&um_lock));
     return get_uid_io_stats_locked();
@@ -151,9 +152,9 @@
 
 } // namespace
 
-std::unordered_map<uint32_t, struct uid_info> uid_monitor::get_uid_io_stats_locked()
+std::unordered_map<uint32_t, uid_info> uid_monitor::get_uid_io_stats_locked()
 {
-    std::unordered_map<uint32_t, struct uid_info> uid_io_stats;
+    std::unordered_map<uint32_t, uid_info> uid_io_stats;
     std::string buffer;
     if (!ReadFileToString(UID_IO_STATS_PATH, &buffer)) {
         PLOG_TO(SYSTEM, ERROR) << UID_IO_STATS_PATH << ": ReadFileToString failed";
@@ -161,7 +162,7 @@
     }
 
     std::vector<std::string> io_stats = Split(std::move(buffer), "\n");
-    struct uid_info u;
+    uid_info u;
     vector<int> uids;
     vector<std::string*> uid_names;
 
@@ -183,7 +184,7 @@
                 uid_io_stats[u.uid].name = last_uid_io_stats[u.uid].name;
             }
         } else {
-            struct task_info t;
+            task_info t;
             if (!t.parse_task_io_stats(std::move(io_stats[i])))
                 continue;
             uid_io_stats[u.uid].tasks[t.pid] = t;
@@ -301,14 +302,14 @@
 
 void uid_monitor::update_curr_io_stats_locked()
 {
-    std::unordered_map<uint32_t, struct uid_info> uid_io_stats =
+    std::unordered_map<uint32_t, uid_info> uid_io_stats =
         get_uid_io_stats_locked();
     if (uid_io_stats.empty()) {
         return;
     }
 
     for (const auto& it : uid_io_stats) {
-        const struct uid_info& uid = it.second;
+        const uid_info& uid = it.second;
 
         if (curr_io_stats.find(uid.name) == curr_io_stats.end()) {
           curr_io_stats[uid.name] = {};
@@ -334,7 +335,7 @@
             (bg_wr_delta < 0) ? 0 : bg_wr_delta;
 
         for (const auto& task_it : uid.tasks) {
-            const struct task_info& task = task_it.second;
+            const task_info& task = task_it.second;
             const pid_t pid = task_it.first;
             const std::string& comm = task_it.second.comm;
             int64_t task_fg_rd_delta = task.io[FOREGROUND].read_bytes -
diff --git a/storaged/storaged_utils.cpp b/storaged/storaged_utils.cpp
index fcd2484..9260c3a 100644
--- a/storaged/storaged_utils.cpp
+++ b/storaged/storaged_utils.cpp
@@ -42,7 +42,7 @@
 #include <storaged.h>
 #include <storaged_utils.h>
 
-bool cmp_uid_info(struct uid_info l, struct uid_info r) {
+bool cmp_uid_info(const UidInfo& l, const UidInfo& r) {
     // Compare background I/O first.
     for (int i = UID_STATS - 1; i >= 0; i--) {
         uint64_t l_bytes = l.io[i].read_bytes + l.io[i].write_bytes;
@@ -61,12 +61,12 @@
     return l.name < r.name;
 }
 
-void sort_running_uids_info(std::vector<struct uid_info> &uids) {
+void sort_running_uids_info(std::vector<UidInfo> &uids) {
     std::sort(uids.begin(), uids.end(), cmp_uid_info);
 }
 
 // Logging functions
-void log_console_running_uids_info(const std::vector<struct uid_info>& uids, bool flag_dump_task) {
+void log_console_running_uids_info(const std::vector<UidInfo>& uids, bool flag_dump_task) {
     printf("name/uid fg_rchar fg_wchar fg_rbytes fg_wbytes "
            "bg_rchar bg_wchar bg_rbytes bg_wbytes fg_fsync bg_fsync\n");
 
@@ -79,7 +79,7 @@
             uid.io[0].fsync, uid.io[1].fsync);
         if (flag_dump_task) {
             for (const auto& task_it : uid.tasks) {
-                const struct task_info& task = task_it.second;
+                const task_info& task = task_it.second;
                 printf("-> %s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
                         " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
                     task.comm.c_str(),
@@ -92,25 +92,33 @@
     fflush(stdout);
 }
 
-void log_console_perf_history(const vector<vector<uint32_t>>& perf_history) {
-    if (perf_history.size() != 3) {
+void log_console_perf_history(const vector<int>& perf_history) {
+    if (perf_history.size() < 3 ||
+        perf_history.size() != perf_history[0] +
+                               perf_history[1] +
+                               perf_history[2] + (size_t)3) {
         return;
     }
 
     printf("\nI/O perf history (KB/s) :  most_recent  <---------  least_recent \n");
 
     std::stringstream line;
-    std::copy(perf_history[0].begin(), perf_history[0].end(),
+    int start = 3;
+    int end = 3 + perf_history[0];
+    std::copy(perf_history.begin() + start, perf_history.begin() + end,
               std::ostream_iterator<int>(line, " "));
     printf("last 24 hours : %s\n", line.str().c_str());
 
     line.str("");
-    std::copy(perf_history[1].begin(), perf_history[1].end(),
+    start = end;
+    end += perf_history[1];
+    std::copy(perf_history.begin() + start, perf_history.begin() + end,
               std::ostream_iterator<int>(line, " "));
     printf("last 7 days   : %s\n", line.str().c_str());
 
     line.str("");
-    std::copy(perf_history[2].begin(), perf_history[2].end(),
+    start = end;
+    std::copy(perf_history.begin() + start, perf_history.end(),
               std::ostream_iterator<int>(line, " "));
     printf("last 52 weeks : %s\n", line.str().c_str());
 }
\ No newline at end of file
diff --git a/storaged/tests/storaged_test.cpp b/storaged/tests/storaged_test.cpp
index 5ae1c91..20638d8 100644
--- a/storaged/tests/storaged_test.cpp
+++ b/storaged/tests/storaged_test.cpp
@@ -380,28 +380,29 @@
         si.update_perf_history((i + 1) * 5, stp);
     }
 
-    vector<vector<uint32_t>> history = si.get_perf_history();
-    EXPECT_EQ(history.size(), 3UL);
-    EXPECT_EQ(history[0].size(), 4UL);
-    EXPECT_EQ(history[1].size(), 7UL);    // 7 days
-    EXPECT_EQ(history[2].size(), 52UL);   // 52 weeks
+    vector<int> history = si.get_perf_history();
+    EXPECT_EQ(history.size(), 66UL);
+    size_t i = 0;
+    EXPECT_EQ(history[i++], 4);
+    EXPECT_EQ(history[i++], 7);    // 7 days
+    EXPECT_EQ(history[i++], 52);   // 52 weeks
     // last 24 hours
-    EXPECT_EQ(history[0][0], 375UL);
-    EXPECT_EQ(history[0][1], 370UL);
-    EXPECT_EQ(history[0][2], 365UL);
-    EXPECT_EQ(history[0][3], 360UL);
+    EXPECT_EQ(history[i++], 375);
+    EXPECT_EQ(history[i++], 370);
+    EXPECT_EQ(history[i++], 365);
+    EXPECT_EQ(history[i++], 360);
     // daily average of last 7 days
-    EXPECT_EQ(history[1][0], 347UL);
-    EXPECT_EQ(history[1][1], 325UL);
-    EXPECT_EQ(history[1][2], 300UL);
-    EXPECT_EQ(history[1][3], 275UL);
-    EXPECT_EQ(history[1][4], 250UL);
-    EXPECT_EQ(history[1][5], 227UL);
-    EXPECT_EQ(history[1][6], 205UL);
+    EXPECT_EQ(history[i++], 347);
+    EXPECT_EQ(history[i++], 325);
+    EXPECT_EQ(history[i++], 300);
+    EXPECT_EQ(history[i++], 275);
+    EXPECT_EQ(history[i++], 250);
+    EXPECT_EQ(history[i++], 227);
+    EXPECT_EQ(history[i++], 205);
     // weekly average of last 52 weeks
-    EXPECT_EQ(history[2][0], 251UL);
-    EXPECT_EQ(history[2][1], 83UL);
-    for (int i = 2; i < 52; i++) {
-        EXPECT_EQ(history[2][i], 0UL);
+    EXPECT_EQ(history[i++], 251);
+    EXPECT_EQ(history[i++], 83);
+    for (; i < history.size(); i++) {
+        EXPECT_EQ(history[i], 0);
     }
 }
diff --git a/storaged/uid_info.cpp b/storaged/uid_info.cpp
new file mode 100644
index 0000000..58e3fd2
--- /dev/null
+++ b/storaged/uid_info.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/Parcel.h>
+
+#include "uid_info.h"
+
+using namespace android;
+using namespace android::os::storaged;
+
+status_t UidInfo::writeToParcel(Parcel* parcel) const {
+    parcel->writeInt32(uid);
+    parcel->writeCString(name.c_str());
+    parcel->write(&io, sizeof(io));
+
+    parcel->writeInt32(tasks.size());
+    for (const auto& task_it : tasks) {
+        parcel->writeInt32(task_it.first);
+        parcel->writeCString(task_it.second.comm.c_str());
+        parcel->write(&task_it.second.io, sizeof(task_it.second.io));
+    }
+    return NO_ERROR;
+}
+
+status_t UidInfo::readFromParcel(const Parcel* parcel) {
+    uid = parcel->readInt32();
+    name = parcel->readCString();
+    parcel->read(&io, sizeof(io));
+
+    uint32_t tasks_size = parcel->readInt32();
+    for (uint32_t i = 0; i < tasks_size; i++) {
+        task_info task;
+        task.pid = parcel->readInt32();
+        task.comm = parcel->readCString();
+        parcel->read(&task.io, sizeof(task.io));
+        tasks[task.pid] = task;
+    }
+    return NO_ERROR;
+}