summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPawan Wagh <waghpawan@google.com>2024-02-23 01:04:29 +0000
committerPawan Wagh <waghpawan@google.com>2024-03-08 03:12:40 +0000
commit2951b024dc4e741125631469d457d89d4bc0a359 (patch)
treea66770db3f6e3a37c8f54db4d30bc52583a37632
parentff6f53b24a9fa19ed75304265c3b9af92d56ea37 (diff)
downloadSettings-2951b024dc4e741125631469d457d89d4bc0a359.tar.gz
Wipe /data with ext4 before 16K OTA
16K developer option needs /data partition to be ext4. Wipe the /data and reformat it to ext4 using RecoverySystem. Test: m Settings && adb install -r $ANDROID_PRODUCT_OUT/system_ext/priv-app/Settings/Settings.apk Test: adb shell cat /proc/mounts | grep f2fs Bug: 295035851 Bug: 320700993 Change-Id: I7ca6f3a7e18d6dbe4e9791b3c83d149365941989
-rw-r--r--res/values/strings.xml6
-rw-r--r--src/com/android/settings/development/Enable16kPagesPreferenceController.java73
-rw-r--r--src/com/android/settings/development/EnableExt4DialogHost.java26
-rw-r--r--src/com/android/settings/development/EnableExt4WarningDialog.java93
4 files changed, 192 insertions, 6 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml
index def5890603a..f0794dd197f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11340,6 +11340,12 @@
<!-- Toast message when 16k OTA update fails -->
<string name="toast_16k_update_failed_text">Failed to update kernel to 16KB pages compatible kernel.</string>
<string name="progress_16k_ota_title">Applying change</string>
+ <!-- Confirmation dialog title and text to reformat data to ext4 -->
+ <string name="confirm_format_ext4_title">Reformat device to ext4?</string>
+ <string name="confirm_format_ext4_text">16K developer option is supported with ext4 filesystem. Device will be wiped and filesystem will be changed to ext4 after confirmation.</string>
+ <!-- Toast on failure to reformat data to ext4 -->
+ <string name="format_ext4_failure_toast">Failed to reformat and wipe the data partiton to ext4.</string>
+
<!-- DSU Loader. Do not translate. -->
<string name="dsu_loader_title" translatable="false">DSU Loader</string>
diff --git a/src/com/android/settings/development/Enable16kPagesPreferenceController.java b/src/com/android/settings/development/Enable16kPagesPreferenceController.java
index 3f9da578bef..7049e79e5d4 100644
--- a/src/com/android/settings/development/Enable16kPagesPreferenceController.java
+++ b/src/com/android/settings/development/Enable16kPagesPreferenceController.java
@@ -22,6 +22,7 @@ import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.PowerManager;
+import android.os.RecoverySystem;
import android.os.SystemProperties;
import android.os.SystemUpdateManager;
import android.os.UpdateEngine;
@@ -34,7 +35,6 @@ import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
@@ -54,6 +54,7 @@ import com.google.common.util.concurrent.MoreExecutors;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -68,7 +69,8 @@ import java.util.zip.ZipFile;
public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferenceController
implements Preference.OnPreferenceChangeListener,
PreferenceControllerMixin,
- Enable16kbPagesDialogHost {
+ Enable16kbPagesDialogHost,
+ EnableExt4DialogHost {
private static final String TAG = "Enable16kPages";
private static final String REBOOT_REASON = "toggle16k";
@@ -87,7 +89,7 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
private static final int OFFSET_TO_FILE_NAME = 30;
public static final String EXPERIMENTAL_UPDATE_TITLE = "Android 16K Kernel Experimental Update";
- private @Nullable DevelopmentSettingsDashboardFragment mFragment = null;
+ private @NonNull DevelopmentSettingsDashboardFragment mFragment;
private boolean mEnable16k;
private final ListeningExecutorService mExecutorService =
@@ -96,9 +98,9 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
private AlertDialog mProgressDialog;
public Enable16kPagesPreferenceController(
- @NonNull Context context, @Nullable DevelopmentSettingsDashboardFragment fragment) {
+ @NonNull Context context, @NonNull DevelopmentSettingsDashboardFragment fragment) {
super(context);
- mFragment = fragment;
+ this.mFragment = fragment;
}
@Override
@@ -114,6 +116,10 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mEnable16k = (Boolean) newValue;
+ if (isDataf2fs()) {
+ EnableExt4WarningDialog.show(mFragment, this);
+ return false;
+ }
Enable16kPagesWarningDialog.show(mFragment, this, mEnable16k);
return true;
}
@@ -162,7 +168,7 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
}
@Override
- public void onFailure(Throwable t) {
+ public void onFailure(@NonNull Throwable t) {
hideProgressDialog();
Log.e(TAG, "Failed to call applyPayload of UpdateEngineStable!");
displayToast(mContext.getString(R.string.toast_16k_update_failed_text));
@@ -291,6 +297,41 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
+ @Override
+ public void onExt4DialogConfirmed() {
+ // user has confirmed to wipe the device
+ ListenableFuture future = mExecutorService.submit(() -> wipeData());
+ Futures.addCallback(
+ future,
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(@NonNull Object result) {
+ Log.i(TAG, "Wiping /data with recovery system.");
+ }
+
+ @Override
+ public void onFailure(@NonNull Throwable t) {
+ Log.e(TAG, "Failed to change the /data partition with ext4");
+ displayToast(mContext.getString(R.string.format_ext4_failure_toast));
+ }
+ },
+ ContextCompat.getMainExecutor(mContext));
+ }
+
+ private void wipeData() {
+ RecoverySystem recoveryService = mContext.getSystemService(RecoverySystem.class);
+ try {
+ recoveryService.wipePartitionToExt4();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void onExt4DialogDismissed() {
+ // Do nothing
+ }
+
private class OtaUpdateCallback extends UpdateEngineStableCallback {
UpdateEngineStable mUpdateEngineStable;
@@ -357,4 +398,24 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
infoBundle.putString(SystemUpdateManager.KEY_TITLE, EXPERIMENTAL_UPDATE_TITLE);
return infoBundle;
}
+
+ private boolean isDataf2fs() {
+ try (BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ Log.i(TAG, line);
+ final String[] fields = line.split(" ");
+ final String partition = fields[1];
+ final String fsType = fields[2];
+ if (partition.equals("/data") && fsType.equals("f2fs")) {
+ return true;
+ }
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to read /proc/mounts");
+ displayToast(mContext.getString(R.string.format_ext4_failure_toast));
+ }
+
+ return false;
+ }
}
diff --git a/src/com/android/settings/development/EnableExt4DialogHost.java b/src/com/android/settings/development/EnableExt4DialogHost.java
new file mode 100644
index 00000000000..6cbd7e18e2a
--- /dev/null
+++ b/src/com/android/settings/development/EnableExt4DialogHost.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 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.android.settings.development;
+
+/** Interface for EnableExt4DialogHost callbacks. */
+public interface EnableExt4DialogHost {
+ /** Callback when the user presses ok the warning dialog. */
+ void onExt4DialogConfirmed();
+
+ /** Callback when the user cancels or dismisses the warning dialog. */
+ void onExt4DialogDismissed();
+}
diff --git a/src/com/android/settings/development/EnableExt4WarningDialog.java b/src/com/android/settings/development/EnableExt4WarningDialog.java
new file mode 100644
index 00000000000..c8ba521de2d
--- /dev/null
+++ b/src/com/android/settings/development/EnableExt4WarningDialog.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 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.android.settings.development;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.internal.annotations.Initializer;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/** Dialog when user interacts 16K pages developer option and data is f2fs */
+public class EnableExt4WarningDialog extends InstrumentedDialogFragment
+ implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+
+ public static final String TAG = "EnableExt4WarningDialog";
+
+ private EnableExt4DialogHost mHost;
+
+ @Initializer
+ private void setHost(@NonNull EnableExt4DialogHost host) {
+ this.mHost = host;
+ }
+
+ /** This method is used to show warning dialog to reformat data to /ext4 */
+ public static void show(
+ @NonNull Fragment hostFragment, @NonNull EnableExt4DialogHost dialogHost) {
+ final FragmentManager manager = hostFragment.getActivity().getSupportFragmentManager();
+ Fragment existingFragment = manager.findFragmentByTag(TAG);
+ if (existingFragment == null) {
+ existingFragment = new EnableExt4WarningDialog();
+ }
+
+ if (existingFragment instanceof EnableExt4WarningDialog) {
+ existingFragment.setTargetFragment(hostFragment, 0 /* requestCode */);
+ ((EnableExt4WarningDialog) existingFragment).setHost(dialogHost);
+ ((EnableExt4WarningDialog) existingFragment).show(manager, TAG);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DIALOG_ENABLE_16K_PAGES;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.confirm_format_ext4_title)
+ .setMessage(R.string.confirm_format_ext4_text)
+ .setPositiveButton(android.R.string.ok, this /* onClickListener */)
+ .setNegativeButton(android.R.string.cancel, this /* onClickListener */)
+ .create();
+ }
+
+ @Override
+ public void onClick(@NonNull DialogInterface dialog, int buttonId) {
+ if (buttonId == DialogInterface.BUTTON_POSITIVE) {
+ mHost.onExt4DialogConfirmed();
+ } else {
+ mHost.onExt4DialogDismissed();
+ }
+ }
+
+ @Override
+ public void onDismiss(@NonNull DialogInterface dialog) {
+ super.onDismiss(dialog);
+ mHost.onExt4DialogDismissed();
+ }
+}