diff options
-rw-r--r-- | ext4_utils/Android.mk | 2 | ||||
-rw-r--r-- | ext4_utils/e4crypt_static.c | 147 | ||||
-rw-r--r-- | ext4_utils/ext4_crypt.cpp | 181 | ||||
-rw-r--r-- | ext4_utils/ext4_crypt_init_extensions.cpp | 186 | ||||
-rw-r--r-- | ext4_utils/ext4_crypt_init_extensions.h | 15 | ||||
-rw-r--r-- | ext4_utils/key_control.cpp | 44 | ||||
-rw-r--r-- | ext4_utils/key_control.h (renamed from ext4_utils/ext4_crypt.h) | 25 | ||||
-rw-r--r-- | ext4_utils/make_ext4fs.c | 1 | ||||
-rw-r--r-- | ext4_utils/make_ext4fs_main.c | 2 | ||||
-rw-r--r-- | ext4_utils/unencrypted_properties.cpp | 32 | ||||
-rw-r--r-- | ext4_utils/unencrypted_properties.h | 24 | ||||
-rw-r--r-- | f2fs_utils/f2fs_ioutils.c | 1 | ||||
-rw-r--r-- | perfprofd/perf_profile.proto | 10 | ||||
-rw-r--r-- | perfprofd/perfprofdcore.cc | 78 | ||||
-rw-r--r-- | perfprofd/perfprofdcore.h | 3 | ||||
-rw-r--r-- | perfprofd/tests/perfprofd_test.cc | 3 | ||||
-rwxr-xr-x | tests/workloads/capture.sh | 22 | ||||
-rwxr-xr-x | tests/workloads/defs.sh | 82 | ||||
-rwxr-xr-x | tests/workloads/recentfling.sh | 64 | ||||
-rwxr-xr-x | tests/workloads/systemapps.sh | 134 | ||||
-rw-r--r-- | verity/Android.mk | 2 |
21 files changed, 506 insertions, 552 deletions
diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk index 08088863..31a4b711 100644 --- a/ext4_utils/Android.mk +++ b/ext4_utils/Android.mk @@ -53,8 +53,8 @@ include $(BUILD_HOST_EXECUTABLE) # libext4_utils_src_files += \ + key_control.cpp \ ext4_crypt.cpp \ - e4crypt_static.c \ unencrypted_properties.cpp ifneq ($(HOST_OS),windows) diff --git a/ext4_utils/e4crypt_static.c b/ext4_utils/e4crypt_static.c deleted file mode 100644 index 1a62ce4a..00000000 --- a/ext4_utils/e4crypt_static.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2015 Google, Inc. - */ - -#define TAG "ext4_utils" - -#include <dirent.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> - -#include <sys/xattr.h> -#include <sys/syscall.h> -#include <sys/stat.h> - -#include <cutils/klog.h> - -#include "ext4_crypt.h" - -/* keyring keyctl commands */ -#define KEYCTL_SETPERM 5 /* set permissions for a key in a keyring */ -#define KEYCTL_UNLINK 9 /* unlink a key from a keyring */ -#define KEYCTL_SEARCH 10 /* search for a key in a keyring */ - -#define XATTR_NAME_ENCRYPTION_POLICY "encryption.policy" -#define EXT4_KEYREF_DELIMITER ((char)'.') - -/* Validate that all path items are available and accessible. */ -static int is_path_valid(const char *path) -{ - if (access(path, W_OK)) { - KLOG_ERROR(TAG, "Can't access %s: %s\n",strerror(errno), path); - return 0; - } - - return 1; -} - -/* Checks whether the policy provided is valid */ -static int is_keyref_valid(const char *keyref) -{ - char *period = 0; - size_t key_location_len = 0; - - /* Key ref must have a key and location delimiter character. */ - period = strchr(keyref, EXT4_KEYREF_DELIMITER); - if (!period) { - return 0; - } - - /* period must be >= keyref. */ - key_location_len = period - keyref; - - if (strncmp(keyref, "@t", key_location_len) == 0 || - strncmp(keyref, "@p", key_location_len) == 0 || - strncmp(keyref, "@s", key_location_len) == 0 || - strncmp(keyref, "@u", key_location_len) == 0 || - strncmp(keyref, "@g", key_location_len) == 0 || - strncmp(keyref, "@us", key_location_len) == 0) - return 1; - - return 0; -} - -static int is_dir_empty(const char *dirname) -{ - int n = 0; - struct dirent *d; - DIR *dir; - - dir = opendir(dirname); - while ((d = readdir(dir)) != NULL) { - if (strcmp(d->d_name, "lost+found") == 0) { - // Skip lost+found directory - } else if (++n > 2) { - break; - } - } - closedir(dir); - return n <= 2; -} - -int do_policy_set(const char *directory, const char *policy) -{ - struct stat st; - ssize_t ret; - - if (!is_keyref_valid(policy)) { - KLOG_ERROR(TAG, "Policy has invalid format.\n"); - return -EINVAL; - } - - if (!is_path_valid(directory)) { - return -EINVAL; - } - - stat(directory, &st); - if (!S_ISDIR(st.st_mode)) { - KLOG_ERROR(TAG, "Can only set policy on a directory (%s)\n", directory); - return -EINVAL; - } - - if (!is_dir_empty(directory)) { - KLOG_ERROR(TAG, "Can only set policy on an empty directory (%s)\n", directory); - return -EINVAL; - } - - ret = lsetxattr(directory, XATTR_NAME_ENCRYPTION_POLICY, policy, - strlen(policy), 0); - - if (ret) { - KLOG_ERROR(TAG, "Failed to set encryption policy for %s: %s\n", - directory, strerror(errno)); - return -EINVAL; - } - - KLOG_INFO(TAG, "Encryption policy for %s is set to %s\n", directory, policy); - return 0; -} - -static long keyctl(int cmd, ...) -{ - va_list va; - unsigned long arg2, arg3, arg4, arg5; - - va_start(va, cmd); - arg2 = va_arg(va, unsigned long); - arg3 = va_arg(va, unsigned long); - arg4 = va_arg(va, unsigned long); - arg5 = va_arg(va, unsigned long); - va_end(va); - return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); -} - -key_serial_t add_key(const char *type, - const char *description, - const void *payload, - size_t plen, - key_serial_t ringid) -{ - return syscall(__NR_add_key, type, description, payload, plen, ringid); -} - -long keyctl_setperm(key_serial_t id, int permissions) -{ - return keyctl(KEYCTL_SETPERM, id, permissions); -} diff --git a/ext4_utils/ext4_crypt.cpp b/ext4_utils/ext4_crypt.cpp index bb573323..886d17a1 100644 --- a/ext4_utils/ext4_crypt.cpp +++ b/ext4_utils/ext4_crypt.cpp @@ -1,120 +1,131 @@ -#define TAG "ext4_utils" +/* + * Copyright (c) 2015 Google, Inc. + */ -#include "ext4_crypt.h" +#define TAG "ext4_utils" -#include <string> -#include <fstream> -#include <map> +#include "ext4_crypt_init_extensions.h" +#include <dirent.h> #include <errno.h> -#include <sys/mount.h> +#include <string.h> +#include <unistd.h> + +#include <fcntl.h> +#include <asm/ioctl.h> +#include <sys/syscall.h> +#include <sys/stat.h> +#include <sys/types.h> #include <cutils/klog.h> -#include <cutils/properties.h> #include "unencrypted_properties.h" -namespace { - std::map<std::string, std::string> s_password_store; -} - -bool e4crypt_non_default_key(const char* dir) +#define XATTR_NAME_ENCRYPTION_POLICY "encryption.policy" +#define EXT4_KEYREF_DELIMITER ((char)'.') + +// ext4enc:TODO Include structure from somewhere sensible +// MUST be in sync with ext4_crypto.c in kernel +#define EXT4_KEY_DESCRIPTOR_SIZE 8 +struct ext4_encryption_policy { + char version; + char contents_encryption_mode; + char filenames_encryption_mode; + char flags; + char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; +} __attribute__((__packed__)); + +#define EXT4_ENCRYPTION_MODE_AES_256_XTS 1 +#define EXT4_ENCRYPTION_MODE_AES_256_CTS 4 + +// ext4enc:TODO Get value from somewhere sensible +#define EXT4_IOC_SET_ENCRYPTION_POLICY \ + _IOR('f', 19, struct ext4_encryption_policy) + +/* Validate that all path items are available and accessible. */ +static int is_path_valid(const char *path) { - int type = e4crypt_get_password_type(dir); + if (access(path, W_OK)) { + KLOG_ERROR(TAG, "Can't access %s: %s\n",strerror(errno), path); + return 0; + } - // ext4enc:TODO Use consts, not 1 here - return type != -1 && type != 1; + return 1; } -int e4crypt_get_password_type(const char* path) +static int is_dir_empty(const char *dirname) { - UnencryptedProperties props(path); - if (props.Get<std::string>(properties::key).empty()) { - KLOG_INFO(TAG, "No master key, so not ext4enc\n"); - return -1; + int n = 0; + struct dirent *d; + DIR *dir; + + dir = opendir(dirname); + while ((d = readdir(dir)) != NULL) { + if (strcmp(d->d_name, "lost+found") == 0) { + // Skip lost+found directory + } else if (++n > 2) { + break; + } } - - return props.Get<int>(properties::type, 1); + closedir(dir); + return n <= 2; } -int e4crypt_change_password(const char* path, int crypt_type, - const char* password) +int do_policy_set(const char *directory, const char *policy, int policy_length) { - // ext4enc:TODO Encrypt master key with password securely. Store hash of - // master key for validation - UnencryptedProperties props(path); - if ( props.Set(properties::password, password) - && props.Set(properties::type, crypt_type)) - return 0; - return -1; -} + struct stat st; + ssize_t ret; -int e4crypt_crypto_complete(const char* path) -{ - KLOG_INFO(TAG, "ext4 crypto complete called on %s\n", path); - if (UnencryptedProperties(path).Get<std::string>(properties::key).empty()) { - KLOG_INFO(TAG, "No master key, so not ext4enc\n"); - return -1; + if (policy_length != EXT4_KEY_DESCRIPTOR_SIZE) { + KLOG_ERROR("Policy wrong length\n"); + return -EINVAL; } - return 0; -} - -int e4crypt_check_passwd(const char* path, const char* password) -{ - UnencryptedProperties props(path); - if (props.Get<std::string>(properties::key).empty()) { - KLOG_INFO(TAG, "No master key, so not ext4enc\n"); - return -1; + if (!is_path_valid(directory)) { + return -EINVAL; } - auto actual_password = props.Get<std::string>(properties::password); - - if (actual_password == password) { - s_password_store[path] = password; - return 0; - } else { - return -1; + stat(directory, &st); + if (!S_ISDIR(st.st_mode)) { + KLOG_ERROR(TAG, "Can only set policy on a directory (%s)\n", directory); + return -EINVAL; } -} -int e4crypt_restart(const char* path) -{ - int rc = 0; - - KLOG_INFO(TAG, "ext4 restart called on %s\n", path); - property_set("vold.decrypt", "trigger_reset_main"); - KLOG_INFO(TAG, "Just asked init to shut down class main\n"); - sleep(2); - - std::string tmp_path = std::string() + path + "/tmp_mnt"; + if (!is_dir_empty(directory)) { + KLOG_ERROR(TAG, "Can only set policy on an empty directory (%s)\n", + directory); + return -EINVAL; + } - // ext4enc:TODO add retry logic - rc = umount(tmp_path.c_str()); - if (rc) { - KLOG_ERROR(TAG, "umount %s failed with rc %d, msg %s\n", - tmp_path.c_str(), rc, strerror(errno)); - return rc; + int fd = open(directory, O_DIRECTORY); + if (fd == -1) { + KLOG_ERROR(TAG, "Failed to open directory (%s)\n", directory); + return -EINVAL; } - // ext4enc:TODO add retry logic - rc = umount(path); - if (rc) { - KLOG_ERROR(TAG, "umount %s failed with rc %d, msg %s\n", - path, rc, strerror(errno)); - return rc; + ext4_encryption_policy eep; + eep.version = 0; + eep.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; + eep.filenames_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; + eep.flags = 0; + memcpy(eep.master_key_descriptor, policy, EXT4_KEY_DESCRIPTOR_SIZE); + ret = ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &eep); + auto preserve_errno = errno; + close(fd); + + if (ret) { + KLOG_ERROR(TAG, "Failed to set encryption policy for %s: %s\n", + directory, strerror(preserve_errno)); + return -EINVAL; } + KLOG_INFO(TAG, "Encryption policy for %s is set to %02x%02x%02x%02x\n", + directory, policy[0], policy[1], policy[2], policy[3]); return 0; } -const char* e4crypt_get_password(const char* path) +bool e4crypt_non_default_key(const char* dir) { - // ext4enc:TODO scrub password after timeout - auto i = s_password_store.find(path); - if (i == s_password_store.end()) { - return 0; - } else { - return i->second.c_str(); - } + UnencryptedProperties props(dir); + return props.Get<int>(properties::is_default, 1) != 1; } diff --git a/ext4_utils/ext4_crypt_init_extensions.cpp b/ext4_utils/ext4_crypt_init_extensions.cpp index 284437f9..3fb04b98 100644 --- a/ext4_utils/ext4_crypt_init_extensions.cpp +++ b/ext4_utils/ext4_crypt_init_extensions.cpp @@ -1,12 +1,10 @@ #define TAG "ext4_utils" -#include "ext4_crypt.h" +#include "ext4_crypt_init_extensions.h" #include <string> -#include <fstream> -#include <iomanip> -#include <sstream> +#include <dirent.h> #include <errno.h> #include <sys/mount.h> #include <sys/stat.h> @@ -16,29 +14,26 @@ #include <cutils/sockets.h> #include <poll.h> +#include "key_control.h" #include "unencrypted_properties.h" -// ext4enc:TODO Include structure from somewhere sensible -// MUST be in sync with ext4_crypto.c in kernel -#define EXT4_MAX_KEY_SIZE 76 -struct ext4_encryption_key { - uint32_t mode; - char raw[EXT4_MAX_KEY_SIZE]; - uint32_t size; -}; - -static const std::string keyring = "@s"; static const std::string arbitrary_sequence_number = "42"; -static const int vold_command_timeout_ms = 10 * 1000; - -static key_serial_t device_keyring = -1; +static const int vold_command_timeout_ms = 60 * 1000; static std::string vold_command(std::string const& command) { KLOG_INFO(TAG, "Running command %s\n", command.c_str()); - int sock = socket_local_client("vold", + int sock = -1; + + while (true) { + sock = socket_local_client("cryptd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); + if (sock >= 0) { + break; + } + usleep(10000); + } if (sock < 0) { KLOG_INFO(TAG, "Cannot open vold, failing command\n"); @@ -65,18 +60,19 @@ static std::string vold_command(std::string const& command) struct pollfd poll_sock = {sock, POLLIN, 0}; - int rc = poll(&poll_sock, 1, vold_command_timeout_ms); + int rc = TEMP_FAILURE_RETRY(poll(&poll_sock, 1, vold_command_timeout_ms)); if (rc < 0) { KLOG_ERROR(TAG, "Error in poll %s\n", strerror(errno)); return ""; } + if (!(poll_sock.revents & POLLIN)) { KLOG_ERROR(TAG, "Timeout\n"); return ""; } char buffer[4096]; memset(buffer, 0, sizeof(buffer)); - rc = read(sock, buffer, sizeof(buffer)); + rc = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); if (rc <= 0) { if (rc == 0) { KLOG_ERROR(TAG, "Lost connection to Vold - did it crash?\n"); @@ -97,52 +93,34 @@ static std::string vold_command(std::string const& command) int e4crypt_create_device_key(const char* dir, int ensure_dir_exists(const char*)) { + // Already encrypted with password? If so bail + std::string temp_folder = std::string() + dir + "/tmp_mnt"; + DIR* temp_dir = opendir(temp_folder.c_str()); + if (temp_dir) { + closedir(temp_dir); + return 0; + } + // Make sure folder exists. Use make_dir to set selinux permissions. - KLOG_INFO(TAG, "Creating test device key\n"); - UnencryptedProperties props(dir); - if (ensure_dir_exists(props.GetPath().c_str())) { + if (ensure_dir_exists(UnencryptedProperties::GetPath(dir).c_str())) { KLOG_ERROR(TAG, "Failed to create %s with error %s\n", - props.GetPath().c_str(), strerror(errno)); + UnencryptedProperties::GetPath(dir).c_str(), + strerror(errno)); return -1; } - if (props.Get<std::string>(properties::key).empty()) { - // Create new key since it doesn't already exist - std::ifstream urandom("/dev/urandom", std::ifstream::binary); - if (!urandom) { - KLOG_ERROR(TAG, "Failed to open /dev/urandom\n"); - return -1; - } - - // ext4enc:TODO Don't hardcode 32 - std::string key_material(32, '\0'); - urandom.read(&key_material[0], key_material.length()); - if (!urandom) { - KLOG_ERROR(TAG, "Failed to read random bytes\n"); - return -1; - } - - if (!props.Set(properties::key, key_material)) { - KLOG_ERROR(TAG, "Failed to write key material\n"); - return -1; - } - } - - if (!props.Remove(properties::ref)) { - KLOG_ERROR(TAG, "Failed to remove key ref\n"); - return -1; - } + auto result = vold_command("cryptfs enablefilecrypto"); + // ext4enc:TODO proper error handling + KLOG_INFO(TAG, "enablefilecrypto returned with result %s\n", + result.c_str()); return 0; } int e4crypt_install_keyring() { - device_keyring = add_key("keyring", - "e4crypt", - 0, - 0, - KEY_SPEC_SESSION_KEYRING); + key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0, + KEY_SPEC_SESSION_KEYRING); if (device_keyring == -1) { KLOG_ERROR(TAG, "Failed to create keyring\n"); @@ -152,90 +130,6 @@ int e4crypt_install_keyring() KLOG_INFO(TAG, "Keyring created wth id %d in process %d\n", device_keyring, getpid()); - // ext4enc:TODO set correct permissions - long result = keyctl_setperm(device_keyring, 0x3f3f3f3f); - if (result) { - KLOG_ERROR(TAG, "KEYCTL_SETPERM failed with error %ld\n", result); - return -1; - } - - return 0; -} - -int e4crypt_install_key(const char* dir) -{ - UnencryptedProperties props(dir); - auto key = props.Get<std::string>(properties::key); - - // Get password to decrypt as needed - if (e4crypt_non_default_key(dir)) { - std::string result = vold_command("cryptfs getpw"); - // result is either - // 200 0 -1 - // or - // 200 0 {{sensitive}} 0001020304 - // where 0001020304 is hex encoding of password - std::istringstream i(result); - std::string bit; - i >> bit; - if (bit != "200") { - KLOG_ERROR(TAG, "Expecting 200\n"); - return -1; - } - - i >> bit; - if (bit != arbitrary_sequence_number) { - KLOG_ERROR(TAG, "Expecting %s\n", arbitrary_sequence_number.c_str()); - return -1; - } - - i >> bit; - if (bit != "{{sensitive}}") { - KLOG_INFO(TAG, "Not encrypted\n"); - return -1; - } - - i >> bit; - } - - // Add key to keyring - ext4_encryption_key ext4_key = {0, {0}, 0}; - if (key.length() > sizeof(ext4_key.raw)) { - KLOG_ERROR(TAG, "Key too long\n"); - return -1; - } - - ext4_key.mode = 0; - memcpy(ext4_key.raw, &key[0], key.length()); - ext4_key.size = key.length(); - - // ext4enc:TODO Use better reference not 1234567890 - key_serial_t key_id = add_key("logon", "ext4-key:1234567890", - (void*)&ext4_key, sizeof(ext4_key), - device_keyring); - - if (key_id == -1) { - KLOG_ERROR(TAG, "Failed to insert key into keyring with error %s\n", - strerror(errno)); - return -1; - } - - KLOG_INFO(TAG, "Added key %d to keyring %d in process %d\n", - key_id, device_keyring, getpid()); - - // ext4enc:TODO set correct permissions - long result = keyctl_setperm(key_id, 0x3f3f3f3f); - if (result) { - KLOG_ERROR(TAG, "KEYCTL_SETPERM failed with error %ld\n", result); - return -1; - } - - // Save reference to key so we can set policy later - if (!props.Set(properties::ref, "ext4-key:1234567890")) { - KLOG_ERROR(TAG, "Cannot save key reference\n"); - return -1; - } - return 0; } @@ -250,12 +144,16 @@ int e4crypt_set_directory_policy(const char* dir) } UnencryptedProperties props("/data"); - std::string ref = props.Get<std::string>(properties::ref); - std::string policy = keyring + "." + ref; - KLOG_INFO(TAG, "Setting policy %s\n", policy.c_str()); - int result = do_policy_set(dir, policy.c_str()); + std::string policy = props.Get<std::string>(properties::ref); + if (policy.empty()) { + return 0; + } + + KLOG_INFO(TAG, "Setting policy on %s\n", dir); + int result = do_policy_set(dir, policy.c_str(), policy.size()); if (result) { - KLOG_ERROR(TAG, "Setting policy on %s failed!\n", dir); + KLOG_ERROR(TAG, "Setting %s policy on %s failed!\n", + policy.c_str(), dir); return -1; } diff --git a/ext4_utils/ext4_crypt_init_extensions.h b/ext4_utils/ext4_crypt_init_extensions.h new file mode 100644 index 00000000..79311246 --- /dev/null +++ b/ext4_utils/ext4_crypt_init_extensions.h @@ -0,0 +1,15 @@ +#include <sys/cdefs.h> +#include <stdbool.h> + +__BEGIN_DECLS + +// These functions assume they are being called from init +// They will not operate properly outside of init +int e4crypt_install_keyring(); +int e4crypt_create_device_key(const char* path, + int ensure_dir_exists(const char* dir)); +int e4crypt_set_directory_policy(const char* path); +bool e4crypt_non_default_key(const char* path); +int do_policy_set(const char *directory, const char *policy, int policy_length); + +__END_DECLS diff --git a/ext4_utils/key_control.cpp b/ext4_utils/key_control.cpp new file mode 100644 index 00000000..3d775b7f --- /dev/null +++ b/ext4_utils/key_control.cpp @@ -0,0 +1,44 @@ +#include "key_control.h" + +#include <stdarg.h> +#include <unistd.h> +#include <sys/syscall.h> + +/* keyring keyctl commands */ +#define KEYCTL_SETPERM 5 /* set permissions for a key in a keyring */ +#define KEYCTL_UNLINK 9 /* unlink a key from a keyring */ +#define KEYCTL_SEARCH 10 /* search for a key in a keyring */ + +static long keyctl(int cmd, ...) +{ + va_list va; + unsigned long arg2, arg3, arg4, arg5; + + va_start(va, cmd); + arg2 = va_arg(va, unsigned long); + arg3 = va_arg(va, unsigned long); + arg4 = va_arg(va, unsigned long); + arg5 = va_arg(va, unsigned long); + va_end(va); + return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); +} + +key_serial_t add_key(const char *type, + const char *description, + const void *payload, + size_t plen, + key_serial_t ringid) +{ + return syscall(__NR_add_key, type, description, payload, plen, ringid); +} + +long keyctl_setperm(key_serial_t id, int permissions) +{ + return keyctl(KEYCTL_SETPERM, id, permissions); +} + +long keyctl_search(key_serial_t ringid, const char *type, + const char *description, key_serial_t destringid) +{ + return keyctl(KEYCTL_SEARCH, ringid, type, description, destringid); +} diff --git a/ext4_utils/ext4_crypt.h b/ext4_utils/key_control.h index cc692735..8e6e32ba 100644 --- a/ext4_utils/ext4_crypt.h +++ b/ext4_utils/key_control.h @@ -1,28 +1,7 @@ -#include <stdbool.h> #include <sys/cdefs.h> #include <sys/types.h> __BEGIN_DECLS -// These functions assume they are being called from init -// They will not operate properly outside of init -int e4crypt_install_keyring(); -int e4crypt_install_key(const char* dir); -int e4crypt_create_device_key(const char* dir, - int ensure_dir_exists(const char* dir)); - -// General functions -bool e4crypt_non_default_key(const char* dir); -int e4crypt_set_directory_policy(const char* dir); -int e4crypt_main(int argc, char* argv[]); -int e4crypt_change_password(const char* path, int crypt_type, - const char* password); -int e4crypt_get_password_type(const char* path); -int e4crypt_crypto_complete(const char* dir); -int e4crypt_check_passwd(const char* dir, const char* password); -const char* e4crypt_get_password(const char* dir); -int e4crypt_restart(const char* dir); - -// Key functions. ext4enc:TODO Move to own file // ext4enc:TODO - get these keyring standard definitions from proper system file // keyring serial number type @@ -44,7 +23,7 @@ key_serial_t add_key(const char *type, long keyctl_setperm(key_serial_t id, int permissions); -// Set policy on directory -int do_policy_set(const char *directory, const char *policy); +long keyctl_search(key_serial_t ringid, const char *type, + const char *description, key_serial_t destringid); __END_DECLS diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c index 5c9e2085..c089d255 100644 --- a/ext4_utils/make_ext4fs.c +++ b/ext4_utils/make_ext4fs.c @@ -61,7 +61,6 @@ #include <selinux/selinux.h> #include <selinux/label.h> -#include <selinux/android.h> #define O_BINARY 0 diff --git a/ext4_utils/make_ext4fs_main.c b/ext4_utils/make_ext4fs_main.c index 0e2ef5e5..f28e1b22 100644 --- a/ext4_utils/make_ext4fs_main.c +++ b/ext4_utils/make_ext4fs_main.c @@ -32,7 +32,9 @@ #ifndef USE_MINGW #include <selinux/selinux.h> #include <selinux/label.h> +#if !defined(HOST) #include <selinux/android.h> +#endif #else struct selabel_handle; #endif diff --git a/ext4_utils/unencrypted_properties.cpp b/ext4_utils/unencrypted_properties.cpp index bef7c57b..d873e91f 100644 --- a/ext4_utils/unencrypted_properties.cpp +++ b/ext4_utils/unencrypted_properties.cpp @@ -1,12 +1,13 @@ #include "unencrypted_properties.h" #include <sys/stat.h> +#include <dirent.h> namespace properties { const char* key = "key"; const char* ref = "ref"; - const char* type = "type"; - const char* password = "password"; + const char* props = "props"; + const char* is_default = "is_default"; } namespace @@ -14,9 +15,20 @@ namespace const char* unencrypted_folder = "unencrypted"; } +std::string UnencryptedProperties::GetPath(const char* device) +{ + return std::string() + device + "/" + unencrypted_folder; +} + UnencryptedProperties::UnencryptedProperties(const char* device) - : folder_(std::string() + device + "/" + unencrypted_folder) + : folder_(GetPath(device)) { + DIR* dir = opendir(folder_.c_str()); + if (dir) { + closedir(dir); + } else { + folder_.clear(); + } } UnencryptedProperties::UnencryptedProperties() @@ -24,7 +36,7 @@ UnencryptedProperties::UnencryptedProperties() } template<> std::string UnencryptedProperties::Get(const char* name, - std::string default_value) + std::string default_value) const { if (!OK()) return default_value; std::ifstream i(folder_ + "/" + name, std::ios::binary); @@ -56,18 +68,18 @@ template<> bool UnencryptedProperties::Set(const char* name, std::string const& return !o.fail(); } -UnencryptedProperties UnencryptedProperties::GetChild(const char* name) +UnencryptedProperties UnencryptedProperties::GetChild(const char* name) const { - UnencryptedProperties e4p; - if (!OK()) return e4p; + UnencryptedProperties up; + if (!OK()) return up; std::string directory(folder_ + "/" + name); if (mkdir(directory.c_str(), 700) == -1 && errno != EEXIST) { - return e4p; + return up; } - e4p.folder_ = directory; - return e4p; + up.folder_ = directory; + return up; } bool UnencryptedProperties::Remove(const char* name) diff --git a/ext4_utils/unencrypted_properties.h b/ext4_utils/unencrypted_properties.h index 80f41df4..b2d1295f 100644 --- a/ext4_utils/unencrypted_properties.h +++ b/ext4_utils/unencrypted_properties.h @@ -5,8 +5,8 @@ namespace properties { extern const char* key; extern const char* ref; - extern const char* type; - extern const char* password; + extern const char* props; + extern const char* is_default; } /** @@ -18,34 +18,38 @@ namespace properties { class UnencryptedProperties { public: + // Get path of folder. Must create before using any properties + // This is to allow proper setting of SELinux policy + static std::string GetPath(const char* device); + // Opens properties folder on named device. - // If folder does not exist, construction will succeed, but all + // If folder does not exist, OK will return false, all // getters will return default properties and setters will fail. UnencryptedProperties(const char* device); // Get named object. Return default if object does not exist or error. - template<typename t> t Get(const char* name, t default_value = t()); + template<typename t> t Get(const char* name, t default_value = t()) const; // Set named object. Return true if success, false otherwise template<typename t> bool Set(const char* name, t const& value); // Get child properties - UnencryptedProperties GetChild(const char* name); + UnencryptedProperties GetChild(const char* name) const; // Remove named object bool Remove(const char* name); - // Get path of folder - std::string const& GetPath() const {return folder_;} + // Does folder exist? + bool OK() const; + private: UnencryptedProperties(); - bool OK() const; std::string folder_; }; template<typename t> t UnencryptedProperties::Get(const char* name, - t default_value) + t default_value) const { if (!OK()) return default_value; t value = default_value; @@ -64,7 +68,7 @@ template<typename t> bool UnencryptedProperties::Set(const char* name, // Specialized getters/setters for strings template<> std::string UnencryptedProperties::Get(const char* name, - std::string default_value); + std::string default_value) const; template<> bool UnencryptedProperties::Set(const char* name, std::string const& value); diff --git a/f2fs_utils/f2fs_ioutils.c b/f2fs_utils/f2fs_ioutils.c index f3b2a638..a050cf8f 100644 --- a/f2fs_utils/f2fs_ioutils.c +++ b/f2fs_utils/f2fs_ioutils.c @@ -78,7 +78,6 @@ struct selabel_handle; #include <selinux/selinux.h> #include <selinux/label.h> -#include <selinux/android.h> #define O_BINARY 0 diff --git a/perfprofd/perf_profile.proto b/perfprofd/perf_profile.proto index ee34163f..3932a162 100644 --- a/perfprofd/perf_profile.proto +++ b/perfprofd/perf_profile.proto @@ -91,4 +91,12 @@ message AndroidPerfProfile { // List of all load modules. repeated LoadModule load_modules = 4; -}
\ No newline at end of file + + // is device screen on at point when profile is collected? + optional bool display_on = 5; + + // system load at point when profile is collected; corresponds + // to first value from /proc/loadavg multiplied by 100 then + // converted to int32 + optional int32 sys_load_average = 6; +} diff --git a/perfprofd/perfprofdcore.cc b/perfprofd/perfprofdcore.cc index b5f1872b..8f5b013c 100644 --- a/perfprofd/perfprofdcore.cc +++ b/perfprofd/perfprofdcore.cc @@ -34,6 +34,7 @@ #include <set> #include <cctype> +#include <base/file.h> #include <base/stringprintf.h> #include <cutils/properties.h> @@ -106,11 +107,6 @@ static const char *config_file_path = "/data/data/com.google.android.gms/files/perfprofd.conf"; // -// Set by SIGHUP signal handler -// -volatile unsigned please_reread_config_file = 0; - -// // This table describes the config file syntax in terms of key/value pairs. // Values come in two flavors: strings, or unsigned integers. In the latter // case the reader sets allowable minimum/maximum for the setting. @@ -126,7 +122,7 @@ class ConfigReader { std::string getStringValue(const char *key) const; // read the specified config file, applying any settings it contains - void readFile(); + void readFile(bool initial); private: void addUnsignedEntry(const char *key, @@ -163,7 +159,7 @@ void ConfigReader::addDefaultEntries() // set to 100, then over time we want to see a perf profile // collected every 100 seconds). The actual time within the interval // for the collection is chosen randomly. - addUnsignedEntry("collection_interval", 901, 100, UINT32_MAX); + addUnsignedEntry("collection_interval", 14400, 100, UINT32_MAX); // Use the specified fixed seed for random number generation (unit // testing) @@ -205,6 +201,11 @@ void ConfigReader::addDefaultEntries() addUnsignedEntry("hardwire_cpus", 1, 0, 1); addUnsignedEntry("hardwire_cpus_max_duration", 5, 1, UINT32_MAX); + // Maximum number of unprocessed profiles we can accumulate in the + // destination directory. Once we reach this limit, we continue + // to collect, but we just overwrite the most recent profile. + addUnsignedEntry("max_unprocessed_profiles", 10, 1, UINT32_MAX); + // If set to 1, pass the -g option when invoking 'perf' (requests // stack traces as opposed to flat profile). addUnsignedEntry("stack_profile", 0, 0, 1); @@ -323,11 +324,13 @@ static bool isblank(const std::string &line) return true; } -void ConfigReader::readFile() +void ConfigReader::readFile(bool initial) { FILE *fp = fopen(config_file_path, "r"); if (!fp) { - W_ALOGE("unable to open configuration file %s", config_file_path); + if (initial) { + W_ALOGE("unable to open configuration file %s", config_file_path); + } return; } @@ -479,6 +482,35 @@ static CKPROFILE_RESULT check_profiling_enabled(ConfigReader &config) return DO_COLLECT_PROFILE; } +static void annotate_encoded_perf_profile(wireless_android_play_playlog::AndroidPerfProfile *profile) +{ + // + // Load average as reported by the kernel + // + std::string load; + double fload = 0.0; + if (android::base::ReadFileToString("/proc/loadavg", &load) && + sscanf(load.c_str(), "%lf", &fload) == 1) { + int iload = static_cast<int>(fload * 100.0); + profile->set_sys_load_average(iload); + } else { + W_ALOGE("Failed to read or scan /proc/loadavg (%s)", strerror(errno)); + } + + // + // Examine the contents of wake_unlock to determine whether the + // device display is on or off. NB: is this really the only way to + // determine this info? + // + std::string disp; + if (android::base::ReadFileToString("/sys/power/wake_unlock", &disp)) { + bool ison = (strstr(disp.c_str(), "PowerManagerService.Display") == 0); + profile->set_display_on(ison); + } else { + W_ALOGE("Failed to read /sys/power/wake_unlock (%s)", strerror(errno)); + } +} + inline char* string_as_array(std::string* str) { return str->empty() ? NULL : &*str->begin(); } @@ -499,6 +531,13 @@ PROFILE_RESULT encode_to_proto(const std::string &data_file_path, return ERR_PERF_ENCODE_FAILED; } + // All of the info in 'encodedProfile' is derived from the perf.data file; + // here we tack display status and system load. + wireless_android_play_playlog::AndroidPerfProfile &prof = + const_cast<wireless_android_play_playlog::AndroidPerfProfile&> + (encodedProfile); + annotate_encoded_perf_profile(&prof); + // // Serialize protobuf to array // @@ -636,6 +675,9 @@ static void cleanup_destination_dir(const ConfigReader &config) } } closedir(dir); + } else { + W_ALOGW("unable to open destination dir %s for cleanup", + dest_dir.c_str()); } } @@ -680,7 +722,8 @@ static bool post_process(const ConfigReader &config, int current_seq) fclose(fp); } - if (produced.size() >= MAX_UNPROCESSED_FILE) { + unsigned maxLive = config.getUnsignedValue("max_unprocessed_profiles"); + if (produced.size() >= maxLive) { return false; } @@ -774,12 +817,11 @@ static PROFILE_RESULT collect_profile(const ConfigReader &config, int seq) } // -// SIGHUP handler. Sets a flag to indicate that we should reread the -// config file +// SIGHUP handler. Sending SIGHUP to the daemon can be used to break it +// out of a sleep() call so as to trigger a new collection (debugging) // static void sig_hup(int /* signum */) { - please_reread_config_file = 1; } // @@ -828,7 +870,7 @@ static void set_seed(ConfigReader &config) // static void init(ConfigReader &config) { - config.readFile(); + config.readFile(true); set_seed(config); cleanup_destination_dir(config); @@ -880,11 +922,9 @@ int perfprofd_main(int argc, char** argv) config.getUnsignedValue("collection_interval")); perfprofd_sleep(sleep_before_collect); - // Reread config file if someone sent a SIGHUP - if (please_reread_config_file) { - config.readFile(); - please_reread_config_file = 0; - } + // Reread config file -- the uploader may have rewritten it as a result + // of a gservices change + config.readFile(false); // Check for profiling enabled... CKPROFILE_RESULT ckresult = check_profiling_enabled(config); diff --git a/perfprofd/perfprofdcore.h b/perfprofd/perfprofdcore.h index f3b1717f..53695e2c 100644 --- a/perfprofd/perfprofdcore.h +++ b/perfprofd/perfprofdcore.h @@ -28,9 +28,6 @@ // by perfprofd within the destination directory; consumed by GmsCore. #define PRODUCED_FILENAME "perfprofd_produced.txt" -// Maximum number of encoded perf.data files stored in destination dir -#define MAX_UNPROCESSED_FILE 10 - // Main routine for perfprofd daemon extern int perfprofd_main(int argc, char **argv); diff --git a/perfprofd/tests/perfprofd_test.cc b/perfprofd/tests/perfprofd_test.cc index 0dd0f737..d13e21e3 100644 --- a/perfprofd/tests/perfprofd_test.cc +++ b/perfprofd/tests/perfprofd_test.cc @@ -304,7 +304,7 @@ TEST_F(PerfProfdTest, MissingGMS) // PerfProfdRunner runner; runner.addToConfig("only_debug_build=0"); - runner.addToConfig("trace_config_read=1"); + runner.addToConfig("trace_config_read=0"); runner.addToConfig("config_directory=/does/not/exist"); runner.addToConfig("main_loop_iterations=1"); runner.addToConfig("use_fixed_seed=1"); @@ -563,6 +563,7 @@ TEST_F(PerfProfdTest, BasicRunWithLivePerf) runner.addToConfig(cfparam); runner.addToConfig("main_loop_iterations=1"); runner.addToConfig("use_fixed_seed=12345678"); + runner.addToConfig("max_unprocessed_profiles=100"); runner.addToConfig("collection_interval=9999"); runner.addToConfig("sample_duration=2"); diff --git a/tests/workloads/capture.sh b/tests/workloads/capture.sh index 721fe8c8..3b2f446e 100755 --- a/tests/workloads/capture.sh +++ b/tests/workloads/capture.sh @@ -5,12 +5,24 @@ # do a throw-away adb in case the server is out-of-date adb devices -l 2>&1 >/dev/null -devInfo=$(adb devices -l | grep -v ^List | head -1) -set -- $devInfo -echo devInfo=$devInfo +while [ $# -gt 0 ] +do + case "$1" in + (-d) DEVICE=$2; shift;; + (*) + echo Unknown option $1 + exit 1;; + esac + shift +done -DEVICE=$(echo $4 | sed 's/product://') +if [ "$DEVICE" = "" ]; then + devInfo=$(adb devices -l | grep -v ^List | head -1) + set -- $devInfo + echo devInfo=$devInfo + DEVICE=$(echo $4 | sed 's/product://') +fi function convert { in=$1 @@ -26,7 +38,7 @@ function convert { case $DEVICE in -(shamu|hammerhead) +(shamu|hammerhead|bullhead) # no scaling necessary xmax=0 ymax=0;; diff --git a/tests/workloads/defs.sh b/tests/workloads/defs.sh index 838d04f4..a2b71387 100755 --- a/tests/workloads/defs.sh +++ b/tests/workloads/defs.sh @@ -11,8 +11,7 @@ generateActivities=0 # default activities. Can dynamically generate with -g. gmailActivity='com.google.android.gm/com.google.android.gm.ConversationListActivityGmail' hangoutsActivity='com.google.android.talk/com.google.android.talk.SigningInActivity' -chromeActivity='com.android.chrome/com.google.android.apps.chrome.ChromeTabbedActivity' -chromeLActivity='com.android.chrome/com.google.android.apps.chrome.document.DocumentActivity' +chromeActivity='com.android.chrome/_not_used' youtubeActivity='com.google.android.youtube/com.google.android.apps.youtube.app.WatchWhileActivity' cameraActivity='com.google.android.GoogleCamera/com.android.camera.CameraActivity' playActivity='com.android.vending/com.google.android.finsky.activities.MainActivity' @@ -209,37 +208,41 @@ function getEndTime { } function resetJankyFrames { - ${ADB}dumpsys gfxinfo $1 reset 2>&1 >/dev/null + _gfxapp=$1 + _gfxapp=${app:="com.android.systemui"} + ${ADB}dumpsys gfxinfo $_gfxapp reset 2>&1 >/dev/null } function getJankyFrames { - if [ -z "$ADB" ]; then - # Note: no awk or sed on devices so have to do this - # purely with bash - total=0 - janky=0 - /system/bin/dumpsys gfxinfo | grep " frames" | while read line - do - if echo $line | grep -q "Total frames"; then - set -- $line - ((total=total+$4)) - elif echo $line | grep -q "Janky frames"; then - set -- $line - ((janky=janky+$3)) - fi - # Note: no tail, awk, or sed on 5.x so get final - # sum via most recently written file - echo $total $janky > ./janky.$$ - done - cat ./janky.$$ - rm -f ./janky.$$ - else - ${ADB}dumpsys gfxinfo $1 | sed -e 's/
//' | awk ' - BEGIN { total=0; janky=0; } - /Total frames/ { total+=$4; } - /Janky frames/ { janky+=$3; } - END { printf "%d %d\n", total, janky; }' - fi + _gfxapp=$1 + _gfxapp=${_gfxapp:="com.android.systemui"} + + # Note: no awk or sed on devices so have to do this + # purely with bash + total=0 + janky=0 + latency=0 + ${ADB}dumpsys gfxinfo $_gfxapp | tr "\r" " " | egrep "9[059]th| frames" | while read line + do + if echo $line | grep -q "Total frames"; then + set -- $line + total=$4 + elif echo $line | grep -q "Janky frames"; then + set -- $line + janky=$3 + elif echo $line | grep -q "90th"; then + set -- $(echo $line | tr m " ") + l90=$3 + elif echo $line | grep -q "95th"; then + set -- $(echo $line | tr m " ") + l95=$3 + elif echo $line | grep -q "99th"; then + set -- $(echo $line | tr m " ") + l99=$3 + echo $total $janky $l90 $l95 $l99 + break + fi + done } function checkForDirectReclaim { @@ -332,9 +335,15 @@ function startActivity { doKeyevent HOME echo 0 return 0 - elif [ "$1" = chromeL ]; then - vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com - set -- $($AM_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime) + elif [ "$1" = chrome ]; then + if [ "$DEVICE" = volantis ]; then + vout $AM_START_NOWAIT -p "$(getPackageName $1)" http://www.theverge.com + $AM_START_NOWAIT -p "$(getPackageName $1)" http://www.theverge.com > /dev/null + set -- 0 0 + else + vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com + set -- $($AM_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime) + fi else vout $AM_START "$(getActivityName $1)" set -- $($AM_START "$(getActivityName $1)" | grep ThisTime) @@ -343,10 +352,9 @@ function startActivity { } function forceStartActivity { - if [ "$1" = chromeL ]; then - # force start doesn't work for chrome (hangs on startup) - startActivity $* - return 0 + if [ "$1" = chrome ]; then + vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com + set -- $($AM_FORCE_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime) else vout $AM_FORCE_START "$(getActivityName $1)" set -- $($AM_FORCE_START "$(getActivityName $1)" | grep ThisTime) diff --git a/tests/workloads/recentfling.sh b/tests/workloads/recentfling.sh index 68fdb2ff..092c8d92 100755 --- a/tests/workloads/recentfling.sh +++ b/tests/workloads/recentfling.sh @@ -44,6 +44,12 @@ case $DEVICE in upCount=6 UP="70 400 70 100 $flingtime" DOWN="70 100 70 400 $flingtime";; +(bullhead) + flingtime=200 + downCount=5 + upCount=5 + UP="500 1200 500 550 $flingtime" + DOWN="500 550 500 1200 $flingtime";; (volantis) flingtime=400 downCount=5 @@ -66,20 +72,6 @@ if [ $startapps -gt 0 ]; then done fi -cur=1 - -set -- $(getJankyFrames) -totalFrames=$1 -jankyFrames=$2 -frameSum=0 -jankSum=0 - -if [ ${totalFrames:=0} -eq 0 ]; then -#echo Error: could not read frame info with \"dumpsys graphicsstats\" - echo Error: could not read frame info with \"dumpsys gfxinfo\" - exit 1 -fi - function swipe { count=0 while [ $count -lt $2 ] @@ -89,14 +81,25 @@ function swipe { done } +cur=1 +frameSum=0 +jankSum=0 +latency90Sum=0 +latency95Sum=0 +latency99Sum=0 + echo Fling recents... -doKeyevent APP_SWITCH +doKeyevent HOME +sleep 0.5 +resetJankyFrames while [ $cur -le $iterations ] do if [ $capturesystrace -gt 0 ]; then ${ADB}atrace --async_start -z -c -b 16000 freq gfx view idle sched fi + doKeyevent APP_SWITCH + sleep 0.5 swipe "$DOWN" $downCount sleep 1 swipe "$UP" $upCount @@ -108,25 +111,40 @@ do if [ $capturesystrace -gt 0 ]; then ${ADB}atrace --async_dump -z -c -b 16000 freq gfx view idle sched > trace.${cur}.out fi + doKeyevent HOME + sleep 0.5 set -- $(getJankyFrames) - newTotalFrames=$1 - newJankyFrames=$2 - ((totalDiff=newTotalFrames-totalFrames)) + totalDiff=$1 + jankyDiff=$2 + latency90=$3 + latency95=$4 + latency99=$5 + if [ ${totalDiff:=0} -eq 0 ]; then + echo Error: could not read frame info with \"dumpsys gfxinfo\" + exit 1 + fi + ((frameSum=frameSum+totalDiff)) - ((jankyDiff=newJankyFrames-jankyFrames)) ((jankSum=jankSum+jankyDiff)) + ((latency90Sum=latency90Sum+latency90)) + ((latency95Sum=latency95Sum+latency95)) + ((latency99Sum=latency99Sum+latency99)) if [ "$totalDiff" -eq 0 ]; then echo Error: no frames detected. Is the display off? exit 1 fi ((jankPct=jankyDiff*100/totalDiff)) - totalFrames=$newTotalFrames - jankyFrames=$newJankyFrames + resetJankyFrames - echo Frames: $totalDiff Janks: $jankyDiff \(${jankPct}%\) + echo Frames: $totalDiff latency: $latency90/$latency95/$latency99 Janks: $jankyDiff\(${jankPct}%\) ((cur=cur+1)) done doKeyevent HOME ((aveJankPct=jankSum*100/frameSum)) -echo AVE: Frames: $frameSum Janks: $jankSum \(${aveJankPct}%\) +((aveJanks=jankSum/iterations)) +((aveFrames=frameSum/iterations)) +((aveLatency90=latency90Sum/iterations)) +((aveLatency95=latency95Sum/iterations)) +((aveLatency99=latency99Sum/iterations)) +echo AVE: Frames: $aveFrames latency: $aveLatency90/$aveLatency95/$aveLatency99 Janks: $aveJanks\(${aveJankPct}%\) diff --git a/tests/workloads/systemapps.sh b/tests/workloads/systemapps.sh index 184c4ee4..a263e7d2 100755 --- a/tests/workloads/systemapps.sh +++ b/tests/workloads/systemapps.sh @@ -26,6 +26,7 @@ iterations=1 tracecategories="gfx view am input memreclaim" totaltimetest=0 forcecoldstart=0 +waitTime=3.0 appList="gmail hangouts chrome youtube play home" @@ -36,6 +37,7 @@ function processLocalOption { (-F) forcecoldstart=1;; (-L) appList=$2; shift; ret=1;; (-T) totaltimetest=1;; + (-W) waitTime=$2; shift; ret=1;; (*) echo "$0: unrecognized option: $1" echo; echo "Usage: $0 [options]" @@ -44,6 +46,7 @@ function processLocalOption { echo "-L applist : list of applications" echo " default: $appList" echo "-T : total time to start all apps" + echo "-W : time to wait between apps" echo "-g : generate activity strings" echo "-i iterations" echo "-n : keep trace files" @@ -74,6 +77,9 @@ function computeStats { reclaim=$4 frames=$5 janks=$6 + l90=$7 + l95=$8 + l99=$9 curMax=$(eval "echo \$${label}max") curMax=${curMax:=0} curMin=$(eval "echo \$${label}min") @@ -88,6 +94,12 @@ function computeStats { curFrames=${curFrames:=0} curJanks=$(eval "echo \$${label}janks") curJanks=${curJanks:=0} + cur90=$(eval "echo \$${label}90") + cur90=${cur90:=0} + cur95=$(eval "echo \$${label}95") + cur95=${cur95:=0} + cur99=$(eval "echo \$${label}99") + cur99=${cur99:=0} if [ $curMax -lt $t ]; then eval "${label}max=$t" fi @@ -105,12 +117,19 @@ function computeStats { eval "${label}frames=$curFrames" ((curJanks=curJanks+${janks:=0})) eval "${label}janks=$curJanks" + ((cur90=cur90+${l90:=0})) + eval "${label}90=$cur90" + ((cur95=cur95+${l95:=0})) + eval "${label}95=$cur95" + ((cur99=cur99+${l99:=0})) + eval "${label}99=$cur99" } function getStats { label=$1 echo $(eval "echo \$${label}max") $(eval "echo \$${label}min") $(eval "echo \$${label}sum") \ $(eval "echo \$${label}restart") $(eval "echo \$${label}reclaim") \ - $(eval "echo \$${label}frames") $(eval "echo \$${label}janks") + $(eval "echo \$${label}frames") $(eval "echo \$${label}janks") \ + $(eval "echo \$${label}90") $(eval "echo \$${label}95") $(eval "echo \$${label}99") } cur=1 @@ -126,7 +145,7 @@ do fi if [ $iterations -gt 1 -o $cur -eq 1 ]; then if [ $totaltimetest -eq 0 ]; then - printf "%-6s %7s(ms) %6s(ms) %s %s %s %s\n" App Time AmTime Restart DirReclaim JankyFrames + printf "%-6s %7s(ms) %6s(ms) %s %s %s %s\n" App Time AmTime Restart DirReclaim Jank Latency fi fi @@ -136,53 +155,80 @@ do vout Starting $app... ((appnum=appnum+1)) loopTimestamp=$(date +"%s %N") - if [ $totaltimetest -gt 0 ]; then - # no instramentation, just cycle through the apps + resetJankyFrames + resetJankyFrames $(getPackageName $app) + if [ $totaltimetest -eq 0 ]; then + tmpTraceOut="$tmpTraceOutBase-$app.out" + >$tmpTraceOut + startInstramentation + else if [ $appnum -eq 0 ]; then - printf "%-8s %5s(ms) %3s(ms)\n" App Start Iter + printf "%-8s %5s(ms) %3s(ms) %s %s\n" App Start Iter Jank Latency fi - if [ $forcecoldstart -eq 0 ]; then - t=$(startActivity $app) - else - t=$(forceStartActivity $app) - fi - loopEndTimestamp=$(date +"%s %N") - diffTime=$(computeTimeDiff $loopTimestamp $loopEndTimestamp) - # Note: "%d" doesn't work right if run on device - printf "%-10s %5.0f %5.0f\n" $app $t $diffTime - ((totaltime=totaltime+t)) - continue fi - tmpTraceOut="$tmpTraceOutBase-$app.out" - >$tmpTraceOut - startInstramentation - resetJankyFrames $(getPackageName $app) - t=$(startActivity $app) + if [ $forcecoldstart -eq 0 ]; then + t=$(startActivity $app) + else + t=$(forceStartActivity $app) + fi + # let app finish drawing before checking janks - sleep 3 + sleep $waitTime set -- $(getJankyFrames $(getPackageName $app)) frames=$1 janks=$2 - ((jankPct=100*janks/frames)) - stopAndDumpInstramentation $tmpTraceOut - actName=$(getActivityName $app) - stime=$(getStartTime $actName $tmpTraceOut) - relaunch=$? - etime=$(getEndTime $actName $tmpTraceOut) - ((tdiff=$etime-$stime)) - if [ $etime -eq 0 -o $stime -eq 0 ]; then - handleError $app : could not compute start time stime=$stime etime=$etime - # use AmTime so statistics make sense - tdiff=$t + l90=$3 + l95=$4 + l99=$5 + set -- $(getJankyFrames) + systemFrames=$1 + systemJanks=$2 + s90=$3 + s95=$4 + s99=$5 + ((frames=frames+systemFrames)) + ((janks=janks+systemJanks)) + ((l90=l90+s90)) + ((l95=l95+s95)) + ((l99=l99+s99)) + + loopEndTimestamp=$(date +"%s %N") + diffTime=$(computeTimeDiff $loopTimestamp $loopEndTimestamp) + + if [ $frames -eq 0 ]; then + janks=0 + jankPct=0 + else + ((jankPct=100*janks/frames)) fi - checkForDirectReclaim $actName $tmpTraceOut - directReclaim=$? + if [ $totaltimetest -gt 0 ]; then + # Note: using %f since %d doesn't work correctly + # when running on lollipop + printf "%-10s %5.0f %5.0f %4.0f(%2.0f%%) %2.0f/%2.0f/%2.0f\n" $app $t $diffTime $janks $jankPct $l90 $l95 $l99 + ((totaltime=totaltime+t)) + continue + else + stopAndDumpInstramentation $tmpTraceOut + actName=$(getActivityName $app) + pkgName=$(getPackageName $app) + stime=$(getStartTime $actName $tmpTraceOut) + relaunch=$? + etime=$(getEndTime $pkgName $tmpTraceOut) + ((tdiff=$etime-$stime)) + if [ $etime -eq 0 -o $stime -eq 0 ]; then + handleError $app : could not compute start time stime=$stime etime=$etime + # use AmTime so statistics make sense + tdiff=$t + fi + checkForDirectReclaim $actName $tmpTraceOut + directReclaim=$? - printf "%-12s %5d %5d %5d %5d %5d(%d%%)\n" "$app" "$tdiff" "$t" "$relaunch" "$directReclaim" "$janks" "$jankPct" - computeStats "$app" "$tdiff" "$relaunch" "$directReclaim" "$frames" "$janks" + printf "%-12s %5d %5d %5d %5d %5d(%d%%) %d/%d/%d\n" "$app" "$tdiff" "$t" "$relaunch" "$directReclaim" "$janks" "$jankPct" $l90 $l95 $l99 + computeStats "$app" "$tdiff" "$relaunch" "$directReclaim" "$frames" "$janks" $l90 $l95 $l99 - if [ $savetmpfiles -eq 0 ]; then - rm -f $tmpTraceOut + if [ $savetmpfiles -eq 0 ]; then + rm -f $tmpTraceOut + fi fi done ((cur=cur+1)) @@ -198,7 +244,7 @@ if [ $iterations -gt 1 -a $totaltimetest -eq 0 ]; then echo ========================================= printf "Stats after $iterations iterations:\n" echo ========================================= - printf "%-6s %7s(ms) %6s(ms) %6s(ms) %s %s %s %s\n" App Max Ave Min Restart DirReclaim JankyFrames + printf "%-6s %7s(ms) %6s(ms) %6s(ms) %s %s %s %s\n" App Max Ave Min Restart DirReclaim Jank Latency for app in $appList do set -- $(getStats $app) @@ -206,7 +252,13 @@ if [ $iterations -gt 1 -a $totaltimetest -eq 0 ]; then ((ave=sum/iterations)) frames=$6 janks=$7 + l90=$8 + l95=$9 + l99=${10} + ((ave90=l90/iterations)) + ((ave95=l95/iterations)) + ((ave99=l99/iterations)) ((jankPct=100*janks/frames)) - printf "%-12s %5d %5d %5d %5d %5d %5d(%d%%)\n" $app $1 $ave $2 $4 $5 $janks $jankPct + printf "%-12s %5d %5d %5d %5d %5d %5d(%d%%) %d/%d/%d\n" $app $1 $ave $2 $4 $5 $janks $jankPct $ave90 $ave95 $ave99 done fi diff --git a/verity/Android.mk b/verity/Android.mk index 46396ca2..75face6f 100644 --- a/verity/Android.mk +++ b/verity/Android.mk @@ -1,5 +1,6 @@ LOCAL_PATH:= $(call my-dir) +ifeq ($(HOST_OS),linux) include $(CLEAR_VARS) LOCAL_MODULE := verify_boot_signature LOCAL_SRC_FILES := verify_boot_signature.c @@ -8,6 +9,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := libcrypto-host LOCAL_C_INCLUDES += external/openssl/include system/extras/ext4_utils system/core/mkbootimg include $(BUILD_HOST_EXECUTABLE) +endif include $(CLEAR_VARS) LOCAL_MODULE := generate_verity_key |