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
diff --git a/CheckBattery.cpp b/CheckBattery.cpp
index 8a674d0..f689bb4 100644
--- a/CheckBattery.cpp
+++ b/CheckBattery.cpp
@@ -26,6 +26,13 @@
{
// 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 @@
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;
}
diff --git a/CheckBattery.h b/CheckBattery.h
index a7bff34..dd11ba9 100644
--- a/CheckBattery.h
+++ b/CheckBattery.h
@@ -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
}
diff --git a/cryptfs.c b/cryptfs.c
index 8680698..fc4259c 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -2049,7 +2049,7 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
}
/* 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 @@
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);