Merge "Add 1.05 and 1.2 as new possible font scale values" into 24D1-dev
diff --git a/data/keyboards/Vendor_054c_Product_05c4.idc b/data/keyboards/Vendor_054c_Product_05c4.idc
index 2cb3f7b..2da6227 100644
--- a/data/keyboards/Vendor_054c_Product_05c4.idc
+++ b/data/keyboards/Vendor_054c_Product_05c4.idc
@@ -13,9 +13,11 @@
# limitations under the License.
#
-# Sony DS4 motion sensor configuration file.
+# Sony Playstation(R) DualShock 4 Controller
#
+## Motion sensor ##
+
# reporting mode 0 - continuous
sensor.accelerometer.reportingMode = 0
# The delay between sensor events corresponding to the lowest frequency in microsecond
@@ -33,3 +35,28 @@
sensor.gyroscope.minDelay = 5000
# The power in mA used by this sensor while in use
sensor.gyroscope.power = 0.8
+
+## Touchpad ##
+
+# After the DualShock 4 has been connected over Bluetooth for a minute or so,
+# its reports start bunching up in time, meaning that we receive 2–4 reports
+# within a millisecond followed by a >10ms wait until the next batch.
+#
+# This uneven timing causes the apparent speed of a finger (calculated using
+# time deltas between received reports) to vary dramatically even if it's
+# actually moving smoothly across the touchpad, triggering the touchpad stack's
+# drumroll detection logic. For moving fingers, the drumroll detection logic
+# splits the finger's single movement into many small movements of consecutive
+# touches, which are then inhibited by the click wiggle filter. For tapping
+# fingers, it prevents tapping to click because it thinks the finger's moving
+# too fast.
+#
+# Since this touchpad doesn't seem to have to drumroll issues, we can safely
+# disable drumroll detection.
+gestureProp.Drumroll_Suppression_Enable = 0
+
+# Because of the way this touchpad is positioned, touches around the edges are
+# no more likely to be palms than ones in the middle, so remove the edge zones
+# from the palm classifier to increase the usable area of the pad.
+gestureProp.Palm_Edge_Zone_Width = 0
+gestureProp.Tap_Exclusion_Border_Width = 0
diff --git a/data/keyboards/Vendor_054c_Product_09cc.idc b/data/keyboards/Vendor_054c_Product_09cc.idc
index 2cb3f7b..2a1a4fc 100644
--- a/data/keyboards/Vendor_054c_Product_09cc.idc
+++ b/data/keyboards/Vendor_054c_Product_09cc.idc
@@ -13,9 +13,11 @@
# limitations under the License.
#
-# Sony DS4 motion sensor configuration file.
+# Sony Playstation(R) DualShock 4 Controller
#
+## Motion sensor ##
+
# reporting mode 0 - continuous
sensor.accelerometer.reportingMode = 0
# The delay between sensor events corresponding to the lowest frequency in microsecond
@@ -33,3 +35,28 @@
sensor.gyroscope.minDelay = 5000
# The power in mA used by this sensor while in use
sensor.gyroscope.power = 0.8
+
+## Touchpad ##
+
+# After the DualShock 4 has been connected over Bluetooth for a minute or so,
+# its reports start bunching up in time, meaning that we receive 2–4 reports
+# within a millisecond followed by a >10ms wait until the next batch.
+#
+# This uneven timing causes the apparent speed of a finger (calculated using
+# time deltas between received reports) to vary dramatically even if it's
+# actually moving smoothly across the touchpad, triggering the touchpad stack's
+# drumroll detection logic. For moving fingers, the drumroll detection logic
+# splits the finger's single movement into many small movements of consecutive
+# touches, which are then inhibited by the click wiggle filter. For tapping
+# fingers, it prevents tapping to click because it thinks the finger's moving
+# too fast.
+#
+# Since this touchpad doesn't seem to have drumroll issues, we can safely
+# disable drumroll detection.
+gestureProp.Drumroll_Suppression_Enable = 0
+
+# Because of the way this touchpad is positioned, touches around the edges are
+# no more likely to be palms than ones in the middle, so remove the edge zones
+# from the palm classifier to increase the usable area of the pad.
+gestureProp.Palm_Edge_Zone_Width = 0
+gestureProp.Tap_Exclusion_Border_Width = 0
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 8baaf2f..38ee6e2 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -45,9 +45,6 @@
<!-- Allow PIP to resize to a slightly bigger state upon touch/showing the menu -->
<bool name="config_pipEnableResizeForMenu">true</bool>
- <!-- PiP minimum size, which is a % based off the shorter side of display width and height -->
- <fraction name="config_pipShortestEdgePercent">40%</fraction>
-
<!-- Time (duration in milliseconds) that the shell waits for an app to close the PiP by itself
if a custom action is present before closing it. -->
<integer name="config_pipForceCloseDelay">1000</integer>
@@ -91,11 +88,45 @@
16x16
</string>
+ <!-- Default percentages for the PIP size logic.
+ 1. Determine max widths
+ Subtract width of system UI and default padding from the shortest edge of the device.
+ This is the max width.
+ 2. Calculate Default and Mins
+ Default is config_pipSystemPreferredDefaultSizePercent of max-width/height.
+ Min is config_pipSystemPreferredMinimumSizePercent of it. -->
+ <item name="config_pipSystemPreferredDefaultSizePercent" format="float" type="dimen">0.6</item>
+ <item name="config_pipSystemPreferredMinimumSizePercent" format="float" type="dimen">0.5</item>
+ <!-- Default percentages for the PIP size logic when the Display is close to square.
+ This is used instead when the display is square-ish, like fold-ables when unfolded,
+ to make sure that default PiP does not cover the hinge (halfway of the display).
+ 0. Determine if the display is square-ish
+ If min(displayWidth, displayHeight) / max(displayWidth, displayHeight) is greater than
+ config_pipSquareDisplayThresholdForSystemPreferredSize, we use the percent for
+ square display listed below.
+ 1. Determine max widths
+ Subtract width of system UI and default padding from the shortest edge of the device.
+ This is the max width.
+ 2. Calculate Default and Mins
+ Default is config_pipSystemPreferredDefaultSizePercentForSquareDisplay of max-width/height.
+ Min is config_pipSystemPreferredMinimumSizePercentForSquareDisplay of it. -->
+ <item name="config_pipSquareDisplayThresholdForSystemPreferredSize"
+ format="float" type="dimen">0.95</item>
+ <item name="config_pipSystemPreferredDefaultSizePercentForSquareDisplay"
+ format="float" type="dimen">0.5</item>
+ <item name="config_pipSystemPreferredMinimumSizePercentForSquareDisplay"
+ format="float" type="dimen">0.4</item>
+
<!-- The percentage of the screen width to use for the default width or height of
picture-in-picture windows. Regardless of the percent set here, calculated size will never
- be smaller than @dimen/default_minimal_size_pip_resizable_task. -->
+ be smaller than @dimen/default_minimal_size_pip_resizable_task.
+ This is used in legacy spec, use config_pipSystemPreferredDefaultSizePercent instead. -->
<item name="config_pictureInPictureDefaultSizePercent" format="float" type="dimen">0.23</item>
+ <!-- PiP minimum size, which is a % based off the shorter side of display width and height.
+ This is used in legacy spec, use config_pipSystemPreferredMinimumSizePercent instead. -->
+ <fraction name="config_pipShortestEdgePercent">40%</fraction>
+
<!-- The default aspect ratio for picture-in-picture windows. -->
<item name="config_pictureInPictureDefaultAspectRatio" format="float" type="dimen">
1.777778
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhoneSizeSpecSource.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhoneSizeSpecSource.kt
index 18c7bdd..7eb0f26 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhoneSizeSpecSource.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhoneSizeSpecSource.kt
@@ -18,7 +18,6 @@
import android.content.Context
import android.content.res.Resources
-import android.os.SystemProperties
import android.util.Size
import com.android.wm.shell.R
import java.io.PrintWriter
@@ -36,30 +35,81 @@
private var mOverrideMinSize: Size? = null
- /** Default and minimum percentages for the PIP size logic. */
- private val mDefaultSizePercent: Float
- private val mMinimumSizePercent: Float
+ /**
+ * Default percentages for the PIP size logic.
+ * 1. Determine max widths
+ * Subtract width of system UI and default padding from the shortest edge of the device.
+ * This is the max width.
+ * 2. Calculate Default and Mins
+ * Default is mSystemPreferredDefaultSizePercent of max-width/height.
+ * Min is mSystemPreferredMinimumSizePercent of it.
+ *
+ * NOTE: Do not use this directly, use the mPreferredDefaultSizePercent getter instead.
+ */
+ private var mSystemPreferredDefaultSizePercent = 0.6f
+ /** Minimum percentages for the PIP size logic. */
+ private var mSystemPreferredMinimumSizePercent = 0.5f
+
+ /** Threshold to categorize the Display as square, calculated as min(w, h) / max(w, h). */
+ private var mSquareDisplayThresholdForSystemPreferredSize = 0.95f
+ /**
+ * Default percentages for the PIP size logic when the Display is square-ish.
+ * This is used instead when the display is square-ish, like fold-ables when unfolded,
+ * to make sure that default PiP does not cover the hinge (halfway of the display).
+ * 1. Determine max widths
+ * Subtract width of system UI and default padding from the shortest edge of the device.
+ * This is the max width.
+ * 2. Calculate Default and Mins
+ * Default is mSystemPreferredDefaultSizePercent of max-width/height.
+ * Min is mSystemPreferredMinimumSizePercent of it.
+ *
+ * NOTE: Do not use this directly, use the mPreferredDefaultSizePercent getter instead.
+ */
+ private var mSystemPreferredDefaultSizePercentForSquareDisplay = 0.5f
+ /** Minimum percentages for the PIP size logic. */
+ private var mSystemPreferredMinimumSizePercentForSquareDisplay = 0.4f
+
+ private val mIsSquareDisplay
+ get() = minOf(pipDisplayLayoutState.displayLayout.width(),
+ pipDisplayLayoutState.displayLayout.height()).toFloat() /
+ maxOf(pipDisplayLayoutState.displayLayout.width(),
+ pipDisplayLayoutState.displayLayout.height()) >
+ mSquareDisplayThresholdForSystemPreferredSize
+ private val mPreferredDefaultSizePercent
+ get() = if (mIsSquareDisplay) mSystemPreferredDefaultSizePercentForSquareDisplay else
+ mSystemPreferredDefaultSizePercent
+
+ private val mPreferredMinimumSizePercent
+ get() = if (mIsSquareDisplay) mSystemPreferredMinimumSizePercentForSquareDisplay else
+ mSystemPreferredMinimumSizePercent
/** Aspect ratio that the PIP size spec logic optimizes for. */
private var mOptimizedAspectRatio = 0f
init {
- mDefaultSizePercent = SystemProperties
- .get("com.android.wm.shell.pip.phone.def_percentage", "0.6").toFloat()
- mMinimumSizePercent = SystemProperties
- .get("com.android.wm.shell.pip.phone.min_percentage", "0.5").toFloat()
-
reloadResources()
}
private fun reloadResources() {
- val res: Resources = context.getResources()
+ val res: Resources = context.resources
mDefaultMinSize = res.getDimensionPixelSize(
R.dimen.default_minimal_size_pip_resizable_task)
mOverridableMinSize = res.getDimensionPixelSize(
R.dimen.overridable_minimal_size_pip_resizable_task)
+ mSystemPreferredDefaultSizePercent = res.getFloat(
+ R.dimen.config_pipSystemPreferredDefaultSizePercent)
+ mSystemPreferredMinimumSizePercent = res.getFloat(
+ R.dimen.config_pipSystemPreferredMinimumSizePercent)
+
+ mSquareDisplayThresholdForSystemPreferredSize = res.getFloat(
+ R.dimen.config_pipSquareDisplayThresholdForSystemPreferredSize)
+ mSystemPreferredDefaultSizePercentForSquareDisplay = res.getFloat(
+ R.dimen.config_pipSystemPreferredDefaultSizePercentForSquareDisplay)
+ mSystemPreferredMinimumSizePercentForSquareDisplay = res.getFloat(
+ R.dimen.config_pipSystemPreferredMinimumSizePercentForSquareDisplay)
+
val requestedOptAspRatio = res.getFloat(R.dimen.config_pipLargeScreenOptimizedAspectRatio)
// make sure the optimized aspect ratio is valid with a default value to fall back to
mOptimizedAspectRatio = if (requestedOptAspRatio > 1) {
@@ -128,7 +178,7 @@
return minSize
}
val maxSize = getMaxSize(aspectRatio)
- val defaultWidth = Math.max(Math.round(maxSize.width * mDefaultSizePercent),
+ val defaultWidth = Math.max(Math.round(maxSize.width * mPreferredDefaultSizePercent),
minSize.width)
val defaultHeight = Math.round(defaultWidth / aspectRatio)
return Size(defaultWidth, defaultHeight)
@@ -146,8 +196,8 @@
return adjustOverrideMinSizeToAspectRatio(aspectRatio)!!
}
val maxSize = getMaxSize(aspectRatio)
- var minWidth = Math.round(maxSize.width * mMinimumSizePercent)
- var minHeight = Math.round(maxSize.height * mMinimumSizePercent)
+ var minWidth = Math.round(maxSize.width * mPreferredMinimumSizePercent)
+ var minHeight = Math.round(maxSize.height * mPreferredMinimumSizePercent)
// make sure the calculated min size is not smaller than the allowed default min size
if (aspectRatio > 1f) {
@@ -244,8 +294,8 @@
pw.println(innerPrefix + "mOverrideMinSize=" + mOverrideMinSize)
pw.println(innerPrefix + "mOverridableMinSize=" + mOverridableMinSize)
pw.println(innerPrefix + "mDefaultMinSize=" + mDefaultMinSize)
- pw.println(innerPrefix + "mDefaultSizePercent=" + mDefaultSizePercent)
- pw.println(innerPrefix + "mMinimumSizePercent=" + mMinimumSizePercent)
+ pw.println(innerPrefix + "mDefaultSizePercent=" + mPreferredDefaultSizePercent)
+ pw.println(innerPrefix + "mMinimumSizePercent=" + mPreferredMinimumSizePercent)
pw.println(innerPrefix + "mOptimizedAspectRatio=" + mOptimizedAspectRatio)
}
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java
index 3d5cd69..85f1da5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java
@@ -16,33 +16,26 @@
package com.android.wm.shell.pip.phone;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
-import android.os.SystemProperties;
import android.testing.AndroidTestingRunner;
import android.util.Size;
import android.view.DisplayInfo;
-import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.wm.shell.R;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.pip.PhoneSizeSpecSource;
import com.android.wm.shell.common.pip.PipDisplayLayoutState;
import com.android.wm.shell.common.pip.SizeSpecSource;
-import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
import java.util.HashMap;
import java.util.Map;
@@ -63,15 +56,24 @@
private static final float DEFAULT_PERCENT = 0.6f;
/** Minimum sizing percentage */
private static final float MIN_PERCENT = 0.5f;
+ /** Threshold to determine if a Display is square-ish. */
+ private static final float SQUARE_DISPLAY_THRESHOLD = 0.95f;
+ /** Default sizing percentage for square-ish Display. */
+ private static final float SQUARE_DISPLAY_DEFAULT_PERCENT = 0.5f;
+ /** Minimum sizing percentage for square-ish Display. */
+ private static final float SQUARE_DISPLAY_MIN_PERCENT = 0.4f;
/** Aspect ratio that the new PIP size spec logic optimizes for. */
private static final float OPTIMIZED_ASPECT_RATIO = 9f / 16;
- /** A map of aspect ratios to be tested to expected sizes */
- private static Map<Float, Size> sExpectedMaxSizes;
- private static Map<Float, Size> sExpectedDefaultSizes;
- private static Map<Float, Size> sExpectedMinSizes;
- /** A static mockito session object to mock {@link SystemProperties} */
- private static StaticMockitoSession sStaticMockitoSession;
+ /** Maps of aspect ratios to be tested to expected sizes on non-square Display. */
+ private static Map<Float, Size> sNonSquareDisplayExpectedMaxSizes;
+ private static Map<Float, Size> sNonSquareDisplayExpectedDefaultSizes;
+ private static Map<Float, Size> sNonSquareDisplayExpectedMinSizes;
+
+ /** Maps of aspect ratios to be tested to expected sizes on square Display. */
+ private static Map<Float, Size> sSquareDisplayExpectedMaxSizes;
+ private static Map<Float, Size> sSquareDisplayExpectedDefaultSizes;
+ private static Map<Float, Size> sSquareDisplayExpectedMinSizes;
@Mock private Context mContext;
@Mock private Resources mResources;
@@ -80,49 +82,55 @@
private SizeSpecSource mSizeSpecSource;
/**
- * Sets up static Mockito session for SystemProperties and mocks necessary static methods.
+ * Initializes the map with the aspect ratios to be tested and corresponding expected max sizes.
+ * This is to initialize the expectations on non-square Display only.
*/
- private static void setUpStaticSystemPropertiesSession() {
- sStaticMockitoSession = mockitoSession()
- .mockStatic(SystemProperties.class).startMocking();
- when(SystemProperties.get(anyString(), anyString())).thenAnswer(invocation -> {
- String property = invocation.getArgument(0);
- if (property.equals("com.android.wm.shell.pip.phone.def_percentage")) {
- return Float.toString(DEFAULT_PERCENT);
- } else if (property.equals("com.android.wm.shell.pip.phone.min_percentage")) {
- return Float.toString(MIN_PERCENT);
- }
+ private static void initNonSquareDisplayExpectedSizes() {
+ sNonSquareDisplayExpectedMaxSizes = new HashMap<>();
+ sNonSquareDisplayExpectedDefaultSizes = new HashMap<>();
+ sNonSquareDisplayExpectedMinSizes = new HashMap<>();
- // throw an exception if illegal arguments are used for these tests
- throw new InvalidUseOfMatchersException(
- String.format("Argument %s does not match", property)
- );
- });
+ sNonSquareDisplayExpectedMaxSizes.put(16f / 9, new Size(1000, 563));
+ sNonSquareDisplayExpectedDefaultSizes.put(16f / 9, new Size(600, 338));
+ sNonSquareDisplayExpectedMinSizes.put(16f / 9, new Size(501, 282));
+
+ sNonSquareDisplayExpectedMaxSizes.put(4f / 3, new Size(893, 670));
+ sNonSquareDisplayExpectedDefaultSizes.put(4f / 3, new Size(536, 402));
+ sNonSquareDisplayExpectedMinSizes.put(4f / 3, new Size(447, 335));
+
+ sNonSquareDisplayExpectedMaxSizes.put(3f / 4, new Size(670, 893));
+ sNonSquareDisplayExpectedDefaultSizes.put(3f / 4, new Size(402, 536));
+ sNonSquareDisplayExpectedMinSizes.put(3f / 4, new Size(335, 447));
+
+ sNonSquareDisplayExpectedMaxSizes.put(9f / 16, new Size(563, 1001));
+ sNonSquareDisplayExpectedDefaultSizes.put(9f / 16, new Size(338, 601));
+ sNonSquareDisplayExpectedMinSizes.put(9f / 16, new Size(282, 501));
}
/**
* Initializes the map with the aspect ratios to be tested and corresponding expected max sizes.
+ * This is to initialize the expectations on square Display only.
*/
- private static void initExpectedSizes() {
- sExpectedMaxSizes = new HashMap<>();
- sExpectedDefaultSizes = new HashMap<>();
- sExpectedMinSizes = new HashMap<>();
+ private static void initSquareDisplayExpectedSizes() {
+ sSquareDisplayExpectedMaxSizes = new HashMap<>();
+ sSquareDisplayExpectedDefaultSizes = new HashMap<>();
+ sSquareDisplayExpectedMinSizes = new HashMap<>();
- sExpectedMaxSizes.put(16f / 9, new Size(1000, 563));
- sExpectedDefaultSizes.put(16f / 9, new Size(600, 338));
- sExpectedMinSizes.put(16f / 9, new Size(501, 282));
+ sSquareDisplayExpectedMaxSizes.put(16f / 9, new Size(1000, 563));
+ sSquareDisplayExpectedDefaultSizes.put(16f / 9, new Size(500, 281));
+ sSquareDisplayExpectedMinSizes.put(16f / 9, new Size(400, 225));
- sExpectedMaxSizes.put(4f / 3, new Size(893, 670));
- sExpectedDefaultSizes.put(4f / 3, new Size(536, 402));
- sExpectedMinSizes.put(4f / 3, new Size(447, 335));
+ sSquareDisplayExpectedMaxSizes.put(4f / 3, new Size(893, 670));
+ sSquareDisplayExpectedDefaultSizes.put(4f / 3, new Size(447, 335));
+ sSquareDisplayExpectedMinSizes.put(4f / 3, new Size(357, 268));
- sExpectedMaxSizes.put(3f / 4, new Size(670, 893));
- sExpectedDefaultSizes.put(3f / 4, new Size(402, 536));
- sExpectedMinSizes.put(3f / 4, new Size(335, 447));
+ sSquareDisplayExpectedMaxSizes.put(3f / 4, new Size(670, 893));
+ sSquareDisplayExpectedDefaultSizes.put(3f / 4, new Size(335, 447));
+ sSquareDisplayExpectedMinSizes.put(3f / 4, new Size(268, 357));
- sExpectedMaxSizes.put(9f / 16, new Size(563, 1001));
- sExpectedDefaultSizes.put(9f / 16, new Size(338, 601));
- sExpectedMinSizes.put(9f / 16, new Size(282, 501));
+ sSquareDisplayExpectedMaxSizes.put(9f / 16, new Size(563, 1001));
+ sSquareDisplayExpectedDefaultSizes.put(9f / 16, new Size(282, 501));
+ sSquareDisplayExpectedMinSizes.put(9f / 16, new Size(225, 400));
}
private void forEveryTestCaseCheck(Map<Float, Size> expectedSizes,
@@ -137,20 +145,38 @@
@Before
public void setUp() {
- initExpectedSizes();
+ initNonSquareDisplayExpectedSizes();
+ initSquareDisplayExpectedSizes();
- when(mResources.getDimensionPixelSize(anyInt())).thenReturn(DEFAULT_MIN_EDGE_SIZE);
- when(mResources.getFloat(anyInt())).thenReturn(OPTIMIZED_ASPECT_RATIO);
- when(mResources.getString(anyInt())).thenReturn("0x0");
+ when(mResources.getFloat(R.dimen.config_pipSystemPreferredDefaultSizePercent))
+ .thenReturn(DEFAULT_PERCENT);
+ when(mResources.getFloat(R.dimen.config_pipSystemPreferredMinimumSizePercent))
+ .thenReturn(MIN_PERCENT);
+ when(mResources.getDimensionPixelSize(R.dimen.default_minimal_size_pip_resizable_task))
+ .thenReturn(DEFAULT_MIN_EDGE_SIZE);
+ when(mResources.getFloat(R.dimen.config_pipLargeScreenOptimizedAspectRatio))
+ .thenReturn(OPTIMIZED_ASPECT_RATIO);
+ when(mResources.getString(R.string.config_defaultPictureInPictureScreenEdgeInsets))
+ .thenReturn("0x0");
when(mResources.getDisplayMetrics())
.thenReturn(getContext().getResources().getDisplayMetrics());
+ when(mResources.getFloat(R.dimen.config_pipSquareDisplayThresholdForSystemPreferredSize))
+ .thenReturn(SQUARE_DISPLAY_THRESHOLD);
+ when(mResources.getFloat(
+ R.dimen.config_pipSystemPreferredDefaultSizePercentForSquareDisplay))
+ .thenReturn(SQUARE_DISPLAY_DEFAULT_PERCENT);
+ when(mResources.getFloat(
+ R.dimen.config_pipSystemPreferredMinimumSizePercentForSquareDisplay))
+ .thenReturn(SQUARE_DISPLAY_MIN_PERCENT);
// set up the mock context for spec handler specifically
when(mContext.getResources()).thenReturn(mResources);
+ }
+ private void setupSizeSpecWithDisplayDimension(int width, int height) {
DisplayInfo displayInfo = new DisplayInfo();
- displayInfo.logicalWidth = DISPLAY_EDGE_SIZE;
- displayInfo.logicalHeight = DISPLAY_EDGE_SIZE;
+ displayInfo.logicalWidth = width;
+ displayInfo.logicalHeight = height;
// use the parent context (not the mocked one) to obtain the display layout
// this is done to avoid unnecessary mocking while allowing for custom display dimensions
@@ -159,38 +185,57 @@
mPipDisplayLayoutState = new PipDisplayLayoutState(mContext);
mPipDisplayLayoutState.setDisplayLayout(displayLayout);
- setUpStaticSystemPropertiesSession();
mSizeSpecSource = new PhoneSizeSpecSource(mContext, mPipDisplayLayoutState);
// no overridden min edge size by default
mSizeSpecSource.setOverrideMinSize(null);
}
- @After
- public void cleanUp() {
- sStaticMockitoSession.finishMocking();
- }
-
@Test
- public void testGetMaxSize() {
- forEveryTestCaseCheck(sExpectedMaxSizes,
+ public void testGetMaxSize_nonSquareDisplay() {
+ setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
+ forEveryTestCaseCheck(sNonSquareDisplayExpectedMaxSizes,
(aspectRatio) -> mSizeSpecSource.getMaxSize(aspectRatio));
}
@Test
- public void testGetDefaultSize() {
- forEveryTestCaseCheck(sExpectedDefaultSizes,
+ public void testGetDefaultSize_nonSquareDisplay() {
+ setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
+ forEveryTestCaseCheck(sNonSquareDisplayExpectedDefaultSizes,
(aspectRatio) -> mSizeSpecSource.getDefaultSize(aspectRatio));
}
@Test
- public void testGetMinSize() {
- forEveryTestCaseCheck(sExpectedMinSizes,
+ public void testGetMinSize_nonSquareDisplay() {
+ setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
+ forEveryTestCaseCheck(sNonSquareDisplayExpectedMinSizes,
+ (aspectRatio) -> mSizeSpecSource.getMinSize(aspectRatio));
+ }
+
+ @Test
+ public void testGetMaxSize_squareDisplay() {
+ setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE, DISPLAY_EDGE_SIZE);
+ forEveryTestCaseCheck(sSquareDisplayExpectedMaxSizes,
+ (aspectRatio) -> mSizeSpecSource.getMaxSize(aspectRatio));
+ }
+
+ @Test
+ public void testGetDefaultSize_squareDisplay() {
+ setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE, DISPLAY_EDGE_SIZE);
+ forEveryTestCaseCheck(sSquareDisplayExpectedDefaultSizes,
+ (aspectRatio) -> mSizeSpecSource.getDefaultSize(aspectRatio));
+ }
+
+ @Test
+ public void testGetMinSize_squareDisplay() {
+ setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE, DISPLAY_EDGE_SIZE);
+ forEveryTestCaseCheck(sSquareDisplayExpectedMinSizes,
(aspectRatio) -> mSizeSpecSource.getMinSize(aspectRatio));
}
@Test
public void testGetSizeForAspectRatio_noOverrideMinSize() {
+ setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
// an initial size with 16:9 aspect ratio
Size initSize = new Size(600, 337);
@@ -202,6 +247,7 @@
@Test
public void testGetSizeForAspectRatio_withOverrideMinSize() {
+ setupSizeSpecWithDisplayDimension(DISPLAY_EDGE_SIZE * 2, DISPLAY_EDGE_SIZE);
// an initial size with a 1:1 aspect ratio
Size initSize = new Size(OVERRIDE_MIN_EDGE_SIZE, OVERRIDE_MIN_EDGE_SIZE);
mSizeSpecSource.setOverrideMinSize(initSize);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index f1eea72..df84653 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1839,18 +1839,19 @@
&& !mBtHelper.isProfilePoxyConnected(btInfo.mProfile)) {
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
"msg: MSG_L_SET_BT_ACTIVE_DEVICE "
- + "received with null profile proxy: "
- + btInfo)).printLog(TAG));
+ + "received with null profile proxy: "
+ + btInfo)).printLog(TAG));
} else {
- @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
+ final Pair<Integer, Boolean> codecAndChanged =
mBtHelper.getCodecWithFallback(btInfo.mDevice,
btInfo.mProfile, btInfo.mIsLeOutput,
"MSG_L_SET_BT_ACTIVE_DEVICE");
- mDeviceInventory.onSetBtActiveDevice(btInfo, codec,
- (btInfo.mProfile
- != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput)
- ? mAudioService.getBluetoothContextualVolumeStream()
- : AudioSystem.STREAM_DEFAULT);
+ mDeviceInventory.onSetBtActiveDevice(btInfo,
+ codecAndChanged.first,
+ (btInfo.mProfile != BluetoothProfile.LE_AUDIO
+ || btInfo.mIsLeOutput)
+ ? mAudioService.getBluetoothContextualVolumeStream()
+ : AudioSystem.STREAM_DEFAULT);
if (btInfo.mProfile == BluetoothProfile.LE_AUDIO
|| btInfo.mProfile == BluetoothProfile.HEARING_AID) {
onUpdateCommunicationRouteClient(isBluetoothScoRequested(),
@@ -1884,12 +1885,13 @@
case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE: {
final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
synchronized (mDeviceStateLock) {
- @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
- mBtHelper.getCodecWithFallback(btInfo.mDevice,
- btInfo.mProfile, btInfo.mIsLeOutput,
- "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
- mDeviceInventory.onBluetoothDeviceConfigChange(
- btInfo, codec, BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
+ final Pair<Integer, Boolean> codecAndChanged =
+ mBtHelper.getCodecWithFallback(
+ btInfo.mDevice, btInfo.mProfile, btInfo.mIsLeOutput,
+ "MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE");
+ mDeviceInventory.onBluetoothDeviceConfigChange(btInfo,
+ codecAndChanged.first, codecAndChanged.second,
+ BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
}
} break;
case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index e0c2425..8b64d93 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -864,7 +864,8 @@
@GuardedBy("mDeviceBroker.mDeviceStateLock")
/*package*/ void onBluetoothDeviceConfigChange(
@NonNull AudioDeviceBroker.BtDeviceInfo btInfo,
- @AudioSystem.AudioFormatNativeEnumForBtCodec int codec, int event) {
+ @AudioSystem.AudioFormatNativeEnumForBtCodec int codec,
+ boolean codecChanged, int event) {
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
+ "onBluetoothDeviceConfigChange")
.set(MediaMetrics.Property.EVENT, BtHelper.deviceEventToString(event));
@@ -912,14 +913,12 @@
if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
- boolean codecChange = false;
if (btInfo.mProfile == BluetoothProfile.A2DP
|| btInfo.mProfile == BluetoothProfile.LE_AUDIO
|| btInfo.mProfile == BluetoothProfile.LE_AUDIO_BROADCAST) {
- if (di.mDeviceCodecFormat != codec) {
+ if (codecChanged) {
di.mDeviceCodecFormat = codec;
mConnectedDevices.replace(key, di);
- codecChange = true;
final int res = mAudioSystem.handleDeviceConfigChange(
btInfo.mAudioSystemDevice, address,
BtHelper.getName(btDevice), codec);
@@ -943,7 +942,7 @@
}
}
}
- if (!codecChange) {
+ if (!codecChanged) {
updateBluetoothPreferredModes_l(btDevice /*connectedDevice*/);
}
}
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 0f3f807..69f7399 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -98,9 +98,16 @@
private @Nullable BluetoothLeAudio mLeAudio;
+ private @Nullable BluetoothLeAudioCodecConfig mLeAudioCodecConfig;
+
// Reference to BluetoothA2dp to query for AbsoluteVolume.
private @Nullable BluetoothA2dp mA2dp;
+ private @Nullable BluetoothCodecConfig mA2dpCodecConfig;
+
+ private @AudioSystem.AudioFormatNativeEnumForBtCodec
+ int mLeAudioBroadcastCodec = AudioSystem.AUDIO_FORMAT_DEFAULT;
+
// If absolute volume is supported in AVRCP device
private boolean mAvrcpAbsVolSupported = false;
@@ -269,12 +276,15 @@
}
}
- /*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec int getCodec(
+ private synchronized Pair<Integer, Boolean> getCodec(
@NonNull BluetoothDevice device, @AudioService.BtProfile int profile) {
+
switch (profile) {
case BluetoothProfile.A2DP: {
+ boolean changed = mA2dpCodecConfig != null;
if (mA2dp == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ mA2dpCodecConfig = null;
+ return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
}
BluetoothCodecStatus btCodecStatus = null;
try {
@@ -283,17 +293,24 @@
Log.e(TAG, "Exception while getting status of " + device, e);
}
if (btCodecStatus == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ mA2dpCodecConfig = null;
+ return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
}
final BluetoothCodecConfig btCodecConfig = btCodecStatus.getCodecConfig();
if (btCodecConfig == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ mA2dpCodecConfig = null;
+ return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
}
- return AudioSystem.bluetoothA2dpCodecToAudioFormat(btCodecConfig.getCodecType());
+ changed = !btCodecConfig.equals(mA2dpCodecConfig);
+ mA2dpCodecConfig = btCodecConfig;
+ return new Pair<>(AudioSystem.bluetoothA2dpCodecToAudioFormat(
+ btCodecConfig.getCodecType()), changed);
}
case BluetoothProfile.LE_AUDIO: {
+ boolean changed = mLeAudioCodecConfig != null;
if (mLeAudio == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ mLeAudioCodecConfig = null;
+ return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
}
BluetoothLeAudioCodecStatus btLeCodecStatus = null;
int groupId = mLeAudio.getGroupId(device);
@@ -303,42 +320,54 @@
Log.e(TAG, "Exception while getting status of " + device, e);
}
if (btLeCodecStatus == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ mLeAudioCodecConfig = null;
+ return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
}
BluetoothLeAudioCodecConfig btLeCodecConfig =
btLeCodecStatus.getOutputCodecConfig();
if (btLeCodecConfig == null) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ mLeAudioCodecConfig = null;
+ return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, changed);
}
- return AudioSystem.bluetoothLeCodecToAudioFormat(btLeCodecConfig.getCodecType());
+ changed = !btLeCodecConfig.equals(mLeAudioCodecConfig);
+ mLeAudioCodecConfig = btLeCodecConfig;
+ return new Pair<>(AudioSystem.bluetoothLeCodecToAudioFormat(
+ btLeCodecConfig.getCodecType()), changed);
+ }
+ case BluetoothProfile.LE_AUDIO_BROADCAST: {
+ // We assume LC3 for LE Audio broadcast codec as there is no API to get the codec
+ // config on LE Broadcast profile proxy.
+ boolean changed = mLeAudioBroadcastCodec != AudioSystem.AUDIO_FORMAT_LC3;
+ mLeAudioBroadcastCodec = AudioSystem.AUDIO_FORMAT_LC3;
+ return new Pair<>(mLeAudioBroadcastCodec, changed);
}
default:
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, false);
}
}
- /*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec
- int getCodecWithFallback(
- @NonNull BluetoothDevice device, @AudioService.BtProfile int profile,
- boolean isLeOutput, @NonNull String source) {
+ /*package*/ synchronized Pair<Integer, Boolean>
+ getCodecWithFallback(@NonNull BluetoothDevice device,
+ @AudioService.BtProfile int profile,
+ boolean isLeOutput, @NonNull String source) {
// For profiles other than A2DP and LE Audio output, the audio codec format must be
// AUDIO_FORMAT_DEFAULT as native audio policy manager expects a specific audio format
// only if audio HW module selection based on format is supported for the device type.
if (!(profile == BluetoothProfile.A2DP
|| (isLeOutput && ((profile == BluetoothProfile.LE_AUDIO)
|| (profile == BluetoothProfile.LE_AUDIO_BROADCAST))))) {
- return AudioSystem.AUDIO_FORMAT_DEFAULT;
+ return new Pair<>(AudioSystem.AUDIO_FORMAT_DEFAULT, false);
}
- @AudioSystem.AudioFormatNativeEnumForBtCodec int codec =
+ Pair<Integer, Boolean> codecAndChanged =
getCodec(device, profile);
- if (codec == AudioSystem.AUDIO_FORMAT_DEFAULT) {
+ if (codecAndChanged.first == AudioSystem.AUDIO_FORMAT_DEFAULT) {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
"getCodec DEFAULT from " + source + " fallback to "
+ (profile == BluetoothProfile.A2DP ? "SBC" : "LC3")));
- return profile == BluetoothProfile.A2DP
- ? AudioSystem.AUDIO_FORMAT_SBC : AudioSystem.AUDIO_FORMAT_LC3;
+ return new Pair<>(profile == BluetoothProfile.A2DP
+ ? AudioSystem.AUDIO_FORMAT_SBC : AudioSystem.AUDIO_FORMAT_LC3, true);
}
- return codec;
+ return codecAndChanged;
}
// @GuardedBy("mDeviceBroker.mSetModeLock")
@@ -543,15 +572,19 @@
break;
case BluetoothProfile.A2DP:
mA2dp = null;
+ mA2dpCodecConfig = null;
break;
case BluetoothProfile.HEARING_AID:
mHearingAid = null;
break;
case BluetoothProfile.LE_AUDIO:
mLeAudio = null;
+ mLeAudioCodecConfig = null;
+ break;
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ mLeAudioBroadcastCodec = AudioSystem.AUDIO_FORMAT_DEFAULT;
break;
case BluetoothProfile.A2DP_SINK:
- case BluetoothProfile.LE_AUDIO_BROADCAST:
// nothing to do in BtHelper
break;
default:
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index a63db88..7b5b07c 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.util;
import static android.telephony.Annotation.DataState;
+import static android.telephony.NetworkRegistrationInfo.FIRST_SERVICE_TYPE;
+import static android.telephony.NetworkRegistrationInfo.LAST_SERVICE_TYPE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -37,6 +39,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.telephony.ITelephony;
@@ -48,6 +51,8 @@
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* This class provides various util functions
@@ -342,4 +347,31 @@
return false;
}
+
+ /**
+ * @param plmn target plmn for validation.
+ * @return {@code true} if the target plmn is valid {@code false} otherwise.
+ */
+ public static boolean isValidPlmn(@Nullable String plmn) {
+ if (TextUtils.isEmpty(plmn)) {
+ return false;
+ }
+ Pattern pattern = Pattern.compile("^(?:[0-9]{3})(?:[0-9]{2}|[0-9]{3})$");
+ Matcher matcher = pattern.matcher(plmn);
+ if (!matcher.matches()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @param serviceType target serviceType for validation.
+ * @return {@code true} if the target serviceType is valid {@code false} otherwise.
+ */
+ public static boolean isValidService(int serviceType) {
+ if (serviceType < FIRST_SERVICE_TYPE || serviceType > LAST_SERVICE_TYPE) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index 36485c6..16983a0 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -83,6 +83,9 @@
*
* @param enableSatellite True to enable the satellite modem and false to disable.
* @param enableDemoMode True to enable demo mode and false to disable.
+ * @param isEmergency To specify the satellite is enabled for emergency session and false for
+ * non emergency session. Note: it is possible that a emergency session started get converted
+ * to a non emergency session and vice versa.
* @param resultCallback The callback to receive the error code result of the operation.
*
* Valid result codes returned:
@@ -96,7 +99,7 @@
* SatelliteResult:SATELLITE_RESULT_NO_RESOURCES
*/
void requestSatelliteEnabled(in boolean enableSatellite, in boolean enableDemoMode,
- in IIntegerConsumer resultCallback);
+ in boolean isEmergency, in IIntegerConsumer resultCallback);
/**
* Request to get whether the satellite modem is enabled.
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index b7dc79f..a623633 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -90,11 +90,11 @@
@Override
public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
- IIntegerConsumer resultCallback) throws RemoteException {
+ boolean isEmergency, IIntegerConsumer resultCallback) throws RemoteException {
executeMethodAsync(
() -> SatelliteImplBase.this
.requestSatelliteEnabled(
- enableSatellite, enableDemoMode, resultCallback),
+ enableSatellite, enableDemoMode, isEmergency, resultCallback),
"requestSatelliteEnabled");
}
@@ -337,6 +337,9 @@
*
* @param enableSatellite True to enable the satellite modem and false to disable.
* @param enableDemoMode True to enable demo mode and false to disable.
+ * @param isEmergency To specify the satellite is enabled for emergency session and false for
+ * non emergency session. Note: it is possible that a emergency session started get converted
+ * to a non emergency session and vice versa.
* @param resultCallback The callback to receive the error code result of the operation.
*
* Valid result codes returned:
@@ -350,7 +353,7 @@
* SatelliteResult:SATELLITE_RESULT_NO_RESOURCES
*/
public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
- @NonNull IIntegerConsumer resultCallback) {
+ boolean isEmergency, @NonNull IIntegerConsumer resultCallback) {
// stub implementation
}
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
index a62103e..7558332 100644
--- a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/TelephonyUtilsTest.java
@@ -16,10 +16,16 @@
package com.android.internal.telephony.tests;
+import static android.telephony.NetworkRegistrationInfo.FIRST_SERVICE_TYPE;
+import static android.telephony.NetworkRegistrationInfo.LAST_SERVICE_TYPE;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
@@ -72,6 +78,22 @@
// getSubscriptionUserHandle should be called if subID is active.
verify(mSubscriptionManager, times(1)).getSubscriptionUserHandle(eq(activeSubId));
}
+
+ @Test
+ public void testIsValidPlmn() {
+ assertTrue(TelephonyUtils.isValidPlmn("310260"));
+ assertTrue(TelephonyUtils.isValidPlmn("45006"));
+ assertFalse(TelephonyUtils.isValidPlmn("1234567"));
+ assertFalse(TelephonyUtils.isValidPlmn("1234"));
+ }
+
+ @Test
+ public void testIsValidService() {
+ assertTrue(TelephonyUtils.isValidService(FIRST_SERVICE_TYPE));
+ assertTrue(TelephonyUtils.isValidService(LAST_SERVICE_TYPE));
+ assertFalse(TelephonyUtils.isValidService(FIRST_SERVICE_TYPE - 1));
+ assertFalse(TelephonyUtils.isValidService(LAST_SERVICE_TYPE + 1));
+ }
}