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

Commit eb81a4db authored by Sumedh Sen's avatar Sumedh Sen
Browse files

Remove dependency of on IPackageDeleteObserver

Use UninstallEventReceiver to get uninstall result and act accordingly.

Bug: 241139604
Test: atest CtsPackageUninstallTestCases
Change-Id: I8582b841f71fa02b3c166b777878df394b5cefb2
parent 17e9266c
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
@@ -41,17 +41,18 @@ import java.nio.charset.StandardCharsets;
/**
 * Persists results of events and calls back observers when a matching result arrives.
 */
class EventResultPersister {
public class EventResultPersister {
    private static final String LOG_TAG = EventResultPersister.class.getSimpleName();

    /** Id passed to {@link #addObserver(int, EventResultObserver)} to generate new id */
    static final int GENERATE_NEW_ID = Integer.MIN_VALUE;
    public static final int GENERATE_NEW_ID = Integer.MIN_VALUE;

    /**
     * The extra with the id to set in the intent delivered to
     * {@link #onEventReceived(Context, Intent)}
     */
    static final String EXTRA_ID = "EventResultPersister.EXTRA_ID";
    public static final String EXTRA_ID = "EventResultPersister.EXTRA_ID";
    public static final String EXTRA_SERVICE_ID = "EventResultPersister.EXTRA_SERVICE_ID";

    /** Persisted state of this object */
    private final AtomicFile mResultsFile;
@@ -90,8 +91,8 @@ class EventResultPersister {
    }

    /** Call back when a result is received. Observer is removed when onResult it called. */
    interface EventResultObserver {
        void onResult(int status, int legacyStatus, @Nullable String message);
    public interface EventResultObserver {
        void onResult(int status, int legacyStatus, @Nullable String message, int serviceId);
    }

    /**
@@ -154,12 +155,14 @@ class EventResultPersister {
                    int status = readIntAttribute(parser, "status");
                    int legacyStatus = readIntAttribute(parser, "legacyStatus");
                    String statusMessage = readStringAttribute(parser, "statusMessage");
                    int serviceId = readIntAttribute(parser, "serviceId");

                    if (mResults.get(id) != null) {
                        throw new Exception("id " + id + " has two results");
                    }

                    mResults.put(id, new EventResult(status, legacyStatus, statusMessage));
                    mResults.put(id, new EventResult(status, legacyStatus, statusMessage,
                            serviceId));
                } else {
                    throw new Exception("unexpected tag");
                }
@@ -191,6 +194,7 @@ class EventResultPersister {
        int id = intent.getIntExtra(EXTRA_ID, 0);
        String statusMessage = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
        int legacyStatus = intent.getIntExtra(PackageInstaller.EXTRA_LEGACY_STATUS, 0);
        int serviceId = intent.getIntExtra(EXTRA_SERVICE_ID, 0);

        EventResultObserver observerToCall = null;
        synchronized (mLock) {
@@ -205,9 +209,9 @@ class EventResultPersister {
            }

            if (observerToCall != null) {
                observerToCall.onResult(status, legacyStatus, statusMessage);
                observerToCall.onResult(status, legacyStatus, statusMessage, serviceId);
            } else {
                mResults.put(id, new EventResult(status, legacyStatus, statusMessage));
                mResults.put(id, new EventResult(status, legacyStatus, statusMessage, serviceId));
                writeState();
            }
        }
@@ -259,6 +263,8 @@ class EventResultPersister {
                                    serializer.attribute(null, "statusMessage",
                                            results.valueAt(i).message);
                                }
                                serializer.attribute(null, "serviceId",
                                        Integer.toString(results.valueAt(i).serviceId));
                                serializer.endTag(null, "result");
                            }

@@ -312,7 +318,8 @@ class EventResultPersister {
            if (resultIndex >= 0) {
                EventResult result = mResults.valueAt(resultIndex);

                observer.onResult(result.status, result.legacyStatus, result.message);
                observer.onResult(result.status, result.legacyStatus, result.message,
                        result.serviceId);
                mResults.removeAt(resultIndex);
                writeState();
            } else {
@@ -342,13 +349,15 @@ class EventResultPersister {
        public final int status;
        public final int legacyStatus;
        @Nullable public final String message;
        public final int serviceId;

        private EventResult(int status, int legacyStatus, @Nullable String message) {
        private EventResult(int status, int legacyStatus, @Nullable String message, int serviceId) {
            this.status = status;
            this.legacyStatus = legacyStatus;
            this.message = message;
            this.serviceId = serviceId;
        }
    }

    class OutOfIdsException extends Exception {}
    public class OutOfIdsException extends Exception {}
}
+5 −2
Original line number Diff line number Diff line
@@ -271,8 +271,11 @@ public class InstallInstalling extends AlertActivity {
     * @param statusCode    The installation result.
     * @param legacyStatus  The installation as used internally in the package manager.
     * @param statusMessage The detailed installation result.
     * @param serviceId     Id for PowerManager.WakeLock service. Used only by Wear devices
     *                      during an uninstall.
     */
    private void launchFinishBasedOnResult(int statusCode, int legacyStatus, String statusMessage) {
    private void launchFinishBasedOnResult(int statusCode, int legacyStatus, String statusMessage,
            int serviceId /* ignore */) {
        if (statusCode == PackageInstaller.STATUS_SUCCESS) {
            launchSuccess();
        } else {
@@ -282,7 +285,7 @@ public class InstallInstalling extends AlertActivity {

    /**
     * Send the package to the package installer and then register a event result observer that
     * will call {@link #launchFinishBasedOnResult(int, int, String)}
     * will call {@link #launchFinishBasedOnResult(int, int, String, int)}
     */
    private final class InstallingAsyncTask extends AsyncTask<Void, Void,
            PackageInstaller.Session> {
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ public class UninstallEventReceiver extends BroadcastReceiver {
     *
     * @return The id for this event
     */
    static int addObserver(@NonNull Context context, int id,
    public static int addObserver(@NonNull Context context, int id,
            @NonNull EventResultPersister.EventResultObserver observer)
            throws EventResultPersister.OutOfIdsException {
        return getReceiver(context).addObserver(id, observer);
+2 −2
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ public class UninstallUninstalling extends Activity implements
        } catch (EventResultPersister.OutOfIdsException | IllegalArgumentException e) {
            Log.e(LOG_TAG, "Fails to start uninstall", e);
            onResult(PackageInstaller.STATUS_FAILURE, PackageManager.DELETE_FAILED_INTERNAL_ERROR,
                    null);
                    null, 0);
        }
    }

@@ -147,7 +147,7 @@ public class UninstallUninstalling extends Activity implements
    }

    @Override
    public void onResult(int status, int legacyStatus, @Nullable String message) {
    public void onResult(int status, int legacyStatus, @Nullable String message, int serviceId) {
        if (mCallback != null) {
            // The caller will be informed about the result via a callback
            final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub
+36 −12
Original line number Diff line number Diff line
@@ -17,14 +17,15 @@
package com.android.packageinstaller.television;

import android.app.Activity;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageDeleteObserver2;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
@@ -40,8 +41,12 @@ import android.util.TypedValue;
import android.view.KeyEvent;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.android.packageinstaller.EventResultPersister;
import com.android.packageinstaller.PackageUtil;
import com.android.packageinstaller.R;
import com.android.packageinstaller.UninstallEventReceiver;

import java.lang.ref.WeakReference;
import java.util.List;
@@ -53,10 +58,13 @@ import java.util.List;
 * by an intent with the intent's class name explicitly set to UninstallAppProgress and expects
 * the application object of the application to uninstall.
 */
public class UninstallAppProgress extends Activity {
public class UninstallAppProgress extends Activity implements
        EventResultPersister.EventResultObserver {
    private static final String TAG = "UninstallAppProgress";

    private static final String FRAGMENT_TAG = "progress_fragment";
    private static final String BROADCAST_ACTION =
            "com.android.packageinstaller.ACTION_UNINSTALL_COMMIT";

    private ApplicationInfo mAppInfo;
    private boolean mAllUsers;
@@ -272,7 +280,6 @@ public class UninstallAppProgress extends Activity {
            user = Process.myUserHandle();
        }

        PackageDeleteObserver observer = new PackageDeleteObserver();

        // Make window transparent until initView is called. In many cases we can avoid showing the
        // UI at all as the app is uninstalled very quickly. If we show the UI and instantly remove
@@ -282,11 +289,29 @@ public class UninstallAppProgress extends Activity {
        getWindow().setNavigationBarColor(Color.TRANSPARENT);

        try {
            getPackageManager().deletePackageAsUser(mAppInfo.packageName, observer,
                    mAllUsers ? PackageManager.DELETE_ALL_USERS : 0, user.getIdentifier());
            int uninstallId = UninstallEventReceiver.addObserver(this,
                    EventResultPersister.GENERATE_NEW_ID, this);

            Intent broadcastIntent = new Intent(BROADCAST_ACTION);
            broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, uninstallId);
            broadcastIntent.setPackage(getPackageName());

            PendingIntent pendingIntent = PendingIntent.getBroadcast(this, uninstallId,
                    broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT
                            | PendingIntent.FLAG_MUTABLE);

            createContextAsUser(user, 0).getPackageManager().getPackageInstaller().uninstall(
                    new VersionedPackage(mAppInfo.packageName, PackageManager.VERSION_CODE_HIGHEST),
                    mAllUsers ? PackageManager.DELETE_ALL_USERS : 0,
                    pendingIntent.getIntentSender());
        } catch (IllegalArgumentException e) {
            // Couldn't find the package, no need to call uninstall.
            Log.w(TAG, "Could not find package, not deleting " + mAppInfo.packageName, e);
        } catch (EventResultPersister.OutOfIdsException e) {
            Log.e(TAG, "Fails to start uninstall", e);
            onResult(PackageInstaller.STATUS_FAILURE, PackageManager.DELETE_FAILED_INTERNAL_ERROR,
                    null, 0);
        }

        mHandler.sendMessageDelayed(mHandler.obtainMessage(UNINSTALL_IS_SLOW),
@@ -297,14 +322,13 @@ public class UninstallAppProgress extends Activity {
        return mAppInfo;
    }

    private class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
        public void packageDeleted(String packageName, int returnCode) {
    @Override
    public void onResult(int status, int legacyStatus, @Nullable String message, int serviceId) {
        Message msg = mHandler.obtainMessage(UNINSTALL_COMPLETE);
            msg.arg1 = returnCode;
            msg.obj = packageName;
        msg.arg1 = legacyStatus;
        msg.obj = mAppInfo.packageName;
        mHandler.sendMessage(msg);
    }
    }

    public void setResultAndFinish() {
        setResult(mResultCode);
Loading