Merge changes from topic "home_sound_exceptions" into sc-dev

* changes:
  Check if package matches home package and allow exceptions.
  Define private manifest flag for home sound exception and add permission
This commit is contained in:
Philip Junker
2021-03-24 16:11:32 +00:00
committed by Android (Google) Code Review
9 changed files with 439 additions and 34 deletions

View File

@@ -92,6 +92,7 @@ package android {
field public static final String CREATE_USERS = "android.permission.CREATE_USERS";
field public static final String CRYPT_KEEPER = "android.permission.CRYPT_KEEPER";
field public static final String DEVICE_POWER = "android.permission.DEVICE_POWER";
field public static final String DISABLE_SYSTEM_SOUND_EFFECTS = "android.permission.DISABLE_SYSTEM_SOUND_EFFECTS";
field public static final String DISPATCH_PROVISIONING_MESSAGE = "android.permission.DISPATCH_PROVISIONING_MESSAGE";
field public static final String DOMAIN_VERIFICATION_AGENT = "android.permission.DOMAIN_VERIFICATION_AGENT";
field public static final String ENTER_CAR_MODE_PRIORITIZED = "android.permission.ENTER_CAR_MODE_PRIORITIZED";
@@ -311,6 +312,7 @@ package android {
field public static final int hotwordDetectionService = 16844326; // 0x1010626
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int minExtensionVersion = 16844305; // 0x1010611
field public static final int playHomeTransitionSound = 16844358; // 0x1010646
field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
field public static final int sdkVersion = 16844304; // 0x1010610

View File

@@ -549,10 +549,19 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
*/
public static final int FLAG_INHERIT_SHOW_WHEN_LOCKED = 0x1;
/**
* Bit in {@link #privateFlags} indicating whether a home sound effect should be played if the
* home app moves to front after the activity with this flag set.
* Set from the {@link android.R.attr#playHomeTransitionSound} attribute.
* @hide
*/
public static final int PRIVATE_FLAG_HOME_TRANSITION_SOUND = 0x2;
/**
* Options that have been set in the activity declaration in the manifest.
* These include:
* {@link #FLAG_INHERIT_SHOW_WHEN_LOCKED}.
* {@link #FLAG_INHERIT_SHOW_WHEN_LOCKED},
* {@link #PRIVATE_FLAG_HOME_TRANSITION_SOUND}.
* @hide
*/
public int privateFlags;

View File

@@ -149,7 +149,10 @@ public class ParsedActivityUtils {
| flag(ActivityInfo.FLAG_TURN_SCREEN_ON, R.styleable.AndroidManifestActivity_turnScreenOn, sa)
| flag(ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING, R.styleable.AndroidManifestActivity_preferMinimalPostProcessing, sa);
activity.privateFlags |= flag(ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED, R.styleable.AndroidManifestActivity_inheritShowWhenLocked, sa);
activity.privateFlags |= flag(ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED,
R.styleable.AndroidManifestActivity_inheritShowWhenLocked, sa)
| flag(ActivityInfo.PRIVATE_FLAG_HOME_TRANSITION_SOUND,
R.styleable.AndroidManifestActivity_playHomeTransitionSound, true, sa);
activity.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode, ActivityInfo.COLOR_MODE_DEFAULT);
activity.documentLaunchMode = sa.getInt(R.styleable.AndroidManifestActivity_documentLaunchMode, ActivityInfo.DOCUMENT_LAUNCH_NONE);

View File

@@ -4440,6 +4440,13 @@
<permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"
android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to disable system sound effects when the user exits one of
the application's activities.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.DISABLE_SYSTEM_SOUND_EFFECTS"
android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to provide remote displays.
<p>Not for use by third-party applications.</p>
@hide -->

View File

@@ -2862,6 +2862,13 @@
{@link android.content.Context#sendBroadcast(Intent, String)} being used.
Multiple tags can be specified separated by '|'. -->
<attr name="attributionTags"/>
<!-- Specifies whether a home sound effect should be played if the home app moves to
front after an activity with this flag set to <code>true</code>.
<p>The default value of this attribute is <code>true</code>.
<p>Also note that home sounds are only played if the device supports home sounds,
usually TVs.
<p>Requires permission {@code android.permission.DISABLE_SYSTEM_SOUND_EFFECTS}. -->
<attr name="playHomeTransitionSound" format="boolean"/>
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new

View File

@@ -3093,6 +3093,8 @@
<public name="suppressesSpellChecker" />
<public name="usesPermissionFlags" />
<public name="requestOptimizedExternalStorageAccess" />
<!-- @hide @SystemApi -->
<public name="playHomeTransitionSound" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">

View File

@@ -591,4 +591,12 @@
<!-- Determines whether to allow the nav bar handle to be forced to be opaque. -->
<bool name="allow_force_nav_bar_handle_opaque">true</bool>
<!-- Whether a transition of ACTIVITY_TYPE_DREAM to the home app should play a home sound
effect -->
<bool name="config_playHomeSoundAfterDream">false</bool>
<!-- Whether a transition of ACTIVITY_TYPE_ASSISTANT to the home app should play a home sound
effect -->
<bool name="config_playHomeSoundAfterAssistant">false</bool>
</resources>

View File

@@ -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:
* <ul>
* <li>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.</li>
* <li>The current activity which moved to front is home</li>
* <li>The topActivity of the last task has {@link android.R.attr#playHomeTransitionSound} set
* to <code>true</code>.</li>
* <li>The topActivity of the last task is not of type
* {@link WindowConfiguration#ACTIVITY_TYPE_ASSISTANT} if config_playHomeSoundAfterAssistant is
* set to <code>false</code> (default).</li>
* <li>The topActivity of the last task is not of type
* {@link WindowConfiguration#ACTIVITY_TYPE_DREAM} if config_playHomeSoundAfterDream is
* set to <code>false</code> (default).</li>
* </ul>
*/
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);
}
}

View File

@@ -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 <code>false</code>
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 <code>false</code>
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 <code>false</code>
mTaskStackChangeListener.onTaskStackChanged();
// Then a different activity from the same task moves to front, which has
// {@link ActivityInfo#PRIVATE_FLAG_HOME_TRANSITION_SOUND} set to <code>true</code>
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 <code>false</code>
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 <code>false</code>
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 <code>true</code>,
// 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;
}
}