1 /*
2  * Copyright (C) 2017 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.annotation.TargetApi;
20 import android.app.Activity;
21 import android.content.ActivityNotFoundException;
22 import android.content.ComponentName;
23 import android.content.Intent;
24 import android.content.IntentSender;
25 import android.content.pm.ActivityInfo;
26 import android.content.pm.LauncherActivityInfo;
27 import android.content.pm.LauncherApps;
28 import android.content.pm.PackageManager;
29 import android.graphics.drawable.Drawable;
30 import android.os.Process;
31 import android.os.UserHandle;
32 import android.util.Log;
33 import android.widget.Toast;
34 
35 import com.android.launcher3.WorkspaceItemInfo;
36 import com.android.launcher3.icons.ComponentWithLabel;
37 import com.android.launcher3.icons.IconCache;
38 import com.android.launcher3.LauncherSettings;
39 import com.android.launcher3.R;
40 
41 /**
42  * Wrapper class for representing a shortcut configure activity.
43  */
44 public abstract class ShortcutConfigActivityInfo implements ComponentWithLabel {
45 
46     private static final String TAG = "SCActivityInfo";
47 
48     private final ComponentName mCn;
49     private final UserHandle mUser;
50 
ShortcutConfigActivityInfo(ComponentName cn, UserHandle user)51     protected ShortcutConfigActivityInfo(ComponentName cn, UserHandle user) {
52         mCn = cn;
53         mUser = user;
54     }
55 
56     @Override
getComponent()57     public ComponentName getComponent() {
58         return mCn;
59     }
60 
61     @Override
getUser()62     public UserHandle getUser() {
63         return mUser;
64     }
65 
getItemType()66     public int getItemType() {
67         return LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
68     }
69 
getFullResIcon(IconCache cache)70     public abstract Drawable getFullResIcon(IconCache cache);
71 
72     /**
73      * Return a WorkspaceItemInfo, if it can be created directly on drop, without requiring any
74      * {@link #startConfigActivity(Activity, int)}.
75      */
createWorkspaceItemInfo()76     public WorkspaceItemInfo createWorkspaceItemInfo() {
77         return null;
78     }
79 
startConfigActivity(Activity activity, int requestCode)80     public boolean startConfigActivity(Activity activity, int requestCode) {
81         Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT)
82                 .setComponent(getComponent());
83         try {
84             activity.startActivityForResult(intent, requestCode);
85             return true;
86         } catch (ActivityNotFoundException e) {
87             Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
88         } catch (SecurityException e) {
89             Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
90             Log.e(TAG, "Launcher does not have the permission to launch " + intent +
91                     ". Make sure to create a MAIN intent-filter for the corresponding activity " +
92                     "or use the exported attribute for this activity.", e);
93         }
94         return false;
95     }
96 
97     /**
98      * Returns true if various properties ({@link #getLabel(PackageManager)},
99      * {@link #getFullResIcon}) can be safely persisted.
100      */
isPersistable()101     public boolean isPersistable() {
102         return true;
103     }
104 
105     static class ShortcutConfigActivityInfoVL extends ShortcutConfigActivityInfo {
106 
107         private final ActivityInfo mInfo;
108 
ShortcutConfigActivityInfoVL(ActivityInfo info)109         public ShortcutConfigActivityInfoVL(ActivityInfo info) {
110             super(new ComponentName(info.packageName, info.name), Process.myUserHandle());
111             mInfo = info;
112         }
113 
114         @Override
getLabel(PackageManager pm)115         public CharSequence getLabel(PackageManager pm) {
116             return mInfo.loadLabel(pm);
117         }
118 
119         @Override
getFullResIcon(IconCache cache)120         public Drawable getFullResIcon(IconCache cache) {
121             return cache.getFullResIcon(mInfo);
122         }
123     }
124 
125     @TargetApi(26)
126     public static class ShortcutConfigActivityInfoVO extends ShortcutConfigActivityInfo {
127 
128         private final LauncherActivityInfo mInfo;
129 
ShortcutConfigActivityInfoVO(LauncherActivityInfo info)130         public ShortcutConfigActivityInfoVO(LauncherActivityInfo info) {
131             super(info.getComponentName(), info.getUser());
132             mInfo = info;
133         }
134 
135         @Override
getLabel(PackageManager pm)136         public CharSequence getLabel(PackageManager pm) {
137             return mInfo.getLabel();
138         }
139 
140         @Override
getFullResIcon(IconCache cache)141         public Drawable getFullResIcon(IconCache cache) {
142             return cache.getFullResIcon(mInfo);
143         }
144 
145         @Override
startConfigActivity(Activity activity, int requestCode)146         public boolean startConfigActivity(Activity activity, int requestCode) {
147             if (getUser().equals(Process.myUserHandle())) {
148                 return super.startConfigActivity(activity, requestCode);
149             }
150             IntentSender is = activity.getSystemService(LauncherApps.class)
151                     .getShortcutConfigActivityIntent(mInfo);
152             try {
153                 activity.startIntentSenderForResult(is, requestCode, null, 0, 0, 0);
154                 return true;
155             } catch (IntentSender.SendIntentException e) {
156                 Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
157                 return false;
158             }
159         }
160     }
161 }
162