Loading src/com/android/settings/CreateShortcut.java +77 −14 Original line number Diff line number Diff line Loading @@ -17,15 +17,21 @@ package com.android.settings; import android.app.LauncherActivity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.drawable.Icon; import android.net.ConnectivityManager; import android.os.AsyncTask; import android.support.annotation.VisibleForTesting; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; Loading @@ -35,34 +41,52 @@ import android.widget.ListView; import com.android.settings.Settings.TetherSettingsActivity; import java.util.ArrayList; import java.util.List; public class CreateShortcut extends LauncherActivity { @VisibleForTesting static final String SHORTCUT_ID_PREFIX = "component-shortcut-"; @Override protected Intent getTargetIntent() { Intent targetIntent = new Intent(Intent.ACTION_MAIN, null); targetIntent.addCategory("com.android.settings.SHORTCUT"); targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return targetIntent; return getBaseIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { Intent shortcutIntent = intentForPosition(position); ListItem item = itemForPosition(position); setResult(RESULT_OK, createResultIntent(intentForPosition(position), item.resolveInfo, item.label)); finish(); } protected Intent createResultIntent(Intent shortcutIntent, ResolveInfo resolveInfo, CharSequence label) { shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); Intent intent = new Intent(); ActivityInfo activityInfo = resolveInfo.activityInfo; Bitmap icon = activityInfo.icon != 0 ? createIcon(activityInfo.icon) : null; String shortcutId = SHORTCUT_ID_PREFIX + shortcutIntent.getComponent().flattenToShortString(); ShortcutInfo info = new ShortcutInfo.Builder(this, shortcutId) .setShortLabel(label) .setIntent(shortcutIntent) .setIcon(icon != null ? Icon.createWithBitmap(icon) : Icon.createWithResource(this, R.mipmap.ic_launcher_settings)) .build(); Intent intent = getSystemService(ShortcutManager.class).createShortcutResultIntent(info); if (intent == null) { intent = new Intent(); } intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(this, R.mipmap.ic_launcher_settings)); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, itemForPosition(position).label); ResolveInfo resolveInfo = itemForPosition(position).resolveInfo; ActivityInfo activityInfo = resolveInfo.activityInfo; if (activityInfo.icon != 0) { intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(activityInfo.icon)); } setResult(RESULT_OK, intent); finish(); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label); intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon); return intent; } private Bitmap createIcon(int resource) { Loading Loading @@ -110,4 +134,43 @@ public class CreateShortcut extends LauncherActivity { } return activities; } @VisibleForTesting static Intent getBaseIntent() { return new Intent(Intent.ACTION_MAIN).addCategory("com.android.settings.SHORTCUT"); } public static class ShortcutsUpdateTask extends AsyncTask<Void, Void, Void> { private final Context mContext; public ShortcutsUpdateTask(Context context) { mContext = context; } @Override public Void doInBackground(Void... params) { ShortcutManager sm = mContext.getSystemService(ShortcutManager.class); PackageManager pm = mContext.getPackageManager(); List<ShortcutInfo> updates = new ArrayList<>(); for (ShortcutInfo info : sm.getPinnedShortcuts()) { if (!info.getId().startsWith(SHORTCUT_ID_PREFIX)) { continue; } ComponentName cn = ComponentName.unflattenFromString( info.getId().substring(SHORTCUT_ID_PREFIX.length())); ResolveInfo ri = pm.resolveActivity(getBaseIntent().setComponent(cn), 0); if (ri == null) { continue; } updates.add(new ShortcutInfo.Builder(mContext, info.getId()) .setShortLabel(ri.loadLabel(pm)).build()); } if (!updates.isEmpty()) { sm.updateShortcuts(updates); } return null; } } } src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java +3 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.widget.CompoundButton; import com.android.internal.app.LocalePicker; import com.android.internal.app.LocaleStore; import com.android.settings.CreateShortcut; import com.android.settings.R; import java.text.NumberFormat; Loading Loading @@ -299,6 +300,8 @@ class LocaleDragAndDropAdapter LocalePicker.updateLocales(mLocalesToSetNext); mLocalesSetLast = mLocalesToSetNext; new CreateShortcut.ShortcutsUpdateTask(mContext).execute(); mLocalesToSetNext = null; mNumberFormatter = NumberFormat.getNumberInstance(Locale.getDefault()); Loading tests/app/src/com/android/settings/CreateShortcutTest.java +108 −7 Original line number Diff line number Diff line Loading @@ -16,29 +16,130 @@ package com.android.settings; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Instrumentation; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; import static android.support.test.espresso.matcher.ViewMatchers.withText; import java.util.Arrays; import java.util.List; /** * Tests for {@link CreateShortcutTest} * m SettingsTests && adb install \ -r -g ${ANDROID_PRODUCT_OUT}/data/app/SettingsTests/SettingsTests.apk && adb shell am instrument -e class com.android.settings.CreateShortcutTest \ -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner */ @RunWith(AndroidJUnit4.class) @SmallTest public class CreateShortcutTest { private static final String SHORTCUT_ID_PREFIX = CreateShortcut.SHORTCUT_ID_PREFIX; private Instrumentation mInstrumentation; private Context mContext; @Mock ShortcutManager mShortcutManager; @Captor ArgumentCaptor<List<ShortcutInfo>> mListCaptor; @Before public void setup() { MockitoAnnotations.initMocks(this); mInstrumentation = InstrumentationRegistry.getInstrumentation(); mContext = mInstrumentation.getTargetContext(); } @Test public void test_layoutDoesNotHaveCancelButton() { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); instrumentation.startActivitySync(new Intent(Intent.ACTION_CREATE_SHORTCUT) .setClassName(instrumentation.getTargetContext(), CreateShortcut.class.getName())); mInstrumentation.startActivitySync(new Intent(Intent.ACTION_CREATE_SHORTCUT) .setClassName(mContext, CreateShortcut.class.getName())); onView(withText(R.string.cancel)).check(doesNotExist()); } @Test public void createResultIntent() { CreateShortcut orgActivity = (CreateShortcut) mInstrumentation.startActivitySync( new Intent(Intent.ACTION_CREATE_SHORTCUT) .setClassName(mContext, CreateShortcut.class.getName())); CreateShortcut activity = spy(orgActivity); doReturn(mShortcutManager).when(activity).getSystemService(eq(Context.SHORTCUT_SERVICE)); when(mShortcutManager.createShortcutResultIntent(any(ShortcutInfo.class))) .thenReturn(new Intent().putExtra("d1", "d2")); Intent intent = CreateShortcut.getBaseIntent() .setClass(activity, Settings.ManageApplicationsActivity.class); ResolveInfo ri = activity.getPackageManager().resolveActivity(intent, 0); Intent result = activity.createResultIntent(intent, ri, "dummy"); assertEquals("d2", result.getStringExtra("d1")); assertNotNull(result.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT)); ArgumentCaptor<ShortcutInfo> infoCaptor = ArgumentCaptor.forClass(ShortcutInfo.class); verify(mShortcutManager, times(1)) .createShortcutResultIntent(infoCaptor.capture()); String expectedId = SHORTCUT_ID_PREFIX + intent.getComponent().flattenToShortString(); assertEquals(expectedId, infoCaptor.getValue().getId()); } @Test public void shortcutsUpdateTask() { mContext = spy(new ContextWrapper(mInstrumentation.getTargetContext())); doReturn(mShortcutManager).when(mContext).getSystemService(eq(Context.SHORTCUT_SERVICE)); List<ShortcutInfo> pinnedShortcuts = Arrays.asList( makeShortcut("d1"), makeShortcut("d2"), makeShortcut(Settings.ManageApplicationsActivity.class), makeShortcut("d3"), makeShortcut(Settings.SoundSettingsActivity.class)); when(mShortcutManager.getPinnedShortcuts()).thenReturn(pinnedShortcuts); new CreateShortcut.ShortcutsUpdateTask(mContext).doInBackground(); verify(mShortcutManager, times(1)).updateShortcuts(mListCaptor.capture()); List<ShortcutInfo> updates = mListCaptor.getValue(); assertEquals(2, updates.size()); assertEquals(pinnedShortcuts.get(2).getId(), updates.get(0).getId()); assertEquals(pinnedShortcuts.get(4).getId(), updates.get(1).getId()); } private ShortcutInfo makeShortcut(Class<?> className) { ComponentName cn = new ComponentName(mContext, className); return makeShortcut(SHORTCUT_ID_PREFIX + cn.flattenToShortString()); } private ShortcutInfo makeShortcut(String id) { return new ShortcutInfo.Builder(mContext, id).build(); } } Loading
src/com/android/settings/CreateShortcut.java +77 −14 Original line number Diff line number Diff line Loading @@ -17,15 +17,21 @@ package com.android.settings; import android.app.LauncherActivity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.drawable.Icon; import android.net.ConnectivityManager; import android.os.AsyncTask; import android.support.annotation.VisibleForTesting; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; Loading @@ -35,34 +41,52 @@ import android.widget.ListView; import com.android.settings.Settings.TetherSettingsActivity; import java.util.ArrayList; import java.util.List; public class CreateShortcut extends LauncherActivity { @VisibleForTesting static final String SHORTCUT_ID_PREFIX = "component-shortcut-"; @Override protected Intent getTargetIntent() { Intent targetIntent = new Intent(Intent.ACTION_MAIN, null); targetIntent.addCategory("com.android.settings.SHORTCUT"); targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return targetIntent; return getBaseIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { Intent shortcutIntent = intentForPosition(position); ListItem item = itemForPosition(position); setResult(RESULT_OK, createResultIntent(intentForPosition(position), item.resolveInfo, item.label)); finish(); } protected Intent createResultIntent(Intent shortcutIntent, ResolveInfo resolveInfo, CharSequence label) { shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); Intent intent = new Intent(); ActivityInfo activityInfo = resolveInfo.activityInfo; Bitmap icon = activityInfo.icon != 0 ? createIcon(activityInfo.icon) : null; String shortcutId = SHORTCUT_ID_PREFIX + shortcutIntent.getComponent().flattenToShortString(); ShortcutInfo info = new ShortcutInfo.Builder(this, shortcutId) .setShortLabel(label) .setIntent(shortcutIntent) .setIcon(icon != null ? Icon.createWithBitmap(icon) : Icon.createWithResource(this, R.mipmap.ic_launcher_settings)) .build(); Intent intent = getSystemService(ShortcutManager.class).createShortcutResultIntent(info); if (intent == null) { intent = new Intent(); } intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(this, R.mipmap.ic_launcher_settings)); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, itemForPosition(position).label); ResolveInfo resolveInfo = itemForPosition(position).resolveInfo; ActivityInfo activityInfo = resolveInfo.activityInfo; if (activityInfo.icon != 0) { intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(activityInfo.icon)); } setResult(RESULT_OK, intent); finish(); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label); intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon); return intent; } private Bitmap createIcon(int resource) { Loading Loading @@ -110,4 +134,43 @@ public class CreateShortcut extends LauncherActivity { } return activities; } @VisibleForTesting static Intent getBaseIntent() { return new Intent(Intent.ACTION_MAIN).addCategory("com.android.settings.SHORTCUT"); } public static class ShortcutsUpdateTask extends AsyncTask<Void, Void, Void> { private final Context mContext; public ShortcutsUpdateTask(Context context) { mContext = context; } @Override public Void doInBackground(Void... params) { ShortcutManager sm = mContext.getSystemService(ShortcutManager.class); PackageManager pm = mContext.getPackageManager(); List<ShortcutInfo> updates = new ArrayList<>(); for (ShortcutInfo info : sm.getPinnedShortcuts()) { if (!info.getId().startsWith(SHORTCUT_ID_PREFIX)) { continue; } ComponentName cn = ComponentName.unflattenFromString( info.getId().substring(SHORTCUT_ID_PREFIX.length())); ResolveInfo ri = pm.resolveActivity(getBaseIntent().setComponent(cn), 0); if (ri == null) { continue; } updates.add(new ShortcutInfo.Builder(mContext, info.getId()) .setShortLabel(ri.loadLabel(pm)).build()); } if (!updates.isEmpty()) { sm.updateShortcuts(updates); } return null; } } }
src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java +3 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.widget.CompoundButton; import com.android.internal.app.LocalePicker; import com.android.internal.app.LocaleStore; import com.android.settings.CreateShortcut; import com.android.settings.R; import java.text.NumberFormat; Loading Loading @@ -299,6 +300,8 @@ class LocaleDragAndDropAdapter LocalePicker.updateLocales(mLocalesToSetNext); mLocalesSetLast = mLocalesToSetNext; new CreateShortcut.ShortcutsUpdateTask(mContext).execute(); mLocalesToSetNext = null; mNumberFormatter = NumberFormat.getNumberInstance(Locale.getDefault()); Loading
tests/app/src/com/android/settings/CreateShortcutTest.java +108 −7 Original line number Diff line number Diff line Loading @@ -16,29 +16,130 @@ package com.android.settings; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Instrumentation; import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; import static android.support.test.espresso.matcher.ViewMatchers.withText; import java.util.Arrays; import java.util.List; /** * Tests for {@link CreateShortcutTest} * m SettingsTests && adb install \ -r -g ${ANDROID_PRODUCT_OUT}/data/app/SettingsTests/SettingsTests.apk && adb shell am instrument -e class com.android.settings.CreateShortcutTest \ -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner */ @RunWith(AndroidJUnit4.class) @SmallTest public class CreateShortcutTest { private static final String SHORTCUT_ID_PREFIX = CreateShortcut.SHORTCUT_ID_PREFIX; private Instrumentation mInstrumentation; private Context mContext; @Mock ShortcutManager mShortcutManager; @Captor ArgumentCaptor<List<ShortcutInfo>> mListCaptor; @Before public void setup() { MockitoAnnotations.initMocks(this); mInstrumentation = InstrumentationRegistry.getInstrumentation(); mContext = mInstrumentation.getTargetContext(); } @Test public void test_layoutDoesNotHaveCancelButton() { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); instrumentation.startActivitySync(new Intent(Intent.ACTION_CREATE_SHORTCUT) .setClassName(instrumentation.getTargetContext(), CreateShortcut.class.getName())); mInstrumentation.startActivitySync(new Intent(Intent.ACTION_CREATE_SHORTCUT) .setClassName(mContext, CreateShortcut.class.getName())); onView(withText(R.string.cancel)).check(doesNotExist()); } @Test public void createResultIntent() { CreateShortcut orgActivity = (CreateShortcut) mInstrumentation.startActivitySync( new Intent(Intent.ACTION_CREATE_SHORTCUT) .setClassName(mContext, CreateShortcut.class.getName())); CreateShortcut activity = spy(orgActivity); doReturn(mShortcutManager).when(activity).getSystemService(eq(Context.SHORTCUT_SERVICE)); when(mShortcutManager.createShortcutResultIntent(any(ShortcutInfo.class))) .thenReturn(new Intent().putExtra("d1", "d2")); Intent intent = CreateShortcut.getBaseIntent() .setClass(activity, Settings.ManageApplicationsActivity.class); ResolveInfo ri = activity.getPackageManager().resolveActivity(intent, 0); Intent result = activity.createResultIntent(intent, ri, "dummy"); assertEquals("d2", result.getStringExtra("d1")); assertNotNull(result.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT)); ArgumentCaptor<ShortcutInfo> infoCaptor = ArgumentCaptor.forClass(ShortcutInfo.class); verify(mShortcutManager, times(1)) .createShortcutResultIntent(infoCaptor.capture()); String expectedId = SHORTCUT_ID_PREFIX + intent.getComponent().flattenToShortString(); assertEquals(expectedId, infoCaptor.getValue().getId()); } @Test public void shortcutsUpdateTask() { mContext = spy(new ContextWrapper(mInstrumentation.getTargetContext())); doReturn(mShortcutManager).when(mContext).getSystemService(eq(Context.SHORTCUT_SERVICE)); List<ShortcutInfo> pinnedShortcuts = Arrays.asList( makeShortcut("d1"), makeShortcut("d2"), makeShortcut(Settings.ManageApplicationsActivity.class), makeShortcut("d3"), makeShortcut(Settings.SoundSettingsActivity.class)); when(mShortcutManager.getPinnedShortcuts()).thenReturn(pinnedShortcuts); new CreateShortcut.ShortcutsUpdateTask(mContext).doInBackground(); verify(mShortcutManager, times(1)).updateShortcuts(mListCaptor.capture()); List<ShortcutInfo> updates = mListCaptor.getValue(); assertEquals(2, updates.size()); assertEquals(pinnedShortcuts.get(2).getId(), updates.get(0).getId()); assertEquals(pinnedShortcuts.get(4).getId(), updates.get(1).getId()); } private ShortcutInfo makeShortcut(Class<?> className) { ComponentName cn = new ComponentName(mContext, className); return makeShortcut(SHORTCUT_ID_PREFIX + cn.flattenToShortString()); } private ShortcutInfo makeShortcut(String id) { return new ShortcutInfo.Builder(mContext, id).build(); } }