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

Commit 155d5648 authored by Kenny Root's avatar Kenny Root Committed by Android (Google) Code Review
Browse files

Merge "Support Resume on Reboot"

parents edfdd415 f76cfc31
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2132,6 +2132,7 @@ package android.content.pm {
    field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
    field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
    field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
    field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow";
    field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
    field public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 16384; // 0x4000
    field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
@@ -6958,9 +6959,12 @@ package android.os {
  public class RecoverySystem {
    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static boolean clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void prepareForUnattendedUpdate(@NonNull android.content.Context, @NonNull String, @Nullable android.content.IntentSender) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static boolean rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException;
    method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException;
    method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException;
    method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException;
+12 −0
Original line number Diff line number Diff line
@@ -2917,6 +2917,18 @@ public abstract class PackageManager {
    @SdkConstant(SdkConstantType.FEATURE)
    public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";

    /**
     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
     * the requisite hardware support to support reboot escrow of synthetic password for updates.
     *
     * <p>This feature implies that the device has the RebootEscrow HAL implementation.
     *
     * @hide
     */
    @SystemApi
    @SdkConstant(SdkConstantType.FEATURE)
    public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow";

    /**
     * Extra field name for the URI to a verification file. Passed to a package
     * verifier.
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

package android.os;

import android.content.IntentSender;
import android.os.IRecoverySystemProgressListener;

/** @hide */
@@ -26,4 +27,7 @@ interface IRecoverySystem {
    boolean setupBcb(in String command);
    boolean clearBcb();
    void rebootRecoveryWithCommand(in String command);
    boolean requestLskf(in String updateToken, in IntentSender sender);
    boolean clearLskf();
    boolean rebootWithLskf(in String updateToken, in String reason);
}
+124 −9
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.os;

import static java.nio.charset.StandardCharsets.UTF_8;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
@@ -29,6 +31,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
@@ -624,22 +627,91 @@ public class RecoverySystem {
    }

    /**
     * Schedule to install the given package on next boot. The caller needs to
     * ensure that the package must have been processed (uncrypt'd) if needed.
     * It sets up the command in BCB (bootloader control block), which will
     * be read by the bootloader and the recovery image.
     * Prepare to apply an unattended update by asking the user for their Lock Screen Knowledge
     * Factor (LSKF). If supplied, the {@code intentSender} will be called when the system is setup
     * and ready to apply the OTA.
     * <p>
     * When the system is already prepared for update and this API is called again with the same
     * {@code updateToken}, it will not call the intent sender nor request the user enter their Lock
     * Screen Knowledge Factor.
     * <p>
     * When this API is called again with a different {@code updateToken}, the prepared-for-update
     * status is reset and process repeats as though it's the initial call to this method as
     * described in the first paragraph.
     *
     * @param Context      the Context to use.
     * @param packageFile  the package to be installed.
     *
     * @throws IOException if there were any errors setting up the BCB.
     * @param context the Context to use.
     * @param updateToken token used to indicate which update was prepared
     * @param intentSender the intent to call when the update is prepared; may be {@code null}
     * @throws IOException if there were any errors setting up unattended update
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.RECOVERY)
    public static void prepareForUnattendedUpdate(@NonNull Context context,
            @NonNull String updateToken, @Nullable IntentSender intentSender) throws IOException {
        if (updateToken == null) {
            throw new NullPointerException("updateToken == null");
        }
        RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
        if (!rs.requestLskf(updateToken, intentSender)) {
            throw new IOException("preparation for update failed");
        }
    }

    /**
     * Request that any previously requested Lock Screen Knowledge Factor (LSKF) is cleared and
     * the preparation for unattended update is reset.
     *
     * @param context the Context to use.
     * @throws IOException if there were any errors setting up unattended update
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.RECOVERY)
    public static void scheduleUpdateOnBoot(Context context, File packageFile)
    public static boolean clearPrepareForUnattendedUpdate(@NonNull Context context)
            throws IOException {
        RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
        return rs.clearLskf();
    }

    /**
     * Request that the device reboot and apply the update that has been prepared. The
     * {@code updateToken} must match what was given for {@link #prepareForUnattendedUpdate} or
     * this will return {@code false}.
     *
     * @param context the Context to use.
     * @param updateToken the token used to call {@link #prepareForUnattendedUpdate} before
     * @param reason the reboot reason to give to the {@link PowerManager}
     * @throws IOException if there were any errors setting up unattended update
     * @return false if the reboot couldn't proceed because the device wasn't ready for an
     *               unattended reboot or if the {@code updateToken} did not match the previously
     *               given token
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.RECOVERY)
    public static boolean rebootAndApply(@NonNull Context context, @NonNull String updateToken,
            @NonNull String reason) throws IOException {
        if (updateToken == null) {
            throw new NullPointerException("updateToken == null");
        }
        RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
        return rs.rebootWithLskf(updateToken, reason);
    }

    /**
     * Schedule to install the given package on next boot. The caller needs to ensure that the
     * package must have been processed (uncrypt'd) if needed. It sets up the command in BCB
     * (bootloader control block), which will be read by the bootloader and the recovery image.
     *
     * @param context the Context to use.
     * @param packageFile the package to be installed.
     * @throws IOException if there were any errors setting up the BCB.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.RECOVERY)
    public static void scheduleUpdateOnBoot(Context context, File packageFile) throws IOException {
        String filename = packageFile.getCanonicalPath();
        boolean securityUpdate = filename.endsWith("_s.zip");

@@ -1203,6 +1275,49 @@ public class RecoverySystem {
        }
    }

    /**
     * Begins the process of asking the user for the Lock Screen Knowledge Factor.
     *
     * @param updateToken token that will be used in calls to {@link #rebootAndApply} to ensure
     *                    that the preparation was for the correct update
     * @return true if the request was correct
     * @throws IOException if the recovery system service could not be contacted
     */
    private boolean requestLskf(String updateToken, IntentSender sender) throws IOException {
        try {
            return mService.requestLskf(updateToken, sender);
        } catch (RemoteException e) {
            throw new IOException("could request update");
        }
    }

    /**
     * Calls the recovery system service and clears the setup for the OTA.
     *
     * @return true if the setup for OTA was cleared
     * @throws IOException if the recovery system service could not be contacted
     */
    private boolean clearLskf() throws IOException {
        try {
            return mService.clearLskf();
        } catch (RemoteException e) {
            throw new IOException("could not clear LSKF");
        }
    }

    /**
     * Calls the recovery system service to reboot and apply update.
     *
     * @param updateToken the update token for which the update was prepared
     */
    private boolean rebootWithLskf(String updateToken, String reason) throws IOException {
        try {
            return mService.rebootWithLskf(updateToken, reason);
        } catch (RemoteException e) {
            throw new IOException("could not reboot for update");
        }
    }

    /**
     * Internally, recovery treats each line of the command file as a separate
     * argv, so we only need to protect against newlines and nulls.
+5 −0
Original line number Diff line number Diff line
@@ -1598,6 +1598,11 @@ public class LockPatternUtils {
         */
        public static final int STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN = 0x20;

        /**
         * Strong authentication is required to prepare for unattended upgrade.
         */
        public static final int STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE = 0x40;

        /**
         * Strong auth flags that do not prevent biometric methods from being accepted as auth.
         * If any other flags are set, biometric authentication is disabled.
Loading