1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.launcher2;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.SharedPreferences;
24 import android.database.Cursor;
25 import android.net.Uri;
26 import android.widget.Toast;
27 
28 import com.android.launcher.R;
29 
30 import java.net.URISyntaxException;
31 import java.util.ArrayList;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.Set;
35 
36 public class UninstallShortcutReceiver extends BroadcastReceiver {
37     private static final String ACTION_UNINSTALL_SHORTCUT =
38             "com.android.launcher.action.UNINSTALL_SHORTCUT";
39 
40     // The set of shortcuts that are pending uninstall
41     private static ArrayList<PendingUninstallShortcutInfo> mUninstallQueue =
42             new ArrayList<PendingUninstallShortcutInfo>();
43 
44     // Determines whether to defer uninstalling shortcuts immediately until
45     // disableAndFlushUninstallQueue() is called.
46     private static boolean mUseUninstallQueue = false;
47 
48     private static class PendingUninstallShortcutInfo {
49         Intent data;
50 
PendingUninstallShortcutInfo(Intent rawData)51         public PendingUninstallShortcutInfo(Intent rawData) {
52             data = rawData;
53         }
54     }
55 
onReceive(Context context, Intent data)56     public void onReceive(Context context, Intent data) {
57         if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) {
58             return;
59         }
60 
61         PendingUninstallShortcutInfo info = new PendingUninstallShortcutInfo(data);
62         if (mUseUninstallQueue) {
63             mUninstallQueue.add(info);
64         } else {
65             processUninstallShortcut(context, info);
66         }
67     }
68 
enableUninstallQueue()69     static void enableUninstallQueue() {
70         mUseUninstallQueue = true;
71     }
72 
disableAndFlushUninstallQueue(Context context)73     static void disableAndFlushUninstallQueue(Context context) {
74         mUseUninstallQueue = false;
75         Iterator<PendingUninstallShortcutInfo> iter = mUninstallQueue.iterator();
76         while (iter.hasNext()) {
77             processUninstallShortcut(context, iter.next());
78             iter.remove();
79         }
80     }
81 
processUninstallShortcut(Context context, PendingUninstallShortcutInfo pendingInfo)82     private static void processUninstallShortcut(Context context,
83             PendingUninstallShortcutInfo pendingInfo) {
84         String spKey = LauncherApplication.getSharedPreferencesKey();
85         SharedPreferences sharedPrefs = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
86 
87         final Intent data = pendingInfo.data;
88 
89         LauncherApplication app = (LauncherApplication) context.getApplicationContext();
90         synchronized (app) {
91             removeShortcut(context, data, sharedPrefs);
92         }
93     }
94 
removeShortcut(Context context, Intent data, final SharedPreferences sharedPrefs)95     private static void removeShortcut(Context context, Intent data,
96             final SharedPreferences sharedPrefs) {
97         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
98         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
99         boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
100 
101         if (intent != null && name != null) {
102             final ContentResolver cr = context.getContentResolver();
103             Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
104                 new String[] { LauncherSettings.Favorites._ID, LauncherSettings.Favorites.INTENT },
105                 LauncherSettings.Favorites.TITLE + "=?", new String[] { name }, null);
106 
107             final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
108             final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
109 
110             boolean changed = false;
111 
112             try {
113                 while (c.moveToNext()) {
114                     try {
115                         if (intent.filterEquals(Intent.parseUri(c.getString(intentIndex), 0))) {
116                             final long id = c.getLong(idIndex);
117                             final Uri uri = LauncherSettings.Favorites.getContentUri(id, false);
118                             cr.delete(uri, null, null);
119                             changed = true;
120                             if (!duplicate) {
121                                 break;
122                             }
123                         }
124                     } catch (URISyntaxException e) {
125                         // Ignore
126                     }
127                 }
128             } finally {
129                 c.close();
130             }
131 
132             if (changed) {
133                 cr.notifyChange(LauncherSettings.Favorites.CONTENT_URI, null);
134                 Toast.makeText(context, context.getString(R.string.shortcut_uninstalled, name),
135                         Toast.LENGTH_SHORT).show();
136             }
137 
138             // Remove any items due to be animated
139             boolean appRemoved;
140             Set<String> newApps = new HashSet<String>();
141             newApps = sharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
142             synchronized (newApps) {
143                 do {
144                     appRemoved = newApps.remove(intent.toUri(0).toString());
145                 } while (appRemoved);
146             }
147             if (appRemoved) {
148                 final Set<String> savedNewApps = newApps;
149                 new Thread("setNewAppsThread-remove") {
150                     public void run() {
151                         synchronized (savedNewApps) {
152                             SharedPreferences.Editor editor = sharedPrefs.edit();
153                             editor.putStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY,
154                                     savedNewApps);
155                             if (savedNewApps.isEmpty()) {
156                                 // Reset the page index if there are no more items
157                                 editor.putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1);
158                             }
159                             editor.commit();
160                         }
161                     }
162                 }.start();
163             }
164         }
165     }
166 }
167