summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-prod (mdb) <android-build-team-robot@google.com>2020-10-01 20:32:09 +0000
committerandroid-build-prod (mdb) <android-build-team-robot@google.com>2020-10-01 20:32:09 +0000
commit7c501746e217b3e8e3af5aa02cc49b2b742f026f (patch)
tree9c900f8a269b5b79b8f0637269bf8c4adeee0325
parent2d8684d825519dd7e4e646eb5dfa86436ed1a2ee (diff)
parentf465eb8c7bd7596566a885c747304f117d801afe (diff)
downloadplatform_system_gsid-sdk-release.tar.gz
platform_system_gsid-sdk-release.tar.bz2
platform_system_gsid-sdk-release.zip
Snap for 6877830 from f465eb8c7bd7596566a885c747304f117d801afe to sdk-releasesdk-release
Change-Id: I9a8c5aea93598164c362b4f8e48e1f53bf7057eb
-rw-r--r--aidl/android/gsi/IGsiService.aidl13
-rw-r--r--gsi_service.cpp21
-rw-r--r--gsi_service.h1
-rw-r--r--gsi_tool.cpp2
-rw-r--r--partition_installer.cpp52
-rw-r--r--partition_installer.h15
-rw-r--r--tests/Android.bp10
-rw-r--r--tests/AndroidManifest.xml30
-rw-r--r--tests/DSUEndtoEndTest.java34
-rw-r--r--tests/LockScreenAutomation.java151
10 files changed, 70 insertions, 259 deletions
diff --git a/aidl/android/gsi/IGsiService.aidl b/aidl/android/gsi/IGsiService.aidl
index 5503493..8b38504 100644
--- a/aidl/android/gsi/IGsiService.aidl
+++ b/aidl/android/gsi/IGsiService.aidl
@@ -179,6 +179,16 @@ interface IGsiService {
int createPartition(in @utf8InCpp String name, long size, boolean readOnly);
/**
+ * Complete the current partition installation. A partition installation is
+ * complete after all pending bytes are written successfully.
+ * Returns an error if current installation still have pending bytes.
+ * Returns an error if there is any internal filesystem error.
+ *
+ * @return 0 on success, an error code on failure.
+ */
+ int closePartition();
+
+ /**
* Wipe a partition. This will not work if the GSI is currently running.
* The partition will not be removed, but the first block will be zeroed.
*
@@ -212,7 +222,8 @@ interface IGsiService {
* 2. Open a new partition installer.
* 3. Create and map the new partition.
*
- * In other words, getAvbPublicKey() works between two createPartition() calls.
+ * In other words, getAvbPublicKey() should be called after
+ * createPartition() is called and before closePartition() is called.
*
* @param dst Output the AVB public key.
* @return 0 on success, an error code on failure.
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 1bcd3dc..3c875f8 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -182,6 +182,21 @@ binder::Status GsiService::createPartition(const ::std::string& name, int64_t si
return binder::Status::ok();
}
+binder::Status GsiService::closePartition(int32_t* _aidl_return) {
+ ENFORCE_SYSTEM;
+ std::lock_guard<std::mutex> guard(lock_);
+
+ if (installer_ == nullptr) {
+ LOG(ERROR) << "createPartition() has to be called before closePartition()";
+ *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
+ return binder::Status::ok();
+ }
+ // It is important to not reset |installer_| here because other methods such
+ // as enableGsi() relies on the state of |installer_|.
+ *_aidl_return = installer_->FinishInstall();
+ return binder::Status::ok();
+}
+
binder::Status GsiService::commitGsiChunkFromStream(const android::os::ParcelFileDescriptor& stream,
int64_t bytes, bool* _aidl_return) {
ENFORCE_SYSTEM;
@@ -272,7 +287,13 @@ binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot,
}
if (installer_) {
ENFORCE_SYSTEM;
+ int status = installer_->FinishInstall();
installer_ = {};
+ if (status != IGsiService::INSTALL_OK) {
+ *_aidl_return = status;
+ LOG(ERROR) << "Installation failed, cannot enable DSU for slot: " << dsuSlot;
+ return binder::Status::ok();
+ }
// Note: create the install status file last, since this is the actual boot
// indicator.
if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
diff --git a/gsi_service.h b/gsi_service.h
index 229db36..3f81786 100644
--- a/gsi_service.h
+++ b/gsi_service.h
@@ -42,6 +42,7 @@ class GsiService : public BinderService<GsiService>, public BnGsiService {
binder::Status closeInstall(int32_t* _aidl_return) override;
binder::Status createPartition(const ::std::string& name, int64_t size, bool readOnly,
int32_t* _aidl_return) override;
+ binder::Status closePartition(int32_t* _aidl_return) override;
binder::Status commitGsiChunkFromStream(const ::android::os::ParcelFileDescriptor& stream,
int64_t bytes, bool* _aidl_return) override;
binder::Status getInstallProgress(::android::gsi::GsiProgress* _aidl_return) override;
diff --git a/gsi_tool.cpp b/gsi_tool.cpp
index f24fa5d..8839246 100644
--- a/gsi_tool.cpp
+++ b/gsi_tool.cpp
@@ -255,7 +255,7 @@ static int Install(sp<IGsiService> gsid, int argc, char** argv) {
return EX_SOFTWARE;
}
- android::base::unique_fd input(dup(1));
+ android::base::unique_fd input(dup(STDIN_FILENO));
if (input < 0) {
std::cerr << "Error duplicating descriptor: " << strerror(errno) << std::endl;
return EX_SOFTWARE;
diff --git a/partition_installer.cpp b/partition_installer.cpp
index 357df50..35ac884 100644
--- a/partition_installer.cpp
+++ b/partition_installer.cpp
@@ -56,33 +56,32 @@ PartitionInstaller::PartitionInstaller(GsiService* service, const std::string& i
}
PartitionInstaller::~PartitionInstaller() {
- Finish();
- if (!succeeded_) {
- // Close open handles before we remove files.
- system_device_ = nullptr;
- PostInstallCleanup(images_.get());
+ if (FinishInstall() != IGsiService::INSTALL_OK) {
+ LOG(ERROR) << "Installation failed: install_dir=" << install_dir_
+ << ", dsu_slot=" << active_dsu_ << ", partition_name=" << name_;
}
if (IsAshmemMapped()) {
UnmapAshmem();
}
}
-void PartitionInstaller::PostInstallCleanup() {
- auto manager = ImageManager::Open(MetadataDir(active_dsu_), install_dir_);
- if (!manager) {
- LOG(ERROR) << "Could not open image manager";
- return;
- }
- return PostInstallCleanup(manager.get());
-}
-
-void PartitionInstaller::PostInstallCleanup(ImageManager* manager) {
- std::string file = GetBackingFile(name_);
- if (manager->IsImageMapped(file)) {
- LOG(ERROR) << "unmap " << file;
- manager->UnmapImageDevice(file);
+int PartitionInstaller::FinishInstall() {
+ if (finished_) {
+ return finished_status_;
+ }
+ finished_ = true;
+ finished_status_ = CheckInstallState();
+ system_device_ = nullptr;
+ if (finished_status_ != IGsiService::INSTALL_OK) {
+ auto file = GetBackingFile(name_);
+ LOG(ERROR) << "Installation failed, clean up: " << file;
+ if (images_->IsImageMapped(file)) {
+ LOG(ERROR) << "unmap " << file;
+ images_->UnmapImageDevice(file);
+ }
+ images_->DeleteBackingImage(file);
}
- manager->DeleteBackingImage(file);
+ return finished_status_;
}
int PartitionInstaller::StartInstall() {
@@ -96,7 +95,6 @@ int PartitionInstaller::StartInstall() {
if (!Format()) {
return IGsiService::INSTALL_ERROR_GENERIC;
}
- succeeded_ = true;
} else {
// Map ${name}_gsi so we can write to it.
system_device_ = OpenPartition(GetBackingFile(name_));
@@ -308,26 +306,22 @@ bool PartitionInstaller::Format() {
return true;
}
-int PartitionInstaller::Finish() {
- if (readOnly_ && gsi_bytes_written_ != size_) {
+int PartitionInstaller::CheckInstallState() {
+ if (readOnly_ && !IsFinishedWriting()) {
// We cannot boot if the image is incomplete.
LOG(ERROR) << "image incomplete; expected " << size_ << " bytes, waiting for "
<< (size_ - gsi_bytes_written_) << " bytes";
return IGsiService::INSTALL_ERROR_GENERIC;
}
- if (system_device_ != nullptr && fsync(system_device_->fd())) {
- PLOG(ERROR) << "fsync failed for " << name_ << "_gsi";
+ if (system_device_ != nullptr && fsync(GetPartitionFd())) {
+ PLOG(ERROR) << "fsync failed for " << GetBackingFile(name_);
return IGsiService::INSTALL_ERROR_GENERIC;
}
- system_device_ = {};
-
// If files moved (are no longer pinned), the metadata file will be invalid.
// This check can be removed once b/133967059 is fixed.
if (!images_->Validate()) {
return IGsiService::INSTALL_ERROR_GENERIC;
}
-
- succeeded_ = true;
return IGsiService::INSTALL_OK;
}
diff --git a/partition_installer.h b/partition_installer.h
index 1503648..920af47 100644
--- a/partition_installer.h
+++ b/partition_installer.h
@@ -53,14 +53,17 @@ class PartitionInstaller final {
static int WipeWritable(const std::string& active_dsu, const std::string& install_dir,
const std::string& name);
- // Clean up install state if gsid crashed and restarted.
- void PostInstallCleanup();
- void PostInstallCleanup(ImageManager* manager);
+ // Finish a partition installation and release resources.
+ // If the installation is incomplete or corrupted, the backing image would
+ // be cleaned up and an error code is returned.
+ // No method other than FinishInstall() and ~PartitionInstaller() should be
+ // called after calling this method.
+ // This method is also called by the destructor to free up resources.
+ int FinishInstall();
const std::string& install_dir() const { return install_dir_; }
private:
- int Finish();
int PerformSanityChecks();
int Preallocate();
bool Format();
@@ -82,10 +85,12 @@ class PartitionInstaller final {
bool readOnly_;
// Remaining data we're waiting to receive for the GSI image.
uint64_t gsi_bytes_written_ = 0;
- bool succeeded_ = false;
uint64_t ashmem_size_ = -1;
void* ashmem_data_ = MAP_FAILED;
+ bool finished_ = false;
+ int finished_status_ = 0;
+
std::unique_ptr<MappedDevice> system_device_;
};
diff --git a/tests/Android.bp b/tests/Android.bp
index 034209f..70d73ee 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -58,13 +58,3 @@ java_test_host {
test_config: "dsu-test.xml",
test_suites: ["general-tests"],
}
-
-android_test {
- name: "LockScreenAutomation",
- srcs: ["LockScreenAutomation.java"],
- libs: ["junit", "android.test.base.stubs"],
- static_libs: ["androidx.test.uiautomator"],
- certificate: "platform",
- manifest: "AndroidManifest.xml",
- test_suites: ["general-tests"],
-}
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
deleted file mode 100644
index 19d0c53..0000000
--- a/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.lockscreenautomation"
- android:sharedUserId="android.uid.system"
- >
-
- <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="28"/>
-
- <application debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="androidx.test.uiautomator.UiAutomatorInstrumentationTestRunner"
- android:targetPackage="com.google.android.lockscreenautomation"
- android:label="Lock Screen Automation"/>
-</manifest>
diff --git a/tests/DSUEndtoEndTest.java b/tests/DSUEndtoEndTest.java
index 69d40ad..e717079 100644
--- a/tests/DSUEndtoEndTest.java
+++ b/tests/DSUEndtoEndTest.java
@@ -47,11 +47,6 @@ import java.util.concurrent.TimeUnit;
@RunWith(DeviceJUnit4ClassRunner.class)
public class DSUEndtoEndTest extends BaseHostJUnit4Test {
private static final long kDefaultUserdataSize = 4L * 1024 * 1024 * 1024;
- private static final String APK = "LockScreenAutomation.apk";
- private static final String PACKAGE = "com.google.android.lockscreenautomation";
- private static final String UI_AUTOMATOR_INSTRUMENTATION_RUNNER =
- "androidx.test.uiautomator.UiAutomatorInstrumentationTestRunner";
- private static final String CLASS = "LockScreenAutomation";
private static final String LPUNPACK_PATH = "bin/lpunpack";
private static final String SIMG2IMG_PATH = "bin/simg2img";
@@ -74,7 +69,6 @@ public class DSUEndtoEndTest extends BaseHostJUnit4Test {
@After
public void teardown() throws Exception {
- uninstallPackage(PACKAGE);
if (mUnsparseSystemImage != null) {
mUnsparseSystemImage.delete();
}
@@ -129,13 +123,6 @@ public class DSUEndtoEndTest extends BaseHostJUnit4Test {
expectGsiStatus("normal");
- installPackage(APK);
- String method = "setPin";
- String testClass = PACKAGE + "." + CLASS;
- String testMethod = testClass + "." + method;
- Assert.assertTrue(testMethod + " failed.",
- runDeviceTests(UI_AUTOMATOR_INSTRUMENTATION_RUNNER, PACKAGE, testClass, method));
-
// Sleep after installing to allow time for gsi_tool to reboot. This prevents a race between
// the device rebooting and waitForDeviceAvailable() returning.
getDevice().executeShellV2Command("gsi_tool install --userdata-size " + mUserdataSize +
@@ -145,7 +132,7 @@ public class DSUEndtoEndTest extends BaseHostJUnit4Test {
expectGsiStatus("running");
- rebootAndUnlock();
+ getDevice().rebootUntilOnline();
expectGsiStatus("installed");
@@ -162,16 +149,10 @@ public class DSUEndtoEndTest extends BaseHostJUnit4Test {
getDevice().executeShellV2Command("gsi_tool wipe");
- rebootAndUnlock();
+ getDevice().rebootUntilOnline();
expectGsiStatus("normal");
- method = "removePin";
- testClass = PACKAGE + "." + CLASS;
- testMethod = testClass + "." + method;
- Assert.assertTrue(testMethod + " failed.",
- runDeviceTests(UI_AUTOMATOR_INSTRUMENTATION_RUNNER, PACKAGE, testClass, method));
-
if (wasRoot) {
getDevice().enableAdbRoot();
}
@@ -182,16 +163,5 @@ public class DSUEndtoEndTest extends BaseHostJUnit4Test {
String status = result.getStdout().split("\n", 2)[0].trim();
Assert.assertEquals("Device not in expected DSU state", expected, status);
}
-
- private void rebootAndUnlock() throws Exception {
- getDevice().rebootUntilOnline();
- getDevice().executeShellV2Command("input keyevent 224"); // KeyEvent.KEYCODE_WAKEUP
- getDevice().executeShellV2Command("wm dismiss-keyguard");
- getDevice().executeShellV2Command("input keyevent 7"); // KeyEvent.KEYCODE_0
- getDevice().executeShellV2Command("input keyevent 7");
- getDevice().executeShellV2Command("input keyevent 7");
- getDevice().executeShellV2Command("input keyevent 7");
- getDevice().executeShellV2Command("input keyevent 66"); // KeyEvent.KEYCODE_ENTER
- }
}
diff --git a/tests/LockScreenAutomation.java b/tests/LockScreenAutomation.java
deleted file mode 100644
index afefa1c..0000000
--- a/tests/LockScreenAutomation.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.lockscreenautomation;
-
-import org.junit.Assert;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.provider.Settings;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.BySelector;
-import androidx.test.uiautomator.UiAutomatorTestCase;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.UiObjectNotFoundException;
-import androidx.test.uiautomator.UiSelector;
-import androidx.test.uiautomator.Until;
-import android.view.KeyEvent;
-
-/**
- * Methods for configuring lock screen settings
- */
-public class LockScreenAutomation extends UiAutomatorTestCase {
-
- private static final String SETTINGS_PACKAGE = "com.android.settings";
-
- private static final long TIMEOUT = 2000L;
-
- private Context mContext;
- private UiDevice mDevice;
-
- public void setPin() throws Exception {
- mContext = getInstrumentation().getContext();
- mDevice = UiDevice.getInstance(getInstrumentation());
-
- mDevice.wakeUp();
- mDevice.pressKeyCode(KeyEvent.KEYCODE_MENU);
- mDevice.waitForIdle(TIMEOUT);
- launchLockScreenSettings();
-
- PackageManager pm = mContext.getPackageManager();
- Resources res = pm.getResourcesForApplication(SETTINGS_PACKAGE);
-
- int resId = res.getIdentifier("unlock_set_unlock_pin_title", "string", SETTINGS_PACKAGE);
- findAndClick(By.text(res.getString(resId)));
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressEnter();
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
-
- // Re-enter PIN
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressEnter();
-
- findAndClick(By.res(SETTINGS_PACKAGE, "redact_sensitive"));
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- findAndClick(By.clazz("android.widget.Button"));
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- }
-
- public void unlock() throws Exception {
- mContext = getInstrumentation().getContext();
- mDevice = UiDevice.getInstance(getInstrumentation());
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_ENTER);
- }
-
- public void removePin() throws Exception {
- mContext = getInstrumentation().getContext();
- mDevice = UiDevice.getInstance(getInstrumentation());
-
- mDevice.wakeUp();
- mDevice.pressKeyCode(KeyEvent.KEYCODE_MENU);
- mDevice.waitForIdle(TIMEOUT);
- launchLockScreenSettings();
-
- PackageManager pm = mContext.getPackageManager();
- Resources res = pm.getResourcesForApplication(SETTINGS_PACKAGE);
-
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
- mDevice.pressEnter();
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
-
- int resId = res.getIdentifier("unlock_set_unlock_off_title", "string", SETTINGS_PACKAGE);
- findAndClick(By.text(res.getString(resId)));
- mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
-
- findAndClick(By.res("android", "button1"));
- mDevice.waitForIdle(TIMEOUT);
- }
-
- private void findAndClick(BySelector selector)
- {
- for (int i = 0; i < 3; i++) {
- mDevice.wait(Until.findObject(selector), TIMEOUT);
- UiObject2 obj = mDevice.findObject(selector);
- if (obj != null) {
- obj.click();
- return;
- }
- }
- Assert.fail("Could not find and click " + selector);
- }
-
- private void launchLockScreenSettings() {
- final Intent intent = new Intent().setClassName(SETTINGS_PACKAGE, "com.android.settings.password.ChooseLockGeneric");
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- mContext.startActivity(intent);
- mDevice.wait(Until.hasObject(By.pkg(SETTINGS_PACKAGE).depth(0)), TIMEOUT);
- }
-}