On low power turn off rather than rebooting to allow device to charge

The code was using encrypted_upto == 0 as an indicator that encryption
has succeeded. This meant that if no encryption happened, we would reboot
continually.

We now set encrypted_upto to fs_size when encryption is complete.

Also don't start to encrypt unless we are at 10% power. Stop when we
get to 5% power. This should lead to partial encryptions only very
rarely.

Bug: 15513202
Change-Id: I6214d78579d1fbbe2f63ee8862473d86a89d29b3
This commit is contained in:
Paul Lawrence 2014-06-09 14:10:09 -07:00
parent cba4ab2aeb
commit 73d7a02dc6
3 changed files with 73 additions and 46 deletions

View file

@ -26,6 +26,13 @@ namespace
{
// How often to check battery in seconds
const int CHECK_PERIOD = 30;
// How charged should the battery be (percent) to start encrypting
const int START_THRESHOLD = 10;
// How charged should the battery be (percent) to continue encrypting
const int CONTINUE_THRESHOLD = 5;
const String16 serviceName("batteryproperties");
sp<IBinder> bs;
@ -33,43 +40,59 @@ namespace
bool singletonInitialized = false;
time_t last_checked = {0};
int battery_ok = 1;
int last_result = 100;
int is_battery_ok(int threshold)
{
time_t now = time(NULL);
if (now == -1 || difftime(now, last_checked) < 5) {
goto finish;
}
last_checked = now;
if (!singletonInitialized) {
bs = defaultServiceManager()->checkService(serviceName);
if (bs == NULL) {
SLOGE("No batteryproperties service!");
goto finish;
}
interface = interface_cast<IBatteryPropertiesRegistrar>(bs);
if (interface == NULL) {
SLOGE("No IBatteryPropertiesRegistrar interface");
goto finish;
}
singletonInitialized = true;
}
{
BatteryProperty val;
status_t status = interface
->getProperty(android::BATTERY_PROP_CAPACITY, &val);
if (status == NO_ERROR) {
SLOGD("Capacity is %d", (int)val.valueInt64);
last_result = val.valueInt64;
} else {
SLOGE("Failed to get battery charge");
last_result = 100;
}
}
finish:
return last_result >= threshold;
}
}
extern "C" int is_battery_ok()
extern "C"
{
time_t now = time(NULL);
if (now == -1 || difftime(now, last_checked) < 5) {
return battery_ok;
}
last_checked = now;
if (!singletonInitialized) {
bs = defaultServiceManager()->checkService(serviceName);
if (bs == NULL) {
SLOGE("No batteryproperties service!");
return 1;
}
interface = interface_cast<IBatteryPropertiesRegistrar>(bs);
if (interface == NULL) {
SLOGE("No IBatteryPropertiesRegistrar interface");
return 1;
}
singletonInitialized = true;
int is_battery_ok_to_start()
{
return is_battery_ok(START_THRESHOLD);
}
BatteryProperty val;
status_t status = interface->getProperty(android::BATTERY_PROP_CAPACITY,
&val);
if (status == NO_ERROR) {
SLOGD("Capacity is %d", (int)val.valueInt64);
battery_ok = val.valueInt64 > 5 ? 1 : 0;
} else {
SLOGE("Failed to get battery charge");
battery_ok = 1;
int is_battery_ok_to_continue()
{
return is_battery_ok(CONTINUE_THRESHOLD);
}
return battery_ok;
}

View file

@ -21,7 +21,8 @@
extern "C" {
#endif
int is_battery_ok();
int is_battery_ok_to_start();
int is_battery_ok_to_continue();
#ifdef __cplusplus
}

View file

@ -2049,7 +2049,7 @@ static int encrypt_groups(struct encryptGroupsData* data)
}
}
if (!is_battery_ok()) {
if (!is_battery_ok_to_continue()) {
SLOGE("Stopping encryption due to low battery");
rc = 0;
goto errout;
@ -2231,7 +2231,7 @@ static int cryptfs_enable_inplace_full(char *crypto_blkdev, char *real_blkdev,
i * CRYPT_SECTORS_PER_BUFSIZE);
}
if (!is_battery_ok()) {
if (!is_battery_ok_to_continue()) {
SLOGE("Stopping encryption due to low battery");
*size_already_done += (i + 1) * CRYPT_SECTORS_PER_BUFSIZE - 1;
rc = 0;
@ -2332,8 +2332,8 @@ static int cryptfs_enable_all_volumes(struct crypt_mnt_ftr *crypt_ftr, int how,
off64_t cur_encryption_done=0, tot_encryption_size=0;
int i, rc = -1;
if (!is_battery_ok()) {
SLOGE("Stopping encryption due to low battery");
if (!is_battery_ok_to_start()) {
SLOGW("Not starting encryption due to low battery");
return 0;
}
@ -2348,11 +2348,11 @@ static int cryptfs_enable_all_volumes(struct crypt_mnt_ftr *crypt_ftr, int how,
tot_encryption_size,
previously_encrypted_upto);
if (!rc && cur_encryption_done != (off64_t)crypt_ftr->fs_size) {
if (!rc) {
crypt_ftr->encrypted_upto = cur_encryption_done;
}
if (!rc && !crypt_ftr->encrypted_upto) {
if (!rc && crypt_ftr->encrypted_upto == crypt_ftr->fs_size) {
/* The inplace routine never actually sets the progress to 100% due
* to the round down nature of integer division, so set it here */
property_set("vold.encrypt_progress", "100");
@ -2601,10 +2601,10 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd,
}
/* Calculate checksum if we are not finished */
if (!rc && crypt_ftr.encrypted_upto) {
if (!rc && crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
rc = cryptfs_SHA256_fileblock(crypto_blkdev,
crypt_ftr.hash_first_block);
if (!rc) {
if (rc) {
SLOGE("Error calculating checksum for continuing encryption");
rc = -1;
}
@ -2618,19 +2618,22 @@ int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd,
if (! rc) {
/* Success */
/* Clear the encryption in progres flag in the footer */
if (!crypt_ftr.encrypted_upto) {
/* Clear the encryption in progress flag in the footer */
if (crypt_ftr.encrypted_upto == crypt_ftr.fs_size) {
crypt_ftr.flags &= ~CRYPT_ENCRYPTION_IN_PROGRESS;
} else {
SLOGD("Encrypted up to sector %lld - will continue after reboot",
crypt_ftr.encrypted_upto);
}
put_crypt_ftr_and_key(&crypt_ftr);
if (crypt_ftr.encrypted_upto) {
put_crypt_ftr_and_key(&crypt_ftr);
}
sleep(2); /* Give the UI a chance to show 100% progress */
/* Partially encrypted - ensure writes are flushed to ssd */
if (!crypt_ftr.encrypted_upto) {
if (crypt_ftr.encrypted_upto == crypt_ftr.fs_size) {
cryptfs_reboot(reboot);
} else {
cryptfs_reboot(shutdown);