Merge changes I33360e15,I2f102fa9,If44c40f8,Ic7bc29ef into nyc-dev
* changes:
vulkan: use CamelCase() for CreateInfoWrapper
vulkan: use CamelCase() for LayerChain
vulkan: use CamelCase() for OverrideExtensionNames
vulkan: use CamelCase() for OverrideLayerNames
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 5481313..20ad5f9 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -74,7 +74,7 @@
uid_t uid = multiuser_get_uid(userid, appid);
int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgname);
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
PLOG(ERROR) << "Failed to prepare " << path;
return -1;
@@ -124,7 +124,7 @@
// consistent location. This only works on non-FBE devices, since we
// never want to risk exposing data on a device with real CE/DE storage.
- auto ce_path = create_data_user_package_path(uuid, userid, pkgname);
+ auto ce_path = create_data_user_ce_package_path(uuid, userid, pkgname);
auto de_path = create_data_user_de_package_path(uuid, userid, pkgname);
// If neither directory is marked as default, assume CE is default
@@ -234,7 +234,8 @@
return success ? 0 : -1;
}
-int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
+int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode) {
std::string suffix = "";
bool only_cache = false;
if (flags & FLAG_CLEAR_CACHE_ONLY) {
@@ -247,7 +248,7 @@
int res = 0;
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgname) + suffix;
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode) + suffix;
if (access(path.c_str(), F_OK) == 0) {
res |= delete_dir_contents(path);
}
@@ -289,11 +290,12 @@
return result;
}
-int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
+int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode) {
int res = 0;
if (flags & FLAG_STORAGE_CE) {
res |= delete_dir_contents_and_dir(
- create_data_user_package_path(uuid, userid, pkgname));
+ create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode));
}
if (flags & FLAG_STORAGE_DE) {
res |= delete_dir_contents_and_dir(
@@ -346,9 +348,9 @@
// Copy private data for all known users
// TODO: handle user_de paths
for (auto user : users) {
- std::string from(create_data_user_package_path(from_uuid, user, package_name));
- std::string to(create_data_user_package_path(to_uuid, user, package_name));
- std::string to_parent(create_data_user_path(to_uuid, user));
+ std::string from(create_data_user_ce_package_path(from_uuid, user, package_name));
+ std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
+ std::string to_parent(create_data_user_ce_path(to_uuid, user));
// Data source may not exist for all users; that's okay
if (access(from.c_str(), F_OK) != 0) {
@@ -356,7 +358,7 @@
continue;
}
- std::string user_path(create_data_user_path(to_uuid, user));
+ std::string user_path(create_data_user_ce_path(to_uuid, user));
if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) {
LOG(ERROR) << "Failed to prepare user target " << user_path;
goto fail;
@@ -409,7 +411,7 @@
}
}
for (auto user : users) {
- std::string to(create_data_user_package_path(to_uuid, user, package_name));
+ std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
LOG(WARNING) << "Failed to rollback " << to;
}
@@ -429,7 +431,7 @@
int delete_user(const char *uuid, userid_t userid) {
int res = 0;
- std::string data_path(create_data_user_path(uuid, userid));
+ std::string data_path(create_data_user_ce_path(uuid, userid));
std::string data_de_path(create_data_user_de_path(uuid, userid));
std::string media_path(create_data_media_path(uuid, userid));
std::string profiles_path(create_data_user_profiles_path(userid));
@@ -480,7 +482,7 @@
// Special case for owner on internal storage
if (uuid == nullptr) {
- std::string _tmpdir(create_data_user_path(nullptr, 0));
+ std::string _tmpdir(create_data_user_ce_path(nullptr, 0));
add_cache_files(cache, _tmpdir.c_str(), "cache");
}
@@ -567,142 +569,96 @@
}
}
-int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
- int64_t *_cachesize, int64_t* _asecsize) {
+static void add_app_data_size(std::string& path, int64_t *codesize, int64_t *datasize,
+ int64_t *cachesize) {
DIR *d;
int dfd;
struct dirent *de;
struct stat s;
- char path[PKG_PATH_MAX];
- int64_t codesize = 0;
- int64_t datasize = 0;
- int64_t cachesize = 0;
- int64_t asecsize = 0;
+ d = opendir(path.c_str());
+ if (d == nullptr) {
+ PLOG(WARNING) << "Failed to open " << path;
+ return;
+ }
+ dfd = dirfd(d);
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
- /* count the source apk as code -- but only if it's not
- * on the /system partition and its not on the sdcard. */
- if (validate_system_app_path(apkpath) &&
- strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
- if (stat(apkpath, &s) == 0) {
- codesize += stat_size(&s);
- if (S_ISDIR(s.st_mode)) {
- d = opendir(apkpath);
- if (d != NULL) {
- dfd = dirfd(d);
- codesize += calculate_dir_size(dfd);
- closedir(d);
- }
+ int64_t statsize = 0;
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ statsize = stat_size(&s);
+ }
+
+ if (de->d_type == DT_DIR) {
+ int subfd;
+ int64_t dirsize = 0;
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
}
- }
- }
-
- /* count the forward locked apk as code if it is given */
- if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
- if (stat(fwdlock_apkpath, &s) == 0) {
- codesize += stat_size(&s);
- }
- }
-
- /* count the cached dexfile as code */
- if (create_cache_path(path, apkpath, instruction_set)) {
- if (stat(path, &s) == 0) {
- codesize += stat_size(&s);
- }
- }
-
- /* add in size of any libraries */
- if (libdirpath != NULL && libdirpath[0] != '!') {
- d = opendir(libdirpath);
- if (d != NULL) {
- dfd = dirfd(d);
- codesize += calculate_dir_size(dfd);
- closedir(d);
- }
- }
-
- /* compute asec size if it is given */
- if (asecpath != NULL && asecpath[0] != '!') {
- if (stat(asecpath, &s) == 0) {
- asecsize += stat_size(&s);
- }
- }
-
- std::vector<userid_t> users;
- if (userid == -1) {
- users = get_known_users(uuid);
- } else {
- users.push_back(userid);
- }
-
- for (auto user : users) {
- // TODO: handle user_de directories
- if (!(flags & FLAG_STORAGE_CE)) continue;
-
- std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
- const char* pkgdir = _pkgdir.c_str();
-
- d = opendir(pkgdir);
- if (d == NULL) {
- PLOG(WARNING) << "Failed to open " << pkgdir;
- continue;
- }
- dfd = dirfd(d);
-
- /* most stuff in the pkgdir is data, except for the "cache"
- * directory and below, which is cache, and the "lib" directory
- * and below, which is code...
- */
- while ((de = readdir(d))) {
- const char *name = de->d_name;
-
- if (de->d_type == DT_DIR) {
- int subfd;
- int64_t statsize = 0;
- int64_t dirsize = 0;
- /* always skip "." and ".." */
- if (name[0] == '.') {
- if (name[1] == 0) continue;
- if ((name[1] == '.') && (name[2] == 0)) continue;
- }
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- statsize = stat_size(&s);
- }
- subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
- if (subfd >= 0) {
- dirsize = calculate_dir_size(subfd);
- }
- if(!strcmp(name,"lib")) {
- codesize += dirsize + statsize;
- } else if(!strcmp(name,"cache")) {
- cachesize += dirsize + statsize;
- } else {
- datasize += dirsize + statsize;
- }
- } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
- // This is the symbolic link to the application's library
- // code. We'll count this as code instead of data, since
- // it is not something that the app creates.
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- codesize += stat_size(&s);
- }
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd >= 0) {
+ dirsize = calculate_dir_size(subfd);
+ close(subfd);
+ }
+ // TODO: check xattrs!
+ if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
+ *datasize += statsize;
+ *cachesize += dirsize;
} else {
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- datasize += stat_size(&s);
- }
+ *datasize += dirsize + statsize;
}
+ } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
+ *codesize += statsize;
+ } else {
+ *datasize += statsize;
}
+ }
+ closedir(d);
+}
+
+int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char *code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+ int64_t* asecsize) {
+ DIR *d;
+ int dfd;
+
+ d = opendir(code_path);
+ if (d != nullptr) {
+ dfd = dirfd(d);
+ *codesize += calculate_dir_size(dfd);
closedir(d);
}
- *_codesize = codesize;
- *_datasize = datasize;
- *_cachesize = cachesize;
- *_asecsize = asecsize;
+
+ if (flags & FLAG_STORAGE_CE) {
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode);
+ add_app_data_size(path, codesize, datasize, cachesize);
+ }
+ if (flags & FLAG_STORAGE_DE) {
+ auto path = create_data_user_de_package_path(uuid, userid, pkgname);
+ add_app_data_size(path, codesize, datasize, cachesize);
+ }
+
+ *asecsize = 0;
+
return 0;
}
+int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) {
+ struct stat buf;
+ memset(&buf, 0, sizeof(buf));
+ if (flags & FLAG_STORAGE_CE) {
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
+ if (stat(path.c_str(), &buf) == 0) {
+ *inode = buf.st_ino;
+ return 0;
+ }
+ }
+ return -1;
+}
+
static int split_count(const char *str)
{
char *ctx;
@@ -1617,7 +1573,7 @@
struct stat s, libStat;
int rc = 0;
- std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname));
+ std::string _pkgdir(create_data_user_ce_package_path(uuid, userId, pkgname));
std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);
const char* pkgdir = _pkgdir.c_str();
@@ -1804,7 +1760,7 @@
uid_t uid = multiuser_get_uid(userid, appid);
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgName);
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgName);
if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
PLOG(ERROR) << "restorecon failed for " << path;
res = -1;
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 13143c5..f13ceea 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -33,16 +33,18 @@
int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
appid_t appid, const char* seinfo);
int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
-int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
-int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
+int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode);
+int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode);
int move_complete_app(const char* from_uuid, const char *to_uuid, const char *package_name,
const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version);
-int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set, int64_t *codesize, int64_t *datasize,
- int64_t *cachesize, int64_t *asecsize);
+int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char* code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+ int64_t *asecsize);
+int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode);
int make_user_config(userid_t userid);
int delete_user(const char *uuid, userid_t userid);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index de3f54a..5c29eb4 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -207,13 +207,13 @@
}
static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
- /* const char *uuid, const char *pkgname, userid_t userid, int flags */
- return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
+ /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
+ return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
}
static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
- /* const char *uuid, const char *pkgname, userid_t userid, int flags */
- return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
+ /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
+ return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
}
// We use otapreopt_chroot to get into the chroot.
@@ -303,11 +303,10 @@
int64_t asecsize = 0;
int res = 0;
- /* const char *uuid, const char *pkgname, userid_t userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set */
- res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4], arg[5],
- arg[6], arg[7], arg[8], &codesize, &datasize, &cachesize, &asecsize);
+ /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char* code_path */
+ res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]),
+ arg[5], &codesize, &datasize, &cachesize, &asecsize);
/*
* Each int64_t can take up 22 characters printed out. Make sure it
@@ -318,6 +317,17 @@
return res;
}
+static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
+ ino_t inode = 0;
+ int res = 0;
+
+ /* const char *uuid, const char *pkgname, int userid, int flags */
+ res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);
+
+ snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode);
+ return res;
+}
+
static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
/* const char* from_uuid, const char *to_uuid, const char *package_name,
const char *data_app_name, appid_t appid, const char* seinfo,
@@ -393,10 +403,11 @@
{ "create_app_data", 7, do_create_app_data },
{ "restorecon_app_data", 6, do_restorecon_app_data },
{ "migrate_app_data", 4, do_migrate_app_data },
- { "clear_app_data", 4, do_clear_app_data },
- { "destroy_app_data", 4, do_destroy_app_data },
+ { "clear_app_data", 5, do_clear_app_data },
+ { "destroy_app_data", 5, do_destroy_app_data },
{ "move_complete_app", 7, do_move_complete_app },
- { "get_app_size", 9, do_get_app_size },
+ { "get_app_size", 6, do_get_app_size },
+ { "get_app_data_inode", 4, do_get_app_data_inode },
{ "dexopt", 9, do_dexopt },
{ "markbootcomplete", 1, do_mark_boot_complete },
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index ff69f4b..9b2de88 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -472,13 +472,13 @@
}
TEST_F(UtilsTest, CreateDataUserPath) {
- EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0));
- EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10));
+ EXPECT_EQ("/data/data", create_data_user_ce_path(nullptr, 0));
+ EXPECT_EQ("/data/user/10", create_data_user_ce_path(nullptr, 10));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0",
- create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
+ create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10",
- create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
+ create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
}
TEST_F(UtilsTest, CreateDataMediaPath) {
@@ -499,13 +499,13 @@
}
TEST_F(UtilsTest, CreateDataUserPackagePath) {
- EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example"));
- EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example"));
+ EXPECT_EQ("/data/data/com.example", create_data_user_ce_package_path(nullptr, 0, "com.example"));
+ EXPECT_EQ("/data/user/10/com.example", create_data_user_ce_package_path(nullptr, 10, "com.example"));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example",
- create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+ create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example",
- create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
+ create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
}
} // namespace installd
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index d84d9f6..878fb2d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -81,11 +81,39 @@
* volume UUID, package name, and user ID. An empty UUID is assumed to be
* internal storage.
*/
-std::string create_data_user_package_path(const char* volume_uuid,
+std::string create_data_user_ce_package_path(const char* volume_uuid,
userid_t user, const char* package_name) {
check_package_name(package_name);
return StringPrintf("%s/%s",
- create_data_user_path(volume_uuid, user).c_str(), package_name);
+ create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
+}
+
+std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
+ const char* package_name, ino_t ce_data_inode) {
+ // For testing purposes, rely on the inode when defined; this could be
+ // optimized to use access() in the future.
+ auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
+ if (ce_data_inode != 0) {
+ auto user_path = create_data_user_ce_path(volume_uuid, user);
+ DIR* dir = opendir(user_path.c_str());
+ if (dir == nullptr) {
+ PLOG(ERROR) << "Failed to opendir " << user_path;
+ return fallback;
+ }
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_ino == ce_data_inode) {
+ closedir(dir);
+ return StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+ }
+ }
+ LOG(WARNING) << "Failed to find inode " << ce_data_inode << " for package " << package_name;
+ closedir(dir);
+ return fallback;
+ } else {
+ return fallback;
+ }
}
std::string create_data_user_de_package_path(const char* volume_uuid,
@@ -102,7 +130,7 @@
return -1;
}
- std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix);
+ std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix);
const char* tmp = _tmp.c_str();
if (strlen(tmp) >= PKG_PATH_MAX) {
path[0] = '\0';
@@ -132,7 +160,7 @@
/**
* Create the path name for user data for a certain userid.
*/
-std::string create_data_user_path(const char* volume_uuid, userid_t userid) {
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
std::string data(create_data_path(volume_uuid));
if (volume_uuid == nullptr) {
if (userid == 0) {
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 416a726..9d9a423 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -73,12 +73,13 @@
std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
-// TODO: finish refactoring to "_ce"
-std::string create_data_user_path(const char* volume_uuid, userid_t userid);
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid);
std::string create_data_user_de_path(const char* volume_uuid, userid_t userid);
-std::string create_data_user_package_path(const char* volume_uuid,
+std::string create_data_user_ce_package_path(const char* volume_uuid,
userid_t user, const char* package_name);
+std::string create_data_user_ce_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name, ino_t ce_data_inode);
std::string create_data_user_de_package_path(const char* volume_uuid,
userid_t user, const char* package_name);
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 3792540..353003c 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -56,7 +56,7 @@
uint8_t b[16];
} uuid_t;
- Sensor();
+ Sensor(const char * name = "");
Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
~Sensor();
@@ -80,6 +80,7 @@
int32_t getMaxDelay() const;
uint32_t getFlags() const;
bool isWakeUpSensor() const;
+ bool isDynamicSensor() const;
int32_t getReportingMode() const;
const uuid_t& getUuid() const;
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
index 7576994..5b5ab70 100644
--- a/libs/diskusage/dirsize.c
+++ b/libs/diskusage/dirsize.c
@@ -24,16 +24,7 @@
int64_t stat_size(struct stat *s)
{
- int64_t blksize = s->st_blksize;
- // count actual blocks used instead of nominal file size
- int64_t size = s->st_blocks * 512;
-
- if (blksize) {
- /* round up to filesystem block size */
- size = (size + blksize - 1) & (~(blksize - 1));
- }
-
- return size;
+ return s->st_blocks * 512;
}
int64_t calculate_dir_size(int dfd)
@@ -51,9 +42,6 @@
while ((de = readdir(d))) {
const char *name = de->d_name;
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- size += stat_size(&s);
- }
if (de->d_type == DT_DIR) {
int subfd;
@@ -65,10 +53,17 @@
continue;
}
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
if (subfd >= 0) {
size += calculate_dir_size(subfd);
}
+ } else {
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
}
}
closedir(d);
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 0b2b942..4b9a2ab 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -35,8 +35,8 @@
namespace android {
// ----------------------------------------------------------------------------
-Sensor::Sensor()
- : mHandle(0), mType(0),
+Sensor::Sensor(const char * name)
+ : mName(name), mHandle(0), mType(0),
mMinValue(0), mMaxValue(0), mResolution(0),
mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
mFifoMaxEventCount(0), mRequiredAppOp(0),
@@ -390,6 +390,10 @@
return mFlags & SENSOR_FLAG_WAKE_UP;
}
+bool Sensor::isDynamicSensor() const {
+ return mFlags & SENSOR_FLAG_DYNAMIC_SENSOR;
+}
+
int32_t Sensor::getReportingMode() const {
return ((mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT);
}
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 57c56a6..85e96d6 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -16,6 +16,7 @@
SensorEventConnection.cpp \
MostRecentEventLogger.cpp \
SensorRecord.cpp \
+ SensorList.cpp \
LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index 7b1f346..788def9 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -39,6 +39,18 @@
break;
}
}
+
+ sensor_t hwSensor;
+ hwSensor.name = "Corrected Gyroscope Sensor";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 1;
+ hwSensor.handle = '_cgy';
+ hwSensor.type = SENSOR_TYPE_GYROSCOPE;
+ hwSensor.maxRange = mGyro.getMaxValue();
+ hwSensor.resolution = mGyro.getResolution();
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mGyro.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool CorrectedGyroSensor::process(sensors_event_t* outEvent,
@@ -66,19 +78,8 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor CorrectedGyroSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Corrected Gyroscope Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_cgy';
- hwSensor.type = SENSOR_TYPE_GYROSCOPE;
- hwSensor.maxRange = mGyro.getMaxValue();
- hwSensor.resolution = mGyro.getResolution();
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mGyro.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& CorrectedGyroSensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/CorrectedGyroSensor.h b/services/sensorservice/CorrectedGyroSensor.h
index 3c49c08..3419a8a 100644
--- a/services/sensorservice/CorrectedGyroSensor.h
+++ b/services/sensorservice/CorrectedGyroSensor.h
@@ -35,15 +35,15 @@
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
Sensor mGyro;
+ Sensor mSensor;
public:
CorrectedGyroSensor(sensor_t const* list, size_t count);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index a165a5b..0e80f16 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -39,6 +39,18 @@
break;
}
}
+
+ sensor_t hwSensor;
+ hwSensor.name = "Gravity Sensor";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 3;
+ hwSensor.handle = '_grv';
+ hwSensor.type = SENSOR_TYPE_GRAVITY;
+ hwSensor.maxRange = GRAVITY_EARTH * 2;
+ hwSensor.resolution = mAccelerometer.getResolution();
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mSensorFusion.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool GravitySensor::process(sensors_event_t* outEvent,
@@ -73,19 +85,8 @@
return mSensorFusion.setDelay(FUSION_NOMAG, ident, ns);
}
-Sensor GravitySensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Gravity Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 3;
- hwSensor.handle = '_grv';
- hwSensor.type = SENSOR_TYPE_GRAVITY;
- hwSensor.maxRange = GRAVITY_EARTH * 2;
- hwSensor.resolution = mAccelerometer.getResolution();
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& GravitySensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
index ac177c4..f9c0a99 100644
--- a/services/sensorservice/GravitySensor.h
+++ b/services/sensorservice/GravitySensor.h
@@ -35,15 +35,15 @@
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
Sensor mAccelerometer;
+ Sensor mSensor;
public:
GravitySensor(sensor_t const* list, size_t count);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
index d5f20d2..04beced 100644
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -33,6 +33,18 @@
: mSensorDevice(SensorDevice::getInstance()),
mGravitySensor(list, count)
{
+ const Sensor &gsensor = mGravitySensor.getSensor();
+ sensor_t hwSensor;
+ hwSensor.name = "Linear Acceleration Sensor";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = gsensor.getVersion();
+ hwSensor.handle = '_lin';
+ hwSensor.type = SENSOR_TYPE_LINEAR_ACCELERATION;
+ hwSensor.maxRange = gsensor.getMaxValue();
+ hwSensor.resolution = gsensor.getResolution();
+ hwSensor.power = gsensor.getPowerUsage();
+ hwSensor.minDelay = gsensor.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool LinearAccelerationSensor::process(sensors_event_t* outEvent,
@@ -58,20 +70,8 @@
return mGravitySensor.setDelay(ident, handle, ns);
}
-Sensor LinearAccelerationSensor::getSensor() const {
- Sensor gsensor(mGravitySensor.getSensor());
- sensor_t hwSensor;
- hwSensor.name = "Linear Acceleration Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = gsensor.getVersion();
- hwSensor.handle = '_lin';
- hwSensor.type = SENSOR_TYPE_LINEAR_ACCELERATION;
- hwSensor.maxRange = gsensor.getMaxValue();
- hwSensor.resolution = gsensor.getResolution();
- hwSensor.power = gsensor.getPowerUsage();
- hwSensor.minDelay = gsensor.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& LinearAccelerationSensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
index 5deb24f..6b8027b 100644
--- a/services/sensorservice/LinearAccelerationSensor.h
+++ b/services/sensorservice/LinearAccelerationSensor.h
@@ -35,15 +35,16 @@
class LinearAccelerationSensor : public SensorInterface {
SensorDevice& mSensorDevice;
GravitySensor mGravitySensor;
+ Sensor mSensor;
virtual bool process(sensors_event_t* outEvent,
const sensors_event_t& event);
public:
LinearAccelerationSensor(sensor_t const* list, size_t count);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index d55f336..20b49be 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -36,6 +36,17 @@
// FIXME: instead of using the SensorFusion code, we should use
// the SENSOR_TYPE_ROTATION_VECTOR instead. This way we could use the
// HAL's implementation.
+ sensor_t hwSensor;
+ hwSensor.name = "Orientation Sensor";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 1;
+ hwSensor.handle = '_ypr';
+ hwSensor.type = SENSOR_TYPE_ORIENTATION;
+ hwSensor.maxRange = 360.0f;
+ hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mSensorFusion.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool OrientationSensor::process(sensors_event_t* outEvent,
@@ -73,19 +84,8 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor OrientationSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Orientation Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_ypr';
- hwSensor.type = SENSOR_TYPE_ORIENTATION;
- hwSensor.maxRange = 360.0f;
- hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& OrientationSensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/OrientationSensor.h b/services/sensorservice/OrientationSensor.h
index 855949d..644a774 100644
--- a/services/sensorservice/OrientationSensor.h
+++ b/services/sensorservice/OrientationSensor.h
@@ -34,15 +34,15 @@
class OrientationSensor : public SensorInterface {
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
+ Sensor mSensor;
public:
OrientationSensor();
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 238845b..5a40ef9 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -32,6 +32,17 @@
mSensorFusion(SensorFusion::getInstance()),
mMode(mode)
{
+ sensor_t hwSensor;
+ hwSensor.name = getSensorName();
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 3;
+ hwSensor.handle = getSensorToken();
+ hwSensor.type = getSensorType();
+ hwSensor.maxRange = 1;
+ hwSensor.resolution = 1.0f / (1<<24);
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mSensorFusion.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool RotationVectorSensor::process(sensors_event_t* outEvent,
@@ -61,19 +72,8 @@
return mSensorFusion.setDelay(mMode, ident, ns);
}
-Sensor RotationVectorSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = getSensorName();
- hwSensor.vendor = "AOSP";
- hwSensor.version = 3;
- hwSensor.handle = getSensorToken();
- hwSensor.type = getSensorType();
- hwSensor.maxRange = 1;
- hwSensor.resolution = 1.0f / (1<<24);
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& RotationVectorSensor::getSensor() const {
+ return mSensor;
}
int RotationVectorSensor::getSensorType() const {
@@ -124,6 +124,17 @@
: mSensorDevice(SensorDevice::getInstance()),
mSensorFusion(SensorFusion::getInstance())
{
+ sensor_t hwSensor;
+ hwSensor.name = "Gyroscope Bias (debug)";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 1;
+ hwSensor.handle = '_gbs';
+ hwSensor.type = SENSOR_TYPE_ACCELEROMETER;
+ hwSensor.maxRange = 1;
+ hwSensor.resolution = 1.0f / (1<<24);
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mSensorFusion.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool GyroDriftSensor::process(sensors_event_t* outEvent,
@@ -152,19 +163,8 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor GyroDriftSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Gyroscope Bias (debug)";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_gbs';
- hwSensor.type = SENSOR_TYPE_ACCELEROMETER;
- hwSensor.maxRange = 1;
- hwSensor.resolution = 1.0f / (1<<24);
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& GyroDriftSensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index 1fc316b..5dba0d5 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -36,6 +36,7 @@
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
int mMode;
+ Sensor mSensor;
int getSensorType() const;
const char* getSensorName() const ;
@@ -43,12 +44,11 @@
public:
RotationVectorSensor(int mode = FUSION_9AXIS);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
class GameRotationVectorSensor : public RotationVectorSensor {
@@ -64,15 +64,15 @@
class GyroDriftSensor : public SensorInterface {
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
+ Sensor mSensor;
public:
GyroDriftSensor();
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index 970220b..bb2a8a2 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -65,7 +65,7 @@
mSensorDevice.autoDisable(ident, handle);
}
-Sensor HardwareSensor::getSensor() const {
+const Sensor& HardwareSensor::getSensor() const {
return mSensor;
}
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index 3e76377..06cca75 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -33,8 +33,7 @@
public:
virtual ~SensorInterface();
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event) = 0;
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) = 0;
virtual status_t activate(void* ident, bool enabled) = 0;
virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
@@ -52,7 +51,7 @@
return -EINVAL;
}
- virtual Sensor getSensor() const = 0;
+ virtual const Sensor& getSensor() const = 0;
virtual bool isVirtual() const = 0;
virtual void autoDisable(void* /*ident*/, int /*handle*/) { }
};
@@ -72,14 +71,14 @@
virtual bool process(sensors_event_t* outEvent,
const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
+ virtual status_t activate(void* ident, bool enabled) override;
virtual status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual status_t flush(void* ident, int handle);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return false; }
- virtual void autoDisable(void *ident, int handle);
+ int64_t maxBatchReportLatencyNs) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual status_t flush(void* ident, int handle) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return false; }
+ virtual void autoDisable(void *ident, int handle) override;
};
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
new file mode 100644
index 0000000..f28acd2
--- /dev/null
+++ b/services/sensorservice/SensorList.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorList.h"
+
+#include <hardware/sensors.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+const Sensor SensorList::mNonSensor = Sensor("unknown");
+
+bool SensorList::add(
+ int handle, SensorInterface* si, bool isForDebug, bool isVirtual) {
+ std::lock_guard<std::mutex> lk(mLock);
+ if (handle == si->getSensor().getHandle() &&
+ mUsedHandle.insert(handle).second) {
+ // will succeed as the mUsedHandle does not have this handle
+ mHandleMap.emplace(handle, Entry(si, isForDebug, isVirtual));
+ return true;
+ }
+ // handle exist already or handle mismatch
+ return false;
+}
+
+bool SensorList::remove(int handle) {
+ std::lock_guard<std::mutex> lk(mLock);
+ auto entry = mHandleMap.find(handle);
+ if (entry != mHandleMap.end()) {
+ mRecycle.push_back(entry->second.si);
+ mHandleMap.erase(entry);
+ return true;
+ }
+ return false;
+}
+
+String8 SensorList::getName(int handle) const {
+ return getOne<String8>(
+ handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();},
+ mNonSensor.getName());
+}
+
+const Sensor& SensorList::get(int handle) const {
+ return getOne<const Sensor&>(
+ handle, [] (const Entry& e) -> const Sensor& {return e.si->getSensor();}, mNonSensor);
+}
+
+SensorInterface* SensorList::getInterface(int handle) const {
+ return getOne<SensorInterface *>(
+ handle, [] (const Entry& e) -> SensorInterface* {return e.si;}, nullptr);
+}
+
+
+bool SensorList::isNewHandle(int handle) const {
+ std::lock_guard<std::mutex> lk(mLock);
+ return mUsedHandle.find(handle) == mUsedHandle.end();
+}
+
+const Vector<Sensor> SensorList::getUserSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getUserDebugSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getDynamicSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.isForDebug && e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getVirtualSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (e.isVirtual) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+std::string SensorList::dump() const {
+ String8 result;
+
+ result.append("Sensor List:\n");
+ forEachSensor([&result] (const Sensor& s) -> bool {
+ result.appendFormat(
+ "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
+ s.getName().string(),
+ s.getVendor().string(),
+ s.getVersion(),
+ s.getStringType().string(),
+ s.getHandle(),
+ s.getRequiredPermission().string(),
+ s.getType());
+
+ const int reportingMode = s.getReportingMode();
+ if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
+ result.append(" continuous | ");
+ } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
+ result.append(" on-change | ");
+ } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
+ result.append(" one-shot | ");
+ } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
+ result.append(" special-trigger | ");
+ } else {
+ result.append(" unknown-mode | ");
+ }
+
+ if (s.getMaxDelay() > 0) {
+ result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
+ } else {
+ result.appendFormat("maxDelay=%dus | ", s.getMaxDelay());
+ }
+
+ if (s.getMinDelay() > 0) {
+ result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
+ } else {
+ result.appendFormat("minDelay=%dus | ", s.getMinDelay());
+ }
+
+ if (s.getFifoMaxEventCount() > 0) {
+ result.appendFormat("FifoMax=%d events | ",
+ s.getFifoMaxEventCount());
+ } else {
+ result.append("no batching | ");
+ }
+
+ if (s.isWakeUpSensor()) {
+ result.appendFormat("wakeUp | ");
+ } else {
+ result.appendFormat("non-wakeUp | ");
+ }
+
+ result.append("\n");
+ return true;
+ });
+ return std::string(result.string());
+}
+
+SensorList::~SensorList() {
+ // from this point on no one should access anything in SensorList
+ mLock.lock();
+ for (auto i : mRecycle) {
+ delete i;
+ }
+ for (auto&& i : mHandleMap) {
+ delete i.second.si;
+ }
+ // the lock will eventually get destructed, there is no guarantee after that.
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
+
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
new file mode 100644
index 0000000..3fe73cc
--- /dev/null
+++ b/services/sensorservice/SensorList.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSOR_LIST_H
+#define ANDROID_SENSOR_LIST_H
+
+#include "SensorInterface.h"
+
+#include <gui/Sensor.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <mutex>
+#include <map>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+class SensorInterface;
+
+namespace SensorServiceUtil {
+
+class Dumpable {
+public:
+ virtual std::string dump() const;
+ virtual void setFormat(std::string ) {}
+ virtual ~Dumpable() {}
+};
+
+class SensorList : public Dumpable {
+public:
+ // After SensorInterface * is added into SensorList, it can be assumed that SensorList own the
+ // object it pointed to and the object should not be released elsewhere.
+ bool add(int handle, SensorInterface* si, bool isForDebug = false, bool isVirtual = false);
+ bool remove(int handle);
+
+ inline bool hasAnySensor() const { return mHandleMap.size() > 0;}
+
+ //helper functions
+ const Vector<Sensor> getUserSensors() const;
+ const Vector<Sensor> getUserDebugSensors() const;
+ const Vector<Sensor> getDynamicSensors() const;
+ const Vector<Sensor> getVirtualSensors() const;
+
+ String8 getName(int handle) const;
+ const Sensor& get(int handle) const;
+ SensorInterface* getInterface(int handle) const;
+ bool isNewHandle(int handle) const;
+
+ // Iterate through Sensor in sensor list and perform operation f on each Sensor object.
+ //
+ // TF is a function with the signature:
+ // bool f(const Sensor &);
+ // A return value of 'false' stops the iteration immediately.
+ //
+ // Note: in the function f, it is illegal to make calls to member functions of the same
+ // SensorList object on which forEachSensor is invoked.
+ template <typename TF>
+ void forEachSensor(const TF& f) const;
+
+ const Sensor& getNonSensor() const { return mNonSensor;}
+
+ // Dumpable interface
+ virtual std::string dump() const override;
+
+ virtual ~SensorList();
+private:
+ struct Entry {
+ //TODO: use sp<> here
+ SensorInterface * const si;
+ const bool isForDebug;
+ const bool isVirtual;
+ Entry(SensorInterface* si_, bool debug_, bool virtual_) :
+ si(si_), isForDebug(debug_), isVirtual(virtual_) {
+ }
+ };
+
+ const static Sensor mNonSensor; //.getName() == "unknown",
+
+ // Iterate through Entry in sensor list and perform operation f on each Entry.
+ //
+ // TF is a function with the signature:
+ // bool f(const Entry &);
+ // A return value of 'false' stops the iteration over entries immediately.
+ //
+ // Note: in the function being passed in, it is illegal to make calls to member functions of the
+ // same SensorList object on which forEachSensor is invoked.
+ template <typename TF>
+ void forEachEntry(const TF& f) const;
+
+ template <typename T, typename TF>
+ T getOne(int handle, const TF& accessor, T def = T()) const;
+
+ mutable std::mutex mLock;
+ std::map<int, Entry> mHandleMap;
+ std::unordered_set<int> mUsedHandle;
+ std::vector<SensorInterface *> mRecycle;
+};
+
+template <typename TF>
+void SensorList::forEachSensor(const TF& f) const {
+ // lock happens in forEachEntry
+ forEachEntry([&f] (const Entry& e) -> bool { return f(e.si->getSensor());});
+}
+
+template <typename TF>
+void SensorList::forEachEntry(const TF& f) const {
+ std::lock_guard<std::mutex> lk(mLock);
+
+ for (auto&& i : mHandleMap) {
+ if (!f(i.second)){
+ break;
+ }
+ }
+}
+
+template <typename T, typename TF>
+T SensorList::getOne(int handle, const TF& accessor, T def) const {
+ std::lock_guard<std::mutex> lk(mLock);
+ auto i = mHandleMap.find(handle);
+ if (i != mHandleMap.end()) {
+ return accessor(i->second);
+ } else {
+ return def;
+ }
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
+
+#endif // ANDROID_SENSOR_LIST_H
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 31ca0e3..f334e29 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -125,78 +125,51 @@
// registered)
SensorFusion::getInstance();
- // build the sensor list returned to users
- mUserSensorList = mSensorList;
-
if (hasGyro && hasAccel && hasMag) {
// Add Android virtual sensors if they're not already
// available in the HAL
- Sensor aSensor;
+ bool needRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) != 0;
- aSensor = registerVirtualSensor( new RotationVectorSensor() );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ registerSensor(new RotationVectorSensor(), !needRotationVector, true);
+ registerSensor(new OrientationSensor(), !needRotationVector, true);
- aSensor = registerVirtualSensor( new OrientationSensor() );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
- // if we are doing our own rotation-vector, also add
- // the orientation sensor and remove the HAL provided one.
- mUserSensorList.replaceAt(aSensor, orientationIndex);
- }
+ bool needLinearAcceleration =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
- aSensor = registerVirtualSensor(
- new LinearAccelerationSensor(list, count) );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
- mUserSensorList.add(aSensor);
- }
+ registerSensor(new LinearAccelerationSensor(list, count),
+ !needLinearAcceleration, true);
- // virtual debugging sensors are not added to mUserSensorList
- registerVirtualSensor( new CorrectedGyroSensor(list, count) );
- registerVirtualSensor( new GyroDriftSensor() );
+ // virtual debugging sensors are not for user
+ registerSensor( new CorrectedGyroSensor(list, count), false, true);
+ registerSensor( new GyroDriftSensor(), false, true);
}
if (hasAccel && hasGyro) {
- Sensor aSensor;
+ bool needGravitySensor = (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) != 0;
+ registerSensor(new GravitySensor(list, count), !needGravitySensor, true);
- aSensor = registerVirtualSensor(
- new GravitySensor(list, count) );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
- mUserSensorList.add(aSensor);
- }
-
- aSensor = registerVirtualSensor(
- new GameRotationVectorSensor() );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ bool needGameRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) != 0;
+ registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);
}
if (hasAccel && hasMag) {
- Sensor aSensor;
-
- aSensor = registerVirtualSensor(
- new GeoMagRotationVectorSensor() );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ bool needGeoMagRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) != 0;
+ registerSensor(new GeoMagRotationVectorSensor(), !needGeoMagRotationVector, true);
}
- // debugging sensor list
- mUserSensorListDebug = mSensorList;
-
// Check if the device really supports batching by looking at the FIFO event
// counts for each sensor.
bool batchingSupported = false;
- for (size_t i = 0; i < mSensorList.size(); ++i) {
- if (mSensorList[i].getFifoMaxEventCount() > 0) {
- batchingSupported = true;
- break;
- }
- }
+ mSensors.forEachSensor(
+ [&batchingSupported] (const Sensor& s) -> bool {
+ if (s.getFifoMaxEventCount() > 0) {
+ batchingSupported = true;
+ }
+ return !batchingSupported;
+ });
if (batchingSupported) {
// Increase socket buffer size to a max of 100 KB for batching capabilities.
@@ -242,75 +215,35 @@
}
}
-Sensor SensorService::registerSensor(SensorInterface* s) {
- const Sensor sensor(s->getSensor());
-
- // add handle to used handle list
- mUsedHandleList.add(sensor.getHandle());
- // add to the sensor list (returned to clients)
- mSensorList.add(sensor);
- // add to our handle->SensorInterface mapping
- mSensorMap.add(sensor.getHandle(), s);
- // create an entry in the mLastEventSeen array
- mLastEventSeen.add(sensor.getHandle(), NULL);
-
- return sensor;
+const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
+ int handle = s->getSensor().getHandle();
+ if (mSensors.add(handle, s, isDebug, isVirtual)){
+ mLastEventSeen.add(handle, nullptr);
+ return s->getSensor();
+ } else {
+ return mSensors.getNonSensor();
+ }
}
-Sensor SensorService::registerDynamicSensor(SensorInterface* s) {
- Sensor sensor = registerSensor(s);
- mDynamicSensorList.add(sensor);
-
- auto compareSensorHandle = [] (const Sensor* lhs, const Sensor* rhs) {
- return lhs->getHandle() - rhs->getHandle();
- };
- mDynamicSensorList.sort(compareSensorHandle);
- return sensor;
+const Sensor& SensorService::registerDynamicSensor(SensorInterface* s, bool isDebug) {
+ return registerSensor(s, isDebug);
}
bool SensorService::unregisterDynamicSensor(int handle) {
- bool found = false;
-
- for (size_t i = 0 ; i < mSensorList.size() ; i++) {
- if (mSensorList[i].getHandle() == handle) {
- mSensorList.removeAt(i);
- found = true;
- break;
- }
+ bool ret = mSensors.remove(handle);
+ MostRecentEventLogger *buf = mLastEventSeen.valueFor(handle);
+ if (buf) {
+ delete buf;
}
-
- if (found) {
- for (size_t i = 0 ; i < mDynamicSensorList.size() ; i++) {
- if (mDynamicSensorList[i].getHandle() == handle) {
- mDynamicSensorList.removeAt(i);
- }
- }
-
- mSensorMap.removeItem(handle);
- mLastEventSeen.removeItem(handle);
- }
- return found;
+ mLastEventSeen.removeItem(handle);
+ return ret;
}
-Sensor SensorService::registerVirtualSensor(SensorInterface* s) {
- Sensor sensor = registerSensor(s);
- mVirtualSensorList.add( s );
- return sensor;
-}
-
-bool SensorService::isNewHandle(int handle) {
- for (int h : mUsedHandleList) {
- if (h == handle) {
- return false;
- }
- }
- return true;
+const Sensor& SensorService::registerVirtualSensor(SensorInterface* s, bool isDebug) {
+ return registerSensor(s, isDebug, true);
}
SensorService::~SensorService() {
- for (size_t i=0 ; i<mSensorMap.size() ; i++) {
- delete mSensorMap.valueAt(i);
- }
}
status_t SensorService::dump(int fd, const Vector<String16>& args) {
@@ -374,73 +307,31 @@
// Transition to data injection mode supported only from NORMAL mode.
return INVALID_OPERATION;
}
- } else if (mSensorList.size() == 0) {
+ } else if (!mSensors.hasAnySensor()) {
result.append("No Sensors on the device\n");
} else {
// Default dump the sensor list and debugging information.
- result.append("Sensor List:\n");
- for (size_t i=0 ; i<mSensorList.size() ; i++) {
- const Sensor& s(mSensorList[i]);
- result.appendFormat(
- "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
- s.getName().string(),
- s.getVendor().string(),
- s.getVersion(),
- s.getStringType().string(),
- s.getHandle(),
- s.getRequiredPermission().string(),
- s.getType());
+ //
+ result.append(mSensors.dump().c_str());
- const int reportingMode = s.getReportingMode();
- if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
- result.append(" continuous | ");
- } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
- result.append(" on-change | ");
- } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
- result.append(" one-shot | ");
- } else {
- result.append(" special-trigger | ");
- }
-
- if (s.getMaxDelay() > 0) {
- result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
- } else {
- result.appendFormat("maxDelay=%dus |", s.getMaxDelay());
- }
-
- if (s.getMinDelay() > 0) {
- result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
- } else {
- result.appendFormat("minDelay=%dus |", s.getMinDelay());
- }
-
- if (s.getFifoMaxEventCount() > 0) {
- result.appendFormat("FifoMax=%d events | ",
- s.getFifoMaxEventCount());
- } else {
- result.append("no batching | ");
- }
-
- if (s.isWakeUpSensor()) {
- result.appendFormat("wakeUp | ");
- } else {
- result.appendFormat("non-wakeUp | ");
- }
-
- int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
- if (bufIndex >= 0) {
- const MostRecentEventLogger* buf = mLastEventSeen.valueAt(bufIndex);
- if (buf != NULL && s.getRequiredPermission().isEmpty()) {
- buf->printBuffer(result);
- } else {
- result.append("last=<> \n");
- }
- }
- result.append("\n");
- }
SensorFusion::getInstance().dump(result);
SensorDevice::getInstance().dump(result);
+ result.append("Recent Sensor events:\n");
+ auto& lastEvents = mLastEventSeen;
+ mSensors.forEachSensor([&result, &lastEvents] (const Sensor& s) -> bool {
+ int bufIndex = lastEvents.indexOfKey(s.getHandle());
+ if (bufIndex >= 0) {
+ const MostRecentEventLogger* buf = lastEvents.valueAt(bufIndex);
+ if (buf != nullptr && s.getRequiredPermission().isEmpty()) {
+ result.appendFormat("%s (handle:0x%08x): ",
+ s.getName().string(), s.getHandle());
+ buf->printBuffer(result);
+ }
+ }
+ return true;
+ });
+
result.append("Active sensors:\n");
for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
int handle = mActiveSensors.keyAt(i);
@@ -508,6 +399,7 @@
return NO_ERROR;
}
+//TODO: move to SensorEventConnection later
void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
sensors_event_t const* buffer, const int count) {
for (int i=0 ; i<count ; i++) {
@@ -516,12 +408,12 @@
handle = buffer[i].meta_data.sensor;
}
if (connection->hasSensor(handle)) {
- SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
+ SensorInterface* si = mSensors.getInterface(handle);
// If this buffer has an event from a one_shot sensor and this connection is registered
// for this particular one_shot sensor, try cleaning up the connection.
- if (sensor != NULL &&
- sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
- sensor->autoDisable(connection.get(), handle);
+ if (si != NULL &&
+ si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+ si->autoDisable(connection.get(), handle);
cleanupWithoutDisableLocked(connection, handle);
}
@@ -535,11 +427,11 @@
// each virtual sensor could generate an event per "real" event, that's why we need to size
// numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT. in practice, this is too
// aggressive, but guaranteed to be enough.
+ const size_t vcount = mSensors.getVirtualSensors().size();
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
- const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
+ const size_t numEventMax = minBufferSize / (1 + vcount);
SensorDevice& device(SensorDevice::getInstance());
- const size_t vcount = mVirtualSensorList.size();
const int halVersion = device.getHalDeviceVersion();
do {
@@ -632,10 +524,10 @@
}
for (int i = 0; i < count; ++i) {
- // Map flush_complete_events in the buffer to SensorEventConnections which called flush on
- // the hardware sensor. mapFlushEventsToConnections[i] will be the SensorEventConnection
- // mapped to the corresponding flush_complete_event in mSensorEventBuffer[i] if such a
- // mapping exists (NULL otherwise).
+ // Map flush_complete_events in the buffer to SensorEventConnections which called flush
+ // on the hardware sensor. mapFlushEventsToConnections[i] will be the
+ // SensorEventConnection mapped to the corresponding flush_complete_event in
+ // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
mMapFlushEventsToConnections[i] = NULL;
if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
@@ -656,7 +548,7 @@
ALOGI("Dynamic sensor handle 0x%x connected, type %d, name %s",
handle, dynamicSensor.type, dynamicSensor.name);
- if (isNewHandle(handle)) {
+ if (mSensors.isNewHandle(handle)) {
sensor_t s = dynamicSensor;
// make sure the dynamic sensor flag is set
s.flags |= DYNAMIC_SENSOR_MASK;
@@ -664,8 +556,8 @@
s.handle = handle;
SensorInterface *si = new HardwareSensor(s);
- // This will release hold on dynamic sensor meta, so it should be called after
- // Sensor object is created.
+ // This will release hold on dynamic sensor meta, so it should be called
+ // after Sensor object is created.
device.handleDynamicSensorConnection(handle, true /*connected*/);
registerDynamicSensor(si);
} else {
@@ -802,14 +694,7 @@
}
String8 SensorService::getSensorName(int handle) const {
- size_t count = mUserSensorList.size();
- for (size_t i=0 ; i<count ; i++) {
- const Sensor& sensor(mUserSensorList[i]);
- if (sensor.getHandle() == handle) {
- return sensor.getName();
- }
- }
- return String8("unknown");
+ return mSensors.getName(handle);
}
bool SensorService::isVirtualSensor(int handle) const {
@@ -830,7 +715,7 @@
char value[PROPERTY_VALUE_MAX];
property_get("debug.sensors", value, "0");
const Vector<Sensor>& initialSensorList = (atoi(value)) ?
- mUserSensorListDebug : mUserSensorList;
+ mSensors.getUserDebugSensors() : mSensors.getUserSensors();
Vector<Sensor> accessibleSensorList;
for (size_t i = 0; i < initialSensorList.size(); i++) {
Sensor sensor = initialSensorList[i];
@@ -848,17 +733,19 @@
Vector<Sensor> SensorService::getDynamicSensorList(const String16& opPackageName) {
Vector<Sensor> accessibleSensorList;
- for (size_t i = 0; i < mDynamicSensorList.size(); i++) {
- Sensor sensor = mDynamicSensorList[i];
- if (canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
- accessibleSensorList.add(sensor);
- } else {
- ALOGI("Skipped sensor %s because it requires permission %s and app op %d",
- sensor.getName().string(),
- sensor.getRequiredPermission().string(),
- sensor.getRequiredAppOp());
- }
- }
+ mSensors.forEachSensor(
+ [&opPackageName, &accessibleSensorList] (const Sensor& sensor) -> bool {
+ if (sensor.isDynamicSensor() &&
+ canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
+ accessibleSensorList.add(sensor);
+ } else {
+ ALOGI("Skipped sensor %s because it requires permission %s and app op %" PRId32,
+ sensor.getName().string(),
+ sensor.getRequiredPermission().string(),
+ sensor.getRequiredAppOp());
+ }
+ return true;
+ });
return accessibleSensorList;
}
@@ -950,13 +837,11 @@
}
SensorInterface* SensorService::getSensorInterfaceFromHandle(int handle) const {
- ssize_t index = mSensorMap.indexOfKey(handle);
- return index < 0 ? nullptr : mSensorMap.valueAt(index);
+ return mSensors.getInterface(handle);
}
-Sensor SensorService::getSensorFromHandle(int handle) const {
- SensorInterface* si = getSensorInterfaceFromHandle(handle);
- return si ? si->getSensor() : Sensor();
+const Sensor& SensorService::getSensorFromHandle(int handle) const {
+ return mSensors.get(handle);
}
status_t SensorService::enable(const sp<SensorEventConnection>& connection,
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index da97286..e535339 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -37,6 +37,7 @@
#include <gui/ISensorEventConnection.h>
#include "SensorInterface.h"
+#include "SensorList.h"
#if __clang__
// Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
@@ -156,18 +157,18 @@
virtual int isDataInjectionEnabled();
virtual status_t dump(int fd, const Vector<String16>& args);
-
static int getNumEventsForSensorType(int sensor_event_type);
String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const;
SensorInterface* getSensorInterfaceFromHandle(int handle) const;
- Sensor getSensorFromHandle(int handle) const;
+ const Sensor& getSensorFromHandle(int handle) const;
bool isWakeUpSensor(int type) const;
void recordLastValueLocked(sensors_event_t const* buffer, size_t count);
static void sortEventBuffer(sensors_event_t* buffer, size_t count);
- Sensor registerSensor(SensorInterface* sensor);
- Sensor registerVirtualSensor(SensorInterface* sensor);
- Sensor registerDynamicSensor(SensorInterface* sensor);
+ const Sensor& registerSensor(SensorInterface* sensor,
+ bool isDebug = false, bool isVirtual = false);
+ const Sensor& registerVirtualSensor(SensorInterface* sensor, bool isDebug = false);
+ const Sensor& registerDynamicSensor(SensorInterface* sensor, bool isDebug = false);
bool unregisterDynamicSensor(int handle);
status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection, int handle);
status_t cleanupWithoutDisableLocked(const sp<SensorEventConnection>& connection, int handle);
@@ -182,7 +183,6 @@
void checkWakeLockStateLocked();
bool isWakeLockAcquired();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
- bool isNewHandle(int handle);
sp<Looper> getLooper() const;
@@ -211,14 +211,7 @@
status_t resetToNormalMode();
status_t resetToNormalModeLocked();
- // lists and maps
- Vector<Sensor> mSensorList;
- Vector<Sensor> mUserSensorListDebug;
- Vector<Sensor> mUserSensorList;
- Vector<Sensor> mDynamicSensorList;
- DefaultKeyedVector<int, SensorInterface*> mSensorMap;
- Vector<SensorInterface *> mVirtualSensorList;
- Vector<int> mUsedHandleList;
+ SensorServiceUtil::SensorList mSensors;
status_t mInitCheck;
// Socket buffersize used to initialize BitTube. This size depends on whether batching is
@@ -233,6 +226,7 @@
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
+ KeyedVector<int32_t, MostRecentEventLogger*> mLastEventSeen;
Mode mCurrentOperatingMode;
// This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
@@ -241,9 +235,6 @@
// sensors.
String8 mWhiteListedPackage;
- // The size of this vector is constant, only the items are mutable
- KeyedVector<int32_t, MostRecentEventLogger *> mLastEventSeen;
-
int mNextSensorRegIndex;
Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
};
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 5ba387d..4cf9370 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -15,6 +15,7 @@
*/
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
// This is needed for stdint.h to define INT64_MAX in C++
#define __STDC_LIMIT_MACROS
@@ -33,12 +34,21 @@
#include "DispSync.h"
#include "EventLog/EventLog.h"
+#include <algorithm>
+
+using std::max;
+using std::min;
+
namespace android {
// Setting this to true enables verbose tracing that can be used to debug
// vsync event model or phase issues.
static const bool kTraceDetailedInfo = false;
+// Setting this to true adds a zero-phase tracer for correlating with hardware
+// vsync events
+static const bool kEnableZeroPhaseTracer = false;
+
// This is the threshold used to determine when hardware vsync events are
// needed to re-synchronize the software vsync model with the hardware. The
// error metric used is the mean of the squared difference between each
@@ -49,28 +59,36 @@
// vsync event.
static const int64_t kPresentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS;
+#undef LOG_TAG
+#define LOG_TAG "DispSyncThread"
class DispSyncThread: public Thread {
public:
- DispSyncThread():
+ DispSyncThread(const char* name):
+ mName(name),
mStop(false),
mPeriod(0),
mPhase(0),
mReferenceTime(0),
- mWakeupLatency(0) {
- }
+ mWakeupLatency(0),
+ mFrameNumber(0) {}
virtual ~DispSyncThread() {}
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
mReferenceTime = referenceTime;
+ ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
+ " mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
+ ns2us(mPhase), ns2us(mReferenceTime));
mCond.signal();
}
void stop() {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mStop = true;
mCond.signal();
@@ -89,6 +107,12 @@
{ // Scope for lock
Mutex::Autolock lock(mMutex);
+ if (kTraceDetailedInfo) {
+ ATRACE_INT64("DispSync:Frame", mFrameNumber);
+ }
+ ALOGV("[%s] Frame %" PRId64, mName, mFrameNumber);
+ ++mFrameNumber;
+
if (mStop) {
return false;
}
@@ -109,6 +133,9 @@
bool isWakeup = false;
if (now < targetTime) {
+ ALOGV("[%s] Waiting until %" PRId64, mName,
+ ns2us(targetTime));
+ if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
err = mCond.waitRelative(mMutex, targetTime - now);
if (err == TIMED_OUT) {
@@ -122,15 +149,15 @@
now = systemTime(SYSTEM_TIME_MONOTONIC);
+ // Don't correct by more than 1.5 ms
+ static const nsecs_t kMaxWakeupLatency = us2ns(1500);
+
if (isWakeup) {
mWakeupLatency = ((mWakeupLatency * 63) +
(now - targetTime)) / 64;
- if (mWakeupLatency > 500000) {
- // Don't correct by more than 500 us
- mWakeupLatency = 500000;
- }
+ mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
if (kTraceDetailedInfo) {
- ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime);
+ ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
}
}
@@ -146,7 +173,9 @@
return false;
}
- status_t addEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
+ status_t addEventListener(const char* name, nsecs_t phase,
+ const sp<DispSync::Callback>& callback) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -156,15 +185,14 @@
}
EventListener listener;
+ listener.mName = name;
listener.mPhase = phase;
listener.mCallback = callback;
// We want to allow the firstmost future event to fire without
- // allowing any past events to fire. Because
- // computeListenerNextEventTimeLocked filters out events within a half
- // a period of the last event time, we need to initialize the last
- // event time to a half a period in the past.
- listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC) - mPeriod / 2;
+ // allowing any past events to fire
+ listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase -
+ mWakeupLatency;
mEventListeners.push(listener);
@@ -174,6 +202,7 @@
}
status_t removeEventListener(const sp<DispSync::Callback>& callback) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -189,6 +218,7 @@
// This method is only here to handle the kIgnorePresentFences case.
bool hasAnyEventListeners() {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
return !mEventListeners.empty();
}
@@ -196,6 +226,7 @@
private:
struct EventListener {
+ const char* mName;
nsecs_t mPhase;
nsecs_t mLastEventTime;
sp<DispSync::Callback> mCallback;
@@ -207,6 +238,8 @@
};
nsecs_t computeNextEventTimeLocked(nsecs_t now) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] computeNextEventTimeLocked", mName);
nsecs_t nextEventTime = INT64_MAX;
for (size_t i = 0; i < mEventListeners.size(); i++) {
nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
@@ -217,21 +250,28 @@
}
}
+ ALOGV("[%s] nextEventTime = %" PRId64, mName, ns2us(nextEventTime));
return nextEventTime;
}
Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName,
+ ns2us(now));
+
Vector<CallbackInvocation> callbackInvocations;
- nsecs_t ref = now - mPeriod;
+ nsecs_t onePeriodAgo = now - mPeriod;
for (size_t i = 0; i < mEventListeners.size(); i++) {
nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
- ref);
+ onePeriodAgo);
if (t < now) {
CallbackInvocation ci;
ci.mCallback = mEventListeners[i].mCallback;
ci.mEventTime = t;
+ ALOGV("[%s] [%s] Preparing to fire", mName,
+ mEventListeners[i].mName);
callbackInvocations.push(ci);
mEventListeners.editItemAt(i).mLastEventTime = t;
}
@@ -241,29 +281,67 @@
}
nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener,
- nsecs_t ref) {
+ nsecs_t baseTime) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")",
+ mName, listener.mName, ns2us(baseTime));
- nsecs_t lastEventTime = listener.mLastEventTime;
- if (ref < lastEventTime) {
- ref = lastEventTime;
+ nsecs_t lastEventTime = listener.mLastEventTime + mWakeupLatency;
+ ALOGV("[%s] lastEventTime: %" PRId64, mName, ns2us(lastEventTime));
+ if (baseTime < lastEventTime) {
+ baseTime = lastEventTime;
+ ALOGV("[%s] Clamping baseTime to lastEventTime -> %" PRId64, mName,
+ ns2us(baseTime));
}
- nsecs_t phase = mReferenceTime + mPhase + listener.mPhase;
- nsecs_t t = (((ref - phase) / mPeriod) + 1) * mPeriod + phase;
+ baseTime -= mReferenceTime;
+ ALOGV("[%s] Relative baseTime = %" PRId64, mName, ns2us(baseTime));
+ nsecs_t phase = mPhase + listener.mPhase;
+ ALOGV("[%s] Phase = %" PRId64, mName, ns2us(phase));
+ baseTime -= phase;
+ ALOGV("[%s] baseTime - phase = %" PRId64, mName, ns2us(baseTime));
- if (t - listener.mLastEventTime < mPeriod / 2) {
+ // If our previous time is before the reference (because the reference
+ // has since been updated), the division by mPeriod will truncate
+ // towards zero instead of computing the floor. Since in all cases
+ // before the reference we want the next time to be effectively now, we
+ // set baseTime to -mPeriod so that numPeriods will be -1.
+ // When we add 1 and the phase, we will be at the correct event time for
+ // this period.
+ if (baseTime < 0) {
+ ALOGV("[%s] Correcting negative baseTime", mName);
+ baseTime = -mPeriod;
+ }
+
+ nsecs_t numPeriods = baseTime / mPeriod;
+ ALOGV("[%s] numPeriods = %" PRId64, mName, numPeriods);
+ nsecs_t t = (numPeriods + 1) * mPeriod + phase;
+ ALOGV("[%s] t = %" PRId64, mName, ns2us(t));
+ t += mReferenceTime;
+ ALOGV("[%s] Absolute t = %" PRId64, mName, ns2us(t));
+
+ // Check that it's been slightly more than half a period since the last
+ // event so that we don't accidentally fall into double-rate vsyncs
+ if (t - listener.mLastEventTime < (3 * mPeriod / 5)) {
t += mPeriod;
+ ALOGV("[%s] Modifying t -> %" PRId64, mName, ns2us(t));
}
+ t -= mWakeupLatency;
+ ALOGV("[%s] Corrected for wakeup latency -> %" PRId64, mName, ns2us(t));
+
return t;
}
void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
+ const char* const mName;
+
bool mStop;
nsecs_t mPeriod;
@@ -271,12 +349,17 @@
nsecs_t mReferenceTime;
nsecs_t mWakeupLatency;
+ int64_t mFrameNumber;
+
Vector<EventListener> mEventListeners;
Mutex mMutex;
Condition mCond;
};
+#undef LOG_TAG
+#define LOG_TAG "DispSync"
+
class ZeroPhaseTracer : public DispSync::Callback {
public:
ZeroPhaseTracer() : mParity(false) {}
@@ -290,9 +373,10 @@
bool mParity;
};
-DispSync::DispSync() :
+DispSync::DispSync(const char* name) :
+ mName(name),
mRefreshSkipCount(0),
- mThread(new DispSyncThread()) {
+ mThread(new DispSyncThread(name)) {
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
@@ -305,8 +389,8 @@
// Even if we're just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
- if (!kIgnorePresentFences) {
- addEventListener(0, new ZeroPhaseTracer());
+ if (!kIgnorePresentFences && kEnableZeroPhaseTracer) {
+ addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer());
}
}
}
@@ -351,7 +435,7 @@
void DispSync::beginResync() {
Mutex::Autolock lock(mMutex);
-
+ ALOGV("[%s] beginResync", mName);
mModelUpdated = false;
mNumResyncSamples = 0;
}
@@ -359,11 +443,17 @@
bool DispSync::addResyncSample(nsecs_t timestamp) {
Mutex::Autolock lock(mMutex);
+ ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
+
size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if (mNumResyncSamples == 0) {
mPhase = 0;
mReferenceTime = timestamp;
+ ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
+ "mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
+ ns2us(mReferenceTime));
+ mThread->updateModel(mPeriod, mPhase, mReferenceTime);
}
if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
@@ -387,17 +477,21 @@
return mThread->hasAnyEventListeners();
}
- return !mModelUpdated || mError > kErrorThreshold;
+ // Check against kErrorThreshold / 2 to add some hysteresis before having to
+ // resync again
+ bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
+ ALOGV("[%s] addResyncSample returning %s", mName,
+ modelLocked ? "locked" : "unlocked");
+ return !modelLocked;
}
void DispSync::endResync() {
}
-status_t DispSync::addEventListener(nsecs_t phase,
+status_t DispSync::addEventListener(const char* name, nsecs_t phase,
const sp<Callback>& callback) {
-
Mutex::Autolock lock(mMutex);
- return mThread->addEventListener(phase, callback);
+ return mThread->addEventListener(name, phase, callback);
}
void DispSync::setRefreshSkipCount(int count) {
@@ -427,20 +521,32 @@
}
void DispSync::updateModelLocked() {
+ ALOGV("[%s] updateModelLocked %zu", mName, mNumResyncSamples);
if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
+ ALOGV("[%s] Computing...", mName);
nsecs_t durationSum = 0;
+ nsecs_t minDuration = INT64_MAX;
+ nsecs_t maxDuration = 0;
for (size_t i = 1; i < mNumResyncSamples; i++) {
size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
- durationSum += mResyncSamples[idx] - mResyncSamples[prev];
+ nsecs_t duration = mResyncSamples[idx] - mResyncSamples[prev];
+ durationSum += duration;
+ minDuration = min(minDuration, duration);
+ maxDuration = max(maxDuration, duration);
}
- mPeriod = durationSum / (mNumResyncSamples - 1);
+ // Exclude the min and max from the average
+ durationSum -= minDuration + maxDuration;
+ mPeriod = durationSum / (mNumResyncSamples - 3);
+
+ ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod));
double sampleAvgX = 0;
double sampleAvgY = 0;
double scale = 2.0 * M_PI / double(mPeriod);
- for (size_t i = 0; i < mNumResyncSamples; i++) {
+ // Intentionally skip the first sample
+ for (size_t i = 1; i < mNumResyncSamples; i++) {
size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
nsecs_t sample = mResyncSamples[idx] - mReferenceTime;
double samplePhase = double(sample % mPeriod) * scale;
@@ -448,18 +554,21 @@
sampleAvgY += sin(samplePhase);
}
- sampleAvgX /= double(mNumResyncSamples);
- sampleAvgY /= double(mNumResyncSamples);
+ sampleAvgX /= double(mNumResyncSamples - 1);
+ sampleAvgY /= double(mNumResyncSamples - 1);
mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);
- if (mPhase < 0) {
+ ALOGV("[%s] mPhase = %" PRId64, mName, ns2us(mPhase));
+
+ if (mPhase < -(mPeriod / 2)) {
mPhase += mPeriod;
+ ALOGV("[%s] Adjusting mPhase -> %" PRId64, mName, ns2us(mPhase));
}
if (kTraceDetailedInfo) {
ATRACE_INT64("DispSync:Period", mPeriod);
- ATRACE_INT64("DispSync:Phase", mPhase);
+ ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
}
// Artificially inflate the period if requested.
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index a8524b9..537c81b 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -26,11 +26,8 @@
namespace android {
// Ignore present (retire) fences if the device doesn't have support for the
-// sync framework, or if all phase offsets are zero. The latter is useful
-// because it allows us to avoid resync bursts on devices that don't need
-// phase-offset VSYNC events.
-#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \
- (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0)
+// sync framework
+#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK)
static const bool kIgnorePresentFences = true;
#else
static const bool kIgnorePresentFences = false;
@@ -64,7 +61,7 @@
virtual void onDispSyncEvent(nsecs_t when) = 0;
};
- DispSync();
+ DispSync(const char* name);
~DispSync();
// reset clears the resync samples and error value.
@@ -114,7 +111,8 @@
// given phase offset from the hardware vsync events. The callback is
// called from a separate thread and it should return reasonably quickly
// (i.e. within a few hundred microseconds).
- status_t addEventListener(nsecs_t phase, const sp<Callback>& callback);
+ status_t addEventListener(const char* name, nsecs_t phase,
+ const sp<Callback>& callback);
// removeEventListener removes an already-registered event callback. Once
// this method returns that callback will no longer be called by the
@@ -137,10 +135,12 @@
void resetErrorLocked();
enum { MAX_RESYNC_SAMPLES = 32 };
- enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 };
+ enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 };
enum { NUM_PRESENT_SAMPLES = 8 };
enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
+ const char* const mName;
+
// mPeriod is the computed period of the modeled vsync events in
// nanoseconds.
nsecs_t mPeriod;
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index f760200..dd88adb 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -44,8 +44,9 @@
return;
}
-EventThread::EventThread(const sp<VSyncSource>& src)
+EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger)
: mVSyncSource(src),
+ mFlinger(flinger),
mUseSoftwareVSync(false),
mVsyncEnabled(false),
mDebugVsyncEnabled(false),
@@ -126,6 +127,9 @@
void EventThread::requestNextVsync(
const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
+
+ mFlinger.resyncWithRateLimit();
+
if (connection->count < 0) {
connection->count = 0;
mCondition.broadcast();
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 9ba179a..34654fa 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -77,7 +77,7 @@
public:
- EventThread(const sp<VSyncSource>& src);
+ EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger);
sp<Connection> createEventConnection() const;
status_t registerDisplayEventConnection(const sp<Connection>& connection);
@@ -116,6 +116,7 @@
// constants
sp<VSyncSource> mVSyncSource;
PowerHAL mPowerHAL;
+ SurfaceFlinger& mFlinger;
mutable Mutex mLock;
mutable Condition mCondition;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1f85bee..a448639 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -149,6 +149,7 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
+ mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mDaltonize(false),
@@ -331,11 +332,12 @@
class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
- const char* label) :
+ const char* name) :
+ mName(name),
mValue(0),
mTraceVsync(traceVsync),
- mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
- mVsyncEventLabel(String8::format("VSYNC-%s", label)),
+ mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
+ mVsyncEventLabel(String8::format("VSYNC-%s", name)),
mDispSync(dispSync),
mCallbackMutex(),
mCallback(),
@@ -348,7 +350,7 @@
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
- status_t err = mDispSync->addEventListener(mPhaseOffset,
+ status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -399,7 +401,7 @@
}
// Add a listener with the new offset
- err = mDispSync->addEventListener(mPhaseOffset,
+ err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -425,6 +427,8 @@
}
}
+ const char* const mName;
+
int mValue;
const bool mTraceVsync;
@@ -455,10 +459,10 @@
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc);
+ mEventThread = new EventThread(vsyncSrc, *this);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc);
+ mSFEventThread = new EventThread(sfVsyncSrc, *this);
mEventQueue.setEventThread(mSFEventThread);
// Get a RenderEngine for the given display / config (can't fail)
@@ -827,6 +831,13 @@
}
}
+void SurfaceFlinger::resyncWithRateLimit() {
+ static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+ if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+ resyncToHardwareVsync(true);
+ }
+}
+
void SurfaceFlinger::onVSyncReceived(int32_t type, nsecs_t timestamp) {
bool needsHwVsync = false;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8c974d0..633e956 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -409,8 +409,11 @@
* VSync
*/
void enableHardwareVsync();
- void disableHardwareVsync(bool makeUnavailable);
void resyncToHardwareVsync(bool makeAvailable);
+ void disableHardwareVsync(bool makeUnavailable);
+public:
+ void resyncWithRateLimit();
+private:
/* ------------------------------------------------------------------------
* Debugging & dumpsys
@@ -522,7 +525,7 @@
static const size_t NUM_BUCKETS = 8; // < 1-7, 7+
nsecs_t mFrameBuckets[NUM_BUCKETS];
nsecs_t mTotalTime;
- nsecs_t mLastSwapTime;
+ std::atomic<nsecs_t> mLastSwapTime;
};
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index e9b3d99..ea685e7 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -148,6 +148,7 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
+ mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mDaltonize(false),
@@ -329,11 +330,12 @@
class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
- const char* label) :
+ const char* name) :
+ mName(name),
mValue(0),
mTraceVsync(traceVsync),
- mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
- mVsyncEventLabel(String8::format("VSYNC-%s", label)),
+ mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
+ mVsyncEventLabel(String8::format("VSYNC-%s", name)),
mDispSync(dispSync),
mCallbackMutex(),
mCallback(),
@@ -346,7 +348,7 @@
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
- status_t err = mDispSync->addEventListener(mPhaseOffset,
+ status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -397,7 +399,7 @@
}
// Add a listener with the new offset
- err = mDispSync->addEventListener(mPhaseOffset,
+ err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -423,6 +425,8 @@
}
}
+ const char* const mName;
+
int mValue;
const bool mTraceVsync;
@@ -452,10 +456,10 @@
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc);
+ mEventThread = new EventThread(vsyncSrc, *this);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc);
+ mSFEventThread = new EventThread(sfVsyncSrc, *this);
mEventQueue.setEventThread(mSFEventThread);
// Initialize the H/W composer object. There may or may not be an
@@ -847,6 +851,13 @@
}
}
+void SurfaceFlinger::resyncWithRateLimit() {
+ static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+ if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+ resyncToHardwareVsync(true);
+ }
+}
+
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
bool needsHwVsync = false;