summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/image/DynamicSystemClient.java17
-rw-r--r--core/java/android/os/image/DynamicSystemManager.java17
-rw-r--r--core/java/android/os/image/IDynamicSystemService.aidl9
-rw-r--r--core/java/android/util/FeatureFlagUtils.java3
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java11
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java28
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynandroid/VerificationActivity.java13
-rw-r--r--services/core/java/com/android/server/DynamicSystemService.java44
8 files changed, 103 insertions, 39 deletions
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index fa2c480aaf41..8f68723e1b7d 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -35,6 +35,8 @@ import android.os.Message;
import android.os.Messenger;
import android.os.ParcelableException;
import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.util.FeatureFlagUtils;
import android.util.Slog;
import java.lang.annotation.Retention;
@@ -315,6 +317,11 @@ public class DynamicSystemClient {
*/
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
public void bind() {
+ if (!featureFlagEnabled()) {
+ Slog.w(TAG, FeatureFlagUtils.DYNAMIC_SYSTEM + " not enabled; bind() aborted.");
+ return;
+ }
+
Intent intent = new Intent();
intent.setClassName("com.android.dynsystem",
"com.android.dynsystem.DynamicSystemInstallationService");
@@ -381,6 +388,11 @@ public class DynamicSystemClient {
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
public void start(@NonNull Uri systemUrl, @BytesLong long systemSize,
@BytesLong long userdataSize) {
+ if (!featureFlagEnabled()) {
+ Slog.w(TAG, FeatureFlagUtils.DYNAMIC_SYSTEM + " not enabled; start() aborted.");
+ return;
+ }
+
Intent intent = new Intent();
intent.setClassName("com.android.dynsystem",
@@ -395,6 +407,11 @@ public class DynamicSystemClient {
mContext.startActivity(intent);
}
+ private boolean featureFlagEnabled() {
+ return SystemProperties.getBoolean(
+ FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.DYNAMIC_SYSTEM, false);
+ }
+
private void handleMessage(Message msg) {
switch (msg.what) {
case MSG_POST_STATUS:
diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java
index 0458c2a8b735..cec19457dd07 100644
--- a/core/java/android/os/image/DynamicSystemManager.java
+++ b/core/java/android/os/image/DynamicSystemManager.java
@@ -159,6 +159,16 @@ public class DynamicSystemManager {
}
}
+ /** @return {@code true} if the device has a dynamic system enabled */
+ @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
+ public boolean isEnabled() {
+ try {
+ return mService.isEnabled();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
/**
* Remove DynamicSystem installation if present
*
@@ -174,14 +184,13 @@ public class DynamicSystemManager {
}
/**
- * Enable DynamicSystem when it's not enabled, otherwise, disable it.
- *
+ * Enable or disable DynamicSystem.
* @return {@code true} if the call succeeds. {@code false} if there is no installed image.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
- public boolean toggle() {
+ public boolean setEnable(boolean enable) {
try {
- return mService.toggle();
+ return mService.setEnable(enable);
} catch (RemoteException e) {
throw new RuntimeException(e.toString());
}
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index 15f5b68e354b..a34daca86ce5 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -58,6 +58,11 @@ interface IDynamicSystemService
boolean isInstalled();
/**
+ * @return true if the device has an DynamicSystem image enabled
+ */
+ boolean isEnabled();
+
+ /**
* Remove DynamicSystem installation if present
*
* @return true if the call succeeds
@@ -65,11 +70,11 @@ interface IDynamicSystemService
boolean remove();
/**
- * Enable DynamicSystem when it's not enabled, otherwise, disable it.
+ * Enable or disable DynamicSystem.
*
* @return true if the call succeeds
*/
- boolean toggle();
+ boolean setEnable(boolean enable);
/**
* Write a chunk of the DynamicSystem system image
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 7f6423a74ced..5d33b49e181b 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -41,6 +41,7 @@ public class FeatureFlagUtils {
public static final String GLOBAL_ACTIONS_GRID_ENABLED = "settings_global_actions_grid_enabled";
public static final String GLOBAL_ACTIONS_PANEL_ENABLED =
"settings_global_actions_panel_enabled";
+ public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
private static final Map<String, String> DEFAULT_FLAGS;
@@ -52,7 +53,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put("settings_slice_injection", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put("settings_mainline_module", "true");
- DEFAULT_FLAGS.put("settings_dynamic_system", "false");
+ DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
DEFAULT_FLAGS.put(SAFETY_HUB, "true");
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java
index 38576ee47283..ea7b378eb607 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/BootCompletedReceiver.java
@@ -19,8 +19,10 @@ package com.android.dynsystem;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.image.DynamicSystemClient;
+import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -35,6 +37,10 @@ public class BootCompletedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ if (!featureFlagEnabled()) {
+ return;
+ }
+
String action = intent.getAction();
Log.d(TAG, "Broadcast received: " + action);
@@ -47,4 +53,9 @@ public class BootCompletedReceiver extends BroadcastReceiver {
context.startServiceAsUser(startServiceIntent, UserHandle.SYSTEM);
}
}
+
+ private boolean featureFlagEnabled() {
+ return SystemProperties.getBoolean(
+ FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.DYNAMIC_SYSTEM, false);
+ }
}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
index 2ad72eb725a9..5c6885a801e8 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/DynamicSystemInstallationService.java
@@ -257,7 +257,7 @@ public class DynamicSystemInstallationService extends Service
return;
}
- if (getStatus() != STATUS_READY) {
+ if (!isDynamicSystemInstalled() && (getStatus() != STATUS_READY)) {
Log.e(TAG, "Trying to discard AOT while there is no complete installation");
return;
}
@@ -273,13 +273,25 @@ public class DynamicSystemInstallationService extends Service
}
private void executeRebootToDynSystemCommand() {
- if (mInstallTask == null || mInstallTask.getStatus() != FINISHED) {
+ boolean enabled = false;
+
+ if (mInstallTask != null && mInstallTask.getStatus() == FINISHED) {
+ enabled = mInstallTask.commit();
+ } else if (isDynamicSystemInstalled()) {
+ enabled = mDynSystem.setEnable(true);
+ } else {
Log.e(TAG, "Trying to reboot to AOT while there is no complete installation");
return;
}
- if (!mInstallTask.commit()) {
- Log.e(TAG, "Failed to commit installation because of native runtime error.");
+ if (enabled) {
+ PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+
+ if (powerManager != null) {
+ powerManager.reboot("dynsystem");
+ }
+ } else {
+ Log.e(TAG, "Failed to enable DynamicSystem because of native runtime error.");
mNM.cancel(NOTIFICATION_ID);
Toast.makeText(this,
@@ -287,14 +299,6 @@ public class DynamicSystemInstallationService extends Service
Toast.LENGTH_LONG).show();
mDynSystem.remove();
-
- return;
- }
-
- PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
-
- if (powerManager != null) {
- powerManager.reboot("dynsystem");
}
}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/VerificationActivity.java
index 269645d8016b..b1c09381823b 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynandroid/VerificationActivity.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynandroid/VerificationActivity.java
@@ -25,8 +25,10 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.image.DynamicSystemClient;
+import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -49,6 +51,12 @@ public class VerificationActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (!featureFlagEnabled()) {
+ Log.w(TAG, FeatureFlagUtils.DYNAMIC_SYSTEM + " not enabled; activity aborted.");
+ finish();
+ return;
+ }
+
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (km != null) {
@@ -98,6 +106,11 @@ public class VerificationActivity extends Activity {
startServiceAsUser(intent, UserHandle.SYSTEM);
}
+ private boolean featureFlagEnabled() {
+ return SystemProperties.getBoolean(
+ FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.DYNAMIC_SYSTEM, false);
+ }
+
static boolean isVerified(String url) {
return sVerifiedUrl != null && sVerifiedUrl.equals(url);
}
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index f5bd11cea779..99bbcf890a0a 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -70,25 +70,24 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements
checkPermission();
if (!"running".equals(SystemProperties.get("init.svc.gsid"))) {
SystemProperties.set("ctl.start", "gsid");
- }
- for (int sleepMs = 64; sleepMs <= (GSID_ROUGH_TIMEOUT_MS << 1); sleepMs <<= 1) {
- try {
- Thread.sleep(sleepMs);
- } catch (InterruptedException e) {
- Slog.e(TAG, "Interrupted when waiting for GSID");
- break;
- }
- if ("running".equals(SystemProperties.get("init.svc.gsid"))) {
- synchronized (this) {
- if (mGsiService == null) {
- mGsiService = connect(this);
- }
- return mGsiService;
+ for (int sleepMs = 64; sleepMs <= (GSID_ROUGH_TIMEOUT_MS << 1); sleepMs <<= 1) {
+ try {
+ Thread.sleep(sleepMs);
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Interrupted when waiting for GSID");
+ break;
+ }
+ if ("running".equals(SystemProperties.get("init.svc.gsid"))) {
+ break;
}
}
}
- Slog.e(TAG, "Unable to start gsid");
- return null;
+ synchronized (this) {
+ if (mGsiService == null) {
+ mGsiService = connect(this);
+ }
+ return mGsiService;
+ }
}
private void checkPermission() {
@@ -125,19 +124,24 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements
}
@Override
+ public boolean isEnabled() throws RemoteException {
+ return getGsiService().isGsiEnabled();
+ }
+
+ @Override
public boolean remove() throws RemoteException {
return getGsiService().removeGsiInstall();
}
@Override
- public boolean toggle() throws RemoteException {
+ public boolean setEnable(boolean enable) throws RemoteException {
IGsiService gsiService = getGsiService();
- if (gsiService.isGsiRunning()) {
- return gsiService.disableGsiInstall();
- } else {
+ if (enable) {
final int status = gsiService.getGsiBootStatus();
final boolean singleBoot = (status == IGsiService.BOOT_STATUS_SINGLE_BOOT);
return gsiService.setGsiBootable(singleBoot) == 0;
+ } else {
+ return gsiService.disableGsiInstall();
}
}