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