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:
committed by
Android (Google) Code Review
commit
2e998fc497
@@ -92,6 +92,7 @@ package android {
|
|||||||
field public static final String CREATE_USERS = "android.permission.CREATE_USERS";
|
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 CRYPT_KEEPER = "android.permission.CRYPT_KEEPER";
|
||||||
field public static final String DEVICE_POWER = "android.permission.DEVICE_POWER";
|
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 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 DOMAIN_VERIFICATION_AGENT = "android.permission.DOMAIN_VERIFICATION_AGENT";
|
||||||
field public static final String ENTER_CAR_MODE_PRIORITIZED = "android.permission.ENTER_CAR_MODE_PRIORITIZED";
|
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 hotwordDetectionService = 16844326; // 0x1010626
|
||||||
field public static final int isVrOnly = 16844152; // 0x1010578
|
field public static final int isVrOnly = 16844152; // 0x1010578
|
||||||
field public static final int minExtensionVersion = 16844305; // 0x1010611
|
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 requiredSystemPropertyName = 16844133; // 0x1010565
|
||||||
field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
|
field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
|
||||||
field public static final int sdkVersion = 16844304; // 0x1010610
|
field public static final int sdkVersion = 16844304; // 0x1010610
|
||||||
|
|||||||
@@ -549,10 +549,19 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final int FLAG_INHERIT_SHOW_WHEN_LOCKED = 0x1;
|
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.
|
* Options that have been set in the activity declaration in the manifest.
|
||||||
* These include:
|
* These include:
|
||||||
* {@link #FLAG_INHERIT_SHOW_WHEN_LOCKED}.
|
* {@link #FLAG_INHERIT_SHOW_WHEN_LOCKED},
|
||||||
|
* {@link #PRIVATE_FLAG_HOME_TRANSITION_SOUND}.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public int privateFlags;
|
public int privateFlags;
|
||||||
|
|||||||
@@ -149,7 +149,10 @@ public class ParsedActivityUtils {
|
|||||||
| flag(ActivityInfo.FLAG_TURN_SCREEN_ON, R.styleable.AndroidManifestActivity_turnScreenOn, sa)
|
| flag(ActivityInfo.FLAG_TURN_SCREEN_ON, R.styleable.AndroidManifestActivity_turnScreenOn, sa)
|
||||||
| flag(ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING, R.styleable.AndroidManifestActivity_preferMinimalPostProcessing, 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.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode, ActivityInfo.COLOR_MODE_DEFAULT);
|
||||||
activity.documentLaunchMode = sa.getInt(R.styleable.AndroidManifestActivity_documentLaunchMode, ActivityInfo.DOCUMENT_LAUNCH_NONE);
|
activity.documentLaunchMode = sa.getInt(R.styleable.AndroidManifestActivity_documentLaunchMode, ActivityInfo.DOCUMENT_LAUNCH_NONE);
|
||||||
|
|||||||
@@ -4440,6 +4440,13 @@
|
|||||||
<permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"
|
<permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"
|
||||||
android:protectionLevel="signature|privileged" />
|
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.
|
<!-- @SystemApi Allows an application to provide remote displays.
|
||||||
<p>Not for use by third-party applications.</p>
|
<p>Not for use by third-party applications.</p>
|
||||||
@hide -->
|
@hide -->
|
||||||
|
|||||||
@@ -2862,6 +2862,13 @@
|
|||||||
{@link android.content.Context#sendBroadcast(Intent, String)} being used.
|
{@link android.content.Context#sendBroadcast(Intent, String)} being used.
|
||||||
Multiple tags can be specified separated by '|'. -->
|
Multiple tags can be specified separated by '|'. -->
|
||||||
<attr name="attributionTags"/>
|
<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>
|
</declare-styleable>
|
||||||
|
|
||||||
<!-- The <code>activity-alias</code> tag declares a new
|
<!-- The <code>activity-alias</code> tag declares a new
|
||||||
|
|||||||
@@ -3093,6 +3093,8 @@
|
|||||||
<public name="suppressesSpellChecker" />
|
<public name="suppressesSpellChecker" />
|
||||||
<public name="usesPermissionFlags" />
|
<public name="usesPermissionFlags" />
|
||||||
<public name="requestOptimizedExternalStorageAccess" />
|
<public name="requestOptimizedExternalStorageAccess" />
|
||||||
|
<!-- @hide @SystemApi -->
|
||||||
|
<public name="playHomeTransitionSound" />
|
||||||
</public-group>
|
</public-group>
|
||||||
|
|
||||||
<public-group type="drawable" first-id="0x010800b5">
|
<public-group type="drawable" first-id="0x010800b5">
|
||||||
|
|||||||
@@ -591,4 +591,12 @@
|
|||||||
|
|
||||||
<!-- Determines whether to allow the nav bar handle to be forced to be opaque. -->
|
<!-- Determines whether to allow the nav bar handle to be forced to be opaque. -->
|
||||||
<bool name="allow_force_nav_bar_handle_opaque">true</bool>
|
<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>
|
</resources>
|
||||||
|
|||||||
@@ -16,38 +16,64 @@
|
|||||||
|
|
||||||
package com.android.systemui.media.systemsounds;
|
package com.android.systemui.media.systemsounds;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.WindowConfiguration;
|
import android.app.WindowConfiguration;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SystemUI;
|
import com.android.systemui.SystemUI;
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
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.TaskStackChangeListener;
|
||||||
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a sound effect is defined for {@link android.media.AudioManager#FX_HOME}, a sound is played
|
* If a sound effect is defined for {@link android.media.AudioManager#FX_HOME}, a
|
||||||
* when the home task moves to front and the last task that moved to front was not the home task.
|
* {@link TaskStackChangeListener} is registered to play a home sound effect when conditions
|
||||||
|
* documented at {@link #handleTaskStackChanged} apply.
|
||||||
*/
|
*/
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
public class HomeSoundEffectController extends SystemUI {
|
public class HomeSoundEffectController extends SystemUI {
|
||||||
|
|
||||||
|
private static final String TAG = "HomeSoundEffectController";
|
||||||
private final AudioManager mAudioManager;
|
private final AudioManager mAudioManager;
|
||||||
private final TaskStackChangeListeners mTaskStackChangeListeners;
|
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.
|
// Initialize true because home sound should not be played when the system boots.
|
||||||
private boolean mIsLastTaskHome = true;
|
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
|
@Inject
|
||||||
public HomeSoundEffectController(
|
public HomeSoundEffectController(
|
||||||
Context context,
|
Context context,
|
||||||
AudioManager audioManager,
|
AudioManager audioManager,
|
||||||
TaskStackChangeListeners taskStackChangeListeners) {
|
TaskStackChangeListeners taskStackChangeListeners,
|
||||||
|
ActivityManagerWrapper activityManagerWrapper,
|
||||||
|
PackageManager packageManager) {
|
||||||
super(context);
|
super(context);
|
||||||
mAudioManager = audioManager;
|
mAudioManager = audioManager;
|
||||||
mTaskStackChangeListeners = taskStackChangeListeners;
|
mTaskStackChangeListeners = taskStackChangeListeners;
|
||||||
|
mActivityManagerWrapper = activityManagerWrapper;
|
||||||
|
mPm = packageManager;
|
||||||
|
mPlayHomeSoundAfterAssistant = context.getResources().getBoolean(
|
||||||
|
R.bool.config_playHomeSoundAfterAssistant);
|
||||||
|
mPlayHomeSoundAfterDream = context.getResources().getBoolean(
|
||||||
|
R.bool.config_playHomeSoundAfterDream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -56,27 +82,94 @@ public class HomeSoundEffectController extends SystemUI {
|
|||||||
mTaskStackChangeListeners.registerTaskStackListener(
|
mTaskStackChangeListeners.registerTaskStackListener(
|
||||||
new TaskStackChangeListener() {
|
new TaskStackChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
|
public void onTaskStackChanged() {
|
||||||
handleHomeTaskMovedToFront(taskInfo);
|
ActivityManager.RunningTaskInfo currentTask =
|
||||||
|
mActivityManagerWrapper.getRunningTask();
|
||||||
|
if (currentTask == null || currentTask.topActivityInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handleTaskStackChanged(currentTask);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHomeTask(ActivityManager.RunningTaskInfo taskInfo) {
|
private boolean hasFlagNoSound(ActivityInfo activityInfo) {
|
||||||
return taskInfo.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_HOME;
|
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) {
|
private boolean shouldPlayHomeSoundForCurrentTransition(
|
||||||
boolean isCurrentTaskHome = isHomeTask(taskInfo);
|
ActivityManager.RunningTaskInfo currentTask) {
|
||||||
// If the last task is home we don't want to play the home sound. This avoids playing
|
boolean isHomeActivity =
|
||||||
// the home sound after FallbackHome transitions to Home
|
currentTask.topActivityType == WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||||
if (!mIsLastTaskHome && isCurrentTaskHome) {
|
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);
|
mAudioManager.playSoundEffect(AudioManager.FX_HOME);
|
||||||
}
|
}
|
||||||
mIsLastTaskHome = isCurrentTaskHome;
|
updateLastTaskInfo(frontTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,20 @@ import static org.mockito.Mockito.doReturn;
|
|||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.WindowConfiguration;
|
import android.app.WindowConfiguration;
|
||||||
import android.content.Context;
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
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.TaskStackChangeListener;
|
||||||
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||||
|
|
||||||
@@ -41,30 +45,50 @@ import org.mockito.ArgumentCaptor;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class HomeSoundEffectControllerTest extends SysuiTestCase {
|
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 AudioManager mAudioManager;
|
||||||
private @Mock TaskStackChangeListeners mTaskStackChangeListeners;
|
private @Mock TaskStackChangeListeners mTaskStackChangeListeners;
|
||||||
private @Mock ActivityManager.RunningTaskInfo mStandardActivityTaskInfo;
|
private @Mock ActivityManagerWrapper mActivityManagerWrapper;
|
||||||
private @Mock ActivityManager.RunningTaskInfo mHomeActivityTaskInfo;
|
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 HomeSoundEffectController mController;
|
||||||
private TaskStackChangeListener mTaskStackChangeListener;
|
private TaskStackChangeListener mTaskStackChangeListener;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mTaskAStandardActivity = createRunningTaskInfo(NON_HOME_PACKAGE_NAME,
|
||||||
doReturn(WindowConfiguration.ACTIVITY_TYPE_STANDARD).when(
|
WindowConfiguration.ACTIVITY_TYPE_STANDARD, NON_HOME_TASK_ID,
|
||||||
mStandardActivityTaskInfo).getActivityType();
|
true /* playHomeTransitionSound */);
|
||||||
doReturn(WindowConfiguration.ACTIVITY_TYPE_HOME).when(
|
mTaskAExceptionActivity = createRunningTaskInfo(NON_HOME_PACKAGE_NAME,
|
||||||
mHomeActivityTaskInfo).getActivityType();
|
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,
|
mController = new HomeSoundEffectController(mContext, mAudioManager,
|
||||||
mTaskStackChangeListeners);
|
mTaskStackChangeListeners, mActivityManagerWrapper, mPackageManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -73,43 +97,60 @@ public class HomeSoundEffectControllerTest extends SysuiTestCase {
|
|||||||
startController(true /* isHomeSoundEffectEnabled */);
|
startController(true /* isHomeSoundEffectEnabled */);
|
||||||
|
|
||||||
// And the home task moves to the front,
|
// 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.
|
// Then no home sound effect should be played.
|
||||||
verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
|
verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task A (playHomeTransitionSound = true) -> HOME
|
||||||
|
* Expectation: Home sound is played
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testHomeSoundEffectPlayedWhenEnabled() {
|
public void testHomeSoundEffectPlayedWhenEnabled() {
|
||||||
// When HomeSoundEffectController is started and the home sound effect is enabled,
|
// When HomeSoundEffectController is started and the home sound effect is enabled,
|
||||||
startController(true /* isHomeSoundEffectEnabled */);
|
startController(true /* isHomeSoundEffectEnabled */);
|
||||||
|
when(mActivityManagerWrapper.getRunningTask()).thenReturn(
|
||||||
|
mTaskAStandardActivity,
|
||||||
|
mHomeTaskHomeActivity);
|
||||||
|
|
||||||
// And first a task different from the home task moves to front,
|
// 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,
|
// And the home task moves to the front,
|
||||||
mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
|
mTaskStackChangeListener.onTaskStackChanged();
|
||||||
|
|
||||||
// Then the home sound effect should be played.
|
// Then the home sound effect should be played.
|
||||||
verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
|
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
|
@Test
|
||||||
public void testHomeSoundEffectNotPlayedTwiceInRow() {
|
public void testHomeSoundEffectNotPlayedTwiceInRow() {
|
||||||
// When HomeSoundEffectController is started and the home sound effect is enabled,
|
// When HomeSoundEffectController is started and the home sound effect is enabled,
|
||||||
startController(true /* isHomeSoundEffectEnabled */);
|
startController(true /* isHomeSoundEffectEnabled */);
|
||||||
|
when(mActivityManagerWrapper.getRunningTask()).thenReturn(
|
||||||
|
mTaskAStandardActivity,
|
||||||
|
mHomeTaskHomeActivity,
|
||||||
|
mHomeTaskHomeActivity);
|
||||||
|
|
||||||
|
|
||||||
// And first a task different from the home task moves to front,
|
// 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,
|
// And the home task moves to the front,
|
||||||
mTaskStackChangeListener.onTaskMovedToFront(mHomeActivityTaskInfo);
|
mTaskStackChangeListener.onTaskStackChanged();
|
||||||
|
|
||||||
// Then the home sound effect should be played.
|
// Then the home sound effect should be played.
|
||||||
verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
|
verify(mAudioManager).playSoundEffect(AudioManager.FX_HOME);
|
||||||
|
|
||||||
// If the home task moves to front a second time in a row,
|
// 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.
|
// Then no home sound effect should be played.
|
||||||
verify(mAudioManager, times(1)).playSoundEffect(AudioManager.FX_HOME);
|
verify(mAudioManager, times(1)).playSoundEffect(AudioManager.FX_HOME);
|
||||||
@@ -121,7 +162,59 @@ public class HomeSoundEffectControllerTest extends SysuiTestCase {
|
|||||||
startController(true /* isHomeSoundEffectEnabled */);
|
startController(true /* isHomeSoundEffectEnabled */);
|
||||||
|
|
||||||
// And a standard, non-home task, moves to the front,
|
// 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.
|
// Then no home sound effect should be played.
|
||||||
verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
|
verify(mAudioManager, never()).playSoundEffect(AudioManager.FX_HOME);
|
||||||
@@ -137,6 +230,171 @@ public class HomeSoundEffectControllerTest extends SysuiTestCase {
|
|||||||
any(TaskStackChangeListener.class));
|
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.
|
* Sets {@link AudioManager#isHomeSoundEffectEnabled()} and starts HomeSoundEffectController.
|
||||||
* If the home sound effect is enabled, the registered TaskStackChangeListener is extracted.
|
* If the home sound effect is enabled, the registered TaskStackChangeListener is extracted.
|
||||||
@@ -155,4 +413,20 @@ public class HomeSoundEffectControllerTest extends SysuiTestCase {
|
|||||||
mTaskStackChangeListener = listenerCaptor.getValue();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user