Merge "Throw new exceptions in SecureChannel from beto-rust update" into main
diff --git a/DREAM_MANAGER_OWNERS b/DREAM_MANAGER_OWNERS
new file mode 100644
index 0000000..48bde60
--- /dev/null
+++ b/DREAM_MANAGER_OWNERS
@@ -0,0 +1 @@
+brycelee@google.com
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 77b74e9..5adcd93 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -707,11 +707,11 @@
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(mDisplay, mSurface);
- mFlingerSurfaceControl->updateDefaultBufferSize(newWidth, newHeight);
const auto limitedSize = limitSurfaceSize(newWidth, newHeight);
mWidth = limitedSize.width;
mHeight = limitedSize.height;
+ mFlingerSurfaceControl->updateDefaultBufferSize(mWidth, mHeight);
EGLConfig config = getEglConfig(mDisplay);
EGLSurface surface = eglCreateWindowSurface(mDisplay, config, mFlingerSurface.get(), nullptr);
if (eglMakeCurrent(mDisplay, surface, surface, mContext) == EGL_FALSE) {
diff --git a/cmds/bootanimation/FORMAT.md b/cmds/bootanimation/FORMAT.md
index 01e8fe1..da8331a 100644
--- a/cmds/bootanimation/FORMAT.md
+++ b/cmds/bootanimation/FORMAT.md
@@ -126,7 +126,7 @@
Use `zopflipng` if you have it, otherwise `pngcrush` will do. e.g.:
for fn in *.png ; do
- zopflipng -m ${fn}s ${fn}s.new && mv -f ${fn}s.new ${fn}
+ zopflipng -m ${fn} ${fn}.new && mv -f ${fn}.new ${fn}
# or: pngcrush -q ....
done
diff --git a/config/Android.bp b/config/Android.bp
index adce203..c9948c3 100644
--- a/config/Android.bp
+++ b/config/Android.bp
@@ -33,7 +33,7 @@
name: "preloaded-classes",
src: "preloaded-classes",
filename: "preloaded-classes",
- installable: false,
+ no_full_install: true,
}
filegroup {
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index 712f3e5..02f00ba 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -60,6 +60,9 @@
# ComponentCaller
per-file ComponentCaller.java = file:COMPONENT_CALLER_OWNERS
+# DreamManager
+per-file DreamManager.java = file:/DREAM_MANAGER_OWNERS
+
# GrammaticalInflectionManager
per-file *GrammaticalInflection* = file:/services/core/java/com/android/server/grammaticalinflection/OWNERS
diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig
index fea2c25..d4d1ed2 100644
--- a/core/java/android/net/vcn/flags.aconfig
+++ b/core/java/android/net/vcn/flags.aconfig
@@ -38,6 +38,16 @@
}
flag{
+ name: "enforce_main_user"
+ namespace: "vcn"
+ description: "Enforce main user to make VCN HSUM compatible"
+ bug: "310310661"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag{
name: "handle_seq_num_leap"
namespace: "vcn"
description: "Do not report bad network when there is a suspected sequence number leap"
@@ -45,4 +55,14 @@
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+flag{
+ name: "allow_disable_ipsec_loss_detector"
+ namespace: "vcn"
+ description: "Allow disabling IPsec packet loss detector"
+ bug: "336638836"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 7d1c86b..aadc8db 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -79,8 +79,15 @@
}
flag {
- name: "report_primary_auth_attempts"
- namespace: "biometrics"
- description: "Report primary auth attempts from LockSettingsService"
- bug: "285053096"
+ name: "report_primary_auth_attempts"
+ namespace: "biometrics"
+ description: "Report primary auth attempts from LockSettingsService"
+ bug: "285053096"
+}
+
+flag {
+ name: "dump_attestation_verifications"
+ namespace: "hardware_backed_security"
+ description: "Add a dump capability for attestation_verification service"
+ bug: "335498868"
}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index a07141b..b7ee0b8 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -520,6 +520,13 @@
* To cancel the request, call <code>filePathCallback.onReceiveValue(null)</code> and
* return {@code true}.
*
+ * <p class="note"><b>Note:</b> WebView does not enforce any restrictions on
+ * the chosen file(s). WebView can access all files that your app can access.
+ * In case the file(s) are chosen through an untrusted source such as a third-party
+ * app, it is your own app's responsibility to check what the returned Uris
+ * refer to before calling the <code>filePathCallback</code>. See
+ * {@link #createIntent} and {@link #parseResult} for more details.</p>
+ *
* @param webView The WebView instance that is initiating the request.
* @param filePathCallback Invoke this callback to supply the list of paths to files to upload,
* or {@code null} to cancel. Must only be called if the
@@ -556,6 +563,15 @@
* Parse the result returned by the file picker activity. This method should be used with
* {@link #createIntent}. Refer to {@link #createIntent} for how to use it.
*
+ * <p class="note"><b>Note:</b> The intent returned by the file picker activity
+ * should be treated as untrusted. A third-party app handling the implicit
+ * intent created by {@link #createIntent} might return Uris that the third-party
+ * app itself does not have access to, such as your own app's sensitive data files.
+ * WebView does not enforce any restrictions on the returned Uris. It is the
+ * app's responsibility to ensure that the untrusted source (such as a third-party
+ * app) has access the Uris it has returned and that the Uris are not pointing
+ * to any sensitive data files.</p>
+ *
* @param resultCode the integer result code returned by the file picker activity.
* @param data the intent returned by the file picker activity.
* @return the Uris of selected file(s) or {@code null} if the resultCode indicates
@@ -618,6 +634,12 @@
* WebChromeClient#onShowFileChooser}</li>
* </ol>
*
+ * <p class="note"><b>Note:</b> The created intent may be handled by
+ * third-party applications on device. The received result must be treated
+ * as untrusted as it can contain Uris pointing to your own app's sensitive
+ * data files. Your app should check the resultant Uris in {@link #parseResult}
+ * before calling the <code>filePathCallback</code>.</p>
+ *
* @return an Intent that supports basic file chooser sources.
*/
public abstract Intent createIntent();
diff --git a/core/java/com/android/internal/util/ProcFileReader.java b/core/java/com/android/internal/util/ProcFileReader.java
index 6cf241e..ddbb586 100644
--- a/core/java/com/android/internal/util/ProcFileReader.java
+++ b/core/java/com/android/internal/util/ProcFileReader.java
@@ -89,6 +89,12 @@
mTail -= count;
if (mTail == 0) {
fillBuf();
+
+ if (mTail > 0 && mBuffer[0] == ' ') {
+ // After filling the buffer, it contains more consecutive
+ // delimiters that need to be skipped.
+ consumeBuf(0);
+ }
}
}
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 66b0158..0734e68 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -886,9 +886,16 @@
cellState.activationAnimator.cancel();
}
AnimatorSet animatorSet = new AnimatorSet();
+
+ // When running the line end animation (see doc for createLineEndAnimation), if cell is in:
+ // - activate state - use finger position at the time of hit detection
+ // - deactivate state - use current position where the end was last during initial animation
+ // Note that deactivate state will only come if mKeepDotActivated is themed true.
+ final float startX = activate == CELL_ACTIVATE ? mInProgressX : cellState.lineEndX;
+ final float startY = activate == CELL_ACTIVATE ? mInProgressY : cellState.lineEndY;
AnimatorSet.Builder animatorSetBuilder = animatorSet
.play(createLineDisappearingAnimation())
- .with(createLineEndAnimation(cellState, mInProgressX, mInProgressY,
+ .with(createLineEndAnimation(cellState, startX, startY,
getCenterXForColumn(cell.column), getCenterYForRow(cell.row)));
if (mDotSize != mDotSizeActivated) {
animatorSetBuilder.with(createDotRadiusAnimation(cellState));
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3ed9f49..dbbcbad 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -116,7 +116,7 @@
using android::zygote::ZygoteFailure;
-using Action = android_mallopt_gwp_asan_options_t::Action;
+using Mode = android_mallopt_gwp_asan_options_t::Mode;
// This type is duplicated in fd_utils.h
typedef const std::function<void(std::string)>& fail_fn_t;
@@ -2101,21 +2101,21 @@
switch (runtime_flags & RuntimeFlags::GWP_ASAN_LEVEL_MASK) {
default:
case RuntimeFlags::GWP_ASAN_LEVEL_DEFAULT:
- gwp_asan_options.desire = GetBoolProperty(kGwpAsanAppRecoverableSysprop, true)
- ? Action::TURN_ON_FOR_APP_SAMPLED_NON_CRASHING
- : Action::DONT_TURN_ON_UNLESS_OVERRIDDEN;
+ gwp_asan_options.mode = GetBoolProperty(kGwpAsanAppRecoverableSysprop, true)
+ ? Mode::APP_MANIFEST_DEFAULT
+ : Mode::APP_MANIFEST_NEVER;
android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
break;
case RuntimeFlags::GWP_ASAN_LEVEL_NEVER:
- gwp_asan_options.desire = Action::DONT_TURN_ON_UNLESS_OVERRIDDEN;
+ gwp_asan_options.mode = Mode::APP_MANIFEST_NEVER;
android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
break;
case RuntimeFlags::GWP_ASAN_LEVEL_ALWAYS:
- gwp_asan_options.desire = Action::TURN_ON_FOR_APP;
+ gwp_asan_options.mode = Mode::APP_MANIFEST_ALWAYS;
android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
break;
case RuntimeFlags::GWP_ASAN_LEVEL_LOTTERY:
- gwp_asan_options.desire = Action::TURN_ON_WITH_SAMPLING;
+ gwp_asan_options.mode = Mode::APP_MANIFEST_DEFAULT;
android_mallopt(M_INITIALIZE_GWP_ASAN, &gwp_asan_options, sizeof(gwp_asan_options));
break;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7bac338..ee7baa1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -178,6 +178,7 @@
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REPLY" />
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
+ <protected-broadcast android:name="android.bluetooth.device.action.KEY_MISSING" />
<protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" />
<protected-broadcast android:name="android.bluetooth.device.action.BATTERY_LEVEL_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.REMOTE_ISSUE_OCCURRED" />
diff --git a/core/res/res/drawable/ic_thread_network.xml b/core/res/res/drawable/ic_thread_network.xml
new file mode 100644
index 0000000..1d7608f
--- /dev/null
+++ b/core/res/res/drawable/ic_thread_network.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2024 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M476,880Q394,879 322,847.5Q250,816 196,761.5Q142,707 111,634.5Q80,562 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,623 791.5,732.5Q703,842 563,871L563,480L607,480Q661,480 699.5,441.5Q738,403 738,349Q738,295 699.5,256.5Q661,218 607,218Q553,218 514.5,256.5Q476,295 476,349L476,393L345,393Q279,393 233,439Q187,485 187,551Q187,617 233,662.5Q279,708 345,708L345,621Q316,621 295,600.5Q274,580 274,551Q274,522 295,501Q316,480 345,480L476,480L476,880ZM563,393L563,349Q563,331 576,318Q589,305 607,305Q625,305 638,318Q651,331 651,349Q651,367 638,380Q625,393 607,393L563,393Z"/>
+</vector>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index fd6158d..7bd74c8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1367,6 +1367,7 @@
<java-symbol type="drawable" name="platlogo" />
<java-symbol type="drawable" name="stat_notify_sync_error" />
<java-symbol type="drawable" name="stat_notify_wifi_in_range" />
+ <java-symbol type="drawable" name="ic_thread_network" />
<java-symbol type="drawable" name="ic_wifi_signal_0" />
<java-symbol type="drawable" name="ic_wifi_signal_1" />
<java-symbol type="drawable" name="ic_wifi_signal_2" />
diff --git a/core/tests/coretests/src/android/net/OWNERS b/core/tests/coretests/src/android/net/OWNERS
index a779c00..beb77dc 100644
--- a/core/tests/coretests/src/android/net/OWNERS
+++ b/core/tests/coretests/src/android/net/OWNERS
@@ -1,4 +1,5 @@
include /services/core/java/com/android/server/net/OWNERS
-per-file SSL*,Uri*,Url* = prb@google.com,oth@google.com,narayan@google.com,ngeoffray@google.com
+per-file SSL*,Url* = prb@google.com,oth@google.com,narayan@google.com,ngeoffray@google.com
per-file SntpClient* = file:/services/core/java/com/android/server/timedetector/OWNERS
+per-file Uri* = varunshah@google.com
diff --git a/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java b/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
index 4c00c16..9785ca7 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
@@ -216,6 +216,46 @@
}
@Test
+ public void testBufferSizeWithConsecutiveDelimiters() throws Exception {
+ // Read numbers using very small buffer size, exercising fillBuf()
+ // Include more consecutive delimiters than the buffer size.
+ final ProcFileReader reader =
+ buildReader("1 21 3 41 5 61 7 81 9 10\n", 3);
+
+ assertEquals(1, reader.nextInt());
+ assertEquals(21, reader.nextInt());
+ assertEquals(3, reader.nextInt());
+ assertEquals(41, reader.nextInt());
+ assertEquals(5, reader.nextInt());
+ assertEquals(61, reader.nextInt());
+ assertEquals(7, reader.nextInt());
+ assertEquals(81, reader.nextInt());
+ assertEquals(9, reader.nextInt());
+ assertEquals(10, reader.nextInt());
+ reader.finishLine();
+ assertFalse(reader.hasMoreData());
+ }
+
+ @Test
+ public void testBufferSizeWithConsecutiveDelimitersAndMultipleLines() throws Exception {
+ final ProcFileReader reader =
+ buildReader("1 21 41 \n 5 7 81 \n 9 10 \n", 3);
+
+ assertEquals(1, reader.nextInt());
+ assertEquals(21, reader.nextInt());
+ assertEquals(41, reader.nextInt());
+ reader.finishLine();
+ assertEquals(5, reader.nextInt());
+ assertEquals(7, reader.nextInt());
+ assertEquals(81, reader.nextInt());
+ reader.finishLine();
+ assertEquals(9, reader.nextInt());
+ assertEquals(10, reader.nextInt());
+ reader.finishLine();
+ assertFalse(reader.hasMoreData());
+ }
+
+ @Test
public void testIgnore() throws Exception {
final ProcFileReader reader = buildReader("a b c\n");
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index cb803f7..5045918 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -322,11 +322,11 @@
<library name="android.hidl.manager-V1.0-java"
file="/system/framework/android.hidl.manager-V1.0-java.jar" />
- <!-- These are the standard packages that are white-listed to always have internet
+ <!-- These are the standard packages that are allowed to always have internet
access while in power save mode, even if they aren't in the foreground. -->
<allow-in-power-save package="com.android.providers.downloads" />
- <!-- These are the standard packages that are white-listed to always have internet
+ <!-- These are the standard packages that are allowed to always have internet
access while in data mode, even if they aren't in the foreground. -->
<allow-in-data-usage-save package="com.android.providers.downloads" />
@@ -338,7 +338,7 @@
<!-- Emergency app needs to run in the background to reliably provide safety features -->
<allow-in-power-save package="com.android.emergency" />
- <!-- Whitelist system providers -->
+ <!-- Allow system providers -->
<!-- Calendar provider needs alarms while in idle -->
<allow-in-power-save package="com.android.providers.calendar" />
<allow-in-power-save-except-idle package="com.android.providers.contacts" />
diff --git a/data/keyboards/Android.bp b/data/keyboards/Android.bp
index f15c153..423b55b 100644
--- a/data/keyboards/Android.bp
+++ b/data/keyboards/Android.bp
@@ -27,3 +27,27 @@
targets: ["droidcore"],
},
}
+
+prebuilt_usr_keylayout {
+ name: "keylayout_data",
+ srcs: [
+ "*.kl",
+ ],
+ no_full_install: true,
+}
+
+prebuilt_usr_keychars {
+ name: "keychars_data",
+ srcs: [
+ "*.kcm",
+ ],
+ no_full_install: true,
+}
+
+prebuilt_usr_idc {
+ name: "idc_data",
+ srcs: [
+ "*.idc",
+ ],
+ no_full_install: true,
+}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
deleted file mode 100644
index d1d7c14..0000000
--- a/keystore/java/android/security/KeyStore.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2009 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 android.security;
-
-/**
- * This class provides some constants and helper methods related to Android's Keystore service.
- * This class was originally much larger, but its functionality was superseded by other classes.
- * It now just contains a few remaining pieces for which the users haven't been updated yet.
- * You may be looking for {@link java.security.KeyStore} instead.
- *
- * @hide
- */
-public class KeyStore {
-
- // Used for UID field to indicate the calling UID.
- public static final int UID_SELF = -1;
-}
diff --git a/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp b/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp
index b511244..6196589 100644
--- a/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp
+++ b/libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp
@@ -19,6 +19,7 @@
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_libs_androidfw_license"],
+ default_team: "trendy_team_android_resources",
}
cc_fuzz {
@@ -31,7 +32,7 @@
static_libs: ["libgmock"],
target: {
android: {
- shared_libs:[
+ shared_libs: [
"libandroidfw",
"libbase",
"libcutils",
@@ -52,4 +53,15 @@
],
},
},
+ fuzz_config: {
+ cc: [
+ "android-resources@google.com",
+ ],
+ componentid: 568761,
+ description: "The fuzzer targets the APIs of libandroidfw",
+ vector: "local_no_privileges_required",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
+ },
}
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index ad86d70..4bae118 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -970,16 +970,16 @@
*
* @param service The ComponentName of the service
* @param status true to enable, false to disable
+ * @param userId the user handle of the user whose information is being requested.
* @return set service for the category and true if service is already set return false.
*
* @hide
*/
- public boolean setServiceEnabledForCategoryOther(ComponentName service, boolean status) {
+ public boolean setServiceEnabledForCategoryOther(ComponentName service, boolean status,
+ int userId) {
if (service == null) {
throw new NullPointerException("activity or service or category is null");
}
- int userId = mContext.getUser().getIdentifier();
-
try {
return sService.setServiceEnabledForCategoryOther(userId, service, status);
} catch (RemoteException e) {
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 25ac3c9..635dc42 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -172,7 +172,7 @@
// This is for testing only now
private boolean mEnableWhenCompleted;
- private boolean mOneShot;
+ private boolean mOneShot = true;
private boolean mHideNotification;
private InstallationAsyncTask.Progress mInstallTaskProgress;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java
index 1ff2bef..5e3bd9a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothBroadcastUtils.java
@@ -43,5 +43,5 @@
/**
* Bluetooth scheme.
*/
- public static final String SCHEME_BT_BROADCAST_METADATA = "BT:";
+ public static final String SCHEME_BT_BROADCAST_METADATA = "BLUETOOTH:UUID:184F;";
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExt.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExt.kt
index 9bb11f8..0c7d6f0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExt.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExt.kt
@@ -31,38 +31,34 @@
object BluetoothLeBroadcastMetadataExt {
private const val TAG = "BtLeBroadcastMetadataExt"
- // BluetoothLeBroadcastMetadata
- private const val KEY_BT_QR_VER = "R"
- private const val KEY_BT_ADDRESS_TYPE = "T"
- private const val KEY_BT_DEVICE = "D"
- private const val KEY_BT_ADVERTISING_SID = "AS"
- private const val KEY_BT_BROADCAST_ID = "B"
+ // Data Elements for directing Broadcast Assistants
private const val KEY_BT_BROADCAST_NAME = "BN"
- private const val KEY_BT_PUBLIC_BROADCAST_DATA = "PM"
- private const val KEY_BT_SYNC_INTERVAL = "SI"
- private const val KEY_BT_BROADCAST_CODE = "C"
- private const val KEY_BT_SUBGROUPS = "SG"
- private const val KEY_BT_VENDOR_SPECIFIC = "V"
- private const val KEY_BT_ANDROID_VERSION = "VN"
+ private const val KEY_BT_ADVERTISER_ADDRESS_TYPE = "AT"
+ private const val KEY_BT_ADVERTISER_ADDRESS = "AD"
+ private const val KEY_BT_BROADCAST_ID = "BI"
+ private const val KEY_BT_BROADCAST_CODE = "BC"
+ private const val KEY_BT_STREAM_METADATA = "MD"
+ private const val KEY_BT_STANDARD_QUALITY = "SQ"
+ private const val KEY_BT_HIGH_QUALITY = "HQ"
- // Subgroup data
+ // Extended Bluetooth URI Data Elements
+ private const val KEY_BT_ADVERTISING_SID = "AS"
+ private const val KEY_BT_PA_INTERVAL = "PI"
+ private const val KEY_BT_NUM_SUBGROUPS = "NS"
+
+ // Subgroup data elements
private const val KEY_BTSG_BIS_SYNC = "BS"
- private const val KEY_BTSG_BIS_MASK = "BM"
- private const val KEY_BTSG_AUDIO_CONTENT = "AC"
+ private const val KEY_BTSG_NUM_BISES = "NB"
+ private const val KEY_BTSG_METADATA = "SM"
- // Vendor specific data
- private const val KEY_BTVSD_COMPANY_ID = "VI"
- private const val KEY_BTVSD_VENDOR_DATA = "VD"
+ // Vendor specific data, not being used
+ private const val KEY_BTVSD_VENDOR_DATA = "VS"
private const val DELIMITER_KEY_VALUE = ":"
- private const val DELIMITER_BT_LEVEL_1 = ";"
- private const val DELIMITER_BT_LEVEL_2 = ","
+ private const val DELIMITER_ELEMENT = ";"
private const val SUFFIX_QR_CODE = ";;"
- private const val ANDROID_VER = "U"
- private const val QR_CODE_VER = 0x010000
-
// BT constants
private const val BIS_SYNC_MAX_CHANNEL = 32
private const val BIS_SYNC_NO_PREFERENCE = 0xFFFFFFFFu
@@ -71,33 +67,55 @@
/**
* Converts [BluetoothLeBroadcastMetadata] to QR code string.
*
- * QR code string will prefix with "BT:".
+ * QR code string will prefix with "BLUETOOTH:UUID:184F".
*/
fun BluetoothLeBroadcastMetadata.toQrCodeString(): String {
val entries = mutableListOf<Pair<String, String>>()
- entries.add(Pair(KEY_BT_QR_VER, QR_CODE_VER.toString()))
- entries.add(Pair(KEY_BT_ADDRESS_TYPE, this.sourceAddressType.toString()))
- entries.add(Pair(KEY_BT_DEVICE, this.sourceDevice.address.replace(":", "-")))
- entries.add(Pair(KEY_BT_ADVERTISING_SID, this.sourceAdvertisingSid.toString()))
- entries.add(Pair(KEY_BT_BROADCAST_ID, this.broadcastId.toString()))
- if (this.broadcastName != null) {
- entries.add(Pair(KEY_BT_BROADCAST_NAME, Base64.encodeToString(
- this.broadcastName?.toByteArray(Charsets.UTF_8), Base64.NO_WRAP)))
- }
- if (this.publicBroadcastMetadata != null) {
- entries.add(Pair(KEY_BT_PUBLIC_BROADCAST_DATA, Base64.encodeToString(
- this.publicBroadcastMetadata?.rawMetadata, Base64.NO_WRAP)))
- }
- entries.add(Pair(KEY_BT_SYNC_INTERVAL, this.paSyncInterval.toString()))
+ // Generate data elements for directing Broadcast Assistants
+ require(this.broadcastName != null) { "Broadcast name is mandatory for QR code" }
+ entries.add(Pair(KEY_BT_BROADCAST_NAME, Base64.encodeToString(
+ this.broadcastName?.toByteArray(Charsets.UTF_8), Base64.NO_WRAP)))
+ entries.add(Pair(KEY_BT_ADVERTISER_ADDRESS_TYPE, this.sourceAddressType.toString()))
+ entries.add(Pair(KEY_BT_ADVERTISER_ADDRESS, this.sourceDevice.address.replace(":", "")))
+ entries.add(Pair(KEY_BT_BROADCAST_ID, String.format("%X", this.broadcastId.toLong())))
if (this.broadcastCode != null) {
entries.add(Pair(KEY_BT_BROADCAST_CODE,
Base64.encodeToString(this.broadcastCode, Base64.NO_WRAP)))
}
+ if (this.publicBroadcastMetadata != null &&
+ this.publicBroadcastMetadata?.rawMetadata?.size != 0) {
+ entries.add(Pair(KEY_BT_STREAM_METADATA, Base64.encodeToString(
+ this.publicBroadcastMetadata?.rawMetadata, Base64.NO_WRAP)))
+ }
+ if ((this.audioConfigQuality and
+ BluetoothLeBroadcastMetadata.AUDIO_CONFIG_QUALITY_STANDARD) != 0) {
+ entries.add(Pair(KEY_BT_STANDARD_QUALITY, "1"))
+ }
+ if ((this.audioConfigQuality and
+ BluetoothLeBroadcastMetadata.AUDIO_CONFIG_QUALITY_HIGH) != 0) {
+ entries.add(Pair(KEY_BT_HIGH_QUALITY, "1"))
+ }
+
+ // Generate extended Bluetooth URI data elements
+ entries.add(Pair(KEY_BT_ADVERTISING_SID,
+ String.format("%X", this.sourceAdvertisingSid.toLong())))
+ entries.add(Pair(KEY_BT_PA_INTERVAL, String.format("%X", this.paSyncInterval.toLong())))
+ entries.add(Pair(KEY_BT_NUM_SUBGROUPS, String.format("%X", this.subgroups.size.toLong())))
+
this.subgroups.forEach {
- subgroup -> entries.add(Pair(KEY_BT_SUBGROUPS, subgroup.toQrCodeString())) }
- entries.add(Pair(KEY_BT_ANDROID_VERSION, ANDROID_VER))
+ val (bisSync, bisCount) = getBisSyncFromChannels(it.channels)
+ entries.add(Pair(KEY_BTSG_BIS_SYNC, String.format("%X", bisSync.toLong())))
+ if (bisCount > 0u) {
+ entries.add(Pair(KEY_BTSG_NUM_BISES, String.format("%X", bisCount.toLong())))
+ }
+ if (it.contentMetadata.rawMetadata.size != 0) {
+ entries.add(Pair(KEY_BTSG_METADATA,
+ Base64.encodeToString(it.contentMetadata.rawMetadata, Base64.NO_WRAP)))
+ }
+ }
+
val qrCodeString = SCHEME_BT_BROADCAST_METADATA +
- entries.toQrCodeString(DELIMITER_BT_LEVEL_1) + SUFFIX_QR_CODE
+ entries.toQrCodeString(DELIMITER_ELEMENT) + SUFFIX_QR_CODE
Log.d(TAG, "Generated QR string : $qrCodeString")
return qrCodeString
}
@@ -105,7 +123,7 @@
/**
* Converts QR code string to [BluetoothLeBroadcastMetadata].
*
- * QR code string should prefix with "BT:BluetoothLeBroadcastMetadata:".
+ * QR code string should prefix with "BLUETOOTH:UUID:184F".
*/
fun convertToBroadcastMetadata(qrCodeString: String): BluetoothLeBroadcastMetadata? {
if (!qrCodeString.startsWith(SCHEME_BT_BROADCAST_METADATA)) {
@@ -126,15 +144,6 @@
}
}
- private fun BluetoothLeBroadcastSubgroup.toQrCodeString(): String {
- val entries = mutableListOf<Pair<String, String>>()
- entries.add(Pair(KEY_BTSG_BIS_SYNC, getBisSyncFromChannels(this.channels).toString()))
- entries.add(Pair(KEY_BTSG_BIS_MASK, getBisMaskFromChannels(this.channels).toString()))
- entries.add(Pair(KEY_BTSG_AUDIO_CONTENT,
- Base64.encodeToString(this.contentMetadata.rawMetadata, Base64.NO_WRAP)))
- return entries.toQrCodeString(DELIMITER_BT_LEVEL_2)
- }
-
private fun List<Pair<String, String>>.toQrCodeString(delimiter: String): String {
val entryStrings = this.map{ it.first + DELIMITER_KEY_VALUE + it.second }
return entryStrings.joinToString(separator = delimiter)
@@ -143,23 +152,29 @@
@TargetApi(Build.VERSION_CODES.TIRAMISU)
private fun parseQrCodeToMetadata(input: String): BluetoothLeBroadcastMetadata {
// Split into a list of list
- val level1Fields = input.split(DELIMITER_BT_LEVEL_1)
+ val elementFields = input.split(DELIMITER_ELEMENT)
.map{it.split(DELIMITER_KEY_VALUE, limit = 2)}
- var qrCodeVersion = -1
+
var sourceAddrType = BluetoothDevice.ADDRESS_TYPE_UNKNOWN
var sourceAddrString: String? = null
var sourceAdvertiserSid = -1
var broadcastId = -1
var broadcastName: String? = null
- var publicBroadcastMetadata: BluetoothLeAudioContentMetadata? = null
+ var streamMetadata: BluetoothLeAudioContentMetadata? = null
var paSyncInterval = -1
var broadcastCode: ByteArray? = null
- // List of VendorID -> Data Pairs
- var vendorDataList = mutableListOf<Pair<Int, ByteArray?>>()
- var androidVersion: String? = null
+ var audioConfigQualityStandard = -1
+ var audioConfigQualityHigh = -1
+ var numSubgroups = -1
+
+ // List of subgroup data
+ var subgroupBisSyncList = mutableListOf<UInt>()
+ var subgroupNumOfBisesList = mutableListOf<UInt>()
+ var subgroupMetadataList = mutableListOf<ByteArray?>()
+
val builder = BluetoothLeBroadcastMetadata.Builder()
- for (field: List<String> in level1Fields) {
+ for (field: List<String> in elementFields) {
if (field.isEmpty()) {
continue
}
@@ -167,190 +182,200 @@
// Ignore 3rd value and after
val value = if (field.size > 1) field[1] else ""
when (key) {
- KEY_BT_QR_VER -> {
- require(qrCodeVersion == -1) { "Duplicate qrCodeVersion: $input" }
- qrCodeVersion = value.toInt()
+ // Parse data elements for directing Broadcast Assistants
+ KEY_BT_BROADCAST_NAME -> {
+ require(broadcastName == null) { "Duplicate broadcastName: $input" }
+ broadcastName = String(Base64.decode(value, Base64.NO_WRAP))
}
- KEY_BT_ADDRESS_TYPE -> {
+ KEY_BT_ADVERTISER_ADDRESS_TYPE -> {
require(sourceAddrType == BluetoothDevice.ADDRESS_TYPE_UNKNOWN) {
"Duplicate sourceAddrType: $input"
}
sourceAddrType = value.toInt()
}
- KEY_BT_DEVICE -> {
+ KEY_BT_ADVERTISER_ADDRESS -> {
require(sourceAddrString == null) { "Duplicate sourceAddr: $input" }
- sourceAddrString = value.replace("-", ":")
- }
- KEY_BT_ADVERTISING_SID -> {
- require(sourceAdvertiserSid == -1) { "Duplicate sourceAdvertiserSid: $input" }
- sourceAdvertiserSid = value.toInt()
+ sourceAddrString = value.chunked(2).joinToString(":")
}
KEY_BT_BROADCAST_ID -> {
require(broadcastId == -1) { "Duplicate broadcastId: $input" }
- broadcastId = value.toInt()
- }
- KEY_BT_BROADCAST_NAME -> {
- require(broadcastName == null) { "Duplicate broadcastName: $input" }
- broadcastName = String(Base64.decode(value, Base64.NO_WRAP))
- }
- KEY_BT_PUBLIC_BROADCAST_DATA -> {
- require(publicBroadcastMetadata == null) {
- "Duplicate publicBroadcastMetadata $input"
- }
- publicBroadcastMetadata = BluetoothLeAudioContentMetadata
- .fromRawBytes(Base64.decode(value, Base64.NO_WRAP))
- }
- KEY_BT_SYNC_INTERVAL -> {
- require(paSyncInterval == -1) { "Duplicate paSyncInterval: $input" }
- paSyncInterval = value.toInt()
+ broadcastId = value.toInt(16)
}
KEY_BT_BROADCAST_CODE -> {
require(broadcastCode == null) { "Duplicate broadcastCode: $input" }
- broadcastCode = Base64.decode(value, Base64.NO_WRAP)
+
+ broadcastCode = Base64.decode(value.dropLastWhile { it.equals(0.toByte()) }
+ .toByteArray(), Base64.NO_WRAP)
}
- KEY_BT_ANDROID_VERSION -> {
- require(androidVersion == null) { "Duplicate androidVersion: $input" }
- androidVersion = value
- Log.i(TAG, "QR code Android version: $androidVersion")
+ KEY_BT_STREAM_METADATA -> {
+ require(streamMetadata == null) {
+ "Duplicate streamMetadata $input"
+ }
+ streamMetadata = BluetoothLeAudioContentMetadata
+ .fromRawBytes(Base64.decode(value, Base64.NO_WRAP))
}
- // Repeatable
- KEY_BT_SUBGROUPS -> {
- builder.addSubgroup(parseSubgroupData(value))
+ KEY_BT_STANDARD_QUALITY -> {
+ require(audioConfigQualityStandard == -1) {
+ "Duplicate audioConfigQualityStandard: $input"
+ }
+ audioConfigQualityStandard = value.toInt()
}
- // Repeatable
- KEY_BT_VENDOR_SPECIFIC -> {
- vendorDataList.add(parseVendorData(value))
+ KEY_BT_HIGH_QUALITY -> {
+ require(audioConfigQualityHigh == -1) {
+ "Duplicate audioConfigQualityHigh: $input"
+ }
+ audioConfigQualityHigh = value.toInt()
+ }
+
+ // Parse extended Bluetooth URI data elements
+ KEY_BT_ADVERTISING_SID -> {
+ require(sourceAdvertiserSid == -1) { "Duplicate sourceAdvertiserSid: $input" }
+ sourceAdvertiserSid = value.toInt(16)
+ }
+ KEY_BT_PA_INTERVAL -> {
+ require(paSyncInterval == -1) { "Duplicate paSyncInterval: $input" }
+ paSyncInterval = value.toInt(16)
+ }
+ KEY_BT_NUM_SUBGROUPS -> {
+ require(numSubgroups == -1) { "Duplicate numSubgroups: $input" }
+ numSubgroups = value.toInt(16)
+ }
+
+ // Repeatable subgroup elements
+ KEY_BTSG_BIS_SYNC -> {
+ subgroupBisSyncList.add(value.toUInt(16))
+ }
+ KEY_BTSG_NUM_BISES -> {
+ subgroupNumOfBisesList.add(value.toUInt(16))
+ }
+ KEY_BTSG_METADATA -> {
+ subgroupMetadataList.add(Base64.decode(value, Base64.NO_WRAP))
}
}
}
- Log.d(TAG, "parseQrCodeToMetadata: sourceAddrType=$sourceAddrType, " +
+ Log.d(TAG, "parseQrCodeToMetadata: main data elements sourceAddrType=$sourceAddrType, " +
"sourceAddr=$sourceAddrString, sourceAdvertiserSid=$sourceAdvertiserSid, " +
"broadcastId=$broadcastId, broadcastName=$broadcastName, " +
- "publicBroadcastMetadata=${publicBroadcastMetadata != null}, " +
+ "streamMetadata=${streamMetadata != null}, " +
"paSyncInterval=$paSyncInterval, " +
- "broadcastCode=${broadcastCode?.toString(Charsets.UTF_8)}")
- Log.d(TAG, "Not used in current code, but part of the specification: " +
- "qrCodeVersion=$qrCodeVersion, androidVersion=$androidVersion, " +
- "vendorDataListSize=${vendorDataList.size}")
+ "broadcastCode=${broadcastCode?.toString(Charsets.UTF_8)}, " +
+ "audioConfigQualityStandard=$audioConfigQualityStandard, " +
+ "audioConfigQualityHigh=$audioConfigQualityHigh")
+
val adapter = BluetoothAdapter.getDefaultAdapter()
+ // Check parsed elements data
+ require(broadcastName != null) {
+ "broadcastName($broadcastName) must present in QR code string"
+ }
+ var addr = sourceAddrString
+ var addrType = sourceAddrType
+ if (sourceAddrString != null) {
+ require(sourceAddrType != BluetoothDevice.ADDRESS_TYPE_UNKNOWN) {
+ "sourceAddrType($sourceAddrType) must present if address present"
+ }
+ } else {
+ // Use placeholder device if not present
+ addr = "FF:FF:FF:FF:FF:FF"
+ addrType = BluetoothDevice.ADDRESS_TYPE_RANDOM
+ }
+ val device = adapter.getRemoteLeDevice(requireNotNull(addr), addrType)
+
// add source device and set broadcast code
- val device = adapter.getRemoteLeDevice(requireNotNull(sourceAddrString), sourceAddrType)
+ var audioConfigQuality = BluetoothLeBroadcastMetadata.AUDIO_CONFIG_QUALITY_NONE or
+ (if (audioConfigQualityStandard != -1) audioConfigQualityStandard else 0) or
+ (if (audioConfigQualityHigh != -1) audioConfigQualityHigh else 0)
+
+ // process subgroup data
+ // metadata should include at least 1 subgroup for metadata, add a placeholder group if not present
+ numSubgroups = if (numSubgroups > 0) numSubgroups else 1
+ for (i in 0 until numSubgroups) {
+ val bisSync = subgroupBisSyncList.getOrNull(i)
+ val bisNum = subgroupNumOfBisesList.getOrNull(i)
+ val metadata = subgroupMetadataList.getOrNull(i)
+
+ val channels = convertToChannels(bisSync, bisNum)
+ val audioCodecConfigMetadata = BluetoothLeAudioCodecConfigMetadata.Builder()
+ .setAudioLocation(0).build()
+ val subgroup = BluetoothLeBroadcastSubgroup.Builder().apply {
+ setCodecId(SUBGROUP_LC3_CODEC_ID)
+ setCodecSpecificConfig(audioCodecConfigMetadata)
+ setContentMetadata(
+ BluetoothLeAudioContentMetadata.fromRawBytes(metadata ?: ByteArray(0)))
+ channels.forEach(::addChannel)
+ }.build()
+
+ Log.d(TAG, "parseQrCodeToMetadata: subgroup $i elements bisSync=$bisSync, " +
+ "bisNum=$bisNum, metadata=${metadata != null}")
+
+ builder.addSubgroup(subgroup)
+ }
+
builder.apply {
- setSourceDevice(device, sourceAddrType)
+ setSourceDevice(device, addrType)
setSourceAdvertisingSid(sourceAdvertiserSid)
setBroadcastId(broadcastId)
setBroadcastName(broadcastName)
- setPublicBroadcast(publicBroadcastMetadata != null)
- setPublicBroadcastMetadata(publicBroadcastMetadata)
+ // QR code should set PBP(public broadcast profile) for auracast
+ setPublicBroadcast(true)
+ setPublicBroadcastMetadata(streamMetadata)
setPaSyncInterval(paSyncInterval)
setEncrypted(broadcastCode != null)
setBroadcastCode(broadcastCode)
// Presentation delay is unknown and not useful when adding source
// Broadcast sink needs to sync to the Broadcast source to get presentation delay
setPresentationDelayMicros(0)
+ setAudioConfigQuality(audioConfigQuality)
}
return builder.build()
}
- private fun parseSubgroupData(input: String): BluetoothLeBroadcastSubgroup {
- Log.d(TAG, "parseSubgroupData: $input")
- val fields = input.split(DELIMITER_BT_LEVEL_2)
- var bisSync: UInt? = null
- var bisMask: UInt? = null
- var metadata: ByteArray? = null
-
- fields.forEach { field ->
- val(key, value) = field.split(DELIMITER_KEY_VALUE)
- when (key) {
- KEY_BTSG_BIS_SYNC -> {
- require(bisSync == null) { "Duplicate bisSync: $input" }
- bisSync = value.toUInt()
- }
- KEY_BTSG_BIS_MASK -> {
- require(bisMask == null) { "Duplicate bisMask: $input" }
- bisMask = value.toUInt()
- }
- KEY_BTSG_AUDIO_CONTENT -> {
- require(metadata == null) { "Duplicate metadata: $input" }
- metadata = Base64.decode(value, Base64.NO_WRAP)
- }
- }
- }
- val channels = convertToChannels(requireNotNull(bisSync), requireNotNull(bisMask))
- val audioCodecConfigMetadata = BluetoothLeAudioCodecConfigMetadata.Builder()
- .setAudioLocation(0).build()
- return BluetoothLeBroadcastSubgroup.Builder().apply {
- setCodecId(SUBGROUP_LC3_CODEC_ID)
- setCodecSpecificConfig(audioCodecConfigMetadata)
- setContentMetadata(
- BluetoothLeAudioContentMetadata.fromRawBytes(metadata ?: ByteArray(0)))
- channels.forEach(::addChannel)
- }.build()
- }
-
- private fun parseVendorData(input: String): Pair<Int, ByteArray?> {
- var companyId = -1
- var data: ByteArray? = null
- val fields = input.split(DELIMITER_BT_LEVEL_2)
- fields.forEach { field ->
- val(key, value) = field.split(DELIMITER_KEY_VALUE)
- when (key) {
- KEY_BTVSD_COMPANY_ID -> {
- require(companyId == -1) { "Duplicate companyId: $input" }
- companyId = value.toInt()
- }
- KEY_BTVSD_VENDOR_DATA -> {
- require(data == null) { "Duplicate data: $input" }
- data = Base64.decode(value, Base64.NO_WRAP)
- }
- }
- }
- return Pair(companyId, data)
- }
-
- private fun getBisSyncFromChannels(channels: List<BluetoothLeBroadcastChannel>): UInt {
+ private fun getBisSyncFromChannels(
+ channels: List<BluetoothLeBroadcastChannel>
+ ): Pair<UInt, UInt> {
var bisSync = 0u
- // channel index starts from 1
- channels.forEach { channel ->
- if (channel.isSelected && channel.channelIndex > 0) {
- bisSync = bisSync or (1u shl (channel.channelIndex - 1))
- }
- }
- // No channel is selected means no preference on Android platform
- return if (bisSync == 0u) BIS_SYNC_NO_PREFERENCE else bisSync
- }
-
- private fun getBisMaskFromChannels(channels: List<BluetoothLeBroadcastChannel>): UInt {
- var bisMask = 0u
+ var bisCount = 0u
// channel index starts from 1
channels.forEach { channel ->
if (channel.channelIndex > 0) {
- bisMask = bisMask or (1u shl (channel.channelIndex - 1))
+ bisCount++
+ if (channel.isSelected) {
+ bisSync = bisSync or (1u shl (channel.channelIndex - 1))
+ }
}
}
- return bisMask
+ // No channel is selected means no preference on Android platform
+ return if (bisSync == 0u) Pair(BIS_SYNC_NO_PREFERENCE, bisCount)
+ else Pair(bisSync, bisCount)
}
- private fun convertToChannels(bisSync: UInt, bisMask: UInt):
- List<BluetoothLeBroadcastChannel> {
- Log.d(TAG, "convertToChannels: bisSync=$bisSync, bisMask=$bisMask")
- var selectionMask = bisSync
- if (bisSync != BIS_SYNC_NO_PREFERENCE) {
- require(bisMask == (bisMask or bisSync)) {
- "bisSync($bisSync) must select a subset of bisMask($bisMask) if it has preferences"
- }
- } else {
- // No channel preference means no channel is selected
- selectionMask = 0u
- }
+ private fun convertToChannels(
+ bisSync: UInt?,
+ bisNum: UInt?
+ ): List<BluetoothLeBroadcastChannel> {
+ Log.d(TAG, "convertToChannels: bisSync=$bisSync, bisNum=$bisNum")
+ // if no BIS_SYNC or BIS_NUM available or BIS_SYNC is no preference
+ // return empty channel map with one placeholder channel
+ var selectedChannels = if (bisSync != null && bisNum != null) bisSync else 0u
val channels = mutableListOf<BluetoothLeBroadcastChannel>()
val audioCodecConfigMetadata = BluetoothLeAudioCodecConfigMetadata.Builder()
.setAudioLocation(0).build()
+
+ if (bisSync == BIS_SYNC_NO_PREFERENCE || selectedChannels == 0u) {
+ // No channel preference means no channel is selected
+ // Generate one placeholder channel for metadata
+ val channel = BluetoothLeBroadcastChannel.Builder().apply {
+ setSelected(false)
+ setChannelIndex(1)
+ setCodecMetadata(audioCodecConfigMetadata)
+ }
+ return listOf(channel.build())
+ }
+
for (i in 0 until BIS_SYNC_MAX_CHANNEL) {
val channelMask = 1u shl i
- if ((bisMask and channelMask) != 0u) {
+ if ((selectedChannels and channelMask) != 0u) {
val channel = BluetoothLeBroadcastChannel.Builder().apply {
- setSelected((selectionMask and channelMask) != 0u)
+ setSelected(true)
setChannelIndex(i + 1)
setCodecMetadata(audioCodecConfigMetadata)
}
diff --git a/packages/SettingsLib/tests/unit/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExtTest.kt b/packages/SettingsLib/tests/unit/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExtTest.kt
index 27d7078..1ad20dc 100644
--- a/packages/SettingsLib/tests/unit/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExtTest.kt
+++ b/packages/SettingsLib/tests/unit/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExtTest.kt
@@ -32,7 +32,7 @@
class BluetoothLeBroadcastMetadataExtTest {
@Test
- fun toQrCodeString() {
+ fun toQrCodeString_encrypted() {
val subgroup = BluetoothLeBroadcastSubgroup.Builder().apply {
setCodecId(0x6)
val audioCodecConfigMetadata = BluetoothLeAudioCodecConfigMetadata.Builder().build()
@@ -70,6 +70,37 @@
}
@Test
+ fun toQrCodeString_non_encrypted() {
+ val subgroup = BluetoothLeBroadcastSubgroup.Builder().apply {
+ setCodecId(0x6)
+ val audioCodecConfigMetadata = BluetoothLeAudioCodecConfigMetadata.Builder().build()
+ setContentMetadata(BluetoothLeAudioContentMetadata.Builder()
+ .build())
+ setCodecSpecificConfig(audioCodecConfigMetadata)
+ addChannel(BluetoothLeBroadcastChannel.Builder().apply {
+ setSelected(true)
+ setChannelIndex(1)
+ setCodecMetadata(audioCodecConfigMetadata)
+ }.build())
+ }.build()
+
+ val metadata = BluetoothLeBroadcastMetadata.Builder().apply {
+ setSourceDevice(DevicePublic, BluetoothDevice.ADDRESS_TYPE_PUBLIC)
+ setSourceAdvertisingSid(1)
+ setBroadcastId(0xDE51E9)
+ setBroadcastName("Hockey")
+ setAudioConfigQuality(BluetoothLeBroadcastMetadata.AUDIO_CONFIG_QUALITY_STANDARD)
+ setPaSyncInterval(0xFFFF)
+ setEncrypted(false)
+ addSubgroup(subgroup)
+ }.build()
+
+ val qrCodeString = metadata.toQrCodeString()
+
+ assertThat(qrCodeString).isEqualTo(QR_CODE_STRING_NON_ENCRYPTED)
+ }
+
+ @Test
fun toQrCodeString_NoChannelSelected() {
val subgroup = BluetoothLeBroadcastSubgroup.Builder().apply {
setCodecId(0x6)
@@ -102,6 +133,7 @@
addSubgroup(subgroup)
}.build()
+ // if no channel is selected, no preference(0xFFFFFFFFu) will be set in BIS
val qrCodeString = metadata.toQrCodeString()
val parsedMetadata =
@@ -111,13 +143,11 @@
assertThat(parsedMetadata.subgroups).isNotNull()
assertThat(parsedMetadata.subgroups.size).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].channels).isNotNull()
- assertThat(parsedMetadata.subgroups[0].channels.size).isEqualTo(2)
+ assertThat(parsedMetadata.subgroups[0].channels.size).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].hasChannelPreference()).isFalse()
- // Input order does not matter due to parsing through bisMask
+ // placeholder channel with not selected
assertThat(parsedMetadata.subgroups[0].channels[0].channelIndex).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].channels[0].isSelected).isFalse()
- assertThat(parsedMetadata.subgroups[0].channels[1].channelIndex).isEqualTo(2)
- assertThat(parsedMetadata.subgroups[0].channels[1].isSelected).isFalse()
}
@Test
@@ -162,13 +192,11 @@
assertThat(parsedMetadata.subgroups).isNotNull()
assertThat(parsedMetadata.subgroups.size).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].channels).isNotNull()
- // Only selected channel can be recovered
- assertThat(parsedMetadata.subgroups[0].channels.size).isEqualTo(2)
+ // Only selected channel can be recovered, non-selected ones will be ignored
+ assertThat(parsedMetadata.subgroups[0].channels.size).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].hasChannelPreference()).isTrue()
- assertThat(parsedMetadata.subgroups[0].channels[0].channelIndex).isEqualTo(1)
- assertThat(parsedMetadata.subgroups[0].channels[0].isSelected).isFalse()
- assertThat(parsedMetadata.subgroups[0].channels[1].channelIndex).isEqualTo(2)
- assertThat(parsedMetadata.subgroups[0].channels[1].isSelected).isTrue()
+ assertThat(parsedMetadata.subgroups[0].channels[0].channelIndex).isEqualTo(2)
+ assertThat(parsedMetadata.subgroups[0].channels[0].isSelected).isTrue()
}
@Test
@@ -180,16 +208,34 @@
assertThat(qrCodeString).isEqualTo(QR_CODE_STRING)
}
+ @Test
+ fun decodeAndEncodeAgain_sameString_non_encrypted() {
+ val metadata =
+ BluetoothLeBroadcastMetadataExt
+ .convertToBroadcastMetadata(QR_CODE_STRING_NON_ENCRYPTED)!!
+
+ val qrCodeString = metadata.toQrCodeString()
+
+ assertThat(qrCodeString).isEqualTo(QR_CODE_STRING_NON_ENCRYPTED)
+ }
+
private companion object {
const val TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"
+ const val TEST_DEVICE_ADDRESS_PUBLIC = "AA:BB:CC:00:11:22"
val Device: BluetoothDevice =
BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(TEST_DEVICE_ADDRESS,
BluetoothDevice.ADDRESS_TYPE_RANDOM)
+ val DevicePublic: BluetoothDevice =
+ BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(TEST_DEVICE_ADDRESS_PUBLIC,
+ BluetoothDevice.ADDRESS_TYPE_PUBLIC)
+
const val QR_CODE_STRING =
- "BT:R:65536;T:1;D:00-A1-A1-A1-A1-A1;AS:1;B:123456;BN:VGVzdA==;" +
- "PM:BgNwVGVzdA==;SI:160;C:VGVzdENvZGU=;SG:BS:3,BM:3,AC:BQNUZXN0BARlbmc=;" +
- "VN:U;;"
+ "BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;" +
+ "MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;"
+ const val QR_CODE_STRING_NON_ENCRYPTED =
+ "BLUETOOTH:UUID:184F;BN:SG9ja2V5;AT:0;AD:AABBCC001122;BI:DE51E9;SQ:1;AS:1;PI:FFFF;" +
+ "NS:1;BS:1;NB:1;;"
}
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 7acca19..e2b6bd6 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -36,6 +36,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -47,6 +48,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.net.vcn.Flags;
import android.net.vcn.IVcnManagementService;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
@@ -68,6 +70,7 @@
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -431,6 +434,8 @@
mTelephonySubscriptionTracker.register();
}
+ // The system server automatically has the required permissions for #getMainUser()
+ @SuppressLint("AndroidFrameworkRequiresPermission")
private void enforcePrimaryUser() {
final int uid = mDeps.getBinderCallingUid();
if (uid == Process.SYSTEM_UID) {
@@ -438,7 +443,20 @@
"Calling identity was System Server. Was Binder calling identity cleared?");
}
- if (!UserHandle.getUserHandleForUid(uid).isSystem()) {
+ final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+
+ if (Flags.enforceMainUser()) {
+ final UserManager userManager = mContext.getSystemService(UserManager.class);
+
+ Binder.withCleanCallingIdentity(
+ () -> {
+ if (!Objects.equals(userManager.getMainUser(), userHandle)) {
+ throw new SecurityException(
+ "VcnManagementService can only be used by callers running as"
+ + " the main user");
+ }
+ });
+ } else if (!userHandle.isSystem()) {
throw new SecurityException(
"VcnManagementService can only be used by callers running as the primary user");
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 5e6cf1a..69c6752 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4408,7 +4408,8 @@
|| usage == AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING) {
voiceActive = true;
}
- if (usage == AudioAttributes.USAGE_MEDIA || usage == AudioAttributes.USAGE_GAME) {
+ if (usage == AudioAttributes.USAGE_MEDIA || usage == AudioAttributes.USAGE_GAME
+ || usage == AudioAttributes.USAGE_UNKNOWN) {
mediaActive = true;
}
}
@@ -9680,9 +9681,9 @@
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
mContentResolver.registerContentObserver(Settings.System.getUriFor(
- Settings.System.MASTER_MONO), false, this);
+ Settings.System.MASTER_MONO), false, this, UserHandle.USER_ALL);
mContentResolver.registerContentObserver(Settings.System.getUriFor(
- Settings.System.MASTER_BALANCE), false, this);
+ Settings.System.MASTER_BALANCE), false, this, UserHandle.USER_ALL);
mEncodedSurroundMode = mSettings.getGlobalInt(
mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
diff --git a/services/core/java/com/android/server/audio/MusicFxHelper.java b/services/core/java/com/android/server/audio/MusicFxHelper.java
index 85b3b49..cf0b2ae 100644
--- a/services/core/java/com/android/server/audio/MusicFxHelper.java
+++ b/services/core/java/com/android/server/audio/MusicFxHelper.java
@@ -70,6 +70,8 @@
// The binder token identifying the UidObserver registration.
private IBinder mUidObserverToken = null;
+ private boolean mIsBound;
+
// Package name and list of open audio sessions for this package
private static class PackageSessions {
String mPackageName;
@@ -90,7 +92,6 @@
* observer will also be removed, and observer token reset to null
*/
private class MySparseArray extends SparseArray<PackageSessions> {
- private final String mMusicFxPackageName = "com.android.musicfx";
@RequiresPermission(anyOf = {
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
@@ -110,6 +111,7 @@
if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
Intent bindIntent = new Intent().setClassName(mMusicFxPackageName,
"com.android.musicfx.KeepAliveService");
+ mIsBound = true;
mContext.bindServiceAsUser(
bindIntent, mMusicFxBindConnection, Context.BIND_AUTO_CREATE,
UserHandle.of(getCurrentUserId()));
@@ -158,9 +160,12 @@
Log.e(TAG, "RemoteException with unregisterUidObserver: " + e);
}
mUidObserverToken = null;
- mContext.unbindService(mMusicFxBindConnection);
- Log.i(TAG, "last session closed, unregister UID observer, and unbind "
- + mMusicFxPackageName);
+ if (mIsBound) {
+ mContext.unbindService(mMusicFxBindConnection);
+ mIsBound = false;
+ Log.i(TAG, "last session closed, unregister UID observer, and unbind "
+ + mMusicFxPackageName);
+ }
}
}
}
@@ -229,6 +234,10 @@
if (ril != null && ril.size() != 0) {
ResolveInfo ri = ril.get(0);
final String senderPackageName = intent.getStringExtra(AudioEffect.EXTRA_PACKAGE_NAME);
+ if (senderPackageName == null) {
+ Log.w(TAG, "Intent package name must not be null");
+ return;
+ }
try {
if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
final int senderUid = pm.getPackageUidAsUser(senderPackageName,
@@ -265,7 +274,7 @@
+ senderUid + ", package: " + senderPackageName + ", abort");
return false;
}
- if (pkgSessions.mPackageName != senderPackageName) {
+ if (!pkgSessions.mPackageName.equals(senderPackageName)) {
Log.w(TAG, "Inconsistency package names for UID open: " + senderUid + " prev: "
+ pkgSessions.mPackageName + ", now: " + senderPackageName);
return false;
@@ -297,7 +306,7 @@
Log.e(TAG, senderPackageName + " UID " + senderUid + " does not exist in map, abort");
return false;
}
- if (pkgSessions.mPackageName != senderPackageName) {
+ if (!pkgSessions.mPackageName.equals(senderPackageName)) {
Log.w(TAG, "Inconsistency package names for UID " + senderUid + " close, prev: "
+ pkgSessions.mPackageName + ", now: " + senderPackageName);
return false;
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 4f7f31d..5be2291 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -342,9 +342,6 @@
//------------------------------------------------------
// routing monitoring
synchronized void onRoutingUpdated() {
- if (!mFeatureEnabled) {
- return;
- }
switch (mState) {
case STATE_UNINITIALIZED:
case STATE_NOT_SUPPORTED:
@@ -388,7 +385,7 @@
setDispatchAvailableState(false);
}
- boolean enabled = able && enabledAvailable.first;
+ boolean enabled = mFeatureEnabled && able && enabledAvailable.first;
if (enabled) {
loglogi("Enabling Spatial Audio since enabled for media device:"
+ currentDevice);
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index 79d1753..348452e 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -534,9 +534,12 @@
} else {
storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
}
- List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
- UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
- true /* onlyCoreApps */);
+ final List<String> deferPackages;
+ synchronized (mPm.mInstallLock) {
+ deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
+ UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
+ true /* onlyCoreApps */);
+ }
Future<?> prepareAppDataFuture = SystemServerInitThreadPool.submit(() -> {
TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
Trace.TRACE_TAG_PACKAGE_MANAGER);
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 93f26ae..c85ceac 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -642,6 +642,8 @@
.getPackages()
.get(0)
.getVersionRolledBackFrom();
+ Slog.i(TAG, "Rolling back high impact rollback for package: "
+ + firstRollback.getPackageName());
rollbackPackage(sortedHighImpactRollbacks.get(0), firstRollback, rollbackReason);
}
diff --git a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
index 519c0ed..7fc0292 100644
--- a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
+++ b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
@@ -293,6 +293,8 @@
return "REASON_APP_NOT_RESPONDING";
case WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT:
return "REASON_NATIVE_CRASH_DURING_BOOT";
+ case WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_BOOT_LOOPING:
+ return "REASON_BOOT_LOOP";
default:
return "UNKNOWN";
}
diff --git a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
index 3619253..47425322 100644
--- a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
+++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -115,6 +115,10 @@
// validation failure.
private static final int IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DEFAULT = 12;
+ /** Carriers can disable the detector by setting the threshold to -1 */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR = -1;
+
private static final int POLL_IPSEC_STATE_INTERVAL_SECONDS_DEFAULT = 20;
// By default, there's no maximum limit enforced
@@ -271,7 +275,10 @@
// When multiple parallel inbound transforms are created, NetworkMetricMonitor will be
// enabled on the last one as a sample
mInboundTransform = inboundTransform;
- start();
+
+ if (!Flags.allowDisableIpsecLossDetector() || canStart()) {
+ start();
+ }
}
@Override
@@ -284,6 +291,14 @@
mPacketLossRatePercentThreshold = getPacketLossRatePercentThreshold(carrierConfig);
mMaxSeqNumIncreasePerSecond = getMaxSeqNumIncreasePerSecond(carrierConfig);
}
+
+ if (Flags.allowDisableIpsecLossDetector() && canStart() != isStarted()) {
+ if (canStart()) {
+ start();
+ } else {
+ stop();
+ }
+ }
}
@Override
@@ -298,6 +313,12 @@
mHandler.postDelayed(new PollIpSecStateRunnable(), mCancellationToken, 0L);
}
+ private boolean canStart() {
+ return mInboundTransform != null
+ && mPacketLossRatePercentThreshold
+ != IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR;
+ }
+
@Override
protected void start() {
super.start();
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 1485b96..231ca5a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -3436,7 +3436,8 @@
}
// System wallpaper does not support multiple displays, attach this display to
// the fallback wallpaper.
- if (mFallbackWallpaper != null) {
+ if (mFallbackWallpaper != null && mFallbackWallpaper
+ .connection != null) {
final DisplayConnector connector = mFallbackWallpaper
.connection.getDisplayConnectorOrCreate(displayId);
if (connector == null) return;
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index ce47f5c..60454fc 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -18,6 +18,7 @@
yunfanc@google.com
wilsonshih@google.com
jiamingliu@google.com
+pdwilliams@google.com
# Files related to background activity launches
per-file Background*Start* = set noparent
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index dd49260..9dfca4d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -432,10 +432,10 @@
import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
-import android.security.KeyStore;
import android.security.keymaster.KeymasterCertificateChain;
import android.security.keystore.AttestationUtils;
import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
import android.security.keystore.ParcelableKeyGenParameterSpec;
import android.stats.devicepolicy.DevicePolicyEnums;
import android.telecom.TelecomManager;
@@ -6248,7 +6248,7 @@
KeyChain.bindAsUser(mContext, caller.getUserHandle());
try {
IKeyChainService keyChain = keyChainConnection.getService();
- if (!keyChain.installKeyPair(privKey, cert, chain, alias, KeyStore.UID_SELF)) {
+ if (!keyChain.installKeyPair(privKey, cert, chain, alias, KeyProperties.UID_SELF)) {
logInstallKeyPairFailure(caller, isCredentialManagementApp);
return false;
}
@@ -6588,7 +6588,7 @@
}
// As the caller will be granted access to the key, ensure no UID was specified, as
// it will not have the desired effect.
- if (keySpec.getUid() != KeyStore.UID_SELF) {
+ if (keySpec.getUid() != KeyProperties.UID_SELF) {
Slogf.e(LOG_TAG, "Only the caller can be granted access to the generated keypair.");
logGenerateKeyPairFailure(caller, isCredentialManagementApp);
return false;
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index f469ab5..33d3cd0 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -2077,8 +2077,20 @@
writer.println("Unknown app ID $appId.")
}
}
+ } else if (args[0] == "--package" && args.size == 2) {
+ val packageName = args[1]
+ service.getState {
+ val packageState = state.externalState.packageStates[packageName]
+ if (packageState != null) {
+ writer.dumpAppIdState(packageState.appId, state, indexedSetOf(packageName))
+ } else {
+ writer.println("Unknown package $packageName.")
+ }
+ }
} else {
- writer.println("Usage: dumpsys permission [--app-id APP_ID]")
+ writer.println(
+ "Usage: dumpsys permissionmgr [--app-id <APP_ID>] [--package <PACKAGE_NAME>]"
+ )
}
}
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 68038fa..54d101a 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -248,6 +248,7 @@
+ e.getMessage());
}
});
+ jobFinished(params, false);
return true;
}
diff --git a/services/tests/apexsystemservices/OWNERS b/services/tests/apexsystemservices/OWNERS
index 0295b9e..8b6675a 100644
--- a/services/tests/apexsystemservices/OWNERS
+++ b/services/tests/apexsystemservices/OWNERS
@@ -1,4 +1 @@
-omakoto@google.com
-satayev@google.com
-
include platform/packages/modules/common:/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 4a21645..42814e7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -239,6 +239,9 @@
@Test
public void testBootLoopDetectionWithExecutionForAllRescueLevels() {
+ // this is old test where the flag needs to be disabled
+ mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
any(Executor.class),
@@ -449,6 +452,9 @@
@Test
public void testNonPersistentAppCrashDetectionWithScopedResets() {
+ // this is old test where the flag needs to be disabled
+ mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
any(Executor.class),
@@ -506,6 +512,9 @@
@Test
public void testNonDeviceConfigSettingsOnlyResetOncePerLevel() {
+ // this is old test where the flag needs to be disabled
+ mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> DeviceConfig.setMonitorCallback(eq(mMockContentResolver),
any(Executor.class),
@@ -879,6 +888,9 @@
@Test
public void testBootLoopLevels() {
+ // this is old test where the flag needs to be disabled
+ mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
assertEquals(observer.onBootLoop(0), PackageHealthObserverImpact.USER_IMPACT_LEVEL_0);
diff --git a/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
index 472a82c..d5638e9 100644
--- a/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
@@ -57,8 +57,9 @@
private ResolveInfo mResolveInfo1 = new ResolveInfo();
private ResolveInfo mResolveInfo2 = new ResolveInfo();
- private final String mTestPkg1 = "testPkg1", mTestPkg2 = "testPkg2", mTestPkg3 = "testPkg3";
- private final String mMusicFxPkgName = "com.android.musicfx";
+ private final String mTestPkg1 = new String("testPkg1"), mTestPkg2 = new String("testPkg2"),
+ mTestPkg3 = new String("testPkg3"), mTestPkg1Equivalent = new String("testPkg1");
+ private final String mMusicFxPkgName = new String("com.android.musicfx");
private final int mTestUid1 = 1, mTestUid2 = 2, mTestUid3 = 3, mMusicFxUid = 78;
private final int mTestSession1 = 11, mTestSession2 = 22, mTestSession3 = 33;
@@ -191,7 +192,8 @@
public void testCloseBroadcastIntent() {
Log.i(TAG, "running testCloseBroadcastIntent");
- closeSessionWithResList(null, 0, 0, null, mTestSession1, mTestUid1);
+ closeSessionWithResList(null, 0 /* unbind */, 0 /* broadcast */, null /* packageName */,
+ mTestSession1, mTestUid1);
}
/**
@@ -225,8 +227,10 @@
public void testBroadcastIntentWithNoPackageAndNoBroadcastReceiver() {
Log.i(TAG, "running testBroadcastIntentWithNoPackageAndNoBroadcastReceiver");
- openSessionWithResList(mEmptyList, 0, 0, null, mTestSession1, mTestUid1);
- closeSessionWithResList(mEmptyList, 0, 0, null, mTestSession1, mTestUid1);
+ openSessionWithResList(mEmptyList, 0 /* bind */, 0 /* broadcast */, null /* packageName */,
+ mTestSession1, mTestUid1);
+ closeSessionWithResList(mEmptyList, 0 /* unbind */, 0 /* broadcast */,
+ null /* packageName */, mTestSession1, mTestUid1);
}
/**
@@ -236,26 +240,10 @@
public void testBroadcastIntentWithNoPackageAndOneBroadcastReceiver() {
Log.i(TAG, "running testBroadcastIntentWithNoPackageAndOneBroadcastReceiver");
- int broadcasts = 1, bind = 1, unbind = 1;
- openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession1, mTestUid1);
- broadcasts = broadcasts + 1;
- closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession1, mTestUid1);
-
- // repeat with different session ID
- broadcasts = broadcasts + 1;
- bind = bind + 1;
- unbind = unbind + 1;
- openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession2, mTestUid1);
- broadcasts = broadcasts + 1;
- closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession2, mTestUid1);
-
- // repeat with different UID
- broadcasts = broadcasts + 1;
- bind = bind + 1;
- unbind = unbind + 1;
- openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession1, mTestUid2);
- broadcasts = broadcasts + 1;
- closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession1, mTestUid2);
+ openSessionWithResList(mSingleList, 0 /* bind */, 0 /* broadcast */,
+ null /* packageName */, mTestSession1, mTestUid1);
+ closeSessionWithResList(mSingleList, 0 /* unbind */, 0 /* broadcast */,
+ null /* packageName */, mTestSession1, mTestUid1);
}
/**
@@ -265,8 +253,50 @@
public void testBroadcastIntentWithNoPackageAndTwoBroadcastReceivers() {
Log.i(TAG, "running testBroadcastIntentWithNoPackageAndTwoBroadcastReceivers");
- openSessionWithResList(mDoubleList, 1, 1, null, mTestSession1, mTestUid1);
- closeSessionWithResList(mDoubleList, 1, 2, null, mTestSession1, mTestUid1);
+ openSessionWithResList(mDoubleList, 0 /* bind */, 0 /* broadcast */,
+ null /* packageName */, mTestSession1, mTestUid1);
+ closeSessionWithResList(mDoubleList, 0 /* bind */, 0 /* broadcast */,
+ null /* packageName */, mTestSession1, mTestUid1);
+ }
+
+ @Test
+ public void testBroadcastIntentWithPackageAndOneBroadcastReceiver() {
+ Log.i(TAG, "running testBroadcastIntentWithPackageAndOneBroadcastReceiver");
+
+ int broadcasts = 1, bind = 1, unbind = 1;
+ openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+
+ // repeat with different session ID
+ broadcasts = broadcasts + 1;
+ bind = bind + 1;
+ unbind = unbind + 1;
+ openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid1);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+ mTestUid1);
+
+ // repeat with different UID
+ broadcasts = broadcasts + 1;
+ bind = bind + 1;
+ unbind = unbind + 1;
+ openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg3, mTestSession1, mTestUid2);
+ broadcasts = broadcasts + 1;
+ closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg3, mTestSession1,
+ mTestUid2);
+ }
+
+ @Test
+ public void testBroadcastIntentWithPackageAndTwoBroadcastReceivers() {
+ Log.i(TAG, "running testBroadcastIntentWithPackageAndTwoBroadcastReceivers");
+
+ openSessionWithResList(mDoubleList, 1 /* bind */, 1 /* broadcast */,
+ mTestPkg1 /* packageName */, mTestSession1, mTestUid1);
+ closeSessionWithResList(mDoubleList, 1 /* unbind */, 2 /* broadcast */,
+ mTestPkg1 /* packageName */, mTestSession1, mTestUid1);
}
/**
@@ -639,4 +669,18 @@
unbind = unbind + 1;
sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid3, unbind, broadcasts);
}
+
+ /**
+ * Test audio session open/close with same package name value but different String object.
+ */
+ @Test
+ public void testSessionOpenCloseWithSamePackageNameValueButDiffObject() {
+ Log.i(TAG, "running testSessionOpenCloseWithSamePackageNameValueButDiffObject");
+ int broadcasts = 1;
+ openSessionWithResList(mSingleList, 1 /* bind */, broadcasts, mTestPkg1, mTestSession1,
+ mTestUid1);
+ closeSessionWithResList(mSingleList, 1 /* unbind */, broadcasts + 1, mTestPkg1Equivalent,
+ mTestSession1, mTestUid1);
+ }
+
}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 960b57c..580efe1 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -70,6 +70,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Uri;
+import android.net.vcn.Flags;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
@@ -82,7 +83,9 @@
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.test.TestLooper;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -101,6 +104,7 @@
import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -118,6 +122,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnManagementServiceTest {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
private static final String TEST_PACKAGE_NAME =
VcnManagementServiceTest.class.getPackage().getName();
@@ -129,7 +135,12 @@
private static final ParcelUuid TEST_UUID_3 = new ParcelUuid(new UUID(2, 2));
private static final VcnConfig TEST_VCN_CONFIG;
private static final VcnConfig TEST_VCN_CONFIG_PKG_2;
- private static final int TEST_UID = Process.FIRST_APPLICATION_UID;
+
+ private static final int TEST_UID = 1010000; // A non-system user
+ private static final UserHandle TEST_USER_HANDLE = UserHandle.getUserHandleForUid(TEST_UID);
+ private static final UserHandle TEST_USER_HANDLE_OTHER =
+ UserHandle.of(TEST_USER_HANDLE.getIdentifier() + 1);
+
private static final String TEST_IFACE_NAME = "TEST_IFACE";
private static final String TEST_IFACE_NAME_2 = "TEST_IFACE2";
private static final LinkProperties TEST_LP_1 = new LinkProperties();
@@ -187,6 +198,7 @@
private final TelephonyManager mTelMgr = mock(TelephonyManager.class);
private final SubscriptionManager mSubMgr = mock(SubscriptionManager.class);
private final AppOpsManager mAppOpsMgr = mock(AppOpsManager.class);
+ private final UserManager mUserManager = mock(UserManager.class);
private final VcnContext mVcnContext = mock(VcnContext.class);
private final PersistableBundleUtils.LockingReadWriteHelper mConfigReadWriteHelper =
mock(PersistableBundleUtils.LockingReadWriteHelper.class);
@@ -218,6 +230,9 @@
Context.TELEPHONY_SUBSCRIPTION_SERVICE,
SubscriptionManager.class);
setupSystemService(mMockContext, mAppOpsMgr, Context.APP_OPS_SERVICE, AppOpsManager.class);
+ setupSystemService(mMockContext, mUserManager, Context.USER_SERVICE, UserManager.class);
+
+ doReturn(TEST_USER_HANDLE).when(mUserManager).getMainUser();
doReturn(TEST_PACKAGE_NAME).when(mMockContext).getOpPackageName();
@@ -267,6 +282,8 @@
@Before
public void setUp() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_MAIN_USER);
+
doNothing()
.when(mMockContext)
.enforceCallingOrSelfPermission(
@@ -717,10 +734,8 @@
}
@Test
- public void testSetVcnConfigRequiresSystemUser() throws Exception {
- doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID))
- .when(mMockDeps)
- .getBinderCallingUid();
+ public void testSetVcnConfigRequiresMainUser() throws Exception {
+ doReturn(TEST_USER_HANDLE_OTHER).when(mUserManager).getMainUser();
try {
mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
@@ -832,10 +847,8 @@
}
@Test
- public void testClearVcnConfigRequiresSystemUser() throws Exception {
- doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID))
- .when(mMockDeps)
- .getBinderCallingUid();
+ public void testClearVcnConfigRequiresMainUser() throws Exception {
+ doReturn(TEST_USER_HANDLE_OTHER).when(mUserManager).getMainUser();
try {
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
@@ -921,10 +934,8 @@
}
@Test
- public void testGetConfiguredSubscriptionGroupsRequiresSystemUser() throws Exception {
- doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID))
- .when(mMockDeps)
- .getBinderCallingUid();
+ public void testGetConfiguredSubscriptionGroupsRequiresMainUser() throws Exception {
+ doReturn(TEST_USER_HANDLE_OTHER).when(mUserManager).getMainUser();
try {
mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME);
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
index c8b60e5..441a4ae 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
@@ -20,6 +20,7 @@
import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY;
import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY;
+import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR;
import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.MIN_VALID_EXPECTED_RX_PACKET_NUM;
import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.getMaxSeqNumIncreasePerSecond;
import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
@@ -584,4 +585,56 @@
MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED,
getMaxSeqNumIncreasePerSecond(mCarrierConfig));
}
+
+ private IpSecPacketLossDetector newDetectorAndSetTransform(int threshold) throws Exception {
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY),
+ anyInt()))
+ .thenReturn(threshold);
+
+ final IpSecPacketLossDetector detector =
+ new IpSecPacketLossDetector(
+ mVcnContext,
+ mNetwork,
+ mCarrierConfig,
+ mMetricMonitorCallback,
+ mDependencies);
+
+ detector.setIsSelectedUnderlyingNetwork(true /* setIsSelected */);
+ detector.setInboundTransformInternal(mIpSecTransform);
+
+ return detector;
+ }
+
+ @Test
+ public void testDisableAndEnableDetectorWithCarrierConfig() throws Exception {
+ final IpSecPacketLossDetector detector =
+ newDetectorAndSetTransform(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR);
+
+ assertFalse(detector.isStarted());
+
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY),
+ anyInt()))
+ .thenReturn(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD);
+ detector.setCarrierConfig(mCarrierConfig);
+
+ assertTrue(detector.isStarted());
+ }
+
+ @Test
+ public void testEnableAndDisableDetectorWithCarrierConfig() throws Exception {
+ final IpSecPacketLossDetector detector =
+ newDetectorAndSetTransform(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD);
+
+ assertTrue(detector.isStarted());
+
+ when(mCarrierConfig.getInt(
+ eq(VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY),
+ anyInt()))
+ .thenReturn(IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_DISABLE_DETECTOR);
+ detector.setCarrierConfig(mCarrierConfig);
+
+ assertFalse(detector.isStarted());
+ }
}
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
index edad678..0439d5f5 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkEvaluationTestBase.java
@@ -123,6 +123,7 @@
mSetFlagsRule.enableFlags(Flags.FLAG_VALIDATE_NETWORK_ON_IPSEC_LOSS);
mSetFlagsRule.enableFlags(Flags.FLAG_EVALUATE_IPSEC_LOSS_ON_LP_NC_CHANGE);
mSetFlagsRule.enableFlags(Flags.FLAG_HANDLE_SEQ_NUM_LEAP);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_DISABLE_IPSEC_LOSS_DETECTOR);
when(mNetwork.getNetId()).thenReturn(-1);
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index b56b4c4..57459e3 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -441,7 +441,7 @@
manifest_action.Action(AutoGenerateIsSplitRequired);
manifest_action.Action(VerifyManifest);
manifest_action.Action(FixCoreAppAttribute);
- manifest_action.Action([&](xml::Element* el) -> bool {
+ manifest_action.Action([this, diag](xml::Element* el) -> bool {
EnsureNamespaceIsDeclared("android", xml::kSchemaAndroid, &el->namespace_decls);
if (options_.version_name_default) {
@@ -504,7 +504,7 @@
manifest_action["eat-comment"];
// Uses-sdk actions.
- manifest_action["uses-sdk"].Action([&](xml::Element* el) -> bool {
+ manifest_action["uses-sdk"].Action([this](xml::Element* el) -> bool {
if (options_.min_sdk_version_default &&
el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
// There was no minSdkVersion defined and we have a default to assign.
@@ -526,7 +526,7 @@
// Instrumentation actions.
manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
- manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
+ manifest_action["instrumentation"].Action([this](xml::Element* el) -> bool {
if (!options_.rename_instrumentation_target_package) {
return true;
}
@@ -542,7 +542,7 @@
manifest_action["attribution"];
manifest_action["attribution"]["inherit-from"];
manifest_action["original-package"];
- manifest_action["overlay"].Action([&](xml::Element* el) -> bool {
+ manifest_action["overlay"].Action([this](xml::Element* el) -> bool {
if (options_.rename_overlay_target_package) {
if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
attr->value = options_.rename_overlay_target_package.value();
@@ -623,7 +623,7 @@
uses_package_action["additional-certificate"];
if (options_.debug_mode) {
- application_action.Action([&](xml::Element* el) -> bool {
+ application_action.Action([](xml::Element* el) -> bool {
xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
attr->value = "true";
return true;