blob: 73881610b41c1daab7ff13109751971d20ca7134 [file] [log] [blame]
Sunny Goyalfa401a12015-04-10 13:45:42 -07001package com.android.launcher3;
2
Sunny Goyal70660032015-05-14 00:07:08 -07003import android.annotation.TargetApi;
Sunny Goyalfa401a12015-04-10 13:45:42 -07004import android.content.ComponentName;
5import android.content.Context;
6import android.os.Build;
7import android.os.Bundle;
8import android.os.UserManager;
9import android.util.AttributeSet;
10import android.util.Pair;
Sunny Goyalaa8ef112015-06-12 20:04:41 -070011
Sunny Goyalfa401a12015-04-10 13:45:42 -070012import com.android.launcher3.compat.UserHandleCompat;
13import com.android.launcher3.util.Thunk;
14
15public class UninstallDropTarget extends ButtonDropTarget {
16
17 public UninstallDropTarget(Context context, AttributeSet attrs) {
18 this(context, attrs, 0);
19 }
20
21 public UninstallDropTarget(Context context, AttributeSet attrs, int defStyle) {
22 super(context, attrs, defStyle);
23 }
24
25 @Override
26 protected void onFinishInflate() {
27 super.onFinishInflate();
28 // Get the hover color
Sunny Goyal3a2698b2015-04-28 21:36:46 -070029 mHoverColor = getResources().getColor(R.color.uninstall_target_hover_tint);
Sunny Goyalfa401a12015-04-10 13:45:42 -070030
Sunny Goyal40b626b2015-06-04 22:40:14 -070031 setDrawable(R.drawable.ic_uninstall_launcher);
Sunny Goyalfa401a12015-04-10 13:45:42 -070032 }
33
34 @Override
Sunny Goyalaa8ef112015-06-12 20:04:41 -070035 protected boolean supportsDrop(DragSource source, ItemInfo info) {
Sunny Goyal1a70cef2015-04-22 11:29:51 -070036 return supportsDrop(getContext(), info);
37 }
38
Sunny Goyal70660032015-05-14 00:07:08 -070039 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
Sunny Goyal1a70cef2015-04-22 11:29:51 -070040 public static boolean supportsDrop(Context context, Object info) {
Sunny Goyal9fc953b2015-08-17 12:24:25 -070041 if (Utilities.ATLEAST_JB_MR2) {
Sunny Goyal1a70cef2015-04-22 11:29:51 -070042 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
Sunny Goyalfa401a12015-04-10 13:45:42 -070043 Bundle restrictions = userManager.getUserRestrictions();
44 if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
45 || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
46 return false;
47 }
48 }
49
50 Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(info);
51 return componentInfo != null && (componentInfo.second & AppInfo.DOWNLOADED_FLAG) != 0;
52 }
53
54 /**
55 * @return the component name and flags if {@param info} is an AppInfo or an app shortcut.
56 */
57 private static Pair<ComponentName, Integer> getAppInfoFlags(Object item) {
58 if (item instanceof AppInfo) {
59 AppInfo info = (AppInfo) item;
60 return Pair.create(info.componentName, info.flags);
61 } else if (item instanceof ShortcutInfo) {
62 ShortcutInfo info = (ShortcutInfo) item;
63 ComponentName component = info.getTargetComponent();
64 if (info.itemType == LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION
65 && component != null) {
66 return Pair.create(component, info.flags);
67 }
68 }
69 return null;
70 }
71
72 @Override
73 public void onDrop(DragObject d) {
74 // Differ item deletion
75 if (d.dragSource instanceof UninstallSource) {
76 ((UninstallSource) d.dragSource).deferCompleteDropAfterUninstallActivity();
77 }
78 super.onDrop(d);
79 }
80
81 @Override
82 void completeDrop(final DragObject d) {
83 final Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(d.dragInfo);
Sunny Goyalaa8ef112015-06-12 20:04:41 -070084 final UserHandleCompat user = d.dragInfo.user;
Tony Wickham734dfbe2015-09-16 16:22:36 -070085 if (startActivityWithUninstallAffordance(d)) {
Sunny Goyalfa401a12015-04-10 13:45:42 -070086
87 final Runnable checkIfUninstallWasSuccess = new Runnable() {
88 @Override
89 public void run() {
Tony Wickhamce86e192015-09-18 16:06:55 -070090 boolean uninstallSuccessful = false;
91 if (componentInfo != null) {
92 String packageName = componentInfo.first.getPackageName();
93 uninstallSuccessful = !AllAppsList.packageHasActivities(
94 getContext(), packageName, user);
95 }
Sunny Goyalfa401a12015-04-10 13:45:42 -070096 sendUninstallResult(d.dragSource, uninstallSuccessful);
97 }
98 };
99 mLauncher.addOnResumeCallback(checkIfUninstallWasSuccess);
100 } else {
101 sendUninstallResult(d.dragSource, false);
102 }
103 }
104
Tony Wickham734dfbe2015-09-16 16:22:36 -0700105 protected boolean startActivityWithUninstallAffordance(DragObject d) {
106 return startUninstallActivity(mLauncher, d.dragInfo);
107 }
108
Sunny Goyalaa8ef112015-06-12 20:04:41 -0700109 public static boolean startUninstallActivity(Launcher launcher, ItemInfo info) {
Sunny Goyal1a70cef2015-04-22 11:29:51 -0700110 final Pair<ComponentName, Integer> componentInfo = getAppInfoFlags(info);
Sunny Goyalaa8ef112015-06-12 20:04:41 -0700111 final UserHandleCompat user = info.user;
Sunny Goyal1a70cef2015-04-22 11:29:51 -0700112 return launcher.startApplicationUninstallActivity(
113 componentInfo.first, componentInfo.second, user);
114 }
115
Sunny Goyalfa401a12015-04-10 13:45:42 -0700116 @Thunk void sendUninstallResult(DragSource target, boolean result) {
117 if (target instanceof UninstallSource) {
118 ((UninstallSource) target).onUninstallActivityReturned(result);
119 }
120 }
121
122 /**
123 * Interface defining an object that can provide uninstallable drag objects.
124 */
Tony Wickham734dfbe2015-09-16 16:22:36 -0700125 public interface UninstallSource {
Sunny Goyalfa401a12015-04-10 13:45:42 -0700126
127 /**
128 * A pending uninstall operation was complete.
129 * @param result true if uninstall was successful, false otherwise.
130 */
131 void onUninstallActivityReturned(boolean result);
132
133 /**
134 * Indicates that an uninstall request are made and the actual result may come
135 * after some time.
136 */
137 void deferCompleteDropAfterUninstallActivity();
138 }
139}