diff --git a/src/com/android/settings/SettingsInitialize.java b/src/com/android/settings/SettingsInitialize.java index 9f2bdcc6fcf..0bc892ca5a5 100644 --- a/src/com/android/settings/SettingsInitialize.java +++ b/src/com/android/settings/SettingsInitialize.java @@ -22,11 +22,15 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; +import android.support.annotation.VisibleForTesting; import android.util.Log; +import java.util.ArrayList; import java.util.List; import static android.content.pm.PackageManager.GET_ACTIVITIES; @@ -39,8 +43,8 @@ import com.android.settings.shortcut.CreateShortcut; /** * Listens to {@link Intent.ACTION_PRE_BOOT_COMPLETED} and {@link Intent.ACTION_USER_INITIALIZED} * performs setup steps for a managed profile (disables the launcher icon of the Settings app, - * adds cross-profile intent filters for the appropriate Settings activities), and disables the - * webview setting for non-admin users. + * adds cross-profile intent filters for the appropriate Settings activities), disables the + * webview setting for non-admin users, and updates the intent flags for any existing shortcuts. */ public class SettingsInitialize extends BroadcastReceiver { private static final String TAG = "Settings"; @@ -56,6 +60,7 @@ public class SettingsInitialize extends BroadcastReceiver { final PackageManager pm = context.getPackageManager(); managedProfileSetup(context, pm, broadcast, userInfo); webviewSettingSetup(context, pm, userInfo); + refreshExistingShortcuts(context); } private void managedProfileSetup(Context context, final PackageManager pm, Intent broadcast, @@ -113,4 +118,22 @@ public class SettingsInitialize extends BroadcastReceiver { PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } + + // Refresh settings shortcuts to have correct intent flags + @VisibleForTesting + void refreshExistingShortcuts(Context context) { + final ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class); + final List pinnedShortcuts = shortcutManager.getPinnedShortcuts(); + final List updates = new ArrayList<>(); + for (ShortcutInfo info : pinnedShortcuts) { + final Intent shortcutIntent = info.getIntent(); + shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + final ShortcutInfo updatedInfo = new ShortcutInfo.Builder(context, info.getId()) + .setIntent(shortcutIntent) + .build(); + updates.add(updatedInfo); + } + shortcutManager.updateShortcuts(updates); + } + } diff --git a/tests/robotests/src/com/android/settings/SettingsInitializeTest.java b/tests/robotests/src/com/android/settings/SettingsInitializeTest.java new file mode 100644 index 00000000000..f09723f507f --- /dev/null +++ b/tests/robotests/src/com/android/settings/SettingsInitializeTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ShortcutInfo; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowShortcutManager; +import java.util.ArrayList; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(shadows = {ShadowShortcutManager.class}) +public class SettingsInitializeTest { + + private Context mContext; + private SettingsInitialize mSettingsInitialize; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = RuntimeEnvironment.application; + mSettingsInitialize = new SettingsInitialize(); + } + + @Test + public void refreshExistingShortcuts_shouldUpdateLaunchIntentFlagsForExistingShortcut() { + final String id = "test_shortcut_id"; + final Intent intent = new Intent(Intent.ACTION_DEFAULT); + intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + final ShortcutInfo info = new ShortcutInfo.Builder(mContext, id) + .setShortLabel("test123") + .setIntent(intent) + .build(); + final List shortcuts = new ArrayList<>(); + shortcuts.add(info); + ShadowShortcutManager.get().setPinnedShortcuts(shortcuts); + + mSettingsInitialize.refreshExistingShortcuts(mContext); + + final List updatedShortcuts = + ShadowShortcutManager.get().getLastUpdatedShortcuts(); + assertThat(updatedShortcuts).hasSize(1); + final ShortcutInfo updateInfo = updatedShortcuts.get(0); + assertThat(updateInfo.getId()).isEqualTo(id); + final int flags = updateInfo.getIntent().getFlags(); + // The original flag should be removed + assertThat(flags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED).isEqualTo(0); + // The new flags should be set + assertThat(flags & Intent.FLAG_ACTIVITY_NEW_TASK).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK); + assertThat(flags & Intent.FLAG_ACTIVITY_CLEAR_TOP).isEqualTo( + Intent.FLAG_ACTIVITY_CLEAR_TOP); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowShortcutManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowShortcutManager.java new file mode 100644 index 00000000000..8e24bd77a51 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowShortcutManager.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.testutils.shadow; + +import static org.robolectric.RuntimeEnvironment.application; + +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; +import java.util.List; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; +import org.robolectric.shadow.api.Shadow; + +@Implements(ShortcutManager.class) +public class ShadowShortcutManager extends org.robolectric.shadows.ShadowShortcutManager { + + private List mPinnedShortcuts; + private List mLastUpdatedShortcuts; + + @Resetter + public void reset() { + mPinnedShortcuts = null; + mLastUpdatedShortcuts = null; + } + + public static ShadowShortcutManager get() { + return Shadow.extract(application.getSystemService(ShortcutManager.class)); + } + + @Implementation + public boolean updateShortcuts(List shortcutInfoList) { + mLastUpdatedShortcuts = shortcutInfoList; + return true; + } + + public List getLastUpdatedShortcuts() { + return mLastUpdatedShortcuts; + } + + @Implementation + public List getPinnedShortcuts() { + return mPinnedShortcuts; + } + + public void setPinnedShortcuts(List shortcutInfos) { + mPinnedShortcuts = shortcutInfos; + } +}