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