1/* 2 * Copyright (C) 2010 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 17package com.android.settings.shortcut; 18 19import android.app.LauncherActivity; 20import android.content.ComponentName; 21import android.content.Context; 22import android.content.Intent; 23import android.content.pm.ActivityInfo; 24import android.content.pm.PackageManager; 25import android.content.pm.ResolveInfo; 26import android.content.pm.ShortcutInfo; 27import android.content.pm.ShortcutManager; 28import android.graphics.Bitmap; 29import android.graphics.Bitmap.Config; 30import android.graphics.Canvas; 31import android.graphics.drawable.Drawable; 32import android.graphics.drawable.Icon; 33import android.graphics.drawable.LayerDrawable; 34import android.net.ConnectivityManager; 35import android.os.AsyncTask; 36import android.support.annotation.VisibleForTesting; 37import android.view.ContextThemeWrapper; 38import android.view.LayoutInflater; 39import android.view.View; 40import android.view.View.MeasureSpec; 41import android.widget.ImageView; 42import android.widget.ListView; 43 44import com.android.internal.logging.nano.MetricsProto; 45import com.android.settings.R; 46import com.android.settings.Settings.TetherSettingsActivity; 47import com.android.settings.overlay.FeatureFactory; 48 49import java.util.ArrayList; 50import java.util.List; 51 52public class CreateShortcut extends LauncherActivity { 53 54 @VisibleForTesting 55 static final String SHORTCUT_ID_PREFIX = "component-shortcut-"; 56 57 @Override 58 protected Intent getTargetIntent() { 59 return getBaseIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 60 } 61 62 @Override 63 protected void onListItemClick(ListView l, View v, int position, long id) { 64 final ListItem item = itemForPosition(position); 65 logCreateShortcut(item.resolveInfo); 66 setResult(RESULT_OK, createResultIntent(intentForPosition(position), 67 item.resolveInfo, item.label)); 68 finish(); 69 } 70 71 @VisibleForTesting 72 Intent createResultIntent(Intent shortcutIntent, ResolveInfo resolveInfo, 73 CharSequence label) { 74 shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 75 ShortcutManager sm = getSystemService(ShortcutManager.class); 76 ActivityInfo activityInfo = resolveInfo.activityInfo; 77 78 Icon maskableIcon = activityInfo.icon != 0 ? Icon.createWithAdaptiveBitmap( 79 createIcon(activityInfo.icon, 80 R.layout.shortcut_badge_maskable, 81 getResources().getDimensionPixelSize(R.dimen.shortcut_size_maskable))) : 82 Icon.createWithResource(this, R.drawable.ic_launcher_settings); 83 String shortcutId = SHORTCUT_ID_PREFIX + 84 shortcutIntent.getComponent().flattenToShortString(); 85 ShortcutInfo info = new ShortcutInfo.Builder(this, shortcutId) 86 .setShortLabel(label) 87 .setIntent(shortcutIntent) 88 .setIcon(maskableIcon) 89 .build(); 90 Intent intent = sm.createShortcutResultIntent(info); 91 if (intent == null) { 92 intent = new Intent(); 93 } 94 intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, 95 Intent.ShortcutIconResource.fromContext(this, R.mipmap.ic_launcher_settings)); 96 intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); 97 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label); 98 99 if (activityInfo.icon != 0) { 100 intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(activityInfo.icon, 101 R.layout.shortcut_badge, 102 getResources().getDimensionPixelSize(R.dimen.shortcut_size))); 103 } 104 return intent; 105 } 106 107 private void logCreateShortcut(ResolveInfo info) { 108 if (info == null || info.activityInfo == null) { 109 return; 110 } 111 FeatureFactory.getFactory(this).getMetricsFeatureProvider().action( 112 this, MetricsProto.MetricsEvent.ACTION_SETTINGS_CREATE_SHORTCUT, 113 info.activityInfo.name); 114 } 115 116 private Bitmap createIcon(int resource, int layoutRes, int size) { 117 Context context = new ContextThemeWrapper(this, android.R.style.Theme_Material); 118 View view = LayoutInflater.from(context).inflate(layoutRes, null); 119 Drawable iconDrawable = getDrawable(resource); 120 if (iconDrawable instanceof LayerDrawable) { 121 iconDrawable = ((LayerDrawable) iconDrawable).getDrawable(1); 122 } 123 ((ImageView) view.findViewById(android.R.id.icon)).setImageDrawable(iconDrawable); 124 125 int spec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); 126 view.measure(spec, spec); 127 Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), 128 Config.ARGB_8888); 129 Canvas canvas = new Canvas(bitmap); 130 view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); 131 view.draw(canvas); 132 return bitmap; 133 } 134 135 @Override 136 protected boolean onEvaluateShowIcons() { 137 return false; 138 } 139 140 @Override 141 protected void onSetContentView() { 142 setContentView(R.layout.activity_list); 143 } 144 145 /** 146 * Perform query on package manager for list items. The default 147 * implementation queries for activities. 148 */ 149 protected List<ResolveInfo> onQueryPackageManager(Intent queryIntent) { 150 List<ResolveInfo> activities = getPackageManager().queryIntentActivities(queryIntent, 151 PackageManager.GET_META_DATA); 152 final ConnectivityManager cm = 153 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 154 if (activities == null) return null; 155 for (int i = activities.size() - 1; i >= 0; i--) { 156 ResolveInfo info = activities.get(i); 157 if (info.activityInfo.name.endsWith(TetherSettingsActivity.class.getSimpleName())) { 158 if (!cm.isTetheringSupported()) { 159 activities.remove(i); 160 } 161 } 162 } 163 return activities; 164 } 165 166 @VisibleForTesting 167 static Intent getBaseIntent() { 168 return new Intent(Intent.ACTION_MAIN).addCategory("com.android.settings.SHORTCUT"); 169 } 170 171 public static class ShortcutsUpdateTask extends AsyncTask<Void, Void, Void> { 172 173 private final Context mContext; 174 175 public ShortcutsUpdateTask(Context context) { 176 mContext = context; 177 } 178 179 @Override 180 public Void doInBackground(Void... params) { 181 ShortcutManager sm = mContext.getSystemService(ShortcutManager.class); 182 PackageManager pm = mContext.getPackageManager(); 183 184 List<ShortcutInfo> updates = new ArrayList<>(); 185 for (ShortcutInfo info : sm.getPinnedShortcuts()) { 186 if (!info.getId().startsWith(SHORTCUT_ID_PREFIX)) { 187 continue; 188 } 189 ComponentName cn = ComponentName.unflattenFromString( 190 info.getId().substring(SHORTCUT_ID_PREFIX.length())); 191 ResolveInfo ri = pm.resolveActivity(getBaseIntent().setComponent(cn), 0); 192 if (ri == null) { 193 continue; 194 } 195 updates.add(new ShortcutInfo.Builder(mContext, info.getId()) 196 .setShortLabel(ri.loadLabel(pm)).build()); 197 } 198 if (!updates.isEmpty()) { 199 sm.updateShortcuts(updates); 200 } 201 return null; 202 } 203 } 204} 205