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

Commit 30295f54 authored by Suprabh Shukla's avatar Suprabh Shukla Committed by Android (Google) Code Review
Browse files

Merge "Add an unsuspend button option to SuspendDialogInfo"

parents 435384cc 0cb5713f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1830,6 +1830,7 @@ package android.content {
    field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_SPECIAL_APP_ACCESSES = "android.intent.action.MANAGE_SPECIAL_APP_ACCESSES";
    field public static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
    field public static final String ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION";
    field public static final String ACTION_PACKAGE_UNSUSPENDED_MANUALLY = "android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY";
    field public static final String ACTION_PENDING_INCIDENT_REPORTS_CHANGED = "android.intent.action.PENDING_INCIDENT_REPORTS_CHANGED";
    field public static final String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
    field public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
@@ -2328,6 +2329,8 @@ package android.content.pm {
  public final class SuspendDialogInfo implements android.os.Parcelable {
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int BUTTON_ACTION_MORE_DETAILS = 0; // 0x0
    field public static final int BUTTON_ACTION_UNSUSPEND = 1; // 0x1
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.SuspendDialogInfo> CREATOR;
  }
@@ -2337,6 +2340,7 @@ package android.content.pm {
    method @NonNull public android.content.pm.SuspendDialogInfo.Builder setIcon(@DrawableRes int);
    method @NonNull public android.content.pm.SuspendDialogInfo.Builder setMessage(@NonNull String);
    method @NonNull public android.content.pm.SuspendDialogInfo.Builder setMessage(@StringRes int);
    method @NonNull public android.content.pm.SuspendDialogInfo.Builder setNeutralButtonAction(int);
    method @NonNull public android.content.pm.SuspendDialogInfo.Builder setNeutralButtonText(@StringRes int);
    method @NonNull public android.content.pm.SuspendDialogInfo.Builder setTitle(@StringRes int);
  }
+29 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.SuspendDialogInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
@@ -2666,6 +2667,34 @@ public class Intent implements Parcelable, Cloneable {
    public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS =
            "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";

    /**
     * Broadcast Action: Sent to indicate that the user unsuspended a package.
     *
     * <p>This can happen when the user taps on the neutral button of the
     * {@linkplain SuspendDialogInfo suspend-dialog} which was created by using
     * {@link SuspendDialogInfo#BUTTON_ACTION_UNSUSPEND}. This broadcast is only sent to the
     * suspending app that originally specified this dialog while calling
     * {@link PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
     * PersistableBundle, SuspendDialogInfo)}.
     *
     * <p>Includes an extra {@link #EXTRA_PACKAGE_NAME} which is the name of the package that just
     * got unsuspended.
     *
     * <p class="note">This is a protected intent that can only be sent
     * by the system. <em>This will be delivered to {@link BroadcastReceiver} components declared in
     * the manifest.</em>
     *
     * @see PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
     * PersistableBundle, SuspendDialogInfo)
     * @see PackageManager#isPackageSuspended()
     * @see SuspendDialogInfo#BUTTON_ACTION_MORE_DETAILS
     * @hide
     */
    @SystemApi
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_PACKAGE_UNSUSPENDED_MANUALLY =
            "android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY";

    /**
     * Broadcast Action: Sent to a package that has been unsuspended.
     *
+89 −13
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.content.pm;
import static android.content.res.Resources.ID_NULL;

import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
@@ -36,20 +37,21 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
import java.util.Objects;

/**
 * A container to describe the dialog to be shown when the user tries to launch a suspended
 * application.
 * The suspending app can customize the dialog's following attributes:
 * application. The suspending app can customize the dialog's following attributes:
 * <ul>
 * <li>The dialog icon, by providing a resource id.
 * <li>The title text, by providing a resource id.
 * <li>The text of the dialog's body, by providing a resource id or a string.
 * <li>The text on the neutral button which starts the
 * {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS SHOW_SUSPENDED_APP_DETAILS}
 * activity, by providing a resource id.
 * <li>The text on the neutral button by providing a resource id.
 * <li>The action performed on tapping the neutral button. Only {@link #BUTTON_ACTION_UNSUSPEND}
 * and {@link #BUTTON_ACTION_MORE_DETAILS} are currently supported.
 * </ul>
 * System defaults are used whenever any of these are not provided, or any of the provided resource
 * ids cannot be resolved at the time of displaying the dialog.
@@ -67,12 +69,47 @@ public final class SuspendDialogInfo implements Parcelable {
    private static final String XML_ATTR_DIALOG_MESSAGE_RES_ID = "dialogMessageResId";
    private static final String XML_ATTR_DIALOG_MESSAGE = "dialogMessage";
    private static final String XML_ATTR_BUTTON_TEXT_RES_ID = "buttonTextResId";
    private static final String XML_ATTR_BUTTON_ACTION = "buttonAction";

    private final int mIconResId;
    private final int mTitleResId;
    private final int mDialogMessageResId;
    private final String mDialogMessage;
    private final int mNeutralButtonTextResId;
    private final int mNeutralButtonAction;

    /**
     * Used with {@link Builder#setNeutralButtonAction(int)} to create a neutral button that
     * starts the {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} activity.
     * @see Builder#setNeutralButtonAction(int)
     */
    public static final int BUTTON_ACTION_MORE_DETAILS = 0;

    /**
     * Used with {@link Builder#setNeutralButtonAction(int)} to create a neutral button that
     * unsuspends the app that the user was trying to launch and continues with the launch. The
     * system also sends the broadcast
     * {@link android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY} to the suspending app
     * when this happens.
     * @see Builder#setNeutralButtonAction(int)
     * @see android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY
     */
    public static final int BUTTON_ACTION_UNSUSPEND = 1;

    /**
     * Button actions to specify what happens when the user taps on the neutral button.
     * To be used with {@link Builder#setNeutralButtonAction(int)}.
     *
     * @hide
     * @see Builder#setNeutralButtonAction(int)
     */
    @IntDef(flag = true, prefix = {"BUTTON_ACTION_"}, value = {
            BUTTON_ACTION_MORE_DETAILS,
            BUTTON_ACTION_UNSUSPEND
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ButtonAction {
    }

    /**
     * @return the resource id of the icon to be used with the dialog
@@ -102,8 +139,8 @@ public final class SuspendDialogInfo implements Parcelable {
    }

    /**
     * @return the text to be shown in the dialog's body. Returns {@code null} if
     * {@link #getDialogMessageResId()} returns a valid resource id.
     * @return the text to be shown in the dialog's body. Returns {@code null} if {@link
     * #getDialogMessageResId()} returns a valid resource id
     * @hide
     */
    @Nullable
@@ -120,6 +157,15 @@ public final class SuspendDialogInfo implements Parcelable {
        return mNeutralButtonTextResId;
    }

    /**
     * @return The {@link ButtonAction} that happens on tapping this button
     * @hide
     */
    @ButtonAction
    public int getNeutralButtonAction() {
        return mNeutralButtonAction;
    }

    /**
     * @hide
     */
@@ -138,6 +184,7 @@ public final class SuspendDialogInfo implements Parcelable {
        if (mNeutralButtonTextResId != ID_NULL) {
            XmlUtils.writeIntAttribute(out, XML_ATTR_BUTTON_TEXT_RES_ID, mNeutralButtonTextResId);
        }
        XmlUtils.writeIntAttribute(out, XML_ATTR_BUTTON_ACTION, mNeutralButtonAction);
    }

    /**
@@ -150,6 +197,8 @@ public final class SuspendDialogInfo implements Parcelable {
            final int titleId = XmlUtils.readIntAttribute(in, XML_ATTR_TITLE_RES_ID, ID_NULL);
            final int buttonTextId = XmlUtils.readIntAttribute(in, XML_ATTR_BUTTON_TEXT_RES_ID,
                    ID_NULL);
            final int buttonAction = XmlUtils.readIntAttribute(in, XML_ATTR_BUTTON_ACTION,
                    BUTTON_ACTION_MORE_DETAILS);
            final int dialogMessageResId = XmlUtils.readIntAttribute(
                    in, XML_ATTR_DIALOG_MESSAGE_RES_ID, ID_NULL);
            final String dialogMessage = XmlUtils.readStringAttribute(in, XML_ATTR_DIALOG_MESSAGE);
@@ -168,6 +217,7 @@ public final class SuspendDialogInfo implements Parcelable {
            } else if (dialogMessage != null) {
                dialogInfoBuilder.setMessage(dialogMessage);
            }
            dialogInfoBuilder.setNeutralButtonAction(buttonAction);
        } catch (Exception e) {
            Slog.e(TAG, "Exception while parsing from xml. Some fields may default", e);
        }
@@ -181,6 +231,7 @@ public final class SuspendDialogInfo implements Parcelable {
        hashCode = 31 * hashCode + mNeutralButtonTextResId;
        hashCode = 31 * hashCode + mDialogMessageResId;
        hashCode = 31 * hashCode + Objects.hashCode(mDialogMessage);
        hashCode = 31 * hashCode + mNeutralButtonAction;
        return hashCode;
    }

@@ -197,6 +248,7 @@ public final class SuspendDialogInfo implements Parcelable {
                && mTitleResId == otherDialogInfo.mTitleResId
                && mDialogMessageResId == otherDialogInfo.mDialogMessageResId
                && mNeutralButtonTextResId == otherDialogInfo.mNeutralButtonTextResId
                && mNeutralButtonAction == otherDialogInfo.mNeutralButtonAction
                && Objects.equals(mDialogMessage, otherDialogInfo.mDialogMessage);
    }

@@ -228,6 +280,8 @@ public final class SuspendDialogInfo implements Parcelable {
            builder.append(mDialogMessage);
            builder.append("\" ");
        }
        builder.append("mNeutralButtonAction = ");
        builder.append(mNeutralButtonAction);
        builder.append("}");
        return builder.toString();
    }
@@ -244,6 +298,7 @@ public final class SuspendDialogInfo implements Parcelable {
        dest.writeInt(mDialogMessageResId);
        dest.writeString(mDialogMessage);
        dest.writeInt(mNeutralButtonTextResId);
        dest.writeInt(mNeutralButtonAction);
    }

    private SuspendDialogInfo(Parcel source) {
@@ -252,6 +307,7 @@ public final class SuspendDialogInfo implements Parcelable {
        mDialogMessageResId = source.readInt();
        mDialogMessage = source.readString();
        mNeutralButtonTextResId = source.readInt();
        mNeutralButtonAction = source.readInt();
    }

    SuspendDialogInfo(Builder b) {
@@ -260,9 +316,11 @@ public final class SuspendDialogInfo implements Parcelable {
        mDialogMessageResId = b.mDialogMessageResId;
        mDialogMessage = (mDialogMessageResId == ID_NULL) ? b.mDialogMessage : null;
        mNeutralButtonTextResId = b.mNeutralButtonTextResId;
        mNeutralButtonAction = b.mNeutralButtonAction;
    }

    public static final @android.annotation.NonNull Creator<SuspendDialogInfo> CREATOR = new Creator<SuspendDialogInfo>() {
    public static final @NonNull Creator<SuspendDialogInfo> CREATOR =
            new Creator<SuspendDialogInfo>() {
        @Override
        public SuspendDialogInfo createFromParcel(Parcel source) {
            return new SuspendDialogInfo(source);
@@ -283,6 +341,7 @@ public final class SuspendDialogInfo implements Parcelable {
        private int mTitleResId = ID_NULL;
        private int mIconResId = ID_NULL;
        private int mNeutralButtonTextResId = ID_NULL;
        private int mNeutralButtonAction = BUTTON_ACTION_MORE_DETAILS;

        /**
         * Set the resource id of the icon to be used. If not provided, no icon will be shown.
@@ -333,8 +392,8 @@ public final class SuspendDialogInfo implements Parcelable {

        /**
         * Set the resource id of the dialog message to be shown. If no dialog message is provided
         * via either this method or {@link #setMessage(String)}, the system will use a
         * default message.
         * via either this method or {@link #setMessage(String)}, the system will use a default
         * message.
         * <p>
         * The system will use {@link android.content.res.Resources#getString(int, Object...)
         * getString} to insert the suspended app name into the message, so an example format string
@@ -353,9 +412,10 @@ public final class SuspendDialogInfo implements Parcelable {
        }

        /**
         * Set the resource id of text to be shown on the neutral button. Tapping this button starts
         * the {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} activity. If this is
         * not provided, the system will use a default text.
         * Set the resource id of text to be shown on the neutral button. Tapping this button would
         * perform the {@link ButtonAction action} specified through
         * {@link #setNeutralButtonAction(int)}. If this is not provided, the system will use a
         * default text.
         *
         * @param resId The resource id of the button text
         * @return this builder object.
@@ -367,6 +427,22 @@ public final class SuspendDialogInfo implements Parcelable {
            return this;
        }

        /**
         * Set the action expected to happen on neutral button tap. Defaults to
         * {@link #BUTTON_ACTION_MORE_DETAILS} if this is not provided.
         *
         * @param buttonAction Either {@link #BUTTON_ACTION_MORE_DETAILS} or
         *                     {@link #BUTTON_ACTION_UNSUSPEND}.
         * @return this builder object
         */
        @NonNull
        public Builder setNeutralButtonAction(@ButtonAction int buttonAction) {
            Preconditions.checkArgument(buttonAction == BUTTON_ACTION_MORE_DETAILS
                    || buttonAction == BUTTON_ACTION_UNSUSPEND, "Invalid button action");
            mNeutralButtonAction = buttonAction;
            return this;
        }

        /**
         * Build the final object based on given inputs.
         *
+97 −22
Original line number Diff line number Diff line
@@ -18,23 +18,31 @@ package com.android.internal.app;

import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_MORE_DETAILS;
import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
import static android.content.res.Resources.ID_NULL;

import android.Manifest;
import android.annotation.Nullable;
import android.app.AlertDialog;
import android.app.AppGlobals;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.SuspendDialogInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import android.view.WindowManager;

import com.android.internal.R;
import com.android.internal.util.ArrayUtils;

public class SuspendedAppActivity extends AlertActivity
        implements DialogInterface.OnClickListener {
@@ -46,8 +54,13 @@ public class SuspendedAppActivity extends AlertActivity
            PACKAGE_NAME + ".extra.SUSPENDING_PACKAGE";
    public static final String EXTRA_DIALOG_INFO = PACKAGE_NAME + ".extra.DIALOG_INFO";
    public static final String EXTRA_ACTIVITY_OPTIONS = PACKAGE_NAME + ".extra.ACTIVITY_OPTIONS";
    public static final String EXTRA_UNSUSPEND_INTENT = PACKAGE_NAME + ".extra.UNSUSPEND_INTENT";

    private Intent mMoreDetailsIntent;
    private IntentSender mOnUnsuspend;
    private String mSuspendedPackage;
    private String mSuspendingPackage;
    private int mNeutralButtonAction;
    private int mUserId;
    private PackageManager mPm;
    private Resources mSuspendingAppResources;
@@ -63,16 +76,15 @@ public class SuspendedAppActivity extends AlertActivity
        return packageName;
    }

    private Intent getMoreDetailsActivity(String suspendingPackage, String suspendedPackage,
            int userId) {
    private Intent getMoreDetailsActivity() {
        final Intent moreDetailsIntent = new Intent(Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS)
                .setPackage(suspendingPackage);
                .setPackage(mSuspendingPackage);
        final String requiredPermission = Manifest.permission.SEND_SHOW_SUSPENDED_APP_DETAILS;
        final ResolveInfo resolvedInfo = mPm.resolveActivityAsUser(moreDetailsIntent,
                MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE, userId);
                MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE, mUserId);
        if (resolvedInfo != null && resolvedInfo.activityInfo != null
                && requiredPermission.equals(resolvedInfo.activityInfo.permission)) {
            moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, suspendedPackage)
            moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, mSuspendedPackage)
                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            return moreDetailsIntent;
        }
@@ -105,8 +117,8 @@ public class SuspendedAppActivity extends AlertActivity
        return getString(R.string.app_suspended_title);
    }

    private String resolveDialogMessage(String suspendingPkg, String suspendedPkg) {
        final CharSequence suspendedAppLabel = getAppLabel(suspendedPkg);
    private String resolveDialogMessage() {
        final CharSequence suspendedAppLabel = getAppLabel(mSuspendedPackage);
        if (mSuppliedDialogInfo != null) {
            final int messageId = mSuppliedDialogInfo.getDialogMessageResId();
            final String message = mSuppliedDialogInfo.getDialogMessage();
@@ -122,10 +134,30 @@ public class SuspendedAppActivity extends AlertActivity
            }
        }
        return getString(R.string.app_suspended_default_message, suspendedAppLabel,
                getAppLabel(suspendingPkg));
                getAppLabel(mSuspendingPackage));
    }

    /**
     * Returns a text to be displayed on the neutral button or {@code null} if the button should
     * not be shown.
     */
    @Nullable
    private String resolveNeutralButtonText() {
        final int defaultButtonTextId;
        switch (mNeutralButtonAction) {
            case BUTTON_ACTION_MORE_DETAILS:
                if (mMoreDetailsIntent == null) {
                    return null;
                }
                defaultButtonTextId = R.string.app_suspended_more_details;
                break;
            case BUTTON_ACTION_UNSUSPEND:
                defaultButtonTextId = R.string.app_suspended_unsuspend_message;
                break;
            default:
                Slog.w(TAG, "Unknown neutral button action: " + mNeutralButtonAction);
                return null;
        }
        final int buttonTextId = (mSuppliedDialogInfo != null)
                ? mSuppliedDialogInfo.getNeutralButtonTextResId() : ID_NULL;
        if (buttonTextId != ID_NULL && mSuspendingAppResources != null) {
@@ -135,7 +167,7 @@ public class SuspendedAppActivity extends AlertActivity
                Slog.e(TAG, "Could not resolve string resource id " + buttonTextId);
            }
        }
        return getString(R.string.app_suspended_more_details);
        return getString(defaultButtonTextId);
    }

    @Override
@@ -152,27 +184,29 @@ public class SuspendedAppActivity extends AlertActivity
            finish();
            return;
        }
        final String suspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
        final String suspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
        mSuspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
        mSuspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
        mSuppliedDialogInfo = intent.getParcelableExtra(EXTRA_DIALOG_INFO);
        mOnUnsuspend = intent.getParcelableExtra(EXTRA_UNSUSPEND_INTENT);
        if (mSuppliedDialogInfo != null) {
            try {
                mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(suspendingPackage,
                mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(mSuspendingPackage,
                        mUserId);
            } catch (PackageManager.NameNotFoundException ne) {
                Slog.e(TAG, "Could not find resources for " + suspendingPackage, ne);
                Slog.e(TAG, "Could not find resources for " + mSuspendingPackage, ne);
            }
        }
        mNeutralButtonAction = (mSuppliedDialogInfo != null)
                ? mSuppliedDialogInfo.getNeutralButtonAction() : BUTTON_ACTION_MORE_DETAILS;
        mMoreDetailsIntent = (mNeutralButtonAction == BUTTON_ACTION_MORE_DETAILS)
                ? getMoreDetailsActivity() : null;

        final AlertController.AlertParams ap = mAlertParams;
        ap.mIcon = resolveIcon();
        ap.mTitle = resolveTitle();
        ap.mMessage = resolveDialogMessage(suspendingPackage, suspendedPackage);
        ap.mMessage = resolveDialogMessage();
        ap.mPositiveButtonText = getString(android.R.string.ok);
        mMoreDetailsIntent = getMoreDetailsActivity(suspendingPackage, suspendedPackage, mUserId);
        if (mMoreDetailsIntent != null) {
        ap.mNeutralButtonText = resolveNeutralButtonText();
        }
        ap.mPositiveButtonListener = ap.mNeutralButtonListener = this;
        setupAlert();
    }
@@ -181,21 +215,62 @@ public class SuspendedAppActivity extends AlertActivity
    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case AlertDialog.BUTTON_NEUTRAL:
                startActivityAsUser(mMoreDetailsIntent, mOptions, UserHandle.of(mUserId));
                Slog.i(TAG, "Started activity: " + mMoreDetailsIntent.getAction()
                        + " in user " + mUserId);
                switch (mNeutralButtonAction) {
                    case BUTTON_ACTION_MORE_DETAILS:
                        if (mMoreDetailsIntent != null) {
                            startActivityAsUser(mMoreDetailsIntent, mOptions,
                                    UserHandle.of(mUserId));
                        } else {
                            Slog.wtf(TAG, "Neutral button should not have existed!");
                        }
                        break;
                    case BUTTON_ACTION_UNSUSPEND:
                        final IPackageManager ipm = AppGlobals.getPackageManager();
                        try {
                            final String[] errored = ipm.setPackagesSuspendedAsUser(
                                    new String[]{mSuspendedPackage}, false, null, null, null,
                                    mSuspendingPackage, mUserId);
                            if (ArrayUtils.contains(errored, mSuspendedPackage)) {
                                Slog.e(TAG, "Could not unsuspend " + mSuspendedPackage);
                                break;
                            }
                        } catch (RemoteException re) {
                            Slog.e(TAG, "Can't talk to system process", re);
                            break;
                        }
                        final Intent reportUnsuspend = new Intent()
                                .setAction(Intent.ACTION_PACKAGE_UNSUSPENDED_MANUALLY)
                                .putExtra(Intent.EXTRA_PACKAGE_NAME, mSuspendedPackage)
                                .setPackage(mSuspendingPackage)
                                .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                        sendBroadcastAsUser(reportUnsuspend, UserHandle.of(mUserId));

                        if (mOnUnsuspend != null) {
                            try {
                                mOnUnsuspend.sendIntent(this, 0, null, null, null);
                            } catch (IntentSender.SendIntentException e) {
                                Slog.e(TAG, "Error while starting intent " + mOnUnsuspend, e);
                            }
                        }
                        break;
                    default:
                        Slog.e(TAG, "Unexpected action on neutral button: " + mNeutralButtonAction);
                        break;
                }
                break;
        }
        finish();
    }

    public static Intent createSuspendedAppInterceptIntent(String suspendedPackage,
            String suspendingPackage, SuspendDialogInfo dialogInfo, Bundle options, int userId) {
            String suspendingPackage, SuspendDialogInfo dialogInfo, Bundle options,
            IntentSender onUnsuspend, int userId) {
        return new Intent()
                .setClassName("android", SuspendedAppActivity.class.getName())
                .putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
                .putExtra(EXTRA_DIALOG_INFO, dialogInfo)
                .putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
                .putExtra(EXTRA_UNSUSPEND_INTENT, onUnsuspend)
                .putExtra(EXTRA_ACTIVITY_OPTIONS, options)
                .putExtra(Intent.EXTRA_USER_ID, userId)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@
    <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" />
    <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" />
    <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" />
    <protected-broadcast android:name="android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY" />
    <protected-broadcast android:name="android.intent.action.DISTRACTING_PACKAGES_CHANGED" />
    <protected-broadcast android:name="android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED" />
    <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
Loading