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;
+}