diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index af6df32a02b04..fbe7175b757f3 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -591,4 +591,12 @@
true
+
+
+ false
+
+
+ false
diff --git a/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java b/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java
index dd3d02a86672a..31e49390b9b8a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java
@@ -16,38 +16,64 @@
package com.android.systemui.media.systemsounds;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.media.AudioManager;
+import android.util.Slog;
+import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import javax.inject.Inject;
/**
- * If a sound effect is defined for {@link android.media.AudioManager#FX_HOME}, a sound is played
- * when the home task moves to front and the last task that moved to front was not the home task.
+ * If a sound effect is defined for {@link android.media.AudioManager#FX_HOME}, a
+ * {@link TaskStackChangeListener} is registered to play a home sound effect when conditions
+ * documented at {@link #handleTaskStackChanged} apply.
*/
@SysUISingleton
public class HomeSoundEffectController extends SystemUI {
+ private static final String TAG = "HomeSoundEffectController";
private final AudioManager mAudioManager;
private final TaskStackChangeListeners mTaskStackChangeListeners;
+ private final ActivityManagerWrapper mActivityManagerWrapper;
+ private final PackageManager mPm;
+ private final boolean mPlayHomeSoundAfterAssistant;
+ private final boolean mPlayHomeSoundAfterDream;
// Initialize true because home sound should not be played when the system boots.
private boolean mIsLastTaskHome = true;
+ // mLastHomePackageName could go out of sync in rare circumstances if launcher changes,
+ // but it's cheaper than the alternative and potential impact is low
+ private String mLastHomePackageName;
+ private @WindowConfiguration.ActivityType int mLastActivityType;
+ private boolean mLastActivityHasNoHomeSound = false;
+ private int mLastTaskId;
@Inject
public HomeSoundEffectController(
Context context,
AudioManager audioManager,
- TaskStackChangeListeners taskStackChangeListeners) {
+ TaskStackChangeListeners taskStackChangeListeners,
+ ActivityManagerWrapper activityManagerWrapper,
+ PackageManager packageManager) {
super(context);
mAudioManager = audioManager;
mTaskStackChangeListeners = taskStackChangeListeners;
+ mActivityManagerWrapper = activityManagerWrapper;
+ mPm = packageManager;
+ mPlayHomeSoundAfterAssistant = context.getResources().getBoolean(
+ R.bool.config_playHomeSoundAfterAssistant);
+ mPlayHomeSoundAfterDream = context.getResources().getBoolean(
+ R.bool.config_playHomeSoundAfterDream);
}
@Override
@@ -56,27 +82,94 @@ public class HomeSoundEffectController extends SystemUI {
mTaskStackChangeListeners.registerTaskStackListener(
new TaskStackChangeListener() {
@Override
- public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
- handleHomeTaskMovedToFront(taskInfo);
+ public void onTaskStackChanged() {
+ ActivityManager.RunningTaskInfo currentTask =
+ mActivityManagerWrapper.getRunningTask();
+ if (currentTask == null || currentTask.topActivityInfo == null) {
+ return;
+ }
+ handleTaskStackChanged(currentTask);
}
});
}
}
- private boolean isHomeTask(ActivityManager.RunningTaskInfo taskInfo) {
- return taskInfo.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_HOME;
+ private boolean hasFlagNoSound(ActivityInfo activityInfo) {
+ if ((activityInfo.privateFlags & ActivityInfo.PRIVATE_FLAG_HOME_TRANSITION_SOUND) == 0) {
+ // Only allow flag if app has permission
+ if (mPm.checkPermission(Manifest.permission.DISABLE_SYSTEM_SOUND_EFFECTS,
+ activityInfo.packageName) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ } else {
+ Slog.w(TAG,
+ "Activity has flag playHomeTransition set to false but doesn't hold "
+ + "required permission "
+ + Manifest.permission.DISABLE_SYSTEM_SOUND_EFFECTS);
+ return false;
+ }
+ }
+ return false;
}
/**
- * To enable a home sound, check if the home app moves to front.
+ * The home sound is played if all of the following conditions are met:
+ *
+ * - The last task which moved to front was not home. This avoids playing the sound
+ * e.g. after FallbackHome transitions to home, another activity of the home app like a
+ * notification panel moved to front, or in case the home app crashed.
+ * - The current activity which moved to front is home
+ * - The topActivity of the last task has {@link android.R.attr#playHomeTransitionSound} set
+ * to
true.
+ * - The topActivity of the last task is not of type
+ * {@link WindowConfiguration#ACTIVITY_TYPE_ASSISTANT} if config_playHomeSoundAfterAssistant is
+ * set to
false (default).
+ * - The topActivity of the last task is not of type
+ * {@link WindowConfiguration#ACTIVITY_TYPE_DREAM} if config_playHomeSoundAfterDream is
+ * set to
false (default).
+ *
*/
- private void handleHomeTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
- boolean isCurrentTaskHome = isHomeTask(taskInfo);
- // If the last task is home we don't want to play the home sound. This avoids playing
- // the home sound after FallbackHome transitions to Home
- if (!mIsLastTaskHome && isCurrentTaskHome) {
+ private boolean shouldPlayHomeSoundForCurrentTransition(
+ ActivityManager.RunningTaskInfo currentTask) {
+ boolean isHomeActivity =
+ currentTask.topActivityType == WindowConfiguration.ACTIVITY_TYPE_HOME;
+ if (currentTask.taskId == mLastTaskId) {
+ return false;
+ }
+ if (mIsLastTaskHome || !isHomeActivity) {
+ return false;
+ }
+ if (mLastActivityHasNoHomeSound) {
+ return false;
+ }
+ if (mLastActivityType == WindowConfiguration.ACTIVITY_TYPE_ASSISTANT
+ && !mPlayHomeSoundAfterAssistant) {
+ return false;
+ }
+ if (mLastActivityType == WindowConfiguration.ACTIVITY_TYPE_DREAM
+ && !mPlayHomeSoundAfterDream) {
+ return false;
+ }
+ return true;
+ }
+
+ private void updateLastTaskInfo(ActivityManager.RunningTaskInfo currentTask) {
+ mLastTaskId = currentTask.taskId;
+ mLastActivityType = currentTask.topActivityType;
+ mLastActivityHasNoHomeSound = hasFlagNoSound(currentTask.topActivityInfo);
+ boolean isHomeActivity =
+ currentTask.topActivityType == WindowConfiguration.ACTIVITY_TYPE_HOME;
+ boolean isHomePackage = currentTask.topActivityInfo.packageName.equals(
+ mLastHomePackageName);
+ mIsLastTaskHome = isHomeActivity || isHomePackage;
+ if (isHomeActivity && !isHomePackage) {
+ mLastHomePackageName = currentTask.topActivityInfo.packageName;
+ }
+ }
+
+ private void handleTaskStackChanged(ActivityManager.RunningTaskInfo frontTask) {
+ if (shouldPlayHomeSoundForCurrentTransition(frontTask)) {
mAudioManager.playSoundEffect(AudioManager.FX_HOME);
}
- mIsLastTaskHome = isCurrentTaskHome;
+ updateLastTaskInfo(frontTask);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
index 3a77f7eec7f91..33a30e0bcc277 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
@@ -21,16 +21,20 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
-import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.media.AudioManager;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -41,30 +45,50 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class HomeSoundEffectControllerTest extends SysuiTestCase {
- private @Mock Context mContext;
+ private static final String HOME_PACKAGE_NAME = "com.android.apps.home";
+ private static final String NON_HOME_PACKAGE_NAME = "com.android.apps.not.home";
+ private static final int HOME_TASK_ID = 0;
+ private static final int NON_HOME_TASK_ID = 1;
+
private @Mock AudioManager mAudioManager;
private @Mock TaskStackChangeListeners mTaskStackChangeListeners;
- private @Mock ActivityManager.RunningTaskInfo mStandardActivityTaskInfo;
- private @Mock ActivityManager.RunningTaskInfo mHomeActivityTaskInfo;
+ private @Mock ActivityManagerWrapper mActivityManagerWrapper;
+ private @Mock PackageManager mPackageManager;
+ private ActivityManager.RunningTaskInfo mTaskAStandardActivity;
+ private ActivityManager.RunningTaskInfo mTaskAExceptionActivity;
+ private ActivityManager.RunningTaskInfo mHomeTaskHomeActivity;
+ private ActivityManager.RunningTaskInfo mHomeTaskStandardActivity;
+ private ActivityManager.RunningTaskInfo mEmptyTask;
private HomeSoundEffectController mController;
private TaskStackChangeListener mTaskStackChangeListener;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
-
- doReturn(WindowConfiguration.ACTIVITY_TYPE_STANDARD).when(
- mStandardActivityTaskInfo).getActivityType();
- doReturn(WindowConfiguration.ACTIVITY_TYPE_HOME).when(
- mHomeActivityTaskInfo).getActivityType();
-
+ mTaskAStandardActivity = createRunningTaskInfo(NON_HOME_PACKAGE_NAME,
+ WindowConfiguration.ACTIVITY_TYPE_STANDARD, NON_HOME_TASK_ID,
+ true /* playHomeTransitionSound */);
+ mTaskAExceptionActivity = createRunningTaskInfo(NON_HOME_PACKAGE_NAME,
+ WindowConfiguration.ACTIVITY_TYPE_STANDARD, NON_HOME_TASK_ID,
+ false /* playHomeTransitionSound */);
+ mHomeTaskHomeActivity = createRunningTaskInfo(HOME_PACKAGE_NAME,
+ WindowConfiguration.ACTIVITY_TYPE_HOME, HOME_TASK_ID,
+ true /* playHomeTransitionSound */);
+ mHomeTaskStandardActivity = createRunningTaskInfo(HOME_PACKAGE_NAME,
+ WindowConfiguration.ACTIVITY_TYPE_STANDARD, HOME_TASK_ID,
+ true /* playHomeTransitionSound */);
+ mEmptyTask = new ActivityManager.RunningTaskInfo();
+ mContext.setMockPackageManager(mPackageManager);
+ when(mPackageManager.checkPermission(Manifest.permission.DISABLE_SYSTEM_SOUND_EFFECTS,
+ NON_HOME_PACKAGE_NAME)).thenReturn(PackageManager.PERMISSION_GRANTED);
mController = new HomeSoundEffectController(mContext, mAudioManager,
- mTaskStackChangeListeners);
+ mTaskStackChangeListeners, mActivityManagerWrapper, mPackageManager);
}
@Test
@@ -73,43 +97,60 @@ public class HomeSoundEffectControllerTest extends SysuiTestCase {
startController(true /* isHomeSoundEffectEnabled */);
// And the home task moves to the front,
- mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(mHomeTaskHomeActivity);
+ mTaskStackChangeListener.onTaskStackChanged();
// Then no home sound effect should be played.
verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
}
+ /**
+ * Task A (playHomeTransitionSound = true) -> HOME
+ * Expectation: Home sound is played
+ */
@Test
public void testHomeSoundEffectPlayedWhenEnabled() {
// When HomeSoundEffectController is started and the home sound effect is enabled,
startController(true /* isHomeSoundEffectEnabled */);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAStandardActivity,
+ mHomeTaskHomeActivity);
// And first a task different from the home task moves to front,
- mTaskStackChangeListener.onTaskMovedToFront(mStandardActivityTaskInfo);
+ mTaskStackChangeListener.onTaskStackChanged();
// And the home task moves to the front,
- mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
+ mTaskStackChangeListener.onTaskStackChanged();
// Then the home sound effect should be played.
verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
}
+ /**
+ * Task A (playHomeTransitionSound = true) -> HOME -> HOME
+ * Expectation: Home sound is played once after HOME moves to front the first time
+ */
@Test
public void testHomeSoundEffectNotPlayedTwiceInRow() {
// When HomeSoundEffectController is started and the home sound effect is enabled,
startController(true /* isHomeSoundEffectEnabled */);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAStandardActivity,
+ mHomeTaskHomeActivity,
+ mHomeTaskHomeActivity);
+
// And first a task different from the home task moves to front,
- mTaskStackChangeListener.onTaskMovedToFront(mStandardActivityTaskInfo);
+ mTaskStackChangeListener.onTaskStackChanged();
// And the home task moves to the front,
- mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
+ mTaskStackChangeListener.onTaskStackChanged();
// Then the home sound effect should be played.
verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
// If the home task moves to front a second time in a row,
- mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
+ mTaskStackChangeListener.onTaskStackChanged();
// Then no home sound effect should be played.
verify(mAudioManager, times(1)).playSoundEffect(AudioManager.FX_HOME);
@@ -121,7 +162,59 @@ public class HomeSoundEffectControllerTest extends SysuiTestCase {
startController(true /* isHomeSoundEffectEnabled */);
// And a standard, non-home task, moves to the front,
- mTaskStackChangeListener.onTaskMovedToFront(mStandardActivityTaskInfo);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(mTaskAStandardActivity);
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then no home sound effect should be played.
+ verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ /**
+ * Task A (playHomeTransitionSound = true) -> HOME -> HOME (activity type standard)
+ * Expectation: Home sound is played once after HOME moves to front
+ */
+ @Test
+ public void testHomeSoundEffectNotPlayedWhenOtherHomeActivityMovesToFront() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAStandardActivity,
+ mHomeTaskHomeActivity,
+ mHomeTaskStandardActivity);
+
+ // And first a task different from the home task moves to front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then the home sound effect should be played.
+ verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
+
+ // If the home task moves to front a second time in a row,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then no home sound effect should be played.
+ verify(mAudioManager, times(1)).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ /**
+ * Task A (playHomeTransitionSound = true) -> HOME (activity type standard)
+ * Expectation: Home sound is not played
+ */
+ @Test
+ public void testHomeSoundEffectNotPlayedWhenOtherHomeActivityMovesToFrontOfOtherApp() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+
+ // And first a task different from the home task moves to front,
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAStandardActivity,
+ mHomeTaskStandardActivity);
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // And an activity from the home package but not the home root activity moves to front
+ mTaskStackChangeListener.onTaskStackChanged();
// Then no home sound effect should be played.
verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
@@ -137,6 +230,171 @@ public class HomeSoundEffectControllerTest extends SysuiTestCase {
any(TaskStackChangeListener.class));
}
+ /**
+ * Task A (playHomeTransitionSound = false) -> HOME
+ * Expectation: Home sound is not played
+ */
+ @Test
+ public void testHomeSoundEffectNotPlayedWhenHomeActivityMovesToFrontAfterException() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+
+ // And first a task different from the home task moves to front, which has
+ // {@link ActivityInfo#PRIVATE_FLAG_HOME_TRANSITION_SOUND} set to false
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAExceptionActivity,
+ mHomeTaskHomeActivity);
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then no home sound effect should be played because the last package is an exception.
+ verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ /**
+ * HOME -> Task A (playHomeTransitionSound = true) -> Task A (playHomeTransitionSound = false)
+ * -> HOME
+ * Expectation: Home sound is not played
+ */
+ @Test
+ public void testHomeSoundEffectNotPlayedWhenHomeActivityMovesToFrontAfterException2() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAStandardActivity,
+ mTaskAExceptionActivity,
+ mHomeTaskHomeActivity);
+
+ // And first a task different from the home task moves to front
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then a different activity from the same task moves to front, which has
+ // {@link ActivityInfo#PRIVATE_FLAG_HOME_TRANSITION_SOUND} set to false
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then no home sound effect should be played.
+ verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ /**
+ * HOME -> Task A (playHomeTransitionSound = false) -> Task A (playHomeTransitionSound = true)
+ * -> HOME
+ * Expectation: Home sound is played
+ */
+ @Test
+ public void testHomeSoundEffectPlayedWhenHomeActivityMovesToFrontAfterException() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAExceptionActivity,
+ mTaskAStandardActivity,
+ mHomeTaskHomeActivity);
+
+ // And first a task different from the home task moves to front,
+ // the topActivity of this task has {@link ActivityInfo#PRIVATE_FLAG_HOME_TRANSITION_SOUND}
+ // set to false
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then a different activity from the same task moves to front, which has
+ // {@link ActivityInfo#PRIVATE_FLAG_HOME_TRANSITION_SOUND} set to true
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then the home sound effect should be played.
+ verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ /**
+ * HOME -> Task A (playHomeTransitionSound = false) -> Task A (empty task, no top activity)
+ * -> HOME
+ * Expectation: Home sound is not played
+ */
+ @Test
+ public void testHomeSoundEffectNotPlayedWhenEmptyTaskMovesToFrontAfterException() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAExceptionActivity,
+ mEmptyTask,
+ mHomeTaskHomeActivity);
+
+ // And first a task different from the home task moves to front, whose topActivity has
+ // {@link ActivityInfo#PRIVATE_FLAG_HOME_TRANSITION_SOUND} set to false
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then a task with no topActivity moves to front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then no home sound effect should be played.
+ verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ /**
+ * HOME -> Task A (playHomeTransitionSound = true) -> Task A (empty task, no top activity)
+ * -> HOME
+ * Expectation: Home sound is played
+ */
+ @Test
+ public void testHomeSoundEffectPlayedWhenEmptyTaskMovesToFrontAfterStandardActivity() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAStandardActivity,
+ mEmptyTask,
+ mHomeTaskHomeActivity);
+
+ // And first a task different from the home task moves to front, whose topActivity has
+ // {@link ActivityInfo#PRIVATE_FLAG_HOME_TRANSITION_SOUND} set to false
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then a task with no topActivity moves to front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then the home sound effect should be played.
+ verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
+ }
+
+ /**
+ * HOME -> Task A (playHomeTransitionSound = false, no permission) -> HOME
+ * Expectation: Home sound is played
+ */
+ @Test
+ public void testHomeSoundEffectPlayedWhenFlagSetButPermissionNotGranted() {
+ // When HomeSoundEffectController is started and the home sound effect is enabled,
+ startController(true /* isHomeSoundEffectEnabled */);
+ when(mActivityManagerWrapper.getRunningTask()).thenReturn(
+ mTaskAStandardActivity,
+ mHomeTaskHomeActivity);
+ when(mPackageManager.checkPermission(Manifest.permission.DISABLE_SYSTEM_SOUND_EFFECTS,
+ NON_HOME_PACKAGE_NAME)).thenReturn(PackageManager.PERMISSION_DENIED);
+
+ // And first a task different from the home task moves to front, whose topActivity has
+ // {@link ActivityInfo#PRIVATE_FLAG_HOME_TRANSITION_SOUND} set to true,
+ // but the app doesn't have the right permission granted
+ mTaskStackChangeListener.onTaskStackChanged();
+
+
+ // And the home task moves to the front,
+ mTaskStackChangeListener.onTaskStackChanged();
+
+ // Then the home sound effect should be played.
+ verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
+ }
+
/**
* Sets {@link AudioManager#isHomeSoundEffectEnabled()} and starts HomeSoundEffectController.
* If the home sound effect is enabled, the registered TaskStackChangeListener is extracted.
@@ -155,4 +413,20 @@ public class HomeSoundEffectControllerTest extends SysuiTestCase {
mTaskStackChangeListener = listenerCaptor.getValue();
}
}
+
+ private ActivityManager.RunningTaskInfo createRunningTaskInfo(String packageName,
+ int activityType, int taskId, boolean playHomeTransitionSound) {
+ ActivityManager.RunningTaskInfo res = new ActivityManager.RunningTaskInfo();
+ res.topActivityInfo = new ActivityInfo();
+ res.topActivityInfo.packageName = packageName;
+ res.topActivityType = activityType;
+ res.taskId = taskId;
+ if (!playHomeTransitionSound) {
+ // set the flag to 0
+ res.topActivityInfo.privateFlags &= ~ActivityInfo.PRIVATE_FLAG_HOME_TRANSITION_SOUND;
+ } else {
+ res.topActivityInfo.privateFlags |= ActivityInfo.PRIVATE_FLAG_HOME_TRANSITION_SOUND;
+ }
+ return res;
+ }
}