diff options
| author | Tao Bao <tbao@google.com> | 2016-09-27 11:15:42 -0700 |
|---|---|---|
| committer | Tao Bao <tbao@google.com> | 2016-09-29 16:07:19 -0700 |
| commit | 794c8b0b3fe16051843c22232d58d6b184dde49b (patch) | |
| tree | 9165917ea4d7b2d036e4731d47a16dfefb42ff84 /core/java/android/os/RecoverySystem.java | |
| parent | f0aa998233c308fcc945493135448dfe51fb39b7 (diff) | |
Handle the race condition when calling uncrypt services.
We call uncrypt services to setup / clear bootloader control block (BCB)
for scheduling tasks under recovery (applying OTAs, performing FDR).
However, we cannot start multiple requests simultaneously. Because they
all use the same socket (/dev/socket/uncrypt) for communication and init
deletes the socket on service exits.
This CL fixes the issue by a) adding synchronized blocks for the service
requests; b) checking the availability of the socket before initiating a
new one.
Note that adding synchronized blocks to RecoverySystem doesn't help,
because the calls could be made from different processes (e.g. priv-app,
system_server).
Bug: 31526152
Test: FDR works while a priv-app keeps calling clear BCB.
Change-Id: I95308989e849a9c98a9503ac509f2bc51ed3de19
Diffstat (limited to 'core/java/android/os/RecoverySystem.java')
| -rw-r--r-- | core/java/android/os/RecoverySystem.java | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 028e30ab93f0..df7df64de813 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -663,28 +663,22 @@ public class RecoverySystem { * @throws IOException if something goes wrong. */ private static void bootCommand(Context context, String... args) throws IOException { - synchronized (sRequestLock) { - LOG_FILE.delete(); + LOG_FILE.delete(); - StringBuilder command = new StringBuilder(); - for (String arg : args) { - if (!TextUtils.isEmpty(arg)) { - command.append(arg); - command.append("\n"); - } + StringBuilder command = new StringBuilder(); + for (String arg : args) { + if (!TextUtils.isEmpty(arg)) { + command.append(arg); + command.append("\n"); } + } - // Write the command into BCB (bootloader control block). - RecoverySystem rs = (RecoverySystem) context.getSystemService( - Context.RECOVERY_SERVICE); - rs.setupBcb(command.toString()); - - // Having set up the BCB, go ahead and reboot. - PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - pm.reboot(PowerManager.REBOOT_RECOVERY); + // Write the command into BCB (bootloader control block) and boot from + // there. Will not return unless failed. + RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE); + rs.rebootRecoveryWithCommand(command.toString()); - throw new IOException("Reboot failed (no permissions?)"); - } + throw new IOException("Reboot failed (no permissions?)"); } // Read last_install; then report time (in seconds) and I/O (in MiB) for @@ -879,6 +873,17 @@ public class RecoverySystem { } /** + * Talks to RecoverySystemService via Binder to set up the BCB command and + * reboot into recovery accordingly. + */ + private void rebootRecoveryWithCommand(String command) { + try { + mService.rebootRecoveryWithCommand(command); + } catch (RemoteException ignored) { + } + } + + /** * Internally, recovery treats each line of the command file as a separate * argv, so we only need to protect against newlines and nulls. */ |
