From 37a10c6f8e4b7f92acdeb0602c0396146df35095 Mon Sep 17 00:00:00 2001 From: changbetty Date: Wed, 11 Jan 2023 16:57:46 +0000 Subject: [LE Audio] To fix the QR Code parse error Bug: 242023882 Test: manual test CRs-Fixed: 3558573 Change-Id: I4dcfb72a038289a480bff21f2ec4756edb441eb2 (cherry picked from commit 429c14f3051450a94e58bcd310218123748159a6) --- .../bluetooth/BluetoothBroadcastUtils.java | 4 +- .../LocalBluetoothLeBroadcastMetadata.java | 199 ++++++++++++++------- 2 files changed, 138 insertions(+), 65 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java index 1f7260972f24..a80061efb19a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java @@ -53,8 +53,8 @@ public final class BluetoothBroadcastUtils { static final String PREFIX_BT_SYNC_INTERVAL = "SI:"; static final String PREFIX_BT_IS_ENCRYPTED = "E:"; static final String PREFIX_BT_BROADCAST_CODE = "C:"; - static final String PREFIX_BT_PRESENTATION_DELAY = "D:"; - static final String PREFIX_BT_SUBGROUPS = "G:"; + static final String PREFIX_BT_PRESENTATION_DELAY = "PD:"; + static final String PREFIX_BT_SUBGROUPS = "SG:"; static final String PREFIX_BT_ANDROID_VERSION = "V:"; // BluetoothLeBroadcastSubgroup diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java index d2329c5f8f24..a65648c38d42 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java @@ -29,7 +29,9 @@ import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,6 +41,43 @@ public class LocalBluetoothLeBroadcastMetadata { private static final String METADATA_START = "<"; private static final String METADATA_END = ">"; private static final String PATTERN_REGEX = "<(.*?)>"; + private static final String PATTERN_BT_BROADCAST_METADATA = + "T:<(.*?)>;+D:<(.*?)>;+AS:<(.*?)>;+B:<(.*?)>;+SI:<(.*?)>;+E:<(.*?)>;+C:<(.*?)>;" + + "+PD:<(.*?)>;+SG:(.*)"; + private static final String PATTERN_BT_SUBGROUP = + "CID:<(.*?)>;+CC:<(.*?);>;+AC:<(.*?);>;+CP:<(.*?)>;+BC:<(.*)>;>;"; + private static final String PATTERN_BT_CHANNEL = "CI:<(.*?)>;+BCCM:<(.*?);>;"; + + /* Index for BluetoothLeBroadcastMetadata */ + private static int MATCH_INDEX_ADDRESS_TYPE = 1; + private static int MATCH_INDEX_DEVICE = 2; + private static int MATCH_INDEX_ADVERTISING_SID = 3; + private static int MATCH_INDEX_BROADCAST_ID = 4; + private static int MATCH_INDEX_SYNC_INTERVAL = 5; + private static int MATCH_INDEX_IS_ENCRYPTED = 6; + private static int MATCH_INDEX_BROADCAST_CODE = 7; + private static int MATCH_INDEX_PRESENTATION_DELAY = 8; + private static int MATCH_INDEX_SUBGROUPS = 9; + + /* Index for BluetoothLeBroadcastSubgroup */ + private static int MATCH_INDEX_CODEC_ID = 1; + private static int MATCH_INDEX_CODEC_CONFIG = 2; + private static int MATCH_INDEX_AUDIO_CONTENT = 3; + private static int MATCH_INDEX_CHANNEL_PREF = 4; + private static int MATCH_INDEX_BROADCAST_CHANNEL = 5; + + /* Index for BluetoothLeAudioCodecConfigMetadata */ + private static int LIST_INDEX_AUDIO_LOCATION = 0; + private static int LIST_INDEX_CODEC_CONFIG_RAW_METADATA = 1; + + /* Index for BluetoothLeAudioContentMetadata */ + private static int LIST_INDEX_PROGRAM_INFO = 0; + private static int LIST_INDEX_LANGUAGE = 1; + private static int LIST_INDEX_AUDIO_CONTENT_RAW_METADATA = 2; + + /* Index for BluetoothLeBroadcastChannel */ + private static int MATCH_INDEX_CHANNEL_INDEX = 1; + private static int MATCH_INDEX_CHANNEL_CODEC_CONFIG = 2; private BluetoothLeBroadcastSubgroup mSubgroup; private List mSubgroupList; @@ -56,17 +95,20 @@ public class LocalBluetoothLeBroadcastMetadata { private byte[] mBroadcastCode; // BluetoothLeBroadcastSubgroup - private long mCodecId; + private int mCodecId; private BluetoothLeAudioContentMetadata mContentMetadata; private BluetoothLeAudioCodecConfigMetadata mConfigMetadata; - private BluetoothLeBroadcastChannel mChannel; + private Boolean mNoChannelPreference; + private List mChannel; // BluetoothLeAudioCodecConfigMetadata private long mAudioLocation; + private byte[] mCodecConfigMetadata; // BluetoothLeAudioContentMetadata private String mLanguage; private String mProgramInfo; + private byte[] mAudioContentMetadata; // BluetoothLeBroadcastChannel private boolean mIsSelected; @@ -136,6 +178,7 @@ public class LocalBluetoothLeBroadcastMetadata { for (BluetoothLeBroadcastSubgroup subgroup: subgroupList) { String audioCodec = convertAudioCodecConfigToString(subgroup.getCodecSpecificConfig()); String audioContent = convertAudioContentToString(subgroup.getContentMetadata()); + boolean hasChannelPreference = subgroup.hasChannelPreference(); String channels = convertChannelToString(subgroup.getChannels()); subgroupString = new StringBuilder() .append(BluetoothBroadcastUtils.PREFIX_BTSG_CODEC_ID) @@ -147,6 +190,9 @@ public class LocalBluetoothLeBroadcastMetadata { .append(BluetoothBroadcastUtils.PREFIX_BTSG_AUDIO_CONTENT) .append(METADATA_START).append(audioContent).append(METADATA_END) .append(BluetoothBroadcastUtils.DELIMITER_QR_CODE) + .append(BluetoothBroadcastUtils.PREFIX_BTSG_CHANNEL_PREF) + .append(METADATA_START).append(hasChannelPreference).append(METADATA_END) + .append(BluetoothBroadcastUtils.DELIMITER_QR_CODE) .append(BluetoothBroadcastUtils.PREFIX_BTSG_BROADCAST_CHANNEL) .append(METADATA_START).append(channels).append(METADATA_END) .append(BluetoothBroadcastUtils.DELIMITER_QR_CODE) @@ -212,19 +258,18 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + qrCodeString + "to BluetoothLeBroadcastMetadata"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + + Pattern pattern = Pattern.compile(PATTERN_BT_BROADCAST_METADATA); Matcher match = pattern.matcher(qrCodeString); if (match.find()) { - ArrayList resultList = new ArrayList<>(); - resultList.add(match.group(1)); - mSourceAddressType = Integer.parseInt(resultList.get(0)); + mSourceAddressType = Integer.parseInt(match.group(MATCH_INDEX_ADDRESS_TYPE)); mSourceDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice( - resultList.get(1)); - mSourceAdvertisingSid = Integer.parseInt(resultList.get(2)); - mBroadcastId = Integer.parseInt(resultList.get(3)); - mPaSyncInterval = Integer.parseInt(resultList.get(4)); - mIsEncrypted = Boolean.valueOf(resultList.get(5)); - String bcode = resultList.get(6); + match.group(MATCH_INDEX_DEVICE)); + mSourceAdvertisingSid = Integer.parseInt(match.group(MATCH_INDEX_ADVERTISING_SID)); + mBroadcastId = Integer.parseInt(match.group(MATCH_INDEX_BROADCAST_ID)); + mPaSyncInterval = Integer.parseInt(match.group(MATCH_INDEX_SYNC_INTERVAL)); + mIsEncrypted = Boolean.valueOf(match.group(MATCH_INDEX_IS_ENCRYPTED)); + String bcode = match.group(MATCH_INDEX_BROADCAST_CODE); mBroadcastCode = null; if (!bcode.equals("[]")) { mBroadcastCode = Arrays.stream(bcode.substring(1, bcode.length()-1).split(",")) @@ -235,13 +280,22 @@ public class LocalBluetoothLeBroadcastMetadata { (b1, b2)->b1.write(b2.toByteArray(), 0, b2.size())) .toByteArray(); } - mPresentationDelayMicros = Integer.parseInt(resultList.get(7)); - mSubgroup = convertToSubgroup(resultList.get(8)); - + mPresentationDelayMicros = + Integer.parseInt(match.group(MATCH_INDEX_PRESENTATION_DELAY)); if (DEBUG) { - Log.d(TAG, "Converted qrCodeString result: " + match.group()); + Log.d(TAG, "Converted qrCodeString result: " + + " ,Type = " + mSourceAddressType + + " ,Device = " + mSourceDevice + + " ,AdSid = " + mSourceAdvertisingSid + + " ,BroadcastId = " + mBroadcastId + + " ,paSync = " + mPaSyncInterval + + " ,encrypted = " + mIsEncrypted + + " ,BroadcastCode = " + Arrays.toString(mBroadcastCode) + + " ,delay = " + mPresentationDelayMicros); } + mSubgroup = convertToSubgroup(match.group(MATCH_INDEX_SUBGROUPS)); + return new BluetoothLeBroadcastMetadata.Builder() .setSourceDevice(mSourceDevice, mSourceAddressType) .setSourceAdvertisingSid(mSourceAdvertisingSid) @@ -265,26 +319,26 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + subgroupString + "to BluetoothLeBroadcastSubgroup"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + Pattern pattern = Pattern.compile(PATTERN_BT_SUBGROUP); Matcher match = pattern.matcher(subgroupString); if (match.find()) { - ArrayList resultList = new ArrayList<>(); - resultList.add(match.group(1)); - mCodecId = Long.getLong(resultList.get(0)); - mConfigMetadata = convertToConfigMetadata(resultList.get(1)); - mContentMetadata = convertToContentMetadata(resultList.get(2)); - mChannel = convertToChannel(resultList.get(3), mConfigMetadata); - - if (DEBUG) { - Log.d(TAG, "Converted subgroupString result: " + match.group()); + mCodecId = Integer.parseInt(match.group(MATCH_INDEX_CODEC_ID)); + mConfigMetadata = convertToConfigMetadata(match.group(MATCH_INDEX_CODEC_CONFIG)); + mContentMetadata = convertToContentMetadata(match.group(MATCH_INDEX_AUDIO_CONTENT)); + mNoChannelPreference = Boolean.valueOf(match.group(MATCH_INDEX_CHANNEL_PREF)); + mChannel = + convertToChannel(match.group(MATCH_INDEX_BROADCAST_CHANNEL), mConfigMetadata); + + BluetoothLeBroadcastSubgroup.Builder subgroupBuilder = + new BluetoothLeBroadcastSubgroup.Builder(); + subgroupBuilder.setCodecId(mCodecId); + subgroupBuilder.setCodecSpecificConfig(mConfigMetadata); + subgroupBuilder.setContentMetadata(mContentMetadata); + + for (BluetoothLeBroadcastChannel channel : mChannel) { + subgroupBuilder.addChannel(channel); } - - return new BluetoothLeBroadcastSubgroup.Builder() - .setCodecId(mCodecId) - .setCodecSpecificConfig(mConfigMetadata) - .setContentMetadata(mContentMetadata) - .addChannel(mChannel) - .build(); + return subgroupBuilder.build(); } else { if (DEBUG) { Log.d(TAG, @@ -302,15 +356,17 @@ public class LocalBluetoothLeBroadcastMetadata { } Pattern pattern = Pattern.compile(PATTERN_REGEX); Matcher match = pattern.matcher(configMetadataString); - if (match.find()) { - ArrayList resultList = new ArrayList<>(); + ArrayList resultList = new ArrayList<>(); + while (match.find()) { resultList.add(match.group(1)); - mAudioLocation = Long.getLong(resultList.get(0)); - - if (DEBUG) { - Log.d(TAG, "Converted configMetadataString result: " + match.group()); - } - + Log.d(TAG, "Codec Config match : " + match.group(1)); + } + if (DEBUG) { + Log.d(TAG, "Converted configMetadataString result: " + resultList.size()); + } + if (resultList.size() > 0) { + mAudioLocation = Long.parseLong(resultList.get(LIST_INDEX_AUDIO_LOCATION)); + mCodecConfigMetadata = resultList.get(LIST_INDEX_CODEC_CONFIG_RAW_METADATA).getBytes(); return new BluetoothLeAudioCodecConfigMetadata.Builder() .setAudioLocation(mAudioLocation) .build(); @@ -330,14 +386,25 @@ public class LocalBluetoothLeBroadcastMetadata { } Pattern pattern = Pattern.compile(PATTERN_REGEX); Matcher match = pattern.matcher(contentMetadataString); - if (match.find()) { - ArrayList resultList = new ArrayList<>(); + ArrayList resultList = new ArrayList<>(); + while (match.find()) { + Log.d(TAG, "Audio Content match : " + match.group(1)); resultList.add(match.group(1)); - mProgramInfo = resultList.get(0); - mLanguage = resultList.get(1); - - if (DEBUG) { - Log.d(TAG, "Converted contentMetadataString result: " + match.group()); + } + if (DEBUG) { + Log.d(TAG, "Converted contentMetadataString result: " + resultList.size()); + } + if (resultList.size() > 0) { + mProgramInfo = resultList.get(LIST_INDEX_PROGRAM_INFO); + mLanguage = resultList.get(LIST_INDEX_LANGUAGE); + mAudioContentMetadata = + resultList.get(LIST_INDEX_AUDIO_CONTENT_RAW_METADATA).getBytes(); + + /* TODO(b/265253566) : Need to set the default value for language when the user starts + * the broadcast. + */ + if (mLanguage.equals("null")) { + mLanguage = "eng"; } return new BluetoothLeAudioContentMetadata.Builder() @@ -353,28 +420,34 @@ public class LocalBluetoothLeBroadcastMetadata { } } - private BluetoothLeBroadcastChannel convertToChannel(String channelString, + private List convertToChannel(String channelString, BluetoothLeAudioCodecConfigMetadata configMetadata) { if (DEBUG) { Log.d(TAG, "Convert " + channelString + "to BluetoothLeBroadcastChannel"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + Pattern pattern = Pattern.compile(PATTERN_BT_CHANNEL); Matcher match = pattern.matcher(channelString); - if (match.find()) { - ArrayList resultList = new ArrayList<>(); - resultList.add(match.group(1)); - mIsSelected = Boolean.valueOf(resultList.get(0)); - mChannelIndex = Integer.parseInt(resultList.get(1)); + Map channel = + new HashMap(); + while (match.find()) { + channel.put(Integer.parseInt(match.group(MATCH_INDEX_CHANNEL_INDEX)), + convertToConfigMetadata(match.group(MATCH_INDEX_CHANNEL_CODEC_CONFIG))); + } - if (DEBUG) { - Log.d(TAG, "Converted channelString result: " + match.group()); + if (channel.size() > 0) { + mIsSelected = false; + ArrayList broadcastChannelList = new ArrayList<>(); + for (Map.Entry entry : + channel.entrySet()) { + + broadcastChannelList.add( + new BluetoothLeBroadcastChannel.Builder() + .setSelected(mIsSelected) + .setChannelIndex(entry.getKey()) + .setCodecMetadata(entry.getValue()) + .build()); } - - return new BluetoothLeBroadcastChannel.Builder() - .setSelected(mIsSelected) - .setChannelIndex(mChannelIndex) - .setCodecMetadata(configMetadata) - .build(); + return broadcastChannelList; } else { if (DEBUG) { Log.d(TAG, -- cgit v1.2.3 From b20e149697948ed1a2cb642183d87c012dd8db3a Mon Sep 17 00:00:00 2001 From: xiaowang Date: Wed, 19 Jul 2023 17:07:15 +0800 Subject: [LeAudio] Enable regex dotall mode for Metadata CRs-Fixed: 3558573 Change-Id: I55668c1602b56596091a30d4e8faa68b8c72f1c9 --- .../bluetooth/LocalBluetoothLeBroadcastMetadata.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java index a65648c38d42..d7393abdafa5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastMetadata.java @@ -259,7 +259,7 @@ public class LocalBluetoothLeBroadcastMetadata { Log.d(TAG, "Convert " + qrCodeString + "to BluetoothLeBroadcastMetadata"); } - Pattern pattern = Pattern.compile(PATTERN_BT_BROADCAST_METADATA); + Pattern pattern = Pattern.compile(PATTERN_BT_BROADCAST_METADATA, Pattern.DOTALL); Matcher match = pattern.matcher(qrCodeString); if (match.find()) { mSourceAddressType = Integer.parseInt(match.group(MATCH_INDEX_ADDRESS_TYPE)); @@ -319,7 +319,7 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + subgroupString + "to BluetoothLeBroadcastSubgroup"); } - Pattern pattern = Pattern.compile(PATTERN_BT_SUBGROUP); + Pattern pattern = Pattern.compile(PATTERN_BT_SUBGROUP, Pattern.DOTALL); Matcher match = pattern.matcher(subgroupString); if (match.find()) { mCodecId = Integer.parseInt(match.group(MATCH_INDEX_CODEC_ID)); @@ -354,7 +354,7 @@ public class LocalBluetoothLeBroadcastMetadata { Log.d(TAG, "Convert " + configMetadataString + "to BluetoothLeAudioCodecConfigMetadata"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + Pattern pattern = Pattern.compile(PATTERN_REGEX, Pattern.DOTALL); Matcher match = pattern.matcher(configMetadataString); ArrayList resultList = new ArrayList<>(); while (match.find()) { @@ -384,7 +384,7 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + contentMetadataString + "to BluetoothLeAudioContentMetadata"); } - Pattern pattern = Pattern.compile(PATTERN_REGEX); + Pattern pattern = Pattern.compile(PATTERN_REGEX, Pattern.DOTALL); Matcher match = pattern.matcher(contentMetadataString); ArrayList resultList = new ArrayList<>(); while (match.find()) { @@ -425,7 +425,7 @@ public class LocalBluetoothLeBroadcastMetadata { if (DEBUG) { Log.d(TAG, "Convert " + channelString + "to BluetoothLeBroadcastChannel"); } - Pattern pattern = Pattern.compile(PATTERN_BT_CHANNEL); + Pattern pattern = Pattern.compile(PATTERN_BT_CHANNEL, Pattern.DOTALL); Matcher match = pattern.matcher(channelString); Map channel = new HashMap(); -- cgit v1.2.3 From a16f46f4bfcba55d931c0b6bd9d57580cab674a2 Mon Sep 17 00:00:00 2001 From: Piyush Mehrotra Date: Thu, 27 Jul 2023 19:35:14 +0000 Subject: [DO NOT MERGE] Check caller's uid in backupAgentCreated callback AM.backupAgentCreated() should enforce that caller belongs the package called in the API. Bug: 289549315 Test: atest android.security.cts.ActivityManagerTest#testActivityManager_backupAgentCreated_rejectIfCallerUidNotEqualsPackageUid (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ff4b0f29e5bcaea805fd5106c8f6353cdc92123d) Merged-In: I9f3ae5ec0b8f00e020d471cc0eddf8bd8bdbb82d Change-Id: I9f3ae5ec0b8f00e020d471cc0eddf8bd8bdbb82d --- .../android/server/am/ActivityManagerService.java | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index ba0aaa1b7d8c..13953d873c0f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2982,6 +2982,22 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** + * Enforces that the uid of the caller matches the uid of the package. + * + * @param packageName the name of the package to match uid against. + * @param callingUid the uid of the caller. + * @throws SecurityException if the calling uid doesn't match uid of the package. + */ + private void enforceCallingPackage(String packageName, int callingUid) { + final int userId = UserHandle.getUserId(callingUid); + final int packageUid = getPackageManagerInternal().getPackageUid(packageName, + /*flags=*/ 0, userId); + if (packageUid != callingUid) { + throw new SecurityException(packageName + " does not belong to uid " + callingUid); + } + } + @Override public void setPackageScreenCompatMode(String packageName, int mode) { mActivityTaskManager.setPackageScreenCompatMode(packageName, mode); @@ -12951,13 +12967,16 @@ public class ActivityManagerService extends IActivityManager.Stub // A backup agent has just come up @Override public void backupAgentCreated(String agentPackageName, IBinder agent, int userId) { + final int callingUid = Binder.getCallingUid(); + enforceCallingPackage(agentPackageName, callingUid); + // Resolve the target user id and enforce permissions. - userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), + userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, /* allowAll */ false, ALLOW_FULL_ONLY, "backupAgentCreated", null); if (DEBUG_BACKUP) { Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName + " = " + agent + " callingUserId = " + UserHandle.getCallingUserId() + " userId = " + userId - + " callingUid = " + Binder.getCallingUid() + " uid = " + Process.myUid()); + + " callingUid = " + callingUid + " uid = " + Process.myUid()); } synchronized(this) { -- cgit v1.2.3 From e7c54eb4eb697d6445d77bc1978cca6821294682 Mon Sep 17 00:00:00 2001 From: kumarashishg Date: Thu, 3 Aug 2023 12:01:29 +0000 Subject: Use type safe API of readParcelableArray Bug: 291299076 Test: Build and flash the device and check if it throws exception for non UsbInterface object Test: atest CtsUsbManagerTestCases (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:85d7e6712a9eeeed3bdd68ea3c3862c7e88bfe70) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:7d8ed27e2e1214aa615065b28f4fef0f1c350e44) Merged-In: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503 Change-Id: I2917c8331b6d56caaa9a6479bcd9a2d089f5f503 --- core/java/android/hardware/usb/UsbConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java index 66269cb772f8..b25f47b11532 100644 --- a/core/java/android/hardware/usb/UsbConfiguration.java +++ b/core/java/android/hardware/usb/UsbConfiguration.java @@ -172,7 +172,8 @@ public class UsbConfiguration implements Parcelable { String name = in.readString(); int attributes = in.readInt(); int maxPower = in.readInt(); - Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader()); + Parcelable[] interfaces = in.readParcelableArray( + UsbInterface.class.getClassLoader(), UsbInterface.class); UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower); configuration.setInterfaces(interfaces); return configuration; -- cgit v1.2.3 From bcf54ce0c8c8c386234787c918b3c2ff6b2eb77f Mon Sep 17 00:00:00 2001 From: Nan Wu Date: Fri, 16 Jun 2023 14:42:24 +0000 Subject: DO NOT MERGE Fix BAL via notification.publicVersion We stripped the token that allows app to retrieve their own notification and fire their own PI to launch activities from background. But we forgot to strip the token from notification.publicVersion Bug: 278558814 Test: NotificationManagerTest#testActivityStartFromRetrievedNotification_isBlocked (cherry picked from commit cf851d81a954f0a6dd0c2fd7defa93932539e7f9) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1896c2e7068c9ec1ab8355d863d7e8107d5d5706) Merged-In: I8f25d7a5e47890a0496af023149717e1df482f98 Change-Id: I8f25d7a5e47890a0496af023149717e1df482f98 --- core/java/android/app/Notification.java | 7 +++++-- .../android/server/notification/NotificationManagerService.java | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index a0fe6c504932..330ab87cdd53 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3413,8 +3413,11 @@ public class Notification implements Parcelable * * @hide */ - public void setAllowlistToken(@Nullable IBinder token) { - mAllowlistToken = token; + public void clearAllowlistToken() { + mAllowlistToken = null; + if (publicVersion != null) { + publicVersion.clearAllowlistToken(); + } } /** diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index d0ae7d59a784..b10c51c67ce4 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -4368,7 +4368,7 @@ public class NotificationManagerService extends SystemService { // Remove background token before returning notification to untrusted app, this // ensures the app isn't able to perform background operations that are // associated with notification interactions. - notification.setAllowlistToken(null); + notification.clearAllowlistToken(); return new StatusBarNotification( sbn.getPackageName(), sbn.getOpPkg(), -- cgit v1.2.3 From ffbe2f2628d995a3a816fc2a77275586dbd3dbb4 Mon Sep 17 00:00:00 2001 From: Songchun Fan Date: Mon, 14 Aug 2023 15:24:11 -0700 Subject: [SettingsProvider] verify ringtone URI before setting Similar to ag/24422287, but the same URI verification should be done in SettingsProvider as well, which can be called by apps via Settings.System API or ContentProvider APIs without using RingtoneManager. BUG: 227201030 Test: manual with a test app. Will add a CTS test. (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1b234678ec122994ccbfc52ac48aafdad7fdb1ed) Merged-In: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b Change-Id: Ic0ffa1db14b5660d02880b632a7f2ad9e6e5d84b --- .../providers/settings/SettingsProvider.java | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index d951121f7323..34328dedaf8d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -1928,6 +1928,9 @@ public class SettingsProvider extends ContentProvider { cacheName = Settings.System.ALARM_ALERT_CACHE; } if (cacheName != null) { + if (!isValidAudioUri(name, value)) { + return false; + } final File cacheFile = new File( getRingtoneCacheDir(owningUserId), cacheName); cacheFile.delete(); @@ -1960,6 +1963,34 @@ public class SettingsProvider extends ContentProvider { } } + private boolean isValidAudioUri(String name, String uri) { + if (uri != null) { + Uri audioUri = Uri.parse(uri); + if (Settings.AUTHORITY.equals( + ContentProvider.getAuthorityWithoutUserId(audioUri.getAuthority()))) { + // Don't accept setting the default uri to self-referential URIs like + // Settings.System.DEFAULT_RINGTONE_URI, which is an alias to the value of this + // setting. + return false; + } + final String mimeType = getContext().getContentResolver().getType(audioUri); + if (mimeType == null) { + Slog.e(LOG_TAG, + "mutateSystemSetting for setting: " + name + " URI: " + audioUri + + " ignored: failure to find mimeType (no access from this context?)"); + return false; + } + if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg") + || mimeType.equals("application/x-flac"))) { + Slog.e(LOG_TAG, + "mutateSystemSetting for setting: " + name + " URI: " + audioUri + + " ignored: associated mimeType: " + mimeType + " is not an audio type"); + return false; + } + } + return true; + } + private boolean hasWriteSecureSettingsPermission() { // Write secure settings is a more protected permission. If caller has it we are good. return getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) -- cgit v1.2.3 From ddb5cc61ea00707a01aea4fbe7839c940ef81841 Mon Sep 17 00:00:00 2001 From: Haining Chen Date: Mon, 27 Mar 2023 22:10:52 -0700 Subject: RESTRICT AUTOMERGE Unset StrongAuthFlags when unlocking a user profile Currently the full user (e.g. userId 0) is required to enter device credential (e.g. device PIN/pattern/password) to unlock the device in certain cases as specified by StrongAuthFlags (e.g. the user has triggered lockdown). After successfully verify the device credential, StrongAuthFlags for the full user will be set back to STRONG_AUTH_NOT_REQUIRED. This may or may not clear StrongAuthFlags for a profile of the user, depending on whether the profile has a separate or unified lock. Case #1: the profile has a seprate lock. In this case, the user will need to enter the device credential on lockscreen to unlock the device, and then enter the different profile lock to unlock the profile. StrongAuthFlags for the profile will only be cleared after successfully verifying the profile lock. Case #2: the profile has a unified lock. Currently in this case, StrongAuthFlags for the profile doesn't get cleared properly after the user verifies the device credential on lockscreen and unpauses the profile. For example, if the user triggers lockdown and later enters the device credential to unlock the device, StrongAuthFlags for the full user gets cleared (so the full user exits lockdown) while StrongAuthFlags for the profile doesn't get cleared (so the profile remains in lockdown), and thus notifications for the profile won't be shown properly. This CL fixes the issue above for the case #2. The user will only need to enter the device credential on lockscreen once to unlock the device. If the profile is already unpaused, at this point StrongAuthFlags should already be cleared; otherwise, StrongAuthFlags will be cleared after the user unpauses the profile (but without having to enter any lock again since the profile uses a unified lock). Test: (1) Set up a profile (e.g. a managed profile) with a unified lock. (2) Trigger the lockdown mode on lockscreen, and verify that StrongAuthFlags for the full user and the profile are both set properly, via "adb shell dumpsys lock_settings". (3) Enter the device credential on lockscreen for the full user, and verify that StrongAuthFlags for the full user is unset. StrongAuthFlags for the profile should also be cleared at this point if the profile was unpaused already before lockdown; otherwise (4) Unpause the profile and verify that StrongAuthFlags for the profile is cleared. Fix: 176924824 Bug: 173721373 (cherry picked from commit ea925cf0b1293ddece4a77f8cce60196ee27f146) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:498867921e79a3809a7cfbbbcf3efc2a1e8eb8eb) Merged-In: Ic466fc22a5be9047d39194ad42c56dc4a2acb4dc Change-Id: Ic466fc22a5be9047d39194ad42c56dc4a2acb4dc --- .../android/server/locksettings/LockSettingsService.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 59794f41d1b7..ac6843cc4994 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -2994,9 +2994,19 @@ public class LockSettingsService extends ILockSettings.Stub { } activateEscrowTokens(authToken, userId); - if (isProfileWithSeparatedLock(userId)) { - setDeviceUnlockedForUser(userId); + if (isCredentialSharableWithParent(userId)) { + if (getSeparateProfileChallengeEnabledInternal(userId)) { + setDeviceUnlockedForUser(userId); + } else { + // Here only clear StrongAuthFlags for a profile that has a unified challenge. + // StrongAuth for a profile with a separate challenge is handled differently and + // is cleared after the user successfully confirms the separate challenge to enter + // the profile. StrongAuth for the full user (e.g. userId 0) is also handled + // separately by Keyguard. + mStrongAuth.reportUnlock(userId); + } } + mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); onAuthTokenKnownForUser(userId, authToken); -- cgit v1.2.3