Merge "Support multiple DSU installations"
am: 69d181aecc
Change-Id: I92e75dcf4bd28f3b9ad6fc876f155d772b3124a5
This commit is contained in:
@@ -106,9 +106,9 @@ public class DynamicSystemManager {
|
||||
* @return true if the call succeeds
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
|
||||
public boolean startInstallation() {
|
||||
public boolean startInstallation(String dsuSlot) {
|
||||
try {
|
||||
return mService.startInstallation();
|
||||
return mService.startInstallation(dsuSlot);
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e.toString());
|
||||
}
|
||||
|
||||
@@ -22,9 +22,10 @@ interface IDynamicSystemService
|
||||
{
|
||||
/**
|
||||
* Start DynamicSystem installation.
|
||||
* @param dsuSlot Name used to identify this installation
|
||||
* @return true if the call succeeds
|
||||
*/
|
||||
boolean startInstallation();
|
||||
boolean startInstallation(@utf8InCpp String dsuSlot);
|
||||
|
||||
/**
|
||||
* Create a DSU partition. This call may take 60~90 seconds. The caller
|
||||
|
||||
@@ -56,6 +56,7 @@ import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.image.DynamicSystemClient;
|
||||
import android.os.image.DynamicSystemManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -74,6 +75,8 @@ public class DynamicSystemInstallationService extends Service
|
||||
|
||||
// TODO (b/131866826): This is currently for test only. Will move this to System API.
|
||||
static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED";
|
||||
static final String KEY_DSU_SLOT = "KEY_DSU_SLOT";
|
||||
static final String DEFAULT_DSU_SLOT = "dsu";
|
||||
|
||||
/*
|
||||
* Intent actions
|
||||
@@ -244,10 +247,15 @@ public class DynamicSystemInstallationService extends Service
|
||||
long systemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0);
|
||||
long userdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0);
|
||||
mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false);
|
||||
String dsuSlot = intent.getStringExtra(KEY_DSU_SLOT);
|
||||
|
||||
if (TextUtils.isEmpty(dsuSlot)) {
|
||||
dsuSlot = DEFAULT_DSU_SLOT;
|
||||
}
|
||||
// TODO: better constructor or builder
|
||||
mInstallTask = new InstallationAsyncTask(
|
||||
url, systemSize, userdataSize, this, mDynSystem, this);
|
||||
mInstallTask =
|
||||
new InstallationAsyncTask(
|
||||
url, dsuSlot, systemSize, userdataSize, this, mDynSystem, this);
|
||||
|
||||
mInstallTask.execute();
|
||||
|
||||
|
||||
@@ -89,10 +89,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
|
||||
|
||||
interface ProgressListener {
|
||||
void onProgressUpdate(Progress progress);
|
||||
|
||||
void onResult(int resultCode, Throwable detail);
|
||||
}
|
||||
|
||||
private final String mUrl;
|
||||
private final String mDsuSlot;
|
||||
private final long mSystemSize;
|
||||
private final long mUserdataSize;
|
||||
private final Context mContext;
|
||||
@@ -106,9 +108,16 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
|
||||
private InputStream mStream;
|
||||
private ZipFile mZipFile;
|
||||
|
||||
InstallationAsyncTask(String url, long systemSize, long userdataSize, Context context,
|
||||
DynamicSystemManager dynSystem, ProgressListener listener) {
|
||||
InstallationAsyncTask(
|
||||
String url,
|
||||
String dsuSlot,
|
||||
long systemSize,
|
||||
long userdataSize,
|
||||
Context context,
|
||||
DynamicSystemManager dynSystem,
|
||||
ProgressListener listener) {
|
||||
mUrl = url;
|
||||
mDsuSlot = dsuSlot;
|
||||
mSystemSize = systemSize;
|
||||
mUserdataSize = userdataSize;
|
||||
mContext = context;
|
||||
@@ -126,14 +135,17 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
|
||||
|
||||
verifyAndPrepare();
|
||||
|
||||
mDynSystem.startInstallation();
|
||||
mDynSystem.startInstallation(mDsuSlot);
|
||||
|
||||
installUserdata();
|
||||
if (isCancelled()) {
|
||||
mDynSystem.remove();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mUrl == null) {
|
||||
mDynSystem.finishInstallation();
|
||||
return null;
|
||||
}
|
||||
installImages();
|
||||
if (isCancelled()) {
|
||||
mDynSystem.remove();
|
||||
@@ -194,6 +206,9 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
|
||||
}
|
||||
|
||||
private void verifyAndPrepare() throws Exception {
|
||||
if (mUrl == null) {
|
||||
return;
|
||||
}
|
||||
String extension = mUrl.substring(mUrl.lastIndexOf('.') + 1);
|
||||
|
||||
if ("gz".equals(extension) || "gzip".equals(extension)) {
|
||||
|
||||
@@ -28,11 +28,9 @@ import android.os.image.DynamicSystemClient;
|
||||
import android.util.FeatureFlagUtils;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
/**
|
||||
* This Activity starts KeyguardManager and ask the user to confirm
|
||||
* before any installation request. If the device is not protected by
|
||||
* a password, it approves the request by default.
|
||||
* This Activity starts KeyguardManager and ask the user to confirm before any installation request.
|
||||
* If the device is not protected by a password, it approves the request by default.
|
||||
*/
|
||||
public class VerificationActivity extends Activity {
|
||||
|
||||
@@ -88,11 +86,15 @@ public class VerificationActivity extends Activity {
|
||||
Uri url = callingIntent.getData();
|
||||
Bundle extras = callingIntent.getExtras();
|
||||
|
||||
sVerifiedUrl = url.toString();
|
||||
if (url != null) {
|
||||
sVerifiedUrl = url.toString();
|
||||
}
|
||||
|
||||
// start service
|
||||
Intent intent = new Intent(this, DynamicSystemInstallationService.class);
|
||||
intent.setData(url);
|
||||
if (url != null) {
|
||||
intent.setData(url);
|
||||
}
|
||||
intent.setAction(DynamicSystemClient.ACTION_START_INSTALL);
|
||||
intent.putExtras(extras);
|
||||
|
||||
@@ -106,6 +108,7 @@ public class VerificationActivity extends Activity {
|
||||
}
|
||||
|
||||
static boolean isVerified(String url) {
|
||||
if (url == null) return true;
|
||||
return sVerifiedUrl != null && sVerifiedUrl.equals(url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements
|
||||
private static final String TAG = "DynamicSystemService";
|
||||
private static final String NO_SERVICE_ERROR = "no gsiservice";
|
||||
private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
|
||||
private static final String PATH_DEFAULT = "/data/gsi";
|
||||
private static final String PATH_DEFAULT = "/data/gsi/";
|
||||
private Context mContext;
|
||||
private String mInstallPath;
|
||||
private String mInstallPath, mDsuSlot;
|
||||
private volatile IGsiService mGsiService;
|
||||
|
||||
DynamicSystemService(Context context) {
|
||||
@@ -115,7 +115,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInstallation() throws RemoteException {
|
||||
public boolean startInstallation(String dsuSlot) throws RemoteException {
|
||||
IGsiService service = getGsiService();
|
||||
// priority from high to low: sysprop -> sdcard -> /data
|
||||
String path = SystemProperties.get("os.aot.path");
|
||||
@@ -129,16 +129,17 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements
|
||||
if (!Environment.MEDIA_MOUNTED.equals(volume.getState())) continue;
|
||||
File sdCard = volume.getPathFile();
|
||||
if (sdCard.isDirectory()) {
|
||||
path = sdCard.getPath();
|
||||
path = new File(sdCard, dsuSlot).getPath();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (path.isEmpty()) {
|
||||
path = PATH_DEFAULT;
|
||||
path = PATH_DEFAULT + dsuSlot;
|
||||
}
|
||||
Slog.i(TAG, "startInstallation -> " + path);
|
||||
}
|
||||
mInstallPath = path;
|
||||
mDsuSlot = dsuSlot;
|
||||
if (service.openInstall(path) != 0) {
|
||||
Slog.i(TAG, "Failed to open " + path);
|
||||
return false;
|
||||
@@ -203,7 +204,7 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements
|
||||
public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException {
|
||||
IGsiService gsiService = getGsiService();
|
||||
if (enable) {
|
||||
return gsiService.enableGsi(oneShot) == 0;
|
||||
return gsiService.enableGsi(oneShot, mDsuSlot) == 0;
|
||||
} else {
|
||||
return gsiService.disableGsi();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class DynamicSystemServiceTest extends AndroidTestCase {
|
||||
public void test1() {
|
||||
assertTrue("dynamic_system service available", mService != null);
|
||||
try {
|
||||
mService.startInstallation();
|
||||
mService.startInstallation("dsu");
|
||||
fail("DynamicSystemService did not throw SecurityException as expected");
|
||||
} catch (SecurityException e) {
|
||||
// expected
|
||||
|
||||
Reference in New Issue
Block a user