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

Commit 6d18d779 authored by Mårten Kongstad's avatar Mårten Kongstad Committed by Todd Kennedy
Browse files

Broadcast PACKAGE_CHANGED in response to OVERLAY_CHANGED

Consolidate what triggers a package change: teach the package manager to
broadcast PACKAGE_CHANGED in response to the overlay manager
broadcasting OVERLAY_CHANGED. Since the overlay manager listens for
PACKAGE_CHANGED, the package manager will include a new extra in the
intent to act as a secret handshake between the managers that the
overlay manager should ignore the intent in order to prevent an endless
loop.

Bug: 140790688
Test: manual (adb shell cmd overlay enable ... && adb shell dumpsys activity broadcasts # check "Historical broadcasts")
Change-Id: I430efcce5adf0dca03058cd6ff694541f0ac3ef5
parent 093f80de
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -17,11 +17,13 @@
package com.android.server.om;

import static android.app.AppGlobals.getPackageManager;
import static android.content.Intent.ACTION_OVERLAY_CHANGED;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_CHANGED;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_REASON;
import static android.content.pm.PackageManager.SIGNATURE_MATCH;
import static android.os.Trace.TRACE_TAG_RRO;
import static android.os.Trace.traceBegin;
@@ -356,7 +358,11 @@ public final class OverlayManagerService extends SystemService {
                    }
                    break;
                case ACTION_PACKAGE_CHANGED:
                    // ignore the intent if it was sent by the package manager as a result of the
                    // overlay manager having sent ACTION_OVERLAY_CHANGED
                    if (!ACTION_OVERLAY_CHANGED.equals(intent.getStringExtra(EXTRA_REASON))) {
                        onPackageChanged(packageName, userIds);
                    }
                    break;
                case ACTION_PACKAGE_REMOVED:
                    if (replacing) {
@@ -885,7 +891,7 @@ public final class OverlayManagerService extends SystemService {
            FgThread.getHandler().post(() -> {
                updateAssets(userId, targetPackageName);

                final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED,
                final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
                        Uri.fromParts("package", targetPackageName, null));
                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

+37 −4
Original line number Diff line number Diff line
@@ -1675,7 +1675,8 @@ public class PackageManagerService extends IPackageManager.Stub
                    }
                    // Send broadcasts
                    for (int i = 0; i < size; i++) {
                        sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
                        sendPackageChangedBroadcast(packages[i], true, components[i], uids[i],
                                null);
                    }
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    break;
@@ -2163,7 +2164,7 @@ public class PackageManagerService extends IPackageManager.Stub
                    // send broadcast that all consumers of the static shared library have changed
                    sendPackageChangedBroadcast(pkg.packageName, false /*killFlag*/,
                            new ArrayList<>(Collections.singletonList(pkg.packageName)),
                            pkg.applicationInfo.uid);
                            pkg.applicationInfo.uid, null);
                }
            }
@@ -20039,7 +20040,7 @@ public class PackageManagerService extends IPackageManager.Stub
            if (sendNow) {
                int packageUid = UserHandle.getUid(userId, pkgSetting.appId);
                sendPackageChangedBroadcast(packageName,
                        (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
                        (flags & PackageManager.DONT_KILL_APP) != 0, components, packageUid, null);
            }
        } finally {
            Binder.restoreCallingIdentity(callingId);
@@ -20071,7 +20072,8 @@ public class PackageManagerService extends IPackageManager.Stub
    }
    private void sendPackageChangedBroadcast(String packageName,
            boolean killFlag, ArrayList<String> componentNames, int packageUid) {
            boolean killFlag, ArrayList<String> componentNames, int packageUid,
            String reason) {
        if (DEBUG_INSTALL)
            Log.v(TAG, "Sending package changed: package=" + packageName + " components="
                    + componentNames);
@@ -20082,6 +20084,9 @@ public class PackageManagerService extends IPackageManager.Stub
        extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
        extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
        extras.putInt(Intent.EXTRA_UID, packageUid);
        if (reason != null) {
            extras.putString(Intent.EXTRA_REASON, reason);
        }
        // If this is not reporting a change of the overall package, then only send it
        // to registered receivers.  We don't want to launch a swath of apps for every
        // little component state change.
@@ -20329,6 +20334,34 @@ public class PackageManagerService extends IPackageManager.Stub
            }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
        }
        IntentFilter overlayFilter = new IntentFilter(Intent.ACTION_OVERLAY_CHANGED);
        overlayFilter.addDataScheme("package");
        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent == null) {
                    return;
                }
                Uri data = intent.getData();
                if (data == null) {
                    return;
                }
                String packageName = data.getSchemeSpecificPart();
                if (packageName == null) {
                    return;
                }
                PackageParser.Package pkg = mPackages.get(packageName);
                if (pkg == null) {
                    return;
                }
                sendPackageChangedBroadcast(pkg.packageName,
                        false /* killFlag */,
                        new ArrayList<>(Collections.singletonList(pkg.packageName)),
                        pkg.applicationInfo.uid,
                        Intent.ACTION_OVERLAY_CHANGED);
            }
        }, overlayFilter);
        mModuleInfoProvider.systemReady();
        // Installer service might attempt to install some packages that have been staged for