diff --git a/res/values/strings.xml b/res/values/strings.xml index 54e6894025b..11625f6016f 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8489,6 +8489,9 @@ Other sounds + + Spatial audio + Dial pad tones diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml index 56632a5e993..e30f13915bf 100644 --- a/res/xml/sound_settings.xml +++ b/res/xml/sound_settings.xml @@ -154,6 +154,13 @@ android:ringtoneType="alarm" android:order="-60"/> + + + getInstalledApplications() { diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index c065c75c7b9..d6a8a927527 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -212,6 +212,10 @@ public class SettingsHomepageActivity extends FragmentActivity implements intent.setAction(null); targetIntent.setFlags(targetIntent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); + targetIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); + + // Sender of intent may want to send intent extra data to the destination of targetIntent. + targetIntent.replaceExtras(intent); targetIntent.putExtra(EXTRA_IS_FROM_SETTINGS_HOMEPAGE, true); diff --git a/src/com/android/settings/notification/SpatialAudioPreferenceController.java b/src/com/android/settings/notification/SpatialAudioPreferenceController.java new file mode 100644 index 00000000000..14200765678 --- /dev/null +++ b/src/com/android/settings/notification/SpatialAudioPreferenceController.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.notification; + +import android.content.Context; +import android.media.AudioManager; +import android.media.Spatializer; + +import com.android.settings.core.TogglePreferenceController; + +/** + * The controller of the Spatial audio setting in the SoundSettings. + */ +public class SpatialAudioPreferenceController extends TogglePreferenceController { + + private static final String KEY_SPATIAL_AUDIO = "spatial_audio"; + + private final Spatializer mSpatializer; + + public SpatialAudioPreferenceController(Context context) { + super(context, KEY_SPATIAL_AUDIO); + AudioManager audioManager = context.getSystemService(AudioManager.class); + mSpatializer = audioManager.getSpatializer(); + } + + @Override + public int getAvailabilityStatus() { + return mSpatializer.getImmersiveAudioLevel() == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE + ? UNSUPPORTED_ON_DEVICE : AVAILABLE; + } + + @Override + public boolean isChecked() { + return mSpatializer.isEnabled(); + } + + @Override + public boolean setChecked(boolean isChecked) { + mSpatializer.setEnabled(isChecked); + return isChecked == isChecked(); + } +} diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java index cfdc9eb5b62..93af23193d4 100644 --- a/src/com/android/settings/overlay/FeatureFactory.java +++ b/src/com/android/settings/overlay/FeatureFactory.java @@ -23,6 +23,7 @@ import android.util.Log; import androidx.annotation.Nullable; import com.android.settings.R; +import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider; import com.android.settings.accessibility.AccessibilitySearchFeatureProvider; import com.android.settings.accounts.AccountFeatureProvider; import com.android.settings.applications.ApplicationFeatureProvider; @@ -111,13 +112,13 @@ public abstract class FeatureFactory { public abstract PowerUsageFeatureProvider getPowerUsageFeatureProvider(Context context); /** - * Retrieve implementation for Battery Status feature. + * Retrieves implementation for Battery Status feature. */ public abstract BatteryStatusFeatureProvider getBatteryStatusFeatureProvider( Context context); /** - * Get implementation for Battery Settings provider. + * Gets implementation for Battery Settings provider. */ public abstract BatterySettingsFeatureProvider getBatterySettingsFeatureProvider( Context context); @@ -161,25 +162,30 @@ public abstract class FeatureFactory { public abstract WifiTrackerLibProvider getWifiTrackerLibProvider(); /** - * Retrieve implementation for Extra App Info feature. + * Retrieves implementation for Extra App Info feature. */ public abstract ExtraAppInfoFeatureProvider getExtraAppInfoFeatureProvider(); /** - * Retrieve implementation for SecuritySettings feature. + * Retrieves implementation for SecuritySettings feature. */ public abstract SecuritySettingsFeatureProvider getSecuritySettingsFeatureProvider(); /** - * Retrieve implementation for Game Settings feature. + * Retrieves implementation for Game Settings feature. */ public abstract GameSettingsFeatureProvider getGameSettingsFeatureProvider(); /** - * Retrieve implementation for Accessibility search index feature. + * Retrieves implementation for Accessibility search index feature. */ public abstract AccessibilitySearchFeatureProvider getAccessibilitySearchFeatureProvider(); + /** + * Retrieves implementation for Accessibility metrics category feature. + */ + public abstract AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider(); + public static final class FactoryNotFoundException extends RuntimeException { public FactoryNotFoundException(Throwable throwable) { super("Unable to create factory. Did you misconfigure Proguard?", throwable); diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java index 9890a109641..2c63856d353 100644 --- a/src/com/android/settings/overlay/FeatureFactoryImpl.java +++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java @@ -25,6 +25,8 @@ import android.os.UserManager; import androidx.annotation.Keep; +import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider; +import com.android.settings.accessibility.AccessibilityMetricsFeatureProviderImpl; import com.android.settings.accessibility.AccessibilitySearchFeatureProvider; import com.android.settings.accessibility.AccessibilitySearchFeatureProviderImpl; import com.android.settings.accounts.AccountFeatureProvider; @@ -109,6 +111,7 @@ public class FeatureFactoryImpl extends FeatureFactory { private SecuritySettingsFeatureProvider mSecuritySettingsFeatureProvider; private GameSettingsFeatureProvider mGameSettingsFeatureProvider; private AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider; + private AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider; @Override public SupportFeatureProvider getSupportFeatureProvider(Context context) { @@ -346,4 +349,12 @@ public class FeatureFactoryImpl extends FeatureFactory { } return mAccessibilitySearchFeatureProvider; } + + @Override + public AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider() { + if (mAccessibilityMetricsFeatureProvider == null) { + mAccessibilityMetricsFeatureProvider = new AccessibilityMetricsFeatureProviderImpl(); + } + return mAccessibilityMetricsFeatureProvider; + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java index 5ac8553b91c..aa1caf98d29 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java @@ -114,6 +114,9 @@ public final class BatteryBackupHelperTest { mockUid(1001 /*fake uid*/, PACKAGE_NAME1); mockUid(1002 /*fake uid*/, PACKAGE_NAME2); mockUid(BatteryUtils.UID_NULL, PACKAGE_NAME3); + doReturn(false).when(mPowerAllowlistBackend).isDefaultActiveApp(anyString()); + doReturn(false).when(mPowerAllowlistBackend).isDefaultActiveApp(anyString()); + doReturn(false).when(mPowerAllowlistBackend).isAllowlistedExceptIdle(anyString()); } @After @@ -218,7 +221,6 @@ public final class BatteryBackupHelperTest { createTestingData(PACKAGE_NAME1, PACKAGE_NAME2, PACKAGE_NAME3); // Sets "com.android.testing.1" as system app. doReturn(true).when(mPowerAllowlistBackend).isSysAllowlisted(PACKAGE_NAME1); - doReturn(false).when(mPowerAllowlistBackend).isDefaultActiveApp(anyString()); mBatteryBackupHelper.backupOptimizationMode(mBackupDataOutput, allowlistedApps); @@ -234,7 +236,21 @@ public final class BatteryBackupHelperTest { createTestingData(PACKAGE_NAME1, PACKAGE_NAME2, PACKAGE_NAME3); // Sets "com.android.testing.1" as device default app. doReturn(true).when(mPowerAllowlistBackend).isDefaultActiveApp(PACKAGE_NAME1); - doReturn(false).when(mPowerAllowlistBackend).isSysAllowlisted(anyString()); + + mBatteryBackupHelper.backupOptimizationMode(mBackupDataOutput, allowlistedApps); + + // "com.android.testing.2" for RESTRICTED mode. + final String expectedResult = PACKAGE_NAME2 + ":1,"; + verifyBackupData(expectedResult); + } + + @Test + public void backupOptimizationMode_backupOptimizationAndIgnoreAppInTheAllowlist() + throws Exception { + final List allowlistedApps = Arrays.asList(PACKAGE_NAME1); + createTestingData(PACKAGE_NAME1, PACKAGE_NAME2, PACKAGE_NAME3); + // Sets "com.android.testing.1" in the allowlist. + doReturn(true).when(mPowerAllowlistBackend).isAllowlistedExceptIdle(PACKAGE_NAME1); mBatteryBackupHelper.backupOptimizationMode(mBackupDataOutput, allowlistedApps); diff --git a/tests/robotests/src/com/android/settings/notification/SpatialAudioPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/SpatialAudioPreferenceControllerTest.java new file mode 100644 index 00000000000..66d18ec8308 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/SpatialAudioPreferenceControllerTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.notification; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.media.AudioManager; +import android.media.Spatializer; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@Ignore("b/200896161") +@RunWith(RobolectricTestRunner.class) +public class SpatialAudioPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private AudioManager mAudioManager; + @Mock + private Spatializer mSpatializer; + + private SpatialAudioPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + when((Object) mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager); + when(mAudioManager.getSpatializer()).thenReturn(mSpatializer); + mController = new SpatialAudioPreferenceController(mContext); + } + + @Test + public void getAvailabilityStatus_levelNone_shouldReturnUnsupported() { + when(mSpatializer.getImmersiveAudioLevel()).thenReturn( + Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE); + assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_levelMultiChannel_shouldReturnAvailable() { + when(mSpatializer.getImmersiveAudioLevel()).thenReturn( + Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL); + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void setChecked_withTrue_shouldEnableSpatializer() { + mController.setChecked(true); + + verify(mSpatializer).setEnabled(true); + } + + @Test + public void setChecked_withFalse_shouldDisableSpatializer() { + mController.setChecked(false); + + verify(mSpatializer).setEnabled(false); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java index de1af23c6ff..bc430e832e5 100644 --- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.when; import android.content.Context; +import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider; import com.android.settings.accessibility.AccessibilitySearchFeatureProvider; import com.android.settings.accounts.AccountFeatureProvider; import com.android.settings.applications.ApplicationFeatureProvider; @@ -89,6 +90,7 @@ public class FakeFeatureFactory extends FeatureFactory { public SecuritySettingsFeatureProvider securitySettingsFeatureProvider; public GameSettingsFeatureProvider gameSettingsFeatureProvider; public AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider; + public AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider; /** * Call this in {@code @Before} method of the test class to use fake factory. @@ -139,6 +141,7 @@ public class FakeFeatureFactory extends FeatureFactory { securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class); gameSettingsFeatureProvider = mock(GameSettingsFeatureProvider.class); mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class); + mAccessibilityMetricsFeatureProvider = mock(AccessibilityMetricsFeatureProvider.class); } @Override @@ -280,4 +283,9 @@ public class FakeFeatureFactory extends FeatureFactory { public AccessibilitySearchFeatureProvider getAccessibilitySearchFeatureProvider() { return mAccessibilitySearchFeatureProvider; } + + @Override + public AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider() { + return mAccessibilityMetricsFeatureProvider; + } } diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java index ba7e0bd02b4..0b6061c7115 100644 --- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.mock; import android.content.Context; +import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider; import com.android.settings.accessibility.AccessibilitySearchFeatureProvider; import com.android.settings.accounts.AccountFeatureProvider; import com.android.settings.applications.ApplicationFeatureProvider; @@ -84,6 +85,7 @@ public class FakeFeatureFactory extends FeatureFactory { public SecuritySettingsFeatureProvider securitySettingsFeatureProvider; public GameSettingsFeatureProvider gameSettingsFeatureProvider; public AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider; + public AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider; /** * Call this in {@code @Before} method of the test class to use fake factory. @@ -124,6 +126,8 @@ public class FakeFeatureFactory extends FeatureFactory { extraAppInfoFeatureProvider = mock(ExtraAppInfoFeatureProvider.class); securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class); gameSettingsFeatureProvider = mock(GameSettingsFeatureProvider.class); + mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class); + mAccessibilityMetricsFeatureProvider = mock(AccessibilityMetricsFeatureProvider.class); } @Override @@ -265,4 +269,9 @@ public class FakeFeatureFactory extends FeatureFactory { public AccessibilitySearchFeatureProvider getAccessibilitySearchFeatureProvider() { return mAccessibilitySearchFeatureProvider; } + + @Override + public AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider() { + return mAccessibilityMetricsFeatureProvider; + } }