OSDN Git Service

resolved conflicts for merge of 13ef17a3 to mnc-dr-dev
[android-x86/packages-apps-Launcher3.git] / src / com / android / launcher3 / compat / LauncherAppsCompatV16.java
1 /*
2  * Copyright (C) 2014 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.launcher3.compat;
18
19 import android.content.BroadcastReceiver;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.ActivityInfo;
25 import android.content.pm.PackageManager;
26 import android.content.pm.PackageManager.NameNotFoundException;
27 import android.content.pm.ResolveInfo;
28 import android.graphics.Rect;
29 import android.net.Uri;
30 import android.os.Build;
31 import android.os.Bundle;
32 import android.provider.Settings;
33
34 import com.android.launcher3.util.Thunk;
35
36 import java.util.ArrayList;
37 import java.util.List;
38
39 /**
40  * Version of {@link LauncherAppsCompat} for devices with API level 16.
41  * Devices Pre-L don't support multiple profiles in one launcher so
42  * user parameters are ignored and all methods operate on the current user.
43  */
44 public class LauncherAppsCompatV16 extends LauncherAppsCompat {
45
46     private PackageManager mPm;
47     private Context mContext;
48     private List<OnAppsChangedCallbackCompat> mCallbacks
49             = new ArrayList<OnAppsChangedCallbackCompat>();
50     private PackageMonitor mPackageMonitor;
51
52     LauncherAppsCompatV16(Context context) {
53         mPm = context.getPackageManager();
54         mContext = context;
55         mPackageMonitor = new PackageMonitor();
56    }
57
58     public List<LauncherActivityInfoCompat> getActivityList(String packageName,
59             UserHandleCompat user) {
60         final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
61         mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
62         mainIntent.setPackage(packageName);
63         List<ResolveInfo> infos = mPm.queryIntentActivities(mainIntent, 0);
64         List<LauncherActivityInfoCompat> list =
65                 new ArrayList<LauncherActivityInfoCompat>(infos.size());
66         for (ResolveInfo info : infos) {
67             list.add(new LauncherActivityInfoCompatV16(mContext, info));
68         }
69         return list;
70     }
71
72     public LauncherActivityInfoCompat resolveActivity(Intent intent, UserHandleCompat user) {
73         ResolveInfo info = mPm.resolveActivity(intent, 0);
74         if (info != null) {
75             return new LauncherActivityInfoCompatV16(mContext, info);
76         }
77         return null;
78     }
79
80     public void startActivityForProfile(ComponentName component, UserHandleCompat user,
81             Rect sourceBounds, Bundle opts) {
82         Intent launchIntent = new Intent(Intent.ACTION_MAIN);
83         launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
84         launchIntent.setComponent(component);
85         launchIntent.setSourceBounds(sourceBounds);
86         launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
87         mContext.startActivity(launchIntent, opts);
88     }
89
90     public void showAppDetailsForProfile(ComponentName component, UserHandleCompat user) {
91         String packageName = component.getPackageName();
92         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
93                 Uri.fromParts("package", packageName, null));
94         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |
95                 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
96         mContext.startActivity(intent, null);
97     }
98
99     public synchronized void addOnAppsChangedCallback(OnAppsChangedCallbackCompat callback) {
100         if (callback != null && !mCallbacks.contains(callback)) {
101             mCallbacks.add(callback);
102             if (mCallbacks.size() == 1) {
103                 registerForPackageIntents();
104             }
105         }
106     }
107
108     public synchronized void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat callback) {
109         mCallbacks.remove(callback);
110         if (mCallbacks.size() == 0) {
111             unregisterForPackageIntents();
112         }
113     }
114
115     public boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user) {
116         return isAppEnabled(mPm, packageName, 0);
117     }
118
119     public boolean isActivityEnabledForProfile(ComponentName component, UserHandleCompat user) {
120         try {
121             ActivityInfo info = mPm.getActivityInfo(component, 0);
122             return info != null && info.isEnabled();
123         } catch (NameNotFoundException e) {
124             return false;
125         }
126     }
127
128     private void unregisterForPackageIntents() {
129         mContext.unregisterReceiver(mPackageMonitor);
130     }
131
132     private void registerForPackageIntents() {
133         IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
134         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
135         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
136         filter.addDataScheme("package");
137         mContext.registerReceiver(mPackageMonitor, filter);
138         filter = new IntentFilter();
139         filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
140         filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
141         mContext.registerReceiver(mPackageMonitor, filter);
142     }
143
144     @Thunk synchronized List<OnAppsChangedCallbackCompat> getCallbacks() {
145         return new ArrayList<OnAppsChangedCallbackCompat>(mCallbacks);
146     }
147
148     @Thunk class PackageMonitor extends BroadcastReceiver {
149         public void onReceive(Context context, Intent intent) {
150             final String action = intent.getAction();
151             final UserHandleCompat user = UserHandleCompat.myUserHandle();
152
153             if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
154                     || Intent.ACTION_PACKAGE_REMOVED.equals(action)
155                     || Intent.ACTION_PACKAGE_ADDED.equals(action)) {
156                 final String packageName = intent.getData().getSchemeSpecificPart();
157                 final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
158
159                 if (packageName == null || packageName.length() == 0) {
160                     // they sent us a bad intent
161                     return;
162                 }
163                 if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
164                     for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
165                         callback.onPackageChanged(packageName, user);
166                     }
167                 } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
168                     if (!replacing) {
169                         for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
170                             callback.onPackageRemoved(packageName, user);
171                         }
172                     }
173                     // else, we are replacing the package, so a PACKAGE_ADDED will be sent
174                     // later, we will update the package at this time
175                 } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
176                     if (!replacing) {
177                         for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
178                             callback.onPackageAdded(packageName, user);
179                         }
180                     } else {
181                         for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
182                             callback.onPackageChanged(packageName, user);
183                         }
184                     }
185                 }
186             } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
187                 // EXTRA_REPLACING is available Kitkat onwards. For lower devices, it is broadcasted
188                 // when moving a package or mounting/un-mounting external storage. Assume that
189                 // it is a replacing operation.
190                 final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING,
191                         Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT);
192                 String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
193                 for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
194                     callback.onPackagesAvailable(packages, user, replacing);
195                 }
196             } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
197                 // This intent is broadcasted when moving a package or mounting/un-mounting
198                 // external storage.
199                 // However on Kitkat this is also sent when a package is being updated, and
200                 // contains an extra Intent.EXTRA_REPLACING=true for that case.
201                 // Using false as default for Intent.EXTRA_REPLACING gives correct value on
202                 // lower devices as the intent is not sent when the app is updating/replacing.
203                 final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
204                 String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
205                 for (OnAppsChangedCallbackCompat callback : getCallbacks()) {
206                     callback.onPackagesUnavailable(packages, user, replacing);
207                 }
208             }
209         }
210     }
211 }