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

Commit 58cdb919 authored by Wale Ogunwale's avatar Wale Ogunwale Committed by Android Git Automerger
Browse files

am 465e9967: Merge "Consolidated processing of package boardcasts in AM service." into lmp-mr1-dev

* commit '465e9967':
  Consolidated processing of package boardcasts in AM service.
parents af56f979 465e9967
Loading
Loading
Loading
Loading
+180 −208
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessStats;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessCpuTracker;
@@ -1832,99 +1831,6 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    };
    /**
     * Monitor for package changes and update our internal state.
     */
    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
        @Override
        public void onPackageRemoved(String packageName, int uid) {
            // Remove all tasks with activities in the specified package from the list of recent tasks
            final int eventUserId = getChangingUserId();
            synchronized (ActivityManagerService.this) {
                for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
                    TaskRecord tr = mRecentTasks.get(i);
                    if (tr.userId != eventUserId) continue;
                    ComponentName cn = tr.intent.getComponent();
                    if (cn != null && cn.getPackageName().equals(packageName)) {
                        // If the package name matches, remove the task
                        removeTaskByIdLocked(tr.taskId, true);
                    }
                }
            }
        }
        @Override
        public boolean onPackageChanged(String packageName, int uid, String[] components) {
            onPackageModified(packageName);
            return true;
        }
        @Override
        public void onPackageModified(String packageName) {
            final int eventUserId = getChangingUserId();
            final IPackageManager pm = AppGlobals.getPackageManager();
            final ArrayList<Pair<Intent, Integer>> recentTaskIntents =
                    new ArrayList<Pair<Intent, Integer>>();
            final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
            final ArrayList<Integer> tasksToRemove = new ArrayList<Integer>();
            // Copy the list of recent tasks so that we don't hold onto the lock on
            // ActivityManagerService for long periods while checking if components exist.
            synchronized (ActivityManagerService.this) {
                for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
                    TaskRecord tr = mRecentTasks.get(i);
                    if (tr.userId != eventUserId) continue;
                    recentTaskIntents.add(new Pair<Intent, Integer>(tr.intent, tr.taskId));
                }
            }
            // Check the recent tasks and filter out all tasks with components that no longer exist.
            for (int i = recentTaskIntents.size() - 1; i >= 0; i--) {
                Pair<Intent, Integer> p = recentTaskIntents.get(i);
                ComponentName cn = p.first.getComponent();
                if (cn != null && cn.getPackageName().equals(packageName)) {
                    if (componentsKnownToExist.contains(cn)) {
                        // If we know that the component still exists in the package, then skip
                        continue;
                    }
                    try {
                        ActivityInfo info = pm.getActivityInfo(cn, 0, eventUserId);
                        if (info != null) {
                            componentsKnownToExist.add(cn);
                        } else {
                            tasksToRemove.add(p.second);
                        }
                    } catch (RemoteException e) {
                        Log.e(TAG, "Failed to query activity info for component: " + cn, e);
                    }
                }
            }
            // Prune all the tasks with removed components from the list of recent tasks
            synchronized (ActivityManagerService.this) {
                for (int i = tasksToRemove.size() - 1; i >= 0; i--) {
                    removeTaskByIdLocked(tasksToRemove.get(i), false);
                }
            }
        }
        @Override
        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
            // Force stop the specified packages
            int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
            if (packages != null) {
                for (String pkg : packages) {
                    synchronized (ActivityManagerService.this) {
                        if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
                                userId, "finished booting")) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
    };
    public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
@@ -6172,8 +6078,26 @@ public final class ActivityManagerService extends ActivityManagerNative
            }
        }
        // Register receivers to handle package update events
        mPackageMonitor.register(mContext, Looper.getMainLooper(), UserHandle.ALL, false);
        IntentFilter pkgFilter = new IntentFilter();
        pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
        pkgFilter.addDataScheme("package");
        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
                if (pkgs != null) {
                    for (String pkg : pkgs) {
                        synchronized (ActivityManagerService.this) {
                            if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
                                    0, "finished booting")) {
                                setResultCode(Activity.RESULT_OK);
                                return;
                            }
                        }
                    }
                }
            }
        }, pkgFilter);
        // Let system services know.
        mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -8407,6 +8331,47 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    private void removeTasksByPackageNameLocked(String packageName, int userId) {
        // Remove all tasks with activities in the specified package from the list of recent tasks
        for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
            TaskRecord tr = mRecentTasks.get(i);
            if (tr.userId != userId) continue;
            ComponentName cn = tr.intent.getComponent();
            if (cn != null && cn.getPackageName().equals(packageName)) {
                // If the package name matches, remove the task.
                removeTaskByIdLocked(tr.taskId, true);
            }
        }
    }
    private void removeTasksByRemovedPackageComponentsLocked(String packageName, int userId) {
        final IPackageManager pm = AppGlobals.getPackageManager();
        final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
        for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
            TaskRecord tr = mRecentTasks.get(i);
            if (tr.userId != userId) continue;
            ComponentName cn = tr.intent.getComponent();
            if (cn != null && cn.getPackageName().equals(packageName)) {
                // Skip if component still exists in the package.
                if (componentsKnownToExist.contains(cn)) continue;
                try {
                    ActivityInfo info = pm.getActivityInfo(cn, 0, userId);
                    if (info != null) {
                        componentsKnownToExist.add(cn);
                    } else {
                        removeTaskByIdLocked(tr.taskId, false);
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "Activity info query failed. component=" + cn, e);
                }
            }
        }
    }
    /**
     * Removes the task with the specified task id.
     *
@@ -15674,21 +15639,31 @@ public final class ActivityManagerService extends ActivityManagerNative
            }
        }
        final String action = intent.getAction();
        if (action != null) {
            switch (action) {
                case Intent.ACTION_UID_REMOVED:
                case Intent.ACTION_PACKAGE_REMOVED:
                case Intent.ACTION_PACKAGE_CHANGED:
                case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
                case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
                    // Handle special intents: if this broadcast is from the package
                    // manager about a package being removed, we need to remove all of
                    // its activities from the history stack.
        final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
                intent.getAction());
        if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
                || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
                || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
                || Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())
                || uidRemoved) {
                    if (checkComponentPermission(
                            android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
                            callingPid, callingUid, -1, true)
                    == PackageManager.PERMISSION_GRANTED) {
                if (uidRemoved) {
                            != PackageManager.PERMISSION_GRANTED) {
                        String msg = "Permission Denial: " + intent.getAction()
                                + " broadcast from " + callerPackage + " (pid=" + callingPid
                                + ", uid=" + callingUid + ")"
                                + " requires "
                                + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
                        Slog.w(TAG, msg);
                        throw new SecurityException(msg);
                    }
                    switch (action) {
                        case Intent.ACTION_UID_REMOVED:
                            final Bundle intentExtras = intent.getExtras();
                            final int uid = intentExtras != null
                                    ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
@@ -15699,101 +15674,98 @@ public final class ActivityManagerService extends ActivityManagerNative
                                }
                                mAppOpsService.uidRemoved(uid);
                            }
                } else {
                    // If resources are unavailable just force stop all
                    // those packages and flush the attribute cache as well.
                    if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
                        String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                        if (list != null && (list.length > 0)) {
                            for (String pkg : list) {
                                forceStopPackageLocked(pkg, -1, false, true, true, false, false, userId,
                                        "storage unmount");
                            break;
                        case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
                            // If resources are unavailable just force stop all those packages
                            // and flush the attribute cache as well.
                            String list[] =
                                    intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                            if (list != null && list.length > 0) {
                                for (int i = 0; i < list.length; i++) {
                                    forceStopPackageLocked(list[i], -1, false, true, true,
                                            false, false, userId, "storage unmount");
                                }
                                cleanupRecentTasksLocked(UserHandle.USER_ALL);
                                sendPackageBroadcastLocked(
                                    IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list, userId);
                                        IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,
                                        userId);
                            }
                    } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(
                            intent.getAction())) {
                            break;
                        case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
                            cleanupRecentTasksLocked(UserHandle.USER_ALL);
                    } else {
                            break;
                        case Intent.ACTION_PACKAGE_REMOVED:
                        case Intent.ACTION_PACKAGE_CHANGED:
                            Uri data = intent.getData();
                            String ssp;
                            if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
                            boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(
                                    intent.getAction());
                                boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
                                boolean fullUninstall = removed &&
                                        !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                                if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
                                    forceStopPackageLocked(ssp, UserHandle.getAppId(
                                        intent.getIntExtra(Intent.EXTRA_UID, -1)), false, true, true,
                                        false, fullUninstall, userId,
                                            intent.getIntExtra(Intent.EXTRA_UID, -1)),
                                            false, true, true, false, fullUninstall, userId,
                                            removed ? "pkg removed" : "pkg changed");
                                }
                                if (removed) {
                                    sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
                                            new String[] {ssp}, userId);
                                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                                    if (fullUninstall) {
                                        mAppOpsService.packageRemoved(
                                                intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
                                        // Remove all permissions granted from/to this package
                                        removeUriPermissionsForPackageLocked(ssp, userId, true);
                                        removeTasksByPackageNameLocked(ssp, userId);
                                    }
                                } else {
                                    removeTasksByRemovedPackageComponentsLocked(ssp, userId);
                                }
                            }
                            break;
                    }
                }
            } else {
                String msg = "Permission Denial: " + intent.getAction()
                        + " broadcast from " + callerPackage + " (pid=" + callingPid
                        + ", uid=" + callingUid + ")"
                        + " requires "
                        + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            }
        // Special case for adding a package: by default turn on compatibility
        // mode.
        } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
                    break;
                case Intent.ACTION_PACKAGE_ADDED:
                    // Special case for adding a package: by default turn on compatibility mode.
                    Uri data = intent.getData();
                    String ssp;
                    if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
                mCompatModePackages.handlePackageAddedLocked(ssp,
                        intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
                        final boolean replacing =
                                intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                        mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
                        if (replacing) {
                            removeTasksByRemovedPackageComponentsLocked(ssp, userId);
                        }
                    }
        /*
         * If this is the time zone changed action, queue up a message that will reset the timezone
         * of all currently running processes. This message will get queued up before the broadcast
         * happens.
         */
        if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
                    break;
                case Intent.ACTION_TIMEZONE_CHANGED:
                    // If this is the time zone changed action, queue up a message that will reset
                    // the timezone of all currently running processes. This message will get
                    // queued up before the broadcast happens.
                    mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
        }
        /*
         * If the user set the time, let all running processes know.
         */
        if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
            final int is24Hour = intent.getBooleanExtra(
                    Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0;
                    break;
                case Intent.ACTION_TIME_CHANGED:
                    // If the user set the time, let all running processes know.
                    final int is24Hour =
                            intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1
                                    : 0;
                    mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
                    BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
                    synchronized (stats) {
                        stats.noteCurrentTimeChangedLocked();
                    }
        }
        if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
                    break;
                case Intent.ACTION_CLEAR_DNS_CACHE:
                    mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
        }
        if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
                    break;
                case Proxy.PROXY_CHANGE_ACTION:
                    ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
                    mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
                    break;
            }
        }
        // Add to the sticky list if requested.