Merge "Support multiple DSU installations" am: 69d181aecc am: fd9ae75440

Change-Id: I236a00274d6b6e7d1c7ac134ef17232c368cdd6a
This commit is contained in:
Automerger Merge Worker
2020-01-16 06:14:51 +00:00
7 changed files with 50 additions and 22 deletions

View File

@@ -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());
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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)) {

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -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