19f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung/*
29f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * Copyright (C) 2014 The Android Open Source Project
39f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung *
49f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
59f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * you may not use this file except in compliance with the License.
69f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * You may obtain a copy of the License at
79f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung *
89f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
99f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung *
109f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * Unless required by applicable law or agreed to in writing, software
119f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
129f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * See the License for the specific language governing permissions and
149f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung * limitations under the License.
159f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung */
169f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
17f1fbd77cf057e43926f9a0347692611386d09f40Winson Chungpackage com.android.systemui.recents.model;
189f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
199f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chungimport android.content.ComponentName;
209f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chungimport android.content.Context;
219f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chungimport android.os.Looper;
2204400672962d2e12132f9465928cbf7615c147c4Winson Chungimport android.os.UserHandle;
239f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chungimport com.android.internal.content.PackageMonitor;
24ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.SystemServicesProxy;
259f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
269f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chungimport java.util.HashSet;
279f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chungimport java.util.List;
289f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
299f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung/**
3004400672962d2e12132f9465928cbf7615c147c4Winson Chung * The package monitor listens for changes from PackageManager to update the contents of the
3104400672962d2e12132f9465928cbf7615c147c4Winson Chung * Recents list.
329f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung */
339f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chungpublic class RecentsPackageMonitor extends PackageMonitor {
349f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    public interface PackageCallbacks {
3504400672962d2e12132f9465928cbf7615c147c4Winson Chung        public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName,
3604400672962d2e12132f9465928cbf7615c147c4Winson Chung                                      int userId);
379f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    }
389f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
399f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    PackageCallbacks mCb;
40d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    SystemServicesProxy mSystemServicesProxy;
419f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
429f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    /** Registers the broadcast receivers with the specified callbacks. */
439f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    public void register(Context context, PackageCallbacks cb) {
44d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        mSystemServicesProxy = new SystemServicesProxy(context);
459f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung        mCb = cb;
46d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        try {
4704400672962d2e12132f9465928cbf7615c147c4Winson Chung            // We register for events from all users, but will cross-reference them with
4804400672962d2e12132f9465928cbf7615c147c4Winson Chung            // packages for the current user and any profiles they have
4904400672962d2e12132f9465928cbf7615c147c4Winson Chung            register(context, Looper.getMainLooper(), UserHandle.ALL, true);
50d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        } catch (IllegalStateException e) {
51d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            e.printStackTrace();
52521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung        }
539f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    }
549f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
559f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    /** Unregisters the broadcast receivers. */
569f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    @Override
579f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    public void unregister() {
58d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        try {
59521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung            super.unregister();
60d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        } catch (IllegalStateException e) {
61d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            e.printStackTrace();
62521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung        }
63d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        mSystemServicesProxy = null;
64d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        mCb = null;
659f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    }
669f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
679f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    @Override
689f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    public void onPackageRemoved(String packageName, int uid) {
699f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung        if (mCb == null) return;
709f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
7104400672962d2e12132f9465928cbf7615c147c4Winson Chung        // Notify callbacks that a package has changed
7204400672962d2e12132f9465928cbf7615c147c4Winson Chung        final int eventUserId = getChangingUserId();
7304400672962d2e12132f9465928cbf7615c147c4Winson Chung        mCb.onPackagesChanged(this, packageName, eventUserId);
749f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    }
759f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
769f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    @Override
779f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    public boolean onPackageChanged(String packageName, int uid, String[] components) {
789f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung        onPackageModified(packageName);
799f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung        return true;
809f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    }
819f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
829f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    @Override
839f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    public void onPackageModified(String packageName) {
849f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung        if (mCb == null) return;
859f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung
8604400672962d2e12132f9465928cbf7615c147c4Winson Chung        // Notify callbacks that a package has changed
8704400672962d2e12132f9465928cbf7615c147c4Winson Chung        final int eventUserId = getChangingUserId();
8804400672962d2e12132f9465928cbf7615c147c4Winson Chung        mCb.onPackagesChanged(this, packageName, eventUserId);
8904400672962d2e12132f9465928cbf7615c147c4Winson Chung    }
9004400672962d2e12132f9465928cbf7615c147c4Winson Chung
9104400672962d2e12132f9465928cbf7615c147c4Winson Chung    /**
9204400672962d2e12132f9465928cbf7615c147c4Winson Chung     * Computes the components that have been removed as a result of a change in the specified
9304400672962d2e12132f9465928cbf7615c147c4Winson Chung     * package.
9404400672962d2e12132f9465928cbf7615c147c4Winson Chung     */
9504400672962d2e12132f9465928cbf7615c147c4Winson Chung    public HashSet<ComponentName> computeComponentsRemoved(List<Task.TaskKey> taskKeys,
9604400672962d2e12132f9465928cbf7615c147c4Winson Chung            String packageName, int userId) {
979f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung        // Identify all the tasks that should be removed as a result of the package being removed.
989f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung        // Using a set to ensure that we callback once per unique component.
9904400672962d2e12132f9465928cbf7615c147c4Winson Chung        HashSet<ComponentName> existingComponents = new HashSet<ComponentName>();
10004400672962d2e12132f9465928cbf7615c147c4Winson Chung        HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
10104400672962d2e12132f9465928cbf7615c147c4Winson Chung        for (Task.TaskKey t : taskKeys) {
10204400672962d2e12132f9465928cbf7615c147c4Winson Chung            // Skip if this doesn't apply to the current user
10304400672962d2e12132f9465928cbf7615c147c4Winson Chung            if (t.userId != userId) continue;
10404400672962d2e12132f9465928cbf7615c147c4Winson Chung
1059f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung            ComponentName cn = t.baseIntent.getComponent();
1069f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung            if (cn.getPackageName().equals(packageName)) {
10704400672962d2e12132f9465928cbf7615c147c4Winson Chung                if (existingComponents.contains(cn)) {
1089f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung                    // If we know that the component still exists in the package, then skip
1099f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung                    continue;
1109f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung                }
11104400672962d2e12132f9465928cbf7615c147c4Winson Chung                if (mSystemServicesProxy.getActivityInfo(cn, userId) != null) {
11204400672962d2e12132f9465928cbf7615c147c4Winson Chung                    existingComponents.add(cn);
1139f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung                } else {
11404400672962d2e12132f9465928cbf7615c147c4Winson Chung                    removedComponents.add(cn);
1159f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung                }
1169f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung            }
1179f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung        }
11804400672962d2e12132f9465928cbf7615c147c4Winson Chung        return removedComponents;
1199f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung    }
1209f49df933f01a32d04bdf92d53c943065aa8ddf7Winson Chung}
121