Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6fac27b6 authored by Jackeagle's avatar Jackeagle
Browse files

Updater: Add functionality to retrieve fsUuid and VolumeRecord for Adoptable Storage devices



- The previous implementation had a drawback wherein if a user removes the SD Card and reboots, the Updater will fail to identify if the user still has adoptable storage enabled or not.
- With the new logic, it fetches private volumes information records and compares them with necessary checks. Therefore, no matter what the user does, as long as Adoptable storage is used, it won't allow the upgrade to continue.

Signed-off-by: default avatarJackeagle <jackeagle102@gmail.com>
parent 7350e218
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -92,7 +92,7 @@ public class UpdatesActivity extends UpdatesListActivity {
        mIsTV = uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
        mIsTV = uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;


        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        mAdapter = new UpdatesListAdapter(this);
        mAdapter = new UpdatesListAdapter(this, this);
        recyclerView.setAdapter(mAdapter);
        recyclerView.setAdapter(mAdapter);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setLayoutManager(layoutManager);
+7 −5
Original line number Original line Diff line number Diff line
@@ -71,6 +71,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
    private static final String TAG = "UpdateListAdapter";
    private static final String TAG = "UpdateListAdapter";


    private final float mAlphaDisabledValue;
    private final float mAlphaDisabledValue;
    private final Context mContext;


    private List<String> mDownloadIds;
    private List<String> mDownloadIds;
    private String mSelectedDownload;
    private String mSelectedDownload;
@@ -115,7 +116,8 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
        }
        }
    }
    }


    public UpdatesListAdapter(UpdatesListActivity activity) {
    public UpdatesListAdapter(Context context, UpdatesListActivity activity) {
        mContext = context;
        mActivity = activity;
        mActivity = activity;


        TypedValue tv = new TypedValue();
        TypedValue tv = new TypedValue();
@@ -212,9 +214,9 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
            viewHolder.itemView.setOnLongClickListener(
            viewHolder.itemView.setOnLongClickListener(
                    getLongClickListener(update, true, viewHolder.mBuildDate));
                    getLongClickListener(update, true, viewHolder.mBuildDate));
            setButtonAction(viewHolder.mAction,
            setButtonAction(viewHolder.mAction,
                    Utils.canInstall(update) ? Action.INSTALL : Action.DELETE,
                    Utils.canInstall(mContext, update) ? Action.INSTALL : Action.DELETE,
                    downloadId, !isBusy());
                    downloadId, !isBusy());
        } else if (!Utils.canInstall(update)) {
        } else if (!Utils.canInstall(mContext, update)) {
            viewHolder.itemView.setOnLongClickListener(
            viewHolder.itemView.setOnLongClickListener(
                    getLongClickListener(update, false, viewHolder.mBuildDate));
                    getLongClickListener(update, false, viewHolder.mBuildDate));
            setButtonAction(viewHolder.mAction, Action.INFO, downloadId, !isBusy());
            setButtonAction(viewHolder.mAction, Action.INFO, downloadId, !isBusy());
@@ -400,7 +402,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
                button.setText(R.string.action_resume);
                button.setText(R.string.action_resume);
                button.setEnabled(enabled);
                button.setEnabled(enabled);
                UpdateInfo update = mUpdaterController.getUpdate(downloadId);
                UpdateInfo update = mUpdaterController.getUpdate(downloadId);
                final boolean canInstall = Utils.canInstall(update) ||
                final boolean canInstall = Utils.canInstall(mContext, update) ||
                        update.getFile().length() == update.getFileSize();
                        update.getFile().length() == update.getFileSize();
                clickListener = enabled ? view -> {
                clickListener = enabled ? view -> {
                    if (canInstall) {
                    if (canInstall) {
@@ -421,7 +423,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
                button.setText(R.string.action_install);
                button.setText(R.string.action_install);
                button.setEnabled(enabled);
                button.setEnabled(enabled);
                UpdateInfo update = mUpdaterController.getUpdate(downloadId);
                UpdateInfo update = mUpdaterController.getUpdate(downloadId);
                final boolean canInstall = Utils.canInstall(update);
                final boolean canInstall = Utils.canInstall(mContext, update);
                clickListener = enabled ? view -> {
                clickListener = enabled ? view -> {
                    if (canInstall) {
                    if (canInstall) {
                        AlertDialog installDialog = getInstallDialog(downloadId);
                        AlertDialog installDialog = getInstallDialog(downloadId);
+3 −3
Original line number Original line Diff line number Diff line
@@ -364,7 +364,7 @@ public class UpdaterService extends Service {
                String text = getString(R.string.download_completed_notification);
                String text = getString(R.string.download_completed_notification);
                boolean hasRequiredSpace = Utils.availableFreeSpace() > (update.getFileSize() * 2);
                boolean hasRequiredSpace = Utils.availableFreeSpace() > (update.getFileSize() * 2);


                if (!Utils.canInstall(update) || !Utils.isBatteryLevelOk(this)
                if (!Utils.canInstall(this, update) || !Utils.isBatteryLevelOk(this)
                        || !hasRequiredSpace) {
                        || !hasRequiredSpace) {
                    /* Show notification if any of the below condition didn't met. */
                    /* Show notification if any of the below condition didn't met. */
                    text = getString(R.string.blocked_update_dialog_title) + ". ";
                    text = getString(R.string.blocked_update_dialog_title) + ". ";
@@ -372,7 +372,7 @@ public class UpdaterService extends Service {
                        text = text + getString(R.string.dialog_battery_low_title);
                        text = text + getString(R.string.dialog_battery_low_title);
                    } else if (!hasRequiredSpace) {
                    } else if (!hasRequiredSpace) {
                        text = text + getString(R.string.dialog_free_space_low_title);
                        text = text + getString(R.string.dialog_free_space_low_title);
                    } else if (!Utils.canInstall(update)) {
                    } else if (!Utils.canInstall(this, update)) {
                        text = text + getString(R.string.verification_failed_notification);
                        text = text + getString(R.string.verification_failed_notification);
                    }
                    }
                } else if (!Utils.isABDevice()) {
                } else if (!Utils.isABDevice()) {
@@ -394,7 +394,7 @@ public class UpdaterService extends Service {
                    - Battery level (Above 30% if discharging or 20% if charging)
                    - Battery level (Above 30% if discharging or 20% if charging)
                    - Free space to install (Double the size of the ota zip)
                    - Free space to install (Double the size of the ota zip)
                */
                */
                if (Utils.isABDevice() && Utils.canInstall(update)
                if (Utils.isABDevice() && Utils.canInstall(this, update)
                        && Utils.isBatteryLevelOk(this) && hasRequiredSpace) {
                        && Utils.isBatteryLevelOk(this) && hasRequiredSpace) {
                    Utils.triggerUpdate(this, update.getDownloadId());
                    Utils.triggerUpdate(this, update.getDownloadId());
                } else {
                } else {
+19 −15
Original line number Original line Diff line number Diff line
@@ -15,7 +15,6 @@
 * limitations under the License.
 * limitations under the License.
 */
 */
package org.lineageos.updater.misc;
package org.lineageos.updater.misc;

import android.app.AlarmManager;
import android.app.AlarmManager;
import android.content.ClipData;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ClipboardManager;
@@ -34,6 +33,8 @@ import android.os.Environment;
import android.os.StatFs;
import android.os.StatFs;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import android.provider.Settings;
import android.provider.Settings;
import android.util.Log;
import android.util.Log;
import android.widget.Toast;
import android.widget.Toast;
@@ -179,31 +180,34 @@ public class Utils {
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }
    }


    public static boolean canInstall(UpdateBaseInfo update) {
    public static boolean canInstall(Context context, UpdateBaseInfo update) {
        return (SystemProperties.getBoolean(Constants.PROP_UPDATER_ALLOW_DOWNGRADING, false) ||
        return (SystemProperties.getBoolean(Constants.PROP_UPDATER_ALLOW_DOWNGRADING, false) ||
                update.getTimestamp() > SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0)) &&
                update.getTimestamp() > SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0)) &&
		isAdoptableStorageEnabled();
		isAdoptableStorageEnabled(context);
    }
    }


    private static boolean isAdoptableStorageEnabled() {
    private static boolean isAdoptableStorageEnabled(Context context) {
        String selinuxProp = SystemProperties.get("selinux.restorecon_recursive", "");
        StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);


        // Prefix of prop output
        // Get a list of all storage volume records
        String expectedPrefix = "/mnt/expand/";
        List<VolumeRecord> volumeRecords = storageManager.getVolumeRecords();


        if (selinuxProp.startsWith(expectedPrefix)) {
        // Check each volume to see if it's adoptable storage
        for (VolumeRecord rec : volumeRecords) {


            // Extract the content after "/mnt/expand/"
            final String fsUuid = rec.getFsUuid();
            String pathContent = selinuxProp.substring(expectedPrefix.length());
            final VolumeInfo info = storageManager.findVolumeByUuid(fsUuid);


            Log.d("Updater", "Adoptable storage is enabled. Blocking OTA Updates");
            if (rec.getType() == VolumeInfo.TYPE_PRIVATE) {
                Log.d(TAG, "Adoptable storage is enabled. Blocking OTA Updates. Found Volume at: " + rec.getFsUuid());
                return false;
                return false;
        } else {
            Log.d("Updater", "Adoptable storage is not enabled or invalid property format");
            return true;
            }
            }
        }
        }


        Log.d(TAG, "Adoptable storage is not enabled");
        return true;
    }

    public static List<UpdateInfo> parseJson(File file, boolean compatibleOnly)
    public static List<UpdateInfo> parseJson(File file, boolean compatibleOnly)
            throws IOException, JSONException {
            throws IOException, JSONException {
        List<UpdateInfo> updates = new ArrayList<>();
        List<UpdateInfo> updates = new ArrayList<>();