Merge "ueventd: fixup ueventd_test.cpp" am: 9aaf66b61f am: 34d4d57b87 am: 5d256bc555
am: 5b1202976e
Change-Id: Icf00ff2e4f9a949900ab6b71bba89c3815c4b5d2
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 80def73..dd8bad9 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -40,6 +40,7 @@
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
+LOCAL_REQUIRED_MODULES := mke2fs e2fsdroid
LOCAL_SRC_FILES_linux := usb_linux.cpp
LOCAL_STATIC_LIBRARIES_linux := libselinux
@@ -85,6 +86,8 @@
include $(BUILD_HOST_EXECUTABLE)
my_dist_files := $(LOCAL_BUILT_MODULE)
+my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
+my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid$(HOST_EXECUTABLE_SUFFIX)
ifeq ($(HOST_OS),linux)
my_dist_files += $(HOST_LIBRARY_PATH)/libf2fs_fmt_host_dyn$(HOST_SHLIB_SUFFIX)
endif
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index 99ca7dd..f3c000e 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -10,14 +10,22 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
+#ifndef WIN32
+#include <sys/wait.h>
+#endif
#include <unistd.h>
+#include <vector>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <ext4_utils/make_ext4fs.h>
#include <sparse/sparse.h>
+using android::base::StringPrintf;
using android::base::unique_fd;
+#ifdef WIN32
static int generate_ext4_image(const char* fileName, long long partSize, const std::string& initial_dir,
unsigned eraseBlkSize, unsigned logicalBlkSize)
{
@@ -34,6 +42,84 @@
}
return 0;
}
+#else
+static int exec_e2fs_cmd(const char* path, char* const argv[]) {
+ int status;
+ pid_t child;
+ if ((child = fork()) == 0) {
+ setenv("MKE2FS_CONFIG", "", 1);
+ execvp(path, argv);
+ _exit(EXIT_FAILURE);
+ }
+ if (child < 0) {
+ fprintf(stderr, "%s failed with fork %s\n", path, strerror(errno));
+ return -1;
+ }
+ if (TEMP_FAILURE_RETRY(waitpid(child, &status, 0)) == -1) {
+ fprintf(stderr, "%s failed with waitpid %s\n", path, strerror(errno));
+ return -1;
+ }
+ int ret = -1;
+ if (WIFEXITED(status)) {
+ ret = WEXITSTATUS(status);
+ if (ret != 0) {
+ fprintf(stderr, "%s failed with status %d\n", path, ret);
+ }
+ }
+ return ret;
+}
+
+static int generate_ext4_image(const char* fileName, long long partSize,
+ const std::string& initial_dir, unsigned eraseBlkSize,
+ unsigned logicalBlkSize) {
+ static constexpr int block_size = 4096;
+ const std::string exec_dir = android::base::GetExecutableDirectory();
+
+ const std::string mke2fs_path = exec_dir + "/mke2fs";
+ std::vector<const char*> mke2fs_args = {mke2fs_path.c_str(), "-t", "ext4", "-b"};
+
+ std::string block_size_str = std::to_string(block_size);
+ mke2fs_args.push_back(block_size_str.c_str());
+
+ std::string ext_attr = "android_sparse";
+ if (eraseBlkSize != 0 && logicalBlkSize != 0) {
+ int raid_stride = logicalBlkSize / block_size;
+ int raid_stripe_width = eraseBlkSize / block_size;
+ // stride should be the max of 8kb and logical block size
+ if (logicalBlkSize != 0 && logicalBlkSize < 8192) raid_stride = 8192 / block_size;
+ ext_attr += StringPrintf(",stride=%d,stripe-width=%d", raid_stride, raid_stripe_width);
+ }
+ mke2fs_args.push_back("-E");
+ mke2fs_args.push_back(ext_attr.c_str());
+ mke2fs_args.push_back(fileName);
+
+ std::string size_str = std::to_string(partSize / block_size);
+ mke2fs_args.push_back(size_str.c_str());
+ mke2fs_args.push_back(nullptr);
+
+ int ret = exec_e2fs_cmd(mke2fs_args[0], const_cast<char**>(mke2fs_args.data()));
+ if (ret != 0) {
+ fprintf(stderr, "mke2fs failed: %d\n", ret);
+ return -1;
+ }
+
+ if (initial_dir.empty()) {
+ return 0;
+ }
+
+ const std::string e2fsdroid_path = exec_dir + "/e2fsdroid";
+ std::vector<const char*> e2fsdroid_args = {e2fsdroid_path.c_str(), "-f", initial_dir.c_str(),
+ fileName, nullptr};
+
+ ret = exec_e2fs_cmd(e2fsdroid_args[0], const_cast<char**>(e2fsdroid_args.data()));
+ if (ret != 0) {
+ fprintf(stderr, "e2fsdroid failed: %d\n", ret);
+ return -1;
+ }
+
+ return 0;
+}
+#endif
#ifdef USE_F2FS
static int generate_f2fs_image(const char* fileName, long long partSize, const std::string& initial_dir,
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index f3ca724..9249343 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -21,6 +21,7 @@
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_MODULE:= fs_mgr
LOCAL_MODULE_TAGS := optional
+LOCAL_REQUIRED_MODULES := mke2fs mke2fs.conf e2fsdroid
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index a03d92c..fc88217 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -24,21 +24,16 @@
#include <cutils/partition_utils.h>
#include <sys/mount.h>
-#include <ext4_utils/ext4_utils.h>
#include <ext4_utils/ext4.h>
-#include <ext4_utils/make_ext4fs.h>
-#include <selinux/selinux.h>
-#include <selinux/label.h>
+#include <ext4_utils/ext4_utils.h>
+#include <logwrap/logwrap.h>
#include <selinux/android.h>
+#include <selinux/label.h>
+#include <selinux/selinux.h>
#include "fs_mgr_priv.h"
#include "cryptfs.h"
-extern "C" {
-extern struct fs_info info; /* magic global from ext4_utils */
-extern void reset_ext4fs_info();
-}
-
static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer)
{
uint64_t dev_sz;
@@ -55,30 +50,36 @@
return -1;
}
- struct selabel_handle *sehandle = selinux_android_file_context_handle();
- if (!sehandle) {
- /* libselinux logs specific error */
- LERROR << "Cannot initialize android file_contexts";
- close(fd);
- return -1;
- }
-
- /* Format the partition using the calculated length */
- reset_ext4fs_info();
- info.len = (off64_t)dev_sz;
- if (crypt_footer) {
- info.len -= CRYPT_FOOTER_OFFSET;
- }
-
- /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */
- rc = make_ext4fs_internal(fd, NULL, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, sehandle, 0, 0, NULL, NULL, NULL);
- if (rc) {
- LERROR << "make_ext4fs returned " << rc;
- }
close(fd);
- if (sehandle) {
- selabel_close(sehandle);
+ /* Format the partition using the calculated length */
+ if (crypt_footer) {
+ dev_sz -= CRYPT_FOOTER_OFFSET;
+ }
+
+ std::string size_str = std::to_string(dev_sz / 4096);
+ const char* const mke2fs_args[] = {
+ "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", fs_blkdev, size_str.c_str(), nullptr};
+
+ rc = android_fork_execvp_ext(arraysize(mke2fs_args), const_cast<char**>(mke2fs_args), NULL,
+ true, LOG_KLOG, true, nullptr, nullptr, 0);
+ if (rc) {
+ LERROR << "mke2fs returned " << rc;
+ return rc;
+ }
+
+ const char* const e2fsdroid_args[] = {
+ "/system/bin/e2fsdroid",
+ "-e",
+ "-a",
+ fs_mnt_point,
+ fs_blkdev,
+ nullptr};
+
+ rc = android_fork_execvp_ext(arraysize(e2fsdroid_args), const_cast<char**>(e2fsdroid_args),
+ NULL, true, LOG_KLOG, true, nullptr, nullptr, 0);
+ if (rc) {
+ LERROR << "e2fsdroid returned " << rc;
}
return rc;
@@ -86,44 +87,10 @@
static int format_f2fs(char *fs_blkdev)
{
- char * args[5];
- int pid;
- int rc = 0;
+ const char* const args[] = {"/system/bin/make_f2fs", "-f", "-O encrypt", fs_blkdev, nullptr};
- args[0] = (char *)"/system/bin/make_f2fs";
- args[1] = (char *)"-f";
- args[2] = (char *)"-O encrypt";
- args[3] = fs_blkdev;
- args[4] = (char *)0;
-
- pid = fork();
- if (pid < 0) {
- return pid;
- }
- if (!pid) {
- /* This doesn't return */
- execv(args[0], args);
- exit(1);
- }
- for(;;) {
- pid_t p = waitpid(pid, &rc, 0);
- if (p != pid) {
- LERROR << "Error waiting for child process - " << p;
- rc = -1;
- break;
- }
- if (WIFEXITED(rc)) {
- rc = WEXITSTATUS(rc);
- LINFO << args[0] << " done, status " << rc;
- if (rc) {
- rc = -1;
- }
- break;
- }
- LERROR << "Still waiting for " << args[0] << "...";
- }
-
- return rc;
+ return android_fork_execvp_ext(arraysize(args), const_cast<char**>(args), NULL, true,
+ LOG_KLOG, true, nullptr, nullptr, 0);
}
int fs_mgr_do_format(struct fstab_rec *fstab, bool crypt_footer)
diff --git a/gatekeeperd/Android.mk b/gatekeeperd/Android.mk
index 0dfd9d8..28f0b07 100644
--- a/gatekeeperd/Android.mk
+++ b/gatekeeperd/Android.mk
@@ -21,8 +21,7 @@
LOCAL_SRC_FILES := \
SoftGateKeeperDevice.cpp \
IGateKeeperService.cpp \
- gatekeeperd.cpp \
- IUserManager.cpp
+ gatekeeperd.cpp
LOCAL_MODULE := gatekeeperd
LOCAL_SHARED_LIBRARIES := \
diff --git a/gatekeeperd/IUserManager.cpp b/gatekeeperd/IUserManager.cpp
deleted file mode 100644
index 8167d19..0000000
--- a/gatekeeperd/IUserManager.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2015 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 "IUserManager"
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/Log.h>
-#include <binder/Parcel.h>
-
-#include "IUserManager.h"
-
-namespace android {
-
-class BpUserManager : public BpInterface<IUserManager>
-{
-public:
- explicit BpUserManager(const sp<IBinder>& impl) :
- BpInterface<IUserManager>(impl) {
- }
- virtual int32_t getCredentialOwnerProfile(int32_t user_id) {
- Parcel data, reply;
- data.writeInterfaceToken(IUserManager::getInterfaceDescriptor());
- data.writeInt32(user_id);
- status_t rc = remote()->transact(GET_CREDENTIAL_OWNER_PROFILE, data, &reply, 0);
- if (rc != NO_ERROR) {
- ALOGE("%s: failed (%d)\n", __func__, rc);
- return -1;
- }
-
- int32_t exception = reply.readExceptionCode();
- if (exception != 0) {
- ALOGE("%s: got exception (%d)\n", __func__, exception);
- return -1;
- }
-
- return reply.readInt32();
- }
-
-};
-
-IMPLEMENT_META_INTERFACE(UserManager, "android.os.IUserManager");
-
-}; // namespace android
-
diff --git a/gatekeeperd/IUserManager.h b/gatekeeperd/IUserManager.h
deleted file mode 100644
index 640e9b5..0000000
--- a/gatekeeperd/IUserManager.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2015 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 IUSERMANAGER_H_
-#define IUSERMANAGER_H_
-
-#include <inttypes.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-/*
-* Communication channel to UserManager
-*/
-class IUserManager : public IInterface {
- public:
- // must be kept in sync with IUserManager.aidl
- enum {
- GET_CREDENTIAL_OWNER_PROFILE = IBinder::FIRST_CALL_TRANSACTION + 0,
- };
-
- virtual int32_t getCredentialOwnerProfile(int32_t user_id) = 0;
-
- DECLARE_META_INTERFACE(UserManager);
-};
-
-}; // namespace android
-
-#endif // IUSERMANAGER_H_
-
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index c6369f9..184c6d2 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -37,7 +37,6 @@
#include <utils/String16.h>
#include "SoftGateKeeperDevice.h"
-#include "IUserManager.h"
#include <hidl/HidlSupport.h>
#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
@@ -334,23 +333,7 @@
return ret;
}
- virtual uint64_t getSecureUserId(uint32_t uid) {
- uint64_t sid = read_sid(uid);
- if (sid == 0) {
- // might be a work profile, look up the parent
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("user"));
- sp<IUserManager> um = interface_cast<IUserManager>(binder);
- int32_t parent = um->getCredentialOwnerProfile(uid);
- if (parent < 0) {
- return 0;
- } else if (parent != (int32_t) uid) {
- return read_sid(parent);
- }
- }
- return sid;
-
- }
+ virtual uint64_t getSecureUserId(uint32_t uid) { return read_sid(uid); }
virtual void clearSecureUserId(uint32_t uid) {
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/healthd/Android.bp b/healthd/Android.bp
new file mode 100644
index 0000000..56f5148
--- /dev/null
+++ b/healthd/Android.bp
@@ -0,0 +1,7 @@
+cc_library_headers {
+ name: "libhealthd_headers",
+ vendor_available: true,
+ export_include_dirs: ["include"],
+ header_libs: ["libbatteryservice_headers"],
+ export_header_lib_headers: ["libbatteryservice_headers"],
+}
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 8b59964..6b14289 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -33,6 +33,30 @@
include $(CLEAR_VARS)
+LOCAL_MODULE := libhealthd_draw
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_STATIC_LIBRARIES := \
+ libminui \
+ libbase
+LOCAL_SRC_FILES := healthd_draw.cpp
+
+ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_SCREEN),)
+LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=$(TARGET_HEALTHD_DRAW_SPLIT_SCREEN)
+else
+LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=0
+endif
+
+ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_OFFSET),)
+LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=$(TARGET_HEALTHD_DRAW_SPLIT_OFFSET)
+else
+LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=0
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
LOCAL_CFLAGS := -Werror
ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true)
LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK
@@ -58,6 +82,7 @@
libutils \
libbase \
libcutils \
+ libhealthd_draw \
liblog \
libm \
libc \
@@ -101,6 +126,7 @@
LOCAL_STATIC_LIBRARIES := \
libhealthd_charger \
+ libhealthd_draw \
libbatterymonitor \
libbase \
libutils \
diff --git a/healthd/healthd_draw.cpp b/healthd/healthd_draw.cpp
new file mode 100644
index 0000000..ea3d991
--- /dev/null
+++ b/healthd/healthd_draw.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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 <android-base/stringprintf.h>
+#include <batteryservice/BatteryService.h>
+#include <cutils/klog.h>
+
+#include "healthd_draw.h"
+
+#define LOGE(x...) KLOG_ERROR("charger", x);
+#define LOGV(x...) KLOG_DEBUG("charger", x);
+
+HealthdDraw::HealthdDraw(animation* anim)
+ : kSplitScreen(HEALTHD_DRAW_SPLIT_SCREEN),
+ kSplitOffset(HEALTHD_DRAW_SPLIT_OFFSET) {
+ gr_init();
+ gr_font_size(gr_sys_font(), &char_width_, &char_height_);
+
+ screen_width_ = gr_fb_width() / (kSplitScreen ? 2 : 1);
+ screen_height_ = gr_fb_height();
+
+ int res;
+ if (!anim->text_clock.font_file.empty() &&
+ (res = gr_init_font(anim->text_clock.font_file.c_str(),
+ &anim->text_clock.font)) < 0) {
+ LOGE("Could not load time font (%d)\n", res);
+ }
+ if (!anim->text_percent.font_file.empty() &&
+ (res = gr_init_font(anim->text_percent.font_file.c_str(),
+ &anim->text_percent.font)) < 0) {
+ LOGE("Could not load percent font (%d)\n", res);
+ }
+}
+
+HealthdDraw::~HealthdDraw() {}
+
+void HealthdDraw::redraw_screen(const animation* batt_anim, GRSurface* surf_unknown) {
+ clear_screen();
+
+ /* try to display *something* */
+ if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0)
+ draw_unknown(surf_unknown);
+ else
+ draw_battery(batt_anim);
+ gr_flip();
+}
+
+void HealthdDraw::blank_screen(bool blank) { gr_fb_blank(blank); }
+
+void HealthdDraw::clear_screen(void) {
+ gr_color(0, 0, 0, 255);
+ gr_clear();
+}
+
+int HealthdDraw::draw_surface_centered(GRSurface* surface) {
+ int w = gr_get_width(surface);
+ int h = gr_get_height(surface);
+ int x = (screen_width_ - w) / 2 + kSplitOffset;
+ int y = (screen_height_ - h) / 2;
+
+ LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
+ gr_blit(surface, 0, 0, w, h, x, y);
+ if (kSplitScreen) {
+ x += screen_width_ - 2 * kSplitOffset;
+ LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
+ gr_blit(surface, 0, 0, w, h, x, y);
+ }
+
+ return y + h;
+}
+
+int HealthdDraw::draw_text(const GRFont* font, int x, int y, const char* str) {
+ int str_len_px = gr_measure(font, str);
+
+ if (x < 0) x = (screen_width_ - str_len_px) / 2;
+ if (y < 0) y = (screen_height_ - char_height_) / 2;
+ gr_text(font, x + kSplitOffset, y, str, false /* bold */);
+ if (kSplitScreen)
+ gr_text(font, x - kSplitOffset + screen_width_, y, str, false /* bold */);
+
+ return y + char_height_;
+}
+
+void HealthdDraw::determine_xy(const animation::text_field& field,
+ const int length, int* x, int* y) {
+ *x = field.pos_x;
+
+ int str_len_px = length * field.font->char_width;
+ if (field.pos_x == CENTER_VAL) {
+ *x = (screen_width_ - str_len_px) / 2;
+ } else if (field.pos_x >= 0) {
+ *x = field.pos_x;
+ } else { // position from max edge
+ *x = screen_width_ + field.pos_x - str_len_px - kSplitOffset;
+ }
+
+ *y = field.pos_y;
+
+ if (field.pos_y == CENTER_VAL) {
+ *y = (screen_height_ - field.font->char_height) / 2;
+ } else if (field.pos_y >= 0) {
+ *y = field.pos_y;
+ } else { // position from max edge
+ *y = screen_height_ + field.pos_y - field.font->char_height;
+ }
+}
+
+void HealthdDraw::draw_clock(const animation* anim) {
+ static constexpr char CLOCK_FORMAT[] = "%H:%M";
+ static constexpr int CLOCK_LENGTH = 6;
+
+ const animation::text_field& field = anim->text_clock;
+
+ if (field.font == nullptr || field.font->char_width == 0 ||
+ field.font->char_height == 0)
+ return;
+
+ time_t rawtime;
+ time(&rawtime);
+ tm* time_info = localtime(&rawtime);
+
+ char clock_str[CLOCK_LENGTH];
+ size_t length = strftime(clock_str, CLOCK_LENGTH, CLOCK_FORMAT, time_info);
+ if (length != CLOCK_LENGTH - 1) {
+ LOGE("Could not format time\n");
+ return;
+ }
+
+ int x, y;
+ determine_xy(field, length, &x, &y);
+
+ LOGV("drawing clock %s %d %d\n", clock_str, x, y);
+ gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
+ draw_text(field.font, x, y, clock_str);
+}
+
+void HealthdDraw::draw_percent(const animation* anim) {
+ int cur_level = anim->cur_level;
+ if (anim->cur_status == BATTERY_STATUS_FULL) {
+ cur_level = 100;
+ }
+
+ if (cur_level <= 0) return;
+
+ const animation::text_field& field = anim->text_percent;
+ if (field.font == nullptr || field.font->char_width == 0 ||
+ field.font->char_height == 0) {
+ return;
+ }
+
+ std::string str = base::StringPrintf("%d%%", cur_level);
+
+ int x, y;
+ determine_xy(field, str.size(), &x, &y);
+
+ LOGV("drawing percent %s %d %d\n", str.c_str(), x, y);
+ gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
+ draw_text(field.font, x, y, str.c_str());
+}
+
+void HealthdDraw::draw_battery(const animation* anim) {
+ const animation::frame& frame = anim->frames[anim->cur_frame];
+
+ if (anim->num_frames != 0) {
+ draw_surface_centered(frame.surface);
+ LOGV("drawing frame #%d min_cap=%d time=%d\n", anim->cur_frame,
+ frame.min_level, frame.disp_time);
+ }
+ draw_clock(anim);
+ draw_percent(anim);
+}
+
+void HealthdDraw::draw_unknown(GRSurface* surf_unknown) {
+ int y;
+ if (surf_unknown) {
+ draw_surface_centered(surf_unknown);
+ } else {
+ gr_color(0xa4, 0xc6, 0x39, 255);
+ y = draw_text(gr_sys_font(), -1, -1, "Charging!");
+ draw_text(gr_sys_font(), -1, y + 25, "?\?/100");
+ }
+}
diff --git a/healthd/healthd_draw.h b/healthd/healthd_draw.h
new file mode 100644
index 0000000..6a6ba76
--- /dev/null
+++ b/healthd/healthd_draw.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 HEALTHD_DRAW_H
+#define HEALTHD_DRAW_H
+
+#include <linux/input.h>
+#include <minui/minui.h>
+
+#include "animation.h"
+
+using namespace android;
+
+class HealthdDraw {
+ public:
+ // Configures font using given animation.
+ HealthdDraw(animation* anim);
+ virtual ~HealthdDraw();
+
+ // Redraws screen.
+ void redraw_screen(const animation* batt_anim, GRSurface* surf_unknown);
+
+ // Blanks screen if true, unblanks if false.
+ virtual void blank_screen(bool blank);
+
+ protected:
+ virtual void clear_screen();
+
+ // returns the last y-offset of where the surface ends.
+ virtual int draw_surface_centered(GRSurface* surface);
+ // Negative x or y coordinates center text.
+ virtual int draw_text(const GRFont* font, int x, int y, const char* str);
+
+ // Negative x or y coordinates position the text away from the opposite edge
+ // that positive ones do.
+ virtual void determine_xy(const animation::text_field& field,
+ const int length, int* x, int* y);
+
+ // Draws battery animation, if it exists.
+ virtual void draw_battery(const animation* anim);
+ // Draws clock text, if animation contains text_field data.
+ virtual void draw_clock(const animation* anim);
+ // Draws battery percentage text if animation contains text_field data.
+ virtual void draw_percent(const animation* anim);
+ // Draws charger->surf_unknown or basic text.
+ virtual void draw_unknown(GRSurface* surf_unknown);
+
+ // Pixel sizes of characters for default font.
+ int char_width_;
+ int char_height_;
+
+ // Width and height of screen in pixels.
+ int screen_width_;
+ int screen_height_;
+
+ // Device screen is split vertically.
+ const bool kSplitScreen;
+ // Pixels to offset graphics towards center split.
+ const int kSplitOffset;
+};
+
+#endif // HEALTHD_DRAW_H
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index c76762d..6c6d738 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013 The Android Open Source Project
+ * Copyright (C) 2011-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.
@@ -18,7 +18,6 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <linux/input.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -34,56 +33,54 @@
#include <android-base/file.h>
#include <android-base/macros.h>
-#include <android-base/stringprintf.h>
-#include <sys/socket.h>
#include <linux/netlink.h>
+#include <sys/socket.h>
-#include <batteryservice/BatteryService.h>
#include <cutils/klog.h>
#include <cutils/misc.h>
-#include <cutils/uevent.h>
#include <cutils/properties.h>
-#include <minui/minui.h>
+#include <cutils/uevent.h>
#include <sys/reboot.h>
#ifdef CHARGER_ENABLE_SUSPEND
#include <suspend/autosuspend.h>
#endif
-#include "animation.h"
#include "AnimationParser.h"
+#include "healthd_draw.h"
#include <healthd/healthd.h>
using namespace android;
-char *locale;
+char* locale;
#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#define MSEC_PER_SEC (1000LL)
-#define NSEC_PER_MSEC (1000000LL)
+#define MSEC_PER_SEC (1000LL)
+#define NSEC_PER_MSEC (1000000LL)
-#define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC)
-#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC)
+#define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC)
+#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC)
#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
-#define LAST_KMSG_MAX_SZ (32 * 1024)
+#define LAST_KMSG_MAX_SZ (32 * 1024)
-#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
-#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0)
-#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)
+#define LOGE(x...) KLOG_ERROR("charger", x);
+#define LOGW(x...) KLOG_WARNING("charger", x);
+#define LOGV(x...) KLOG_DEBUG("charger", x);
-static constexpr const char* animation_desc_path = "/res/values/charger/animation.txt";
+static constexpr const char* animation_desc_path =
+ "/res/values/charger/animation.txt";
struct key_state {
bool pending;
@@ -98,34 +95,36 @@
int64_t next_key_check;
int64_t next_pwr_check;
- struct key_state keys[KEY_MAX + 1];
+ key_state keys[KEY_MAX + 1];
- struct animation *batt_anim;
+ animation* batt_anim;
GRSurface* surf_unknown;
int boot_min_cap;
};
-static const struct animation BASE_ANIMATION = {
- .text_clock = {
- .pos_x = 0,
- .pos_y = 0,
+static const animation BASE_ANIMATION = {
+ .text_clock =
+ {
+ .pos_x = 0,
+ .pos_y = 0,
- .color_r = 255,
- .color_g = 255,
- .color_b = 255,
- .color_a = 255,
+ .color_r = 255,
+ .color_g = 255,
+ .color_b = 255,
+ .color_a = 255,
- .font = nullptr,
- },
- .text_percent = {
- .pos_x = 0,
- .pos_y = 0,
+ .font = nullptr,
+ },
+ .text_percent =
+ {
+ .pos_x = 0,
+ .pos_y = 0,
- .color_r = 255,
- .color_g = 255,
- .color_b = 255,
- .color_a = 255,
- },
+ .color_r = 255,
+ .color_g = 255,
+ .color_b = 255,
+ .color_a = 255,
+ },
.run = false,
@@ -141,8 +140,7 @@
.cur_status = BATTERY_STATUS_UNKNOWN,
};
-
-static struct animation::frame default_animation_frames[] = {
+static animation::frame default_animation_frames[] = {
{
.disp_time = 750,
.min_level = 0,
@@ -181,35 +179,25 @@
},
};
-static struct animation battery_animation = BASE_ANIMATION;
+static animation battery_animation = BASE_ANIMATION;
-static struct charger charger_state;
-static struct healthd_config *healthd_config;
-static struct android::BatteryProperties *batt_prop;
-static int char_width;
-static int char_height;
-static bool minui_inited;
+static charger charger_state;
+static healthd_config* healthd_config;
+static android::BatteryProperties* batt_prop;
+static std::unique_ptr<HealthdDraw> healthd_draw;
/* current time in milliseconds */
-static int64_t curr_time_ms(void)
-{
- struct timespec tm;
+static int64_t curr_time_ms() {
+ timespec tm;
clock_gettime(CLOCK_MONOTONIC, &tm);
return tm.tv_sec * MSEC_PER_SEC + (tm.tv_nsec / NSEC_PER_MSEC);
}
-static void clear_screen(void)
-{
- gr_color(0, 0, 0, 255);
- gr_clear();
-}
-
#define MAX_KLOG_WRITE_BUF_SZ 256
-static void dump_last_kmsg(void)
-{
- char *buf;
- char *ptr;
+static void dump_last_kmsg(void) {
+ char* buf;
+ char* ptr;
unsigned sz = 0;
int len;
@@ -239,11 +227,10 @@
while (len > 0) {
int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
char yoink;
- char *nl;
+ char* nl;
- nl = (char *)memrchr(ptr, '\n', cnt - 1);
- if (nl)
- cnt = nl - ptr + 1;
+ nl = (char*)memrchr(ptr, '\n', cnt - 1);
+ if (nl) cnt = nl - ptr + 1;
yoink = ptr[cnt];
ptr[cnt] = '\0';
@@ -263,241 +250,59 @@
}
#ifdef CHARGER_ENABLE_SUSPEND
-static int request_suspend(bool enable)
-{
+static int request_suspend(bool enable) {
if (enable)
return autosuspend_enable();
else
return autosuspend_disable();
}
#else
-static int request_suspend(bool /*enable*/)
-{
+static int request_suspend(bool /*enable*/) {
return 0;
}
#endif
-static int draw_text(const char *str, int x, int y)
-{
- int str_len_px = gr_measure(gr_sys_font(), str);
-
- if (x < 0)
- x = (gr_fb_width() - str_len_px) / 2;
- if (y < 0)
- y = (gr_fb_height() - char_height) / 2;
- gr_text(gr_sys_font(), x, y, str, 0);
-
- return y + char_height;
-}
-
-static void android_green(void)
-{
- gr_color(0xa4, 0xc6, 0x39, 255);
-}
-
-// Negative x or y coordinates position the text away from the opposite edge that positive ones do.
-void determine_xy(const animation::text_field& field, const int length, int* x, int* y)
-{
- *x = field.pos_x;
- *y = field.pos_y;
-
- int str_len_px = length * field.font->char_width;
- if (field.pos_x == CENTER_VAL) {
- *x = (gr_fb_width() - str_len_px) / 2;
- } else if (field.pos_x >= 0) {
- *x = field.pos_x;
- } else { // position from max edge
- *x = gr_fb_width() + field.pos_x - str_len_px;
- }
-
- if (field.pos_y == CENTER_VAL) {
- *y = (gr_fb_height() - field.font->char_height) / 2;
- } else if (field.pos_y >= 0) {
- *y = field.pos_y;
- } else { // position from max edge
- *y = gr_fb_height() + field.pos_y - field.font->char_height;
- }
-}
-
-static void draw_clock(const animation& anim)
-{
- static constexpr char CLOCK_FORMAT[] = "%H:%M";
- static constexpr int CLOCK_LENGTH = 6;
-
- const animation::text_field& field = anim.text_clock;
-
- if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) return;
-
- time_t rawtime;
- time(&rawtime);
- struct tm* time_info = localtime(&rawtime);
-
- char clock_str[CLOCK_LENGTH];
- size_t length = strftime(clock_str, CLOCK_LENGTH, CLOCK_FORMAT, time_info);
- if (length != CLOCK_LENGTH - 1) {
- LOGE("Could not format time\n");
- return;
- }
-
- int x, y;
- determine_xy(field, length, &x, &y);
-
- LOGV("drawing clock %s %d %d\n", clock_str, x, y);
- gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
- gr_text(field.font, x, y, clock_str, false);
-}
-
-static void draw_percent(const animation& anim)
-{
- int cur_level = anim.cur_level;
- if (anim.cur_status == BATTERY_STATUS_FULL) {
- cur_level = 100;
- }
-
- if (cur_level <= 0) return;
-
- const animation::text_field& field = anim.text_percent;
- if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) {
- return;
- }
-
- std::string str = base::StringPrintf("%d%%", cur_level);
-
- int x, y;
- determine_xy(field, str.size(), &x, &y);
-
- LOGV("drawing percent %s %d %d\n", str.c_str(), x, y);
- gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
- gr_text(field.font, x, y, str.c_str(), false);
-}
-
-/* returns the last y-offset of where the surface ends */
-static int draw_surface_centered(GRSurface* surface)
-{
- int w;
- int h;
- int x;
- int y;
-
- w = gr_get_width(surface);
- h = gr_get_height(surface);
- x = (gr_fb_width() - w) / 2 ;
- y = (gr_fb_height() - h) / 2 ;
-
- LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
- gr_blit(surface, 0, 0, w, h, x, y);
- return y + h;
-}
-
-static void draw_unknown(struct charger *charger)
-{
- int y;
- if (charger->surf_unknown) {
- draw_surface_centered(charger->surf_unknown);
- } else {
- android_green();
- y = draw_text("Charging!", -1, -1);
- draw_text("?\?/100", -1, y + 25);
- }
-}
-
-static void draw_battery(const struct charger* charger)
-{
- const struct animation& anim = *charger->batt_anim;
- const struct animation::frame& frame = anim.frames[anim.cur_frame];
-
- if (anim.num_frames != 0) {
- draw_surface_centered(frame.surface);
- LOGV("drawing frame #%d min_cap=%d time=%d\n",
- anim.cur_frame, frame.min_level,
- frame.disp_time);
- }
- draw_clock(anim);
- draw_percent(anim);
-}
-
-static void redraw_screen(struct charger *charger)
-{
- struct animation *batt_anim = charger->batt_anim;
-
- clear_screen();
-
- /* try to display *something* */
- if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0)
- draw_unknown(charger);
- else
- draw_battery(charger);
- gr_flip();
-}
-
-static void kick_animation(struct animation *anim)
-{
+static void kick_animation(animation* anim) {
anim->run = true;
}
-static void reset_animation(struct animation *anim)
-{
+static void reset_animation(animation* anim) {
anim->cur_cycle = 0;
anim->cur_frame = 0;
anim->run = false;
}
-static void init_status_display(struct animation* anim)
-{
- int res;
-
- if (!anim->text_clock.font_file.empty()) {
- if ((res =
- gr_init_font(anim->text_clock.font_file.c_str(), &anim->text_clock.font)) < 0) {
- LOGE("Could not load time font (%d)\n", res);
- }
- }
-
- if (!anim->text_percent.font_file.empty()) {
- if ((res =
- gr_init_font(anim->text_percent.font_file.c_str(), &anim->text_percent.font)) < 0) {
- LOGE("Could not load percent font (%d)\n", res);
- }
- }
-}
-
-static void update_screen_state(struct charger *charger, int64_t now)
-{
- struct animation *batt_anim = charger->batt_anim;
+static void update_screen_state(charger* charger, int64_t now) {
+ animation* batt_anim = charger->batt_anim;
int disp_time;
if (!batt_anim->run || now < charger->next_screen_transition) return;
- if (!minui_inited) {
+ if (healthd_draw == nullptr) {
if (healthd_config && healthd_config->screen_on) {
if (!healthd_config->screen_on(batt_prop)) {
LOGV("[%" PRId64 "] leave screen off\n", now);
batt_anim->run = false;
charger->next_screen_transition = -1;
- if (charger->charger_connected)
- request_suspend(true);
+ if (charger->charger_connected) request_suspend(true);
return;
}
}
- gr_init();
- gr_font_size(gr_sys_font(), &char_width, &char_height);
- init_status_display(batt_anim);
+ healthd_draw.reset(new HealthdDraw(batt_anim));
#ifndef CHARGER_DISABLE_INIT_BLANK
- gr_fb_blank(true);
+ healthd_draw->blank_screen(true);
#endif
- minui_inited = true;
}
/* animation is over, blank screen and leave */
if (batt_anim->num_cycles > 0 && batt_anim->cur_cycle == batt_anim->num_cycles) {
reset_animation(batt_anim);
charger->next_screen_transition = -1;
- gr_fb_blank(true);
+ healthd_draw->blank_screen(true);
LOGV("[%" PRId64 "] animation done\n", now);
- if (charger->charger_connected)
- request_suspend(true);
+ if (charger->charger_connected) request_suspend(true);
return;
}
@@ -505,7 +310,6 @@
/* animation starting, set up the animation */
if (batt_anim->cur_frame == 0) {
-
LOGV("[%" PRId64 "] animation starting\n", now);
if (batt_prop) {
batt_anim->cur_level = batt_prop->batteryLevel;
@@ -522,17 +326,16 @@
// repeat the first frame first_frame_repeats times
disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time *
- batt_anim->first_frame_repeats;
+ batt_anim->first_frame_repeats;
}
}
}
/* unblank the screen on first cycle */
- if (batt_anim->cur_cycle == 0)
- gr_fb_blank(false);
+ if (batt_anim->cur_cycle == 0) healthd_draw->blank_screen(false);
/* draw the new frame (@ cur_frame) */
- redraw_screen(charger);
+ healthd_draw->redraw_screen(charger->batt_anim, charger->surf_unknown);
/* if we don't have anim frames, we only have one image, so just bump
* the cycle counter and exit
@@ -576,22 +379,18 @@
}
}
-static int set_key_callback(struct charger *charger, int code, int value)
-{
+static int set_key_callback(charger* charger, int code, int value) {
int64_t now = curr_time_ms();
int down = !!value;
- if (code > KEY_MAX)
- return -1;
+ if (code > KEY_MAX) return -1;
/* ignore events that don't modify our state */
- if (charger->keys[code].down == down)
- return 0;
+ if (charger->keys[code].down == down) return 0;
/* only record the down even timestamp, as the amount
* of time the key spent not being pressed is not useful */
- if (down)
- charger->keys[code].timestamp = now;
+ if (down) charger->keys[code].timestamp = now;
charger->keys[code].down = down;
charger->keys[code].pending = true;
if (down) {
@@ -600,34 +399,27 @@
int64_t duration = now - charger->keys[code].timestamp;
int64_t secs = duration / 1000;
int64_t msecs = duration - secs * 1000;
- LOGV("[%" PRId64 "] key[%d] up (was down for %" PRId64 ".%" PRId64 "sec)\n",
- now, code, secs, msecs);
+ LOGV("[%" PRId64 "] key[%d] up (was down for %" PRId64 ".%" PRId64 "sec)\n", now, code,
+ secs, msecs);
}
return 0;
}
-static void update_input_state(struct charger *charger,
- struct input_event *ev)
-{
- if (ev->type != EV_KEY)
- return;
+static void update_input_state(charger* charger, input_event* ev) {
+ if (ev->type != EV_KEY) return;
set_key_callback(charger, ev->code, ev->value);
}
-static void set_next_key_check(struct charger *charger,
- struct key_state *key,
- int64_t timeout)
-{
+static void set_next_key_check(charger* charger, key_state* key, int64_t timeout) {
int64_t then = key->timestamp + timeout;
if (charger->next_key_check == -1 || then < charger->next_key_check)
charger->next_key_check = then;
}
-static void process_key(struct charger *charger, int code, int64_t now)
-{
- struct key_state *key = &charger->keys[code];
+static void process_key(charger* charger, int code, int64_t now) {
+ key_state* key = &charger->keys[code];
if (code == KEY_POWER) {
if (key->down) {
@@ -644,8 +436,10 @@
LOGW("[%" PRId64 "] rebooting\n", now);
reboot(RB_AUTOBOOT);
} else {
- LOGV("[%" PRId64 "] ignore power-button press, battery level "
- "less than minimum\n", now);
+ LOGV("[%" PRId64
+ "] ignore power-button press, battery level "
+ "less than minimum\n",
+ now);
}
}
} else {
@@ -654,9 +448,9 @@
*/
set_next_key_check(charger, key, POWER_ON_KEY_TIME);
- /* Turn on the display and kick animation on power-key press
- * rather than on key release
- */
+ /* Turn on the display and kick animation on power-key press
+ * rather than on key release
+ */
kick_animation(charger->batt_anim);
request_suspend(false);
}
@@ -671,21 +465,17 @@
key->pending = false;
}
-static void handle_input_state(struct charger *charger, int64_t now)
-{
+static void handle_input_state(charger* charger, int64_t now) {
process_key(charger, KEY_POWER, now);
if (charger->next_key_check != -1 && now > charger->next_key_check)
charger->next_key_check = -1;
}
-static void handle_power_supply_state(struct charger *charger, int64_t now)
-{
- if (!charger->have_battery_state)
- return;
+static void handle_power_supply_state(charger* charger, int64_t now) {
+ if (!charger->have_battery_state) return;
if (!charger->charger_connected) {
-
/* Last cycle would have stopped at the extreme top of battery-icon
* Need to show the correct level corresponding to capacity.
*/
@@ -711,9 +501,8 @@
}
}
-void healthd_mode_charger_heartbeat()
-{
- struct charger *charger = &charger_state;
+void healthd_mode_charger_heartbeat() {
+ charger* charger = &charger_state;
int64_t now = curr_time_ms();
handle_input_state(charger, now);
@@ -725,14 +514,11 @@
update_screen_state(charger, now);
}
-void healthd_mode_charger_battery_update(
- struct android::BatteryProperties *props)
-{
- struct charger *charger = &charger_state;
+void healthd_mode_charger_battery_update(android::BatteryProperties* props) {
+ charger* charger = &charger_state;
charger->charger_connected =
- props->chargerAcOnline || props->chargerUsbOnline ||
- props->chargerWirelessOnline;
+ props->chargerAcOnline || props->chargerUsbOnline || props->chargerWirelessOnline;
if (!charger->have_battery_state) {
charger->have_battery_state = true;
@@ -743,19 +529,16 @@
batt_prop = props;
}
-int healthd_mode_charger_preparetowait(void)
-{
- struct charger *charger = &charger_state;
+int healthd_mode_charger_preparetowait(void) {
+ charger* charger = &charger_state;
int64_t now = curr_time_ms();
int64_t next_event = INT64_MAX;
int64_t timeout;
- LOGV("[%" PRId64 "] next screen: %" PRId64 " next key: %" PRId64 " next pwr: %" PRId64 "\n", now,
- charger->next_screen_transition, charger->next_key_check,
- charger->next_pwr_check);
+ LOGV("[%" PRId64 "] next screen: %" PRId64 " next key: %" PRId64 " next pwr: %" PRId64 "\n",
+ now, charger->next_screen_transition, charger->next_key_check, charger->next_pwr_check);
- if (charger->next_screen_transition != -1)
- next_event = charger->next_screen_transition;
+ if (charger->next_screen_transition != -1) next_event = charger->next_screen_transition;
if (charger->next_key_check != -1 && charger->next_key_check < next_event)
next_event = charger->next_key_check;
if (charger->next_pwr_check != -1 && charger->next_pwr_check < next_event)
@@ -766,32 +549,27 @@
else
timeout = -1;
- return (int)timeout;
+ return (int)timeout;
}
-static int input_callback(struct charger *charger, int fd, unsigned int epevents)
-{
- struct input_event ev;
+static int input_callback(charger* charger, int fd, unsigned int epevents) {
+ input_event ev;
int ret;
ret = ev_get_input(fd, epevents, &ev);
- if (ret)
- return -1;
+ if (ret) return -1;
update_input_state(charger, &ev);
return 0;
}
-static void charger_event_handler(uint32_t /*epevents*/)
-{
+static void charger_event_handler(uint32_t /*epevents*/) {
int ret;
ret = ev_wait(-1);
- if (!ret)
- ev_dispatch();
+ if (!ret) ev_dispatch();
}
-animation* init_animation()
-{
+animation* init_animation() {
bool parse_success;
std::string content;
@@ -814,32 +592,29 @@
}
LOGV("Animation Description:\n");
- LOGV(" animation: %d %d '%s' (%d)\n",
- battery_animation.num_cycles, battery_animation.first_frame_repeats,
- battery_animation.animation_file.c_str(), battery_animation.num_frames);
+ LOGV(" animation: %d %d '%s' (%d)\n", battery_animation.num_cycles,
+ battery_animation.first_frame_repeats, battery_animation.animation_file.c_str(),
+ battery_animation.num_frames);
LOGV(" fail_file: '%s'\n", battery_animation.fail_file.c_str());
- LOGV(" clock: %d %d %d %d %d %d '%s'\n",
- battery_animation.text_clock.pos_x, battery_animation.text_clock.pos_y,
- battery_animation.text_clock.color_r, battery_animation.text_clock.color_g,
- battery_animation.text_clock.color_b, battery_animation.text_clock.color_a,
- battery_animation.text_clock.font_file.c_str());
- LOGV(" percent: %d %d %d %d %d %d '%s'\n",
- battery_animation.text_percent.pos_x, battery_animation.text_percent.pos_y,
- battery_animation.text_percent.color_r, battery_animation.text_percent.color_g,
- battery_animation.text_percent.color_b, battery_animation.text_percent.color_a,
- battery_animation.text_percent.font_file.c_str());
+ LOGV(" clock: %d %d %d %d %d %d '%s'\n", battery_animation.text_clock.pos_x,
+ battery_animation.text_clock.pos_y, battery_animation.text_clock.color_r,
+ battery_animation.text_clock.color_g, battery_animation.text_clock.color_b,
+ battery_animation.text_clock.color_a, battery_animation.text_clock.font_file.c_str());
+ LOGV(" percent: %d %d %d %d %d %d '%s'\n", battery_animation.text_percent.pos_x,
+ battery_animation.text_percent.pos_y, battery_animation.text_percent.color_r,
+ battery_animation.text_percent.color_g, battery_animation.text_percent.color_b,
+ battery_animation.text_percent.color_a, battery_animation.text_percent.font_file.c_str());
for (int i = 0; i < battery_animation.num_frames; i++) {
LOGV(" frame %.2d: %d %d %d\n", i, battery_animation.frames[i].disp_time,
- battery_animation.frames[i].min_level, battery_animation.frames[i].max_level);
+ battery_animation.frames[i].min_level, battery_animation.frames[i].max_level);
}
return &battery_animation;
}
-void healthd_mode_charger_init(struct healthd_config* config)
-{
+void healthd_mode_charger_init(struct healthd_config* config) {
int ret;
- struct charger *charger = &charger_state;
+ charger* charger = &charger_state;
int i;
int epollfd;
@@ -847,14 +622,13 @@
LOGW("--------------- STARTING CHARGER MODE ---------------\n");
- ret = ev_init(std::bind(&input_callback, charger, std::placeholders::_1,
- std::placeholders::_2));
+ ret = ev_init(std::bind(&input_callback, charger, std::placeholders::_1, std::placeholders::_2));
if (!ret) {
epollfd = ev_get_epollfd();
healthd_register_event(epollfd, charger_event_handler, EVENT_WAKEUP_FD);
}
- struct animation* anim = init_animation();
+ animation* anim = init_animation();
charger->batt_anim = anim;
ret = res_create_display_surface(anim->fail_file.c_str(), &charger->surf_unknown);
@@ -871,15 +645,15 @@
int scale_count;
int scale_fps; // Not in use (charger/battery_scale doesn't have FPS text
// chunk). We are using hard-coded frame.disp_time instead.
- ret = res_create_multi_display_surface(anim->animation_file.c_str(),
- &scale_count, &scale_fps, &scale_frames);
+ ret = res_create_multi_display_surface(anim->animation_file.c_str(), &scale_count, &scale_fps,
+ &scale_frames);
if (ret < 0) {
LOGE("Cannot load battery_scale image\n");
anim->num_frames = 0;
anim->num_cycles = 1;
} else if (scale_count != anim->num_frames) {
- LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n",
- scale_count, anim->num_frames);
+ LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n", scale_count,
+ anim->num_frames);
anim->num_frames = 0;
anim->num_cycles = 1;
} else {
@@ -887,8 +661,8 @@
anim->frames[i].surface = scale_frames[i];
}
}
- ev_sync_key_state(std::bind(&set_key_callback, charger, std::placeholders::_1,
- std::placeholders::_2));
+ ev_sync_key_state(
+ std::bind(&set_key_callback, charger, std::placeholders::_1, std::placeholders::_2));
charger->next_screen_transition = -1;
charger->next_key_check = -1;
diff --git a/init/init.cpp b/init/init.cpp
index e84d069..55d5fa8 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -910,7 +910,6 @@
selinux_android_restorecon("/dev/urandom", 0);
selinux_android_restorecon("/dev/__properties__", 0);
- selinux_android_restorecon("/file_contexts.bin", 0);
selinux_android_restorecon("/plat_file_contexts", 0);
selinux_android_restorecon("/nonplat_file_contexts", 0);
selinux_android_restorecon("/plat_property_contexts", 0);
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index 0792307..8b0c53e 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -179,7 +179,11 @@
}
const uint32_t opcode = buffer_.request.header.opcode;
- LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode;
+ const uint64_t unique = buffer_.request.header.unique;
+ LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode << " unique=" << unique;
+ if (unique == 0) {
+ return FuseBridgeState::kWaitToReadEither;
+ }
switch (opcode) {
case FUSE_FORGET:
// Do not reply to FUSE_FORGET.
diff --git a/libappfuse/tests/FuseBridgeLoopTest.cc b/libappfuse/tests/FuseBridgeLoopTest.cc
index 51d6051..0a28451 100644
--- a/libappfuse/tests/FuseBridgeLoopTest.cc
+++ b/libappfuse/tests/FuseBridgeLoopTest.cc
@@ -67,6 +67,7 @@
memset(&request_, 0, sizeof(FuseRequest));
request_.header.opcode = opcode;
request_.header.len = sizeof(fuse_in_header);
+ request_.header.unique = 1;
ASSERT_TRUE(request_.Write(dev_sockets_[0]));
memset(&response_, 0, sizeof(FuseResponse));
diff --git a/liblog/Android.bp b/liblog/Android.bp
index e74aa82..b98d18f 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -42,6 +42,24 @@
"logd_writer.c",
]
+cc_library_headers {
+ name: "liblog_headers",
+ host_supported: true,
+ vendor_available: true,
+ export_include_dirs: ["include"],
+ target: {
+ windows: {
+ enabled: true,
+ },
+ linux_bionic: {
+ enabled: true,
+ },
+ vendor: {
+ export_include_dirs: ["include_vndk"],
+ },
+ },
+}
+
// Shared and static library for host and device
// ========================================================
cc_library {
@@ -81,7 +99,8 @@
},
},
- export_include_dirs: ["include"],
+ header_libs: ["liblog_headers"],
+ export_header_lib_headers: ["liblog_headers"],
cflags: [
"-Werror",
@@ -100,7 +119,7 @@
}
ndk_headers {
- name: "liblog_headers",
+ name: "liblog_ndk_headers",
from: "include/android",
to: "android",
srcs: ["include/android/log.h"],
diff --git a/liblog/include/log/log_main.h b/liblog/include/log/log_main.h
index da16158..68c2e9a 100644
--- a/liblog/include/log/log_main.h
+++ b/liblog/include/log/log_main.h
@@ -18,10 +18,9 @@
#define _LIBS_LOG_LOG_MAIN_H
#include <android/log.h>
+#include <sys/cdefs.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
/*
* Normally we strip the effects of ALOGV (VERBOSE messages),
@@ -385,8 +384,6 @@
#pragma clang diagnostic pop
#endif
-#ifdef __cplusplus
-}
-#endif
+__END_DECLS
#endif /* _LIBS_LOG_LOG_MAIN_H */
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index ab96429..91044ab 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -89,7 +89,7 @@
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
LOCAL_STATIC_LIBRARIES := libgtest libgtest_main
-LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_COMPATIBILITY_SUITE := cts vts
LOCAL_CTS_TEST_PACKAGE := android.core.liblog
include $(BUILD_CTS_EXECUTABLE)
diff --git a/libsync/libsync.map.txt b/libsync/libsync.map.txt
index daa28ae..f9057bd 100644
--- a/libsync/libsync.map.txt
+++ b/libsync/libsync.map.txt
@@ -17,8 +17,8 @@
LIBSYNC {
global:
sync_merge; # introduced=26
- sync_get_fence_info; # introduced=26
- sync_free_fence_info; # introduced=26
+ sync_file_info; # introduced=26
+ sync_file_info_free; # introduced=26
local:
*;
};
diff --git a/libutils/Android.bp b/libutils/Android.bp
index a1bdbf3..9e7cc13 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -18,10 +18,12 @@
host_supported: true,
header_libs: [
+ "liblog_headers",
"libsystem_headers",
"libcutils_headers"
],
export_header_lib_headers: [
+ "liblog_headers",
"libsystem_headers",
"libcutils_headers"
],
@@ -78,6 +80,10 @@
"libutils_headers",
],
+ shared_libs: [
+ "liblog",
+ ],
+
arch: {
mips: {
cflags: ["-DALIGN_DOUBLE"],
@@ -98,7 +104,6 @@
"libbacktrace",
"libcutils",
"libdl",
- "liblog",
"libvndksupport",
],
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 8a6168c..c095315 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -40,7 +40,8 @@
#endif
#define MEMCG_SYSFS_PATH "/dev/memcg/"
-#define MEMPRESSURE_WATCH_LEVEL "low"
+#define MEMPRESSURE_WATCH_MEDIUM_LEVEL "medium"
+#define MEMPRESSURE_WATCH_CRITICAL_LEVEL "critical"
#define ZONEINFO_PATH "/proc/zoneinfo"
#define LINE_MAX 128
@@ -48,6 +49,7 @@
#define INKERNEL_ADJ_PATH "/sys/module/lowmemorykiller/parameters/adj"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+#define EIGHT_MEGA (1 << 23)
enum lmk_cmd {
LMK_TARGET,
@@ -66,15 +68,17 @@
static int use_inkernel_interface = 1;
/* memory pressure level medium event */
-static int mpevfd;
+static int mpevfd[2];
+#define CRITICAL_INDEX 1
+#define MEDIUM_INDEX 0
/* control socket listen and data */
static int ctrl_lfd;
static int ctrl_dfd = -1;
static int ctrl_dfd_reopened; /* did we reopen ctrl conn on this loop? */
-/* 1 memory pressure level, 1 ctrl listen socket, 1 ctrl data socket */
-#define MAX_EPOLL_EVENTS 3
+/* 2 memory pressure levels, 1 ctrl listen socket, 1 ctrl data socket */
+#define MAX_EPOLL_EVENTS 4
static int epollfd;
static int maxevents;
@@ -113,14 +117,6 @@
#define ADJTOSLOT(adj) ((adj) + -OOM_SCORE_ADJ_MIN)
static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1];
-/*
- * Wait 1-2 seconds for the death report of a killed process prior to
- * considering killing more processes.
- */
-#define KILL_TIMEOUT 2
-/* Time of last process kill we initiated, stop me before I kill again */
-static time_t kill_lasttime;
-
/* PAGE_SIZE / 1024 */
static long page_k;
@@ -241,6 +237,7 @@
struct proc *procp;
char path[80];
char val[20];
+ int soft_limit_mult;
if (oomadj < OOM_SCORE_ADJ_MIN || oomadj > OOM_SCORE_ADJ_MAX) {
ALOGE("Invalid PROCPRIO oomadj argument %d", oomadj);
@@ -254,6 +251,36 @@
if (use_inkernel_interface)
return;
+ if (oomadj >= 900) {
+ soft_limit_mult = 0;
+ } else if (oomadj >= 800) {
+ soft_limit_mult = 0;
+ } else if (oomadj >= 700) {
+ soft_limit_mult = 0;
+ } else if (oomadj >= 600) {
+ soft_limit_mult = 0;
+ } else if (oomadj >= 500) {
+ soft_limit_mult = 0;
+ } else if (oomadj >= 400) {
+ soft_limit_mult = 0;
+ } else if (oomadj >= 300) {
+ soft_limit_mult = 1;
+ } else if (oomadj >= 200) {
+ soft_limit_mult = 2;
+ } else if (oomadj >= 100) {
+ soft_limit_mult = 10;
+ } else if (oomadj >= 0) {
+ soft_limit_mult = 20;
+ } else {
+ // Persistent processes will have a large
+ // soft limit 512MB.
+ soft_limit_mult = 64;
+ }
+
+ snprintf(path, sizeof(path), "/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_bytes", uid, pid);
+ snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA);
+ writefilestring(path, val);
+
procp = pid_lookup(pid);
if (!procp) {
procp = malloc(sizeof(struct proc));
@@ -278,7 +305,6 @@
return;
pid_remove(pid);
- kill_lasttime = 0;
}
static void cmd_target(int ntargets, int *params) {
@@ -574,7 +600,6 @@
first ? "" : "~", other_file * page_k, minfree * page_k, min_score_adj,
first ? "" : "~", other_free * page_k, other_free >= 0 ? "above" : "below");
r = kill(pid, SIGKILL);
- killProcessGroup(uid, pid, SIGKILL);
pid_remove(pid);
if (r) {
@@ -589,24 +614,12 @@
* Find a process to kill based on the current (possibly estimated) free memory
* and cached memory sizes. Returns the size of the killed processes.
*/
-static int find_and_kill_process(int other_free, int other_file, bool first)
+static int find_and_kill_process(int other_free, int other_file, bool first, int min_score_adj)
{
int i;
- int min_score_adj = OOM_SCORE_ADJ_MAX + 1;
int minfree = 0;
int killed_size = 0;
- for (i = 0; i < lowmem_targets_size; i++) {
- minfree = lowmem_minfree[i];
- if (other_free < minfree && other_file < minfree) {
- min_score_adj = lowmem_adj[i];
- break;
- }
- }
-
- if (min_score_adj == OOM_SCORE_ADJ_MAX + 1)
- return 0;
-
for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) {
struct proc *procp;
@@ -626,42 +639,33 @@
return 0;
}
-static void mp_event(uint32_t events __unused) {
+static void mp_event_common(bool is_critical) {
int ret;
unsigned long long evcount;
- struct sysmeminfo mi;
- int other_free;
- int other_file;
- int killed_size;
bool first = true;
+ int min_adj_score = is_critical ? 0 : 800;
+ int index = is_critical ? CRITICAL_INDEX : MEDIUM_INDEX;
- ret = read(mpevfd, &evcount, sizeof(evcount));
+ ret = read(mpevfd[index], &evcount, sizeof(evcount));
if (ret < 0)
ALOGE("Error reading memory pressure event fd; errno=%d",
errno);
- if (time(NULL) - kill_lasttime < KILL_TIMEOUT)
- return;
-
- while (zoneinfo_parse(&mi) < 0) {
- // Failed to read /proc/zoneinfo, assume ENOMEM and kill something
- find_and_kill_process(0, 0, true);
+ if (find_and_kill_process(0, 0, first, min_adj_score) == 0) {
+ ALOGI("Nothing to kill");
}
-
- other_free = mi.nr_free_pages - mi.totalreserve_pages;
- other_file = mi.nr_file_pages - mi.nr_shmem;
-
- do {
- killed_size = find_and_kill_process(other_free, other_file, first);
- if (killed_size > 0) {
- first = false;
- other_free += killed_size;
- other_file += killed_size;
- }
- } while (killed_size > 0);
}
-static int init_mp(char *levelstr, void *event_handler)
+static void mp_event(uint32_t events __unused) {
+ mp_event_common(false);
+}
+
+static void mp_event_critical(uint32_t events __unused) {
+ ALOGI("Memory pressure critical");
+ mp_event_common(true);
+}
+
+static int init_mp_common(char *levelstr, void *event_handler, bool is_critical)
{
int mpfd;
int evfd;
@@ -669,6 +673,7 @@
char buf[256];
struct epoll_event epev;
int ret;
+ int mpevfd_index = is_critical ? CRITICAL_INDEX : MEDIUM_INDEX;
mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY | O_CLOEXEC);
if (mpfd < 0) {
@@ -709,7 +714,7 @@
goto err;
}
maxevents++;
- mpevfd = evfd;
+ mpevfd[mpevfd_index] = evfd;
return 0;
err:
@@ -722,6 +727,16 @@
return -1;
}
+static int init_mp_medium()
+{
+ return init_mp_common(MEMPRESSURE_WATCH_MEDIUM_LEVEL, (void *)&mp_event, false);
+}
+
+static int init_mp_critical()
+{
+ return init_mp_common(MEMPRESSURE_WATCH_CRITICAL_LEVEL, (void *)&mp_event_critical, true);
+}
+
static int init(void) {
struct epoll_event epev;
int i;
@@ -763,7 +778,8 @@
if (use_inkernel_interface) {
ALOGI("Using in-kernel low memory killer interface");
} else {
- ret = init_mp(MEMPRESSURE_WATCH_LEVEL, (void *)&mp_event);
+ ret = init_mp_medium();
+ ret |= init_mp_critical();
if (ret)
ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer");
}
diff --git a/logd/tests/Android.mk b/logd/tests/Android.mk
index 1915677..a0875ea 100644
--- a/logd/tests/Android.mk
+++ b/logd/tests/Android.mk
@@ -63,7 +63,7 @@
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_SHARED_LIBRARIES := libbase libcutils liblog libselinux
LOCAL_STATIC_LIBRARIES := libgtest libgtest_main
-LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_COMPATIBILITY_SUITE := cts vts
LOCAL_CTS_TEST_PACKAGE := android.core.logd
include $(BUILD_CTS_EXECUTABLE)
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 2e5575f..046557e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -194,7 +194,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := ld.config.txt
-ifeq ($(PRODUCT_FULL_TREBLE),true)
+ifeq ($(PRODUCT_FULL_TREBLE)|$(SANITIZE_TARGET),true|)
LOCAL_SRC_FILES := etc/ld.config.txt
else
LOCAL_SRC_FILES := etc/ld.config.legacy.txt
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 859fcd2..7ba7bde 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -95,10 +95,10 @@
# This namespace is exclusively for vndk-sp libs.
###############################################################################
namespace.vndk.isolated = true
-namespace.vndk.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.vndk.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp
namespace.vndk.permitted.paths = /vendor/${LIB}/hw:/vendor/${LIB}/egl
-namespace.vndk.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+namespace.vndk.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp
namespace.vndk.asan.permitted.paths = /data/asan/vendor/${LIB}/hw:/vendor/${LIB}/hw:/data/asan/vendor/${LIB}/egl:/vendor/${LIB}/egl
# When these NDK libs are required inside this namespace, then it is redirected
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 424dbee..901d066 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -321,7 +321,6 @@
# Make sure /sys/kernel/debug (if present) is labeled properly
# Note that tracefs may be mounted under debug, so we need to cross filesystems
restorecon --recursive --cross-filesystems /sys/kernel/debug
- chmod 0755 /sys/kernel/debug/tracing
# We chown/chmod /cache again so because mount is run as root + defaults
chown system cache /cache
@@ -359,6 +358,10 @@
mkdir /cache/lost+found 0770 root root
on late-fs
+ # Ensure that tracefs has the correct permissions.
+ # This does not work correctly if it is called in post-fs.
+ chmod 0755 /sys/kernel/debug/tracing
+
# HALs required before storage encryption can get unlocked (FBE/FDE)
class_start early_hal
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index 514798b..fa68406 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -256,6 +256,7 @@
uid_monitor mUidm;
time_t mStarttime;
sp<IBatteryPropertiesRegistrar> battery_properties;
+ std::unique_ptr<storage_info_t> storage_info;
public:
storaged_t(void);
~storaged_t() {}
@@ -285,6 +286,8 @@
void init_battery_service();
virtual void batteryPropertiesChanged(struct BatteryProperties props);
void binderDied(const wp<IBinder>& who);
+
+ void report_storage_info();
};
// Eventlog tag
diff --git a/storaged/include/storaged_info.h b/storaged/include/storaged_info.h
index 913c814..7d04c7a 100644
--- a/storaged/include/storaged_info.h
+++ b/storaged/include/storaged_info.h
@@ -27,39 +27,46 @@
class storage_info_t {
protected:
FRIEND_TEST(storaged_test, storage_info_t);
+ // emmc lifetime
uint16_t eol; // pre-eol (end of life) information
uint16_t lifetime_a; // device life time estimation (type A)
uint16_t lifetime_b; // device life time estimation (type B)
string version; // version string
+ // free space
+ const string userdata_path = "/data";
+ uint64_t userdata_total_kb;
+ uint64_t userdata_free_kb;
+
+ storage_info_t() : eol(0), lifetime_a(0), lifetime_b(0),
+ userdata_total_kb(0), userdata_free_kb(0) {}
void publish();
+ storage_info_t* s_info;
public:
- storage_info_t() : eol(0), lifetime_a(0), lifetime_b(0) {}
+ static storage_info_t* get_storage_info();
virtual ~storage_info_t() {}
- virtual bool report() = 0;
+ virtual void report() {};
+ void refresh();
};
class emmc_info_t : public storage_info_t {
private:
- const string emmc_sysfs = "/sys/bus/mmc/devices/mmc0:0001/";
- const string emmc_debugfs = "/d/mmc0/mmc0:0001/ext_csd";
- const char* emmc_ver_str[9] = {
- "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0", "5.1"
- };
-public:
- virtual ~emmc_info_t() {}
- bool report();
bool report_sysfs();
bool report_debugfs();
+public:
+ static const string emmc_sysfs;
+ static const string emmc_debugfs;
+ static const char* emmc_ver_str[];
+
+ virtual ~emmc_info_t() {}
+ virtual void report();
};
class ufs_info_t : public storage_info_t {
-private:
- const string health_file = "/sys/devices/soc/624000.ufshc/health";
public:
- virtual ~ufs_info_t() {}
- bool report();
-};
+ static const string health_file;
-void report_storage_health();
+ virtual ~ufs_info_t() {}
+ virtual void report();
+};
#endif /* _STORAGED_INFO_H_ */
diff --git a/storaged/main.cpp b/storaged/main.cpp
index 4d1e430..6b82904 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -49,6 +49,7 @@
storaged = new storaged_t();
storaged->init_battery_service();
+ storaged->report_storage_info();
LOG_TO(SYSTEM, INFO) << "storaged: Start";
@@ -113,7 +114,6 @@
}
if (flag_main_service) { // start main thread
- report_storage_health();
// Start the main thread of storaged
pthread_t storaged_main_thread;
errno = pthread_create(&storaged_main_thread, NULL, storaged_main, NULL);
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 54d429c..06afea6 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -200,6 +200,10 @@
}
}
+void storaged_t::report_storage_info() {
+ storage_info->report();
+}
+
/* storaged_t */
storaged_t::storaged_t(void) {
if (access(MMC_DISK_STATS_PATH, R_OK) < 0 && access(SDA_DISK_STATS_PATH, R_OK) < 0) {
@@ -222,6 +226,8 @@
mConfig.periodic_chores_interval_uid_io =
property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO);
+ storage_info.reset(storage_info_t::get_storage_info());
+
mStarttime = time(NULL);
}
@@ -229,6 +235,7 @@
if (mConfig.diskstats_available) {
mDiskStats.update();
mDsm.update();
+ storage_info->refresh();
if (mTimer && (mTimer % mConfig.periodic_chores_interval_disk_stats_publish) == 0) {
mDiskStats.publish();
}
diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp
index 434bd74..b5fb13e 100644
--- a/storaged/storaged_info.cpp
+++ b/storaged/storaged_info.cpp
@@ -18,6 +18,7 @@
#include <stdio.h>
#include <string.h>
+#include <sys/statvfs.h>
#include <android-base/file.h>
#include <android-base/parseint.h>
@@ -30,13 +31,42 @@
using namespace std;
using namespace android::base;
-void report_storage_health()
-{
- emmc_info_t mmc;
- ufs_info_t ufs;
+const string emmc_info_t::emmc_sysfs = "/sys/bus/mmc/devices/mmc0:0001/";
+const string emmc_info_t::emmc_debugfs = "/d/mmc0/mmc0:0001/ext_csd";
+const char* emmc_info_t::emmc_ver_str[9] = {
+ "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0", "5.1"
+};
- mmc.report();
- ufs.report();
+const string ufs_info_t::health_file = "/sys/devices/soc/624000.ufshc/health";
+
+static bool FileExists(const std::string& filename)
+{
+ struct stat buffer;
+ return stat(filename.c_str(), &buffer) == 0;
+}
+
+storage_info_t* storage_info_t::get_storage_info()
+{
+ if (FileExists(emmc_info_t::emmc_sysfs) ||
+ FileExists(emmc_info_t::emmc_debugfs)) {
+ return new emmc_info_t;
+ }
+ if (FileExists(ufs_info_t::health_file)) {
+ return new ufs_info_t;
+ }
+ return new storage_info_t;
+}
+
+void storage_info_t::refresh()
+{
+ struct statvfs buf;
+ if (statvfs(userdata_path.c_str(), &buf) != 0) {
+ PLOG_TO(SYSTEM, WARNING) << "Failed to get userdata info";
+ return;
+ }
+
+ userdata_total_kb = buf.f_bsize * buf.f_blocks >> 10;
+ userdata_free_kb = buf.f_bfree * buf.f_blocks >> 10;
}
void storage_info_t::publish()
@@ -46,13 +76,12 @@
<< LOG_ID_EVENTS;
}
-bool emmc_info_t::report()
+void emmc_info_t::report()
{
if (!report_sysfs() && !report_debugfs())
- return false;
+ return;
publish();
- return true;
}
bool emmc_info_t::report_sysfs()
@@ -136,21 +165,21 @@
return true;
}
-bool ufs_info_t::report()
+void ufs_info_t::report()
{
string buffer;
if (!ReadFileToString(health_file, &buffer)) {
- return false;
+ return;
}
vector<string> lines = Split(buffer, "\n");
if (lines.empty()) {
- return false;
+ return;
}
char rev[8];
if (sscanf(lines[0].c_str(), "ufs version: 0x%7s\n", rev) < 1) {
- return false;
+ return;
}
version = "ufs " + string(rev);
@@ -175,10 +204,9 @@
}
if (eol == 0 || (lifetime_a == 0 && lifetime_b == 0)) {
- return false;
+ return;
}
publish();
- return true;
}