diff options
author | Fei Zheng <quic_zfei@quicinc.com> | 2019-12-25 13:53:16 +0800 |
---|---|---|
committer | Fei Zheng <quic_zfei@quicinc.com> | 2020-06-26 07:27:35 +0800 |
commit | bc5eaa9e36e7414fd63445f0f83d0f804bdca534 (patch) | |
tree | 2c225c41bf5ad082d7c9282d8ac2e9b644a978c2 /core/tests/bluetoothtests | |
parent | 1413b254eb8f46ea0c8912a9e654826bb8137a89 (diff) |
Bluetooth: MCE: Add new API to set message read status or deleted status
Bug: 146314855
Test:
1. Pair with a remote device which address is like 00:01:02:03:04:05
2. On remote device allow MAP connection
3. Make sure there is at least 1 unread message in last week on remote device
4. adb shell am instrument -w -e mce_set_message_status_iterations 1 -e device_address
00:01:02:03:04:05 -e class android.bluetooth.BluetoothStressTest#testMceSetMessageStatus
com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner
Change-Id: I7a3e337142bc39a55c1bfd425e0966e1fb1b9a68
Diffstat (limited to 'core/tests/bluetoothtests')
4 files changed, 194 insertions, 3 deletions
diff --git a/core/tests/bluetoothtests/AndroidManifest.xml b/core/tests/bluetoothtests/AndroidManifest.xml index 7f9d8749358c..6849a90f5010 100644 --- a/core/tests/bluetoothtests/AndroidManifest.xml +++ b/core/tests/bluetoothtests/AndroidManifest.xml @@ -15,14 +15,18 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.bluetooth.tests" > + package="com.android.bluetooth.tests" + android:sharedUserId="android.uid.bluetooth" > <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> + <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> + <uses-permission android:name="android.permission.RECEIVE_SMS" /> + <uses-permission android:name="android.permission.READ_SMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java index 4b32ceae0617..89dbe3f75b56 100644 --- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java +++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothStressTest.java @@ -360,6 +360,30 @@ public class BluetoothStressTest extends InstrumentationTestCase { mTestUtils.unpair(mAdapter, device); } + /* Make sure there is at least 1 unread message in the last week on remote device */ + public void testMceSetMessageStatus() { + int iterations = BluetoothTestRunner.sMceSetMessageStatusIterations; + if (iterations == 0) { + return; + } + + BluetoothDevice device = mAdapter.getRemoteDevice(BluetoothTestRunner.sDeviceAddress); + mTestUtils.enable(mAdapter); + mTestUtils.connectProfile(mAdapter, device, BluetoothProfile.MAP_CLIENT, null); + mTestUtils.mceGetUnreadMessage(mAdapter, device); + + for (int i = 0; i < iterations; i++) { + mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.READ); + mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.UNREAD); + } + + /** + * It is hard to find device to support set undeleted status, so just + * set deleted in 1 iteration + **/ + mTestUtils.mceSetMessageStatus(mAdapter, device, BluetoothMapClient.DELETED); + } + private void sleep(long time) { try { Thread.sleep(time); diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java index 56e691d8c246..d19c2c3e7e24 100644 --- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java +++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java @@ -40,6 +40,7 @@ import android.util.Log; * [-e connect_input_iterations <iterations>] \ * [-e connect_pan_iterations <iterations>] \ * [-e start_stop_sco_iterations <iterations>] \ + * [-e mce_set_message_status_iterations <iterations>] \ * [-e pair_address <address>] \ * [-e headset_address <address>] \ * [-e a2dp_address <address>] \ @@ -64,6 +65,7 @@ public class BluetoothTestRunner extends InstrumentationTestRunner { public static int sConnectInputIterations = 100; public static int sConnectPanIterations = 100; public static int sStartStopScoIterations = 100; + public static int sMceSetMessageStatusIterations = 100; public static String sDeviceAddress = ""; public static byte[] sDevicePairPin = {'1', '2', '3', '4'}; @@ -173,6 +175,15 @@ public class BluetoothTestRunner extends InstrumentationTestRunner { } } + val = arguments.getString("mce_set_message_status_iterations"); + if (val != null) { + try { + sMceSetMessageStatusIterations = Integer.parseInt(val); + } catch (NumberFormatException e) { + // Invalid argument, fall back to default value + } + } + val = arguments.getString("device_address"); if (val != null) { sDeviceAddress = val; diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java index ed613c36b89b..409025bc670d 100644 --- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java +++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java @@ -56,6 +56,10 @@ public class BluetoothTestUtils extends Assert { private static final int CONNECT_PROXY_TIMEOUT = 5000; /** Time between polls in ms. */ private static final int POLL_TIME = 100; + /** Timeout to get map message in ms. */ + private static final int GET_UNREAD_MESSAGE_TIMEOUT = 10000; + /** Timeout to set map message status in ms. */ + private static final int SET_MESSAGE_STATUS_TIMEOUT = 2000; private abstract class FlagReceiver extends BroadcastReceiver { private int mExpectedFlags = 0; @@ -98,6 +102,8 @@ public class BluetoothTestUtils extends Assert { private static final int STATE_TURNING_ON_FLAG = 1 << 6; private static final int STATE_ON_FLAG = 1 << 7; private static final int STATE_TURNING_OFF_FLAG = 1 << 8; + private static final int STATE_GET_MESSAGE_FINISHED_FLAG = 1 << 9; + private static final int STATE_SET_MESSAGE_STATUS_FINISHED_FLAG = 1 << 10; public BluetoothReceiver(int expectedFlags) { super(expectedFlags); @@ -231,6 +237,9 @@ public class BluetoothTestUtils extends Assert { case BluetoothProfile.PAN: mConnectionAction = BluetoothPan.ACTION_CONNECTION_STATE_CHANGED; break; + case BluetoothProfile.MAP_CLIENT: + mConnectionAction = BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED; + break; default: mConnectionAction = null; } @@ -308,6 +317,34 @@ public class BluetoothTestUtils extends Assert { } } + + private class MceSetMessageStatusReceiver extends FlagReceiver { + private static final int MESSAGE_RECEIVED_FLAG = 1; + private static final int STATUS_CHANGED_FLAG = 1 << 1; + + public MceSetMessageStatusReceiver(int expectedFlags) { + super(expectedFlags); + } + + @Override + public void onReceive(Context context, Intent intent) { + if (BluetoothMapClient.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) { + String handle = intent.getStringExtra(BluetoothMapClient.EXTRA_MESSAGE_HANDLE); + assertNotNull(handle); + setFiredFlag(MESSAGE_RECEIVED_FLAG); + mMsgHandle = handle; + } else if (BluetoothMapClient.ACTION_MESSAGE_DELETED_STATUS_CHANGED.equals(intent.getAction())) { + int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, BluetoothMapClient.RESULT_FAILURE); + assertEquals(result, BluetoothMapClient.RESULT_SUCCESS); + setFiredFlag(STATUS_CHANGED_FLAG); + } else if (BluetoothMapClient.ACTION_MESSAGE_READ_STATUS_CHANGED.equals(intent.getAction())) { + int result = intent.getIntExtra(BluetoothMapClient.EXTRA_RESULT_CODE, BluetoothMapClient.RESULT_FAILURE); + assertEquals(result, BluetoothMapClient.RESULT_SUCCESS); + setFiredFlag(STATUS_CHANGED_FLAG); + } + } + } + private BluetoothProfile.ServiceListener mServiceListener = new BluetoothProfile.ServiceListener() { @Override @@ -326,6 +363,9 @@ public class BluetoothTestUtils extends Assert { case BluetoothProfile.PAN: mPan = (BluetoothPan) proxy; break; + case BluetoothProfile.MAP_CLIENT: + mMce = (BluetoothMapClient) proxy; + break; } } } @@ -346,6 +386,9 @@ public class BluetoothTestUtils extends Assert { case BluetoothProfile.PAN: mPan = null; break; + case BluetoothProfile.MAP_CLIENT: + mMce = null; + break; } } } @@ -362,6 +405,8 @@ public class BluetoothTestUtils extends Assert { private BluetoothHeadset mHeadset = null; private BluetoothHidHost mInput = null; private BluetoothPan mPan = null; + private BluetoothMapClient mMce = null; + private String mMsgHandle = null; /** * Creates a utility instance for testing Bluetooth. @@ -898,7 +943,7 @@ public class BluetoothTestUtils extends Assert { * @param adapter The BT adapter. * @param device The remote device. * @param profile The profile to connect. One of {@link BluetoothProfile#A2DP}, - * {@link BluetoothProfile#HEADSET}, or {@link BluetoothProfile#HID_HOST}. + * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#HID_HOST} or {@link BluetoothProfile#MAP_CLIENT}.. * @param methodName The method name to printed in the logs. If null, will be * "connectProfile(profile=<profile>, device=<device>)" */ @@ -941,6 +986,8 @@ public class BluetoothTestUtils extends Assert { assertTrue(((BluetoothHeadset)proxy).connect(device)); } else if (profile == BluetoothProfile.HID_HOST) { assertTrue(((BluetoothHidHost)proxy).connect(device)); + } else if (profile == BluetoothProfile.MAP_CLIENT) { + assertTrue(((BluetoothMapClient)proxy).connect(device)); } break; default: @@ -1016,6 +1063,8 @@ public class BluetoothTestUtils extends Assert { assertTrue(((BluetoothHeadset)proxy).disconnect(device)); } else if (profile == BluetoothProfile.HID_HOST) { assertTrue(((BluetoothHidHost)proxy).disconnect(device)); + } else if (profile == BluetoothProfile.MAP_CLIENT) { + assertTrue(((BluetoothMapClient)proxy).disconnect(device)); } break; case BluetoothProfile.STATE_DISCONNECTED: @@ -1373,6 +1422,89 @@ public class BluetoothTestUtils extends Assert { } } + public void mceGetUnreadMessage(BluetoothAdapter adapter, BluetoothDevice device) { + int mask; + String methodName = "getUnreadMessage"; + + if (!adapter.isEnabled()) { + fail(String.format("%s bluetooth not enabled", methodName)); + } + + if (!adapter.getBondedDevices().contains(device)) { + fail(String.format("%s device not paired", methodName)); + } + + mMce = (BluetoothMapClient) connectProxy(adapter, BluetoothProfile.MAP_CLIENT); + assertNotNull(mMce); + + if (mMce.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) { + fail(String.format("%s device is not connected", methodName)); + } + + mMsgHandle = null; + mask = MceSetMessageStatusReceiver.MESSAGE_RECEIVED_FLAG; + MceSetMessageStatusReceiver receiver = getMceSetMessageStatusReceiver(device, mask); + assertTrue(mMce.getUnreadMessages(device)); + + long s = System.currentTimeMillis(); + while (System.currentTimeMillis() - s < GET_UNREAD_MESSAGE_TIMEOUT) { + if ((receiver.getFiredFlags() & mask) == mask) { + writeOutput(String.format("%s completed", methodName)); + removeReceiver(receiver); + return; + } + sleep(POLL_TIME); + } + int firedFlags = receiver.getFiredFlags(); + removeReceiver(receiver); + fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)", + methodName, mMce.getConnectionState(device), BluetoothMapClient.STATE_CONNECTED, firedFlags, mask)); + } + + /** + * Set a message to read/unread/deleted/undeleted + */ + public void mceSetMessageStatus(BluetoothAdapter adapter, BluetoothDevice device, int status) { + int mask; + String methodName = "setMessageStatus"; + + if (!adapter.isEnabled()) { + fail(String.format("%s bluetooth not enabled", methodName)); + } + + if (!adapter.getBondedDevices().contains(device)) { + fail(String.format("%s device not paired", methodName)); + } + + mMce = (BluetoothMapClient) connectProxy(adapter, BluetoothProfile.MAP_CLIENT); + assertNotNull(mMce); + + if (mMce.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) { + fail(String.format("%s device is not connected", methodName)); + } + + assertNotNull(mMsgHandle); + mask = MceSetMessageStatusReceiver.STATUS_CHANGED_FLAG; + MceSetMessageStatusReceiver receiver = getMceSetMessageStatusReceiver(device, mask); + + assertTrue(mMce.setMessageStatus(device, mMsgHandle, status)); + + long s = System.currentTimeMillis(); + while (System.currentTimeMillis() - s < SET_MESSAGE_STATUS_TIMEOUT) { + if ((receiver.getFiredFlags() & mask) == mask) { + writeOutput(String.format("%s completed", methodName)); + removeReceiver(receiver); + return; + } + sleep(POLL_TIME); + } + + int firedFlags = receiver.getFiredFlags(); + removeReceiver(receiver); + fail(String.format("%s timeout: state=%d (expected %d), flags=0x%x (expected 0x%s)", + methodName, mMce.getConnectionState(device), BluetoothPan.STATE_CONNECTED, firedFlags, mask)); + } + private void addReceiver(BroadcastReceiver receiver, String[] actions) { IntentFilter filter = new IntentFilter(); for (String action: actions) { @@ -1408,7 +1540,8 @@ public class BluetoothTestUtils extends Assert { String[] actions = { BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED, BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED, - BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED}; + BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED, + BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED}; ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile, expectedFlags); addReceiver(receiver, actions); @@ -1430,6 +1563,16 @@ public class BluetoothTestUtils extends Assert { return receiver; } + private MceSetMessageStatusReceiver getMceSetMessageStatusReceiver(BluetoothDevice device, + int expectedFlags) { + String[] actions = {BluetoothMapClient.ACTION_MESSAGE_RECEIVED, + BluetoothMapClient.ACTION_MESSAGE_READ_STATUS_CHANGED, + BluetoothMapClient.ACTION_MESSAGE_DELETED_STATUS_CHANGED}; + MceSetMessageStatusReceiver receiver = new MceSetMessageStatusReceiver(expectedFlags); + addReceiver(receiver, actions); + return receiver; + } + private void removeReceiver(BroadcastReceiver receiver) { mContext.unregisterReceiver(receiver); mReceivers.remove(receiver); @@ -1456,6 +1599,10 @@ public class BluetoothTestUtils extends Assert { if (mPan != null) { return mPan; } + case BluetoothProfile.MAP_CLIENT: + if (mMce != null) { + return mMce; + } break; default: return null; @@ -1483,6 +1630,11 @@ public class BluetoothTestUtils extends Assert { sleep(POLL_TIME); } return mPan; + case BluetoothProfile.MAP_CLIENT: + while (mMce == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) { + sleep(POLL_TIME); + } + return mMce; default: return null; } |