Merge "Add a method to get rawContact"
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 591e8ba..4becc6b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1008,13 +1008,21 @@
}
@Override
- public void onUserUnlocked(@NonNull TargetUser user) {
+ public void onUserStarting(@NonNull TargetUser user) {
synchronized (mLock) {
- // Note that the user has started after its unlocked instead of when the user
- // actually starts because the storage won't be decrypted until unlock.
mStartedUsers = ArrayUtils.appendInt(mStartedUsers, user.getUserIdentifier());
}
- // Let's kick any outstanding jobs for this user.
+ // The user is starting but credential encrypted storage is still locked.
+ // Only direct-boot-aware jobs can safely run.
+ // Let's kick off any eligible jobs for this user.
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ }
+
+ @Override
+ public void onUserUnlocked(@NonNull TargetUser user) {
+ // The user is fully unlocked and credential encrypted storage is now decrypted.
+ // Direct-boot-UNaware jobs can now safely run.
+ // Let's kick off any outstanding jobs for this user.
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
diff --git a/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS b/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS
new file mode 100644
index 0000000..f560434
--- /dev/null
+++ b/core/java/android/app/admin/EnterprisePlatformSecurity_OWNERS
@@ -0,0 +1,4 @@
+rubinxu@google.com
+acjohnston@google.com
+pgrafov@google.com
+alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/app/admin/EnterprisePlatform_OWNERS b/core/java/android/app/admin/EnterprisePlatform_OWNERS
new file mode 100644
index 0000000..fb00fe5
--- /dev/null
+++ b/core/java/android/app/admin/EnterprisePlatform_OWNERS
@@ -0,0 +1,2 @@
+file:WorkDeviceExperience_OWNERS
+file:EnterprisePlatformSecurity_OWNERS
\ No newline at end of file
diff --git a/core/java/android/app/admin/OWNERS b/core/java/android/app/admin/OWNERS
index 6acbef2..10a5f14 100644
--- a/core/java/android/app/admin/OWNERS
+++ b/core/java/android/app/admin/OWNERS
@@ -1,11 +1,5 @@
# Bug component: 142675
-# Android Enterprise team
-rubinxu@google.com
-sandness@google.com
-alexkershaw@google.com
-pgrafov@google.com
+file:EnterprisePlatform_OWNERS
-# Emeritus
-yamasani@google.com
-eranm@google.com
+yamasani@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/app/admin/WorkDeviceExperience_OWNERS b/core/java/android/app/admin/WorkDeviceExperience_OWNERS
new file mode 100644
index 0000000..dcacaa2
--- /dev/null
+++ b/core/java/android/app/admin/WorkDeviceExperience_OWNERS
@@ -0,0 +1,5 @@
+work-device-experience+reviews@google.com
+scottjonathan@google.com
+arangelov@google.com
+kholoudm@google.com
+alexkershaw@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index c71fcc6..9caeb29 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1186,11 +1186,6 @@
mAttributionSource = attributionSource;
}
- /** {@hide} */
- public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
- setAttributionSource(attributionSource);
- }
-
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof BluetoothDevice) {
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 20152f3..b5df4db 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -62,15 +62,15 @@
private static final String TAG = "BluetoothManager";
private static final boolean DBG = false;
- private final AttributionSource mAttributionSource;
+ private static AttributionSource sAttributionSource = null;
private final BluetoothAdapter mAdapter;
/**
* @hide
*/
public BluetoothManager(Context context) {
- mAttributionSource = resolveAttributionSource(context);
- mAdapter = BluetoothAdapter.createAdapter(mAttributionSource);
+ sAttributionSource = resolveAttributionSource(context);
+ mAdapter = BluetoothAdapter.createAdapter(sAttributionSource);
}
/** {@hide} */
@@ -79,6 +79,9 @@
if (context != null) {
res = context.getAttributionSource();
}
+ else if (sAttributionSource != null) {
+ return sAttributionSource;
+ }
if (res == null) {
res = ActivityThread.currentAttributionSource();
}
@@ -198,8 +201,8 @@
IBluetoothGatt iGatt = managerService.getBluetoothGatt();
if (iGatt == null) return devices;
devices = Attributable.setAttributionSource(
- iGatt.getDevicesMatchingConnectionStates(states, mAttributionSource),
- mAttributionSource);
+ iGatt.getDevicesMatchingConnectionStates(states, sAttributionSource),
+ sAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d811040..2fd437d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -31,7 +31,6 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.AppGlobals;
-import android.bluetooth.BluetoothDevice;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -11462,16 +11461,6 @@
if (fromProtectedComponent) {
mLocalFlags |= LOCAL_FLAG_FROM_PROTECTED_COMPONENT;
}
-
- // Special attribution fix-up logic for any BluetoothDevice extras
- // passed via Bluetooth intents
- if (mAction != null && mAction.startsWith("android.bluetooth.")
- && hasExtra(BluetoothDevice.EXTRA_DEVICE)) {
- final BluetoothDevice device = getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (device != null) {
- device.prepareToEnterProcess(source);
- }
- }
}
/** @hide */
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index b66f048..755114e 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1736,35 +1736,9 @@
* object and the given one. Does not change the values of either. Any
* undefined fields in <var>delta</var> are ignored.
* @return Returns a bit mask indicating which configuration
- * values has changed, containing any combination of
- * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
- * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
- * {@link android.content.pm.ActivityInfo#CONFIG_MCC
- * PackageManager.ActivityInfo.CONFIG_MCC},
- * {@link android.content.pm.ActivityInfo#CONFIG_MNC
- * PackageManager.ActivityInfo.CONFIG_MNC},
- * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
- * PackageManager.ActivityInfo.CONFIG_LOCALE},
- * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
- * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
- * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
- * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
- * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
- * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
- * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
- * PackageManager.ActivityInfo.CONFIG_ORIENTATION},
- * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
- * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
- * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
- * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
- * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
- * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
- * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
- * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}.
- * {@link android.content.pm.ActivityInfo#CONFIG_FONT_WEIGHT_ADJUSTMENT
- * PackageManager.ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT.
+ * values have changed.
*/
- public int diff(Configuration delta) {
+ public @Config int diff(Configuration delta) {
return diff(delta, false /* compareUndefined */, false /* publicOnly */);
}
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 24a06df..f55bcd3 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -2,5 +2,5 @@
include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS
-per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, ngeoffray@google.com
-per-file SntpClient*, sntp/* = file:/services/core/java/com/android/server/timedetector/OWNERS
+per-file SSL*,Uri*,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
diff --git a/core/java/android/net/sntp/OWNERS b/core/java/android/net/sntp/OWNERS
new file mode 100644
index 0000000..9a3e264
--- /dev/null
+++ b/core/java/android/net/sntp/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/timedetector/OWNERS
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index fa578be..ab2c8c0 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -401,7 +401,7 @@
private static final int WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS = 1000;
@CriticalNative
- private static native long nativeGetBlobAshmemSize(long nativePtr);
+ private static native long nativeGetOpenAshmemSize(long nativePtr);
public final static Parcelable.Creator<String> STRING_CREATOR
= new Parcelable.Creator<String>() {
@@ -2891,9 +2891,11 @@
/**
* Same as {@link #readList(List, ClassLoader)} but accepts {@code clazz} parameter as
- * the type required for each item. If the item to be deserialized is not an instance
- * of that class or any of its children class
- * a {@link BadParcelableException} will be thrown.
+ * the type required for each item.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children classes or there was an error
+ * trying to instantiate an element.
*/
public <T> void readList(@NonNull List<? super T> outVal,
@Nullable ClassLoader loader, @NonNull Class<T> clazz) {
@@ -3894,8 +3896,11 @@
/**
* Same as {@link #readParcelable(ClassLoader)} but accepts {@code clazz} parameter as the type
- * required for each item. If the item to be deserialized is not an instance of that class or
- * any of its children classes a {@link BadParcelableException} will be thrown.
+ * required for each item.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children classes or there was an error
+ * trying to instantiate an element.
*/
@Nullable
public <T extends Parcelable> T readParcelable(@Nullable ClassLoader loader,
@@ -3961,8 +3966,11 @@
/**
* Same as {@link #readParcelableCreator(ClassLoader)} but accepts {@code clazz} parameter
- * as the required type. If the item to be deserialized is not an instance of that class
- * or any of its children classes a {@link BadParcelableException} will be thrown.
+ * as the required type.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children class or there there was an error
+ * trying to read the {@link Parcelable.Creator}.
*/
@Nullable
public <T> Parcelable.Creator<T> readParcelableCreator(
@@ -4373,8 +4381,8 @@
/**
* @hide For testing
*/
- public long getBlobAshmemSize() {
- return nativeGetBlobAshmemSize(mNativePtr);
+ public long getOpenAshmemSize() {
+ return nativeGetOpenAshmemSize(mNativePtr);
}
private static String valueTypeToString(int type) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index dd4de0a..3028a6d 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -691,6 +691,11 @@
* {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
* subscription ID. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ *
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
void onMessageWaitingIndicatorChanged(boolean mwi);
@@ -710,6 +715,11 @@
* {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
* subscription ID. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ *
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
void onCallForwardingIndicatorChanged(boolean cfi);
@@ -868,6 +878,10 @@
* subscription ID. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+ *
* @param callState {@link PreciseCallState}
*/
@RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -910,6 +924,10 @@
* subscription ID. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+ *
* @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
*/
@RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -932,9 +950,9 @@
* subscription ID. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
- * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
- * or the calling app has carrier privileges
- * (see {@link TelephonyManager#hasCarrierPrivileges}).
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
*
* @param dataConnectionState {@link PreciseDataConnectionState}
*/
@@ -1063,6 +1081,10 @@
* given subscription ID. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ *
* @param emergencyNumberList Map associating all active subscriptions on the device with
* the list of emergency numbers originating from that
* subscription.
@@ -1157,6 +1179,11 @@
* For example, it could be the current active opportunistic subscription
* in use, or the subscription user selected as default data subscription in
* DSDS mode.
+ *
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ *
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
void onActiveDataSubscriptionIdChanged(int subId);
@@ -1225,6 +1252,11 @@
* <p>Because registration failures are ephemeral, this callback is not sticky.
* Registrants will not receive the most recent past value when registering.
*
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} and
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ *
* @param cellIdentity the CellIdentity, which must include the globally unique
* identifier
* for the cell (for example, all components of the CGI or ECGI).
@@ -1308,6 +1340,10 @@
* subscription ID. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+ *
* @param callAttributes the call attributes
*/
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -1324,6 +1360,11 @@
* <p>Barring info is provided for all services applicable to the current camped/registered
* cell, for the registered PLMN and current access class/access category.
*
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} and
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ *
* @param barringInfo for all services on the current cell.
* @see android.telephony.BarringInfo
*/
@@ -1341,6 +1382,10 @@
/**
* Callback invoked when the current physical channel configuration has changed
*
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+ *
* @param configs List of the current {@link PhysicalChannelConfig}s
*/
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
@@ -1357,6 +1402,10 @@
/**
* Callback invoked when the data enabled changes.
*
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+ *
* @param enabled {@code true} if data is enabled, otherwise disabled.
* @param reason Reason for data enabled/disabled.
* See {@link TelephonyManager.DataEnabledReason}.
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 8fee610..0d33807 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -740,11 +740,11 @@
return Parcel::getGlobalAllocCount();
}
-static jlong android_os_Parcel_getBlobAshmemSize(jlong nativePtr)
+static jlong android_os_Parcel_getOpenAshmemSize(jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
- return parcel->getBlobAshmemSize();
+ return parcel->getOpenAshmemSize();
}
return 0;
}
@@ -852,7 +852,7 @@
{"getGlobalAllocCount", "()J", (void*)android_os_Parcel_getGlobalAllocCount},
// @CriticalNative
- {"nativeGetBlobAshmemSize", "(J)J", (void*)android_os_Parcel_getBlobAshmemSize},
+ {"nativeGetOpenAshmemSize", "(J)J", (void*)android_os_Parcel_getOpenAshmemSize},
// @CriticalNative
{"nativeReadCallingWorkSourceUid", "(J)I", (void*)android_os_Parcel_readCallingWorkSourceUid},
diff --git a/core/tests/coretests/src/android/net/OWNERS b/core/tests/coretests/src/android/net/OWNERS
index aa87958..4e5136f 100644
--- a/core/tests/coretests/src/android/net/OWNERS
+++ b/core/tests/coretests/src/android/net/OWNERS
@@ -1 +1,3 @@
include /services/core/java/com/android/server/net/OWNERS
+
+per-file SntpClient* = file:/services/core/java/com/android/server/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/net/sntp/OWNERS b/core/tests/coretests/src/android/net/sntp/OWNERS
new file mode 100644
index 0000000..232c2eb
--- /dev/null
+++ b/core/tests/coretests/src/android/net/sntp/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/net/sntp/OWNERS
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 7e9d2d8..9c9e83b 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -106,7 +106,7 @@
@IntDef({
TYPE_UNKNOWN, TYPE_BUILTIN_SPEAKER, TYPE_WIRED_HEADSET,
TYPE_WIRED_HEADPHONES, TYPE_BLUETOOTH_A2DP, TYPE_HDMI, TYPE_USB_DEVICE,
- TYPE_USB_ACCESSORY, TYPE_DOCK, TYPE_USB_HEADSET, TYPE_HEARING_AID,
+ TYPE_USB_ACCESSORY, TYPE_DOCK, TYPE_USB_HEADSET, TYPE_HEARING_AID, TYPE_BLE_HEADSET,
TYPE_REMOTE_TV, TYPE_REMOTE_SPEAKER, TYPE_GROUP})
@Retention(RetentionPolicy.SOURCE)
public @interface Type {}
@@ -202,6 +202,14 @@
public static final int TYPE_HEARING_AID = AudioDeviceInfo.TYPE_HEARING_AID;
/**
+ * A route type describing a BLE HEADSET.
+ *
+ * @see #getType
+ * @hide
+ */
+ public static final int TYPE_BLE_HEADSET = AudioDeviceInfo.TYPE_BLE_HEADSET;
+
+ /**
* A route type indicating the presentation of the media is happening on a TV.
*
* @see #getType
diff --git a/packages/SettingsLib/res/drawable/ic_bt_le_audio.xml b/packages/SettingsLib/res/drawable/ic_bt_le_audio.xml
new file mode 100644
index 0000000..5b52a04
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_bt_le_audio.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal" >
+ <path
+ android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"
+ android:fillColor="#FFFFFFFF"/>
+ <path
+ android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"
+ android:fillColor="#FFFFFFFF"/>
+ <path
+ android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 6b840bd..a56c490 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -257,8 +257,12 @@
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the Hearing Aid profile. -->
<string name="bluetooth_profile_hearing_aid">Hearing Aids</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the LE_AUDIO profile. -->
+ <string name="bluetooth_profile_le_audio">LE_AUDIO</string>
<!-- Bluetooth settings. Connection options screen. The summary for the Hearing Aid checkbox preference when Hearing Aid is connected. -->
<string name="bluetooth_hearing_aid_profile_summary_connected">Connected to Hearing Aids</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the LE_AUDIO checkbox preference when LE_AUDIO is connected. -->
+ <string name="bluetooth_le_audio_profile_summary_connected">Connected to LE_AUDIO</string>
<!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. -->
<string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string>
@@ -299,6 +303,8 @@
<string name="bluetooth_hid_profile_summary_use_for">Use for input</string>
<!-- Bluetooth settings. Connection options screen. The summary for the Hearing Aid checkbox preference that describes how checking it will set the Hearing Aid profile as preferred. -->
<string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aids</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the LE_AUDIO checkbox preference that describes how checking it will set the LE_AUDIO profile as preferred. -->
+ <string name="bluetooth_le_audio_profile_summary_use_for">Use for LE_AUDIO</string>
<!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] -->
<string name="bluetooth_pairing_accept">Pair</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 8750309..58d2185 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -22,6 +22,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -116,6 +117,8 @@
addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler());
addHandler(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
new ActiveDeviceChangedHandler());
+ addHandler(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED,
+ new ActiveDeviceChangedHandler());
// Headset state changed broadcasts
addHandler(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
@@ -127,9 +130,6 @@
addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());
- addHandler(BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE,
- new SetMemberAvailableHandler());
-
registerAdapterIntentReceiver();
}
@@ -455,6 +455,9 @@
bluetoothProfile = BluetoothProfile.HEADSET;
} else if (Objects.equals(action, BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED)) {
bluetoothProfile = BluetoothProfile.HEARING_AID;
+ } else if (Objects.equals(action,
+ BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED)) {
+ bluetoothProfile = BluetoothProfile.LE_AUDIO;
} else {
Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action);
return;
@@ -515,29 +518,4 @@
dispatchAudioModeChanged();
}
}
-
- private class SetMemberAvailableHandler implements Handler {
- @Override
- public void onReceive(Context context, Intent intent, BluetoothDevice device) {
- final String action = intent.getAction();
- if (device == null) {
- Log.e(TAG, "SetMemberAvailableHandler: device is null");
- return;
- }
-
- if (action == null) {
- Log.e(TAG, "SetMemberAvailableHandler: action is null");
- return;
- }
-
- final int groupId = intent.getIntExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID,
- BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
- if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
- Log.e(TAG, "SetMemberAvailableHandler: Invalid group id");
- return;
- }
-
- mDeviceManager.onSetMemberAppear(device, groupId);
- }
- }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 2431941..021ba224 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -21,6 +21,7 @@
import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
@@ -109,10 +110,12 @@
private boolean mIsActiveDeviceA2dp = false;
private boolean mIsActiveDeviceHeadset = false;
private boolean mIsActiveDeviceHearingAid = false;
+ private boolean mIsActiveDeviceLeAudio = false;
// Media profile connect state
private boolean mIsA2dpProfileConnectedFail = false;
private boolean mIsHeadsetProfileConnectedFail = false;
private boolean mIsHearingAidProfileConnectedFail = false;
+ private boolean mIsLeAudioProfileConnectedFail = false;
// Group second device for Hearing Aid
private CachedBluetoothDevice mSubDevice;
// Group member devices for the coordinated set
@@ -133,6 +136,9 @@
case BluetoothProfile.HEARING_AID:
mIsHearingAidProfileConnectedFail = true;
break;
+ case BluetoothProfile.LE_AUDIO:
+ mIsLeAudioProfileConnectedFail = true;
+ break;
default:
Log.w(TAG, "handleMessage(): unknown message : " + msg.what);
break;
@@ -266,6 +272,9 @@
case BluetoothProfile.HEARING_AID:
mIsHearingAidProfileConnectedFail = isFailed;
break;
+ case BluetoothProfile.LE_AUDIO:
+ mIsLeAudioProfileConnectedFail = isFailed;
+ break;
default:
Log.w(TAG, "setProfileConnectedStatus(): unknown profile id : " + profileId);
break;
@@ -541,6 +550,13 @@
result = true;
}
}
+ LeAudioProfile leAudioProfile = mProfileManager.getLeAudioProfile();
+ if ((leAudioProfile != null) && isConnectedProfile(leAudioProfile)) {
+ if (leAudioProfile.setActiveDevice(getDevice())) {
+ Log.i(TAG, "OnPreferenceClickListener: LeAudio active device=" + this);
+ result = true;
+ }
+ }
return result;
}
@@ -619,6 +635,10 @@
changed = (mIsActiveDeviceHearingAid != isActive);
mIsActiveDeviceHearingAid = isActive;
break;
+ case BluetoothProfile.LE_AUDIO:
+ changed = (mIsActiveDeviceLeAudio != isActive);
+ mIsActiveDeviceLeAudio = isActive;
+ break;
default:
Log.w(TAG, "onActiveDeviceChanged: unknown profile " + bluetoothProfile +
" isActive " + isActive);
@@ -650,6 +670,8 @@
return mIsActiveDeviceHeadset;
case BluetoothProfile.HEARING_AID:
return mIsActiveDeviceHearingAid;
+ case BluetoothProfile.LE_AUDIO:
+ return mIsActiveDeviceLeAudio;
default:
Log.w(TAG, "getActiveDevice: unknown profile " + bluetoothProfile);
break;
@@ -744,6 +766,10 @@
if (hearingAidProfile != null) {
mIsActiveDeviceHearingAid = hearingAidProfile.getActiveDevices().contains(mDevice);
}
+ LeAudioProfile leAudio = mProfileManager.getLeAudioProfile();
+ if (leAudio != null) {
+ mIsActiveDeviceLeAudio = leAudio.getActiveDevices().contains(mDevice);
+ }
}
/**
@@ -984,6 +1010,7 @@
boolean a2dpConnected = true; // A2DP is connected
boolean hfpConnected = true; // HFP is connected
boolean hearingAidConnected = true; // Hearing Aid is connected
+ boolean leAudioConnected = true; // LeAudio is connected
int leftBattery = -1;
int rightBattery = -1;
@@ -1015,6 +1042,8 @@
hfpConnected = false;
} else if (profile instanceof HearingAidProfile) {
hearingAidConnected = false;
+ } else if (profile instanceof LeAudioProfile) {
+ leAudioConnected = false;
}
}
break;
@@ -1057,7 +1086,8 @@
// 1. Hearing Aid device active.
// 2. Headset device active with in-calling state.
// 3. A2DP device active without in-calling state.
- if (a2dpConnected || hfpConnected || hearingAidConnected) {
+ // 4. Le Audio device active
+ if (a2dpConnected || hfpConnected || hearingAidConnected || leAudioConnected) {
final boolean isOnCall = Utils.isAudioModeOngoingCall(mContext);
if ((mIsActiveDeviceHearingAid)
|| (mIsActiveDeviceHeadset && isOnCall)
@@ -1092,7 +1122,8 @@
private boolean isProfileConnectedFail() {
return mIsA2dpProfileConnectedFail || mIsHearingAidProfileConnectedFail
- || (!isConnectedSapDevice() && mIsHeadsetProfileConnectedFail);
+ || (!isConnectedSapDevice() && mIsHeadsetProfileConnectedFail)
+ || mIsLeAudioProfileConnectedFail;
}
/**
@@ -1103,6 +1134,7 @@
boolean a2dpNotConnected = false; // A2DP is preferred but not connected
boolean hfpNotConnected = false; // HFP is preferred but not connected
boolean hearingAidNotConnected = false; // Hearing Aid is preferred but not connected
+ boolean leAudioNotConnected = false; // LeAudio is preferred but not connected
synchronized (mProfileLock) {
for (LocalBluetoothProfile profile : getProfiles()) {
@@ -1128,6 +1160,8 @@
hfpNotConnected = true;
} else if (profile instanceof HearingAidProfile) {
hearingAidNotConnected = true;
+ } else if (profile instanceof LeAudioProfile) {
+ leAudioNotConnected = true;
}
}
break;
@@ -1166,6 +1200,11 @@
return mContext.getString(R.string.bluetooth_connected, activeDeviceString);
}
+ if (!leAudioNotConnected && mIsActiveDeviceLeAudio) {
+ activeDeviceString = activeDeviceStringsArray[1];
+ return mContext.getString(R.string.bluetooth_connected, activeDeviceString);
+ }
+
if (profileConnected) {
if (a2dpNotConnected && hfpNotConnected) {
if (batteryLevelPercentageString != null) {
@@ -1235,6 +1274,15 @@
BluetoothProfile.STATE_CONNECTED;
}
+ /**
+ * @return {@code true} if {@code cachedBluetoothDevice} is LeAudio device
+ */
+ public boolean isConnectedLeAudioDevice() {
+ LeAudioProfile leAudio = mProfileManager.getLeAudioProfile();
+ return leAudio != null && leAudio.getConnectionStatus(mDevice) ==
+ BluetoothProfile.STATE_CONNECTED;
+ }
+
private boolean isConnectedSapDevice() {
SapProfile sapProfile = mProfileManager.getSapProfile();
return sapProfile != null && sapProfile.getConnectionStatus(mDevice)
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 1f75ae3..b429fe6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -340,22 +340,24 @@
/**
* Called when we found a set member of a group. The function will check the {@code groupId} if
- * it exists and if there is a ongoing pair, the device would be ignored.
+ * it exists and the bond state of the device is BOND_NOE, and if there isn't any ongoing pair
+ * , and then return {@code true} to pair the device automatically.
*
* @param device The found device
* @param groupId The group id of the found device
+ *
+ * @return {@code true}, if the device should pair automatically; Otherwise, return
+ * {@code false}.
*/
- public synchronized void onSetMemberAppear(BluetoothDevice device, int groupId) {
- Log.d(TAG, "onSetMemberAppear, groupId: " + groupId + " device: " + device.toString());
-
- if (mOngoingSetMemberPair != null) {
- Log.d(TAG, "Ongoing set memberPairing in process, drop it!");
- return;
+ public synchronized boolean shouldPairByCsip(BluetoothDevice device, int groupId) {
+ if (mOngoingSetMemberPair != null || device.getBondState() != BluetoothDevice.BOND_NONE
+ || !mCsipDeviceManager.isExistedGroupId(groupId)) {
+ return false;
}
- if (mCsipDeviceManager.onSetMemberAppear(device, groupId)) {
- mOngoingSetMemberPair = device;
- }
+ Log.d(TAG, "Bond " + device.getName() + " by CSIP");
+ mOngoingSetMemberPair = device;
+ return true;
}
/**
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index 347e14b..1d29966 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -240,22 +240,15 @@
}
/**
- * Called when we found a set member of a group. The function will check bond state, and
- * the {@code groupId} if it exists, and then create the bond.
+ * Check if the {@code groupId} is existed.
*
- * @param device The found device
- * @param groupId The group id of the found device
+ * @param groupId The group id
*
- * @return {@code true}, if the we create bond with the device. Otherwise, return
- * {@code false}.
+ * @return {@code true}, if we could find a device with this {@code groupId}; Otherwise,
+ * return {@code false}.
*/
- public boolean onSetMemberAppear(BluetoothDevice device, int groupId) {
- if (device.getBondState() != BluetoothDevice.BOND_NONE) {
- return false;
- }
-
+ public boolean isExistedGroupId(int groupId) {
if (getCachedDevice(groupId) != null) {
- device.createBond(BluetoothDevice.TRANSPORT_LE);
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
new file mode 100644
index 0000000..209507a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -0,0 +1,264 @@
+/* Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA
+- www.ehima.com
+*/
+
+/* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.settingslib.bluetooth;
+
+import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_ALL;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.Build;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class LeAudioProfile implements LocalBluetoothProfile {
+ private static final String TAG = "LeAudioProfile";
+ private static boolean DEBUG = true;
+
+ private Context mContext;
+
+ private BluetoothLeAudio mService;
+ private boolean mIsProfileReady;
+
+ private final CachedBluetoothDeviceManager mDeviceManager;
+
+ static final String NAME = "LE_AUDIO";
+ private final LocalBluetoothProfileManager mProfileManager;
+ private final BluetoothAdapter mBluetoothAdapter;
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 1;
+
+ // These callbacks run on the main thread.
+ private final class LeAudioServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ @RequiresApi(Build.VERSION_CODES.S)
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (DEBUG) {
+ Log.d(TAG,"Bluetooth service connected");
+ }
+ mService = (BluetoothLeAudio) proxy;
+ // We just bound to the service, so refresh the UI for any connected LeAudio devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ if (DEBUG) {
+ Log.d(TAG, "LeAudioProfile found new device: " + nextDevice);
+ }
+ device = mDeviceManager.addDevice(nextDevice);
+ }
+ device.onProfileStateChanged(LeAudioProfile.this,
+ BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+
+ mProfileManager.callServiceConnectedListeners();
+ mIsProfileReady = true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (DEBUG) {
+ Log.d(TAG,"Bluetooth service disconnected");
+ }
+ mProfileManager.callServiceDisconnectedListeners();
+ mIsProfileReady = false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ @Override
+ public int getProfileId() {
+ return BluetoothProfile.LE_AUDIO;
+ }
+
+ LeAudioProfile(Context context, CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mContext = context;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ mBluetoothAdapter.getProfileProxy(
+ context, new LeAudioServiceListener(),
+ BluetoothProfile.LE_AUDIO);
+ }
+
+ public boolean accessProfileEnabled() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService == null) {
+ return new ArrayList<BluetoothDevice>(0);
+ }
+ return mService.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ /*
+ * @hide
+ */
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) {
+ return false;
+ }
+ return mService.connect(device);
+ }
+
+ /*
+ * @hide
+ */
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) {
+ return false;
+ }
+ return mService.disconnect(device);
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ return mService.getConnectionState(device);
+ }
+
+ public boolean setActiveDevice(BluetoothDevice device) {
+ if (mBluetoothAdapter == null) {
+ return false;
+ }
+ return device == null
+ ? mBluetoothAdapter.removeActiveDevice(ACTIVE_DEVICE_ALL)
+ : mBluetoothAdapter.setActiveDevice(device, ACTIVE_DEVICE_ALL);
+ }
+
+ public List<BluetoothDevice> getActiveDevices() {
+ if (mService == null) {
+ return new ArrayList<>();
+ }
+ return mService.getActiveDevices();
+ }
+
+ @Override
+ public boolean isEnabled(BluetoothDevice device) {
+ if (mService == null || device == null) {
+ return false;
+ }
+ return mService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN;
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device) {
+ if (mService == null || device == null) {
+ return CONNECTION_POLICY_FORBIDDEN;
+ }
+ return mService.getConnectionPolicy(device);
+ }
+
+ @Override
+ public boolean setEnabled(BluetoothDevice device, boolean enabled) {
+ boolean isEnabled = false;
+ if (mService == null || device == null) {
+ return false;
+ }
+ if (enabled) {
+ if (mService.getConnectionPolicy(device) < CONNECTION_POLICY_ALLOWED) {
+ isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
+ }
+ } else {
+ isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_FORBIDDEN);
+ }
+
+ return isEnabled;
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_le_audio;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_le_audio_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_le_audio_profile_summary_connected;
+
+ default:
+ return BluetoothUtils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_le_audio;
+ }
+
+ @RequiresApi(Build.VERSION_CODES.S)
+ protected void finalize() {
+ if (DEBUG) {
+ Log.d(TAG, "finalize()");
+ }
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.LE_AUDIO,
+ mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up LeAudio proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index bcb3455..3347920 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -24,6 +24,7 @@
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothHidDevice;
import android.bluetooth.BluetoothHidHost;
import android.bluetooth.BluetoothMap;
@@ -102,6 +103,7 @@
private PbapServerProfile mPbapProfile;
private HearingAidProfile mHearingAidProfile;
private CsipSetCoordinatorProfile mCsipSetCoordinatorProfile;
+ private LeAudioProfile mLeAudioProfile;
private SapProfile mSapProfile;
private VolumeControlProfile mVolumeControlProfile;
@@ -232,6 +234,14 @@
// Note: no event handler for VCP, only for being connectable.
mProfileNameMap.put(VolumeControlProfile.NAME, mVolumeControlProfile);
}
+ if (mLeAudioProfile == null && supportedList.contains(BluetoothProfile.LE_AUDIO)) {
+ if (DEBUG) {
+ Log.d(TAG, "Adding local LE_AUDIO profile");
+ }
+ mLeAudioProfile = new LeAudioProfile(mContext, mDeviceManager, this);
+ addProfile(mLeAudioProfile, LeAudioProfile.NAME,
+ BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
+ }
if (mCsipSetCoordinatorProfile == null
&& supportedList.contains(BluetoothProfile.CSIP_SET_COORDINATOR)) {
if (DEBUG) {
@@ -487,6 +497,10 @@
return mHearingAidProfile;
}
+ public LeAudioProfile getLeAudioProfile() {
+ return mLeAudioProfile;
+ }
+
SapProfile getSapProfile() {
return mSapProfile;
}
@@ -614,6 +628,11 @@
removedProfiles.remove(mHearingAidProfile);
}
+ if (ArrayUtils.contains(uuids, BluetoothUuid.LE_AUDIO) && mLeAudioProfile != null) {
+ profiles.add(mLeAudioProfile);
+ removedProfiles.remove(mLeAudioProfile);
+ }
+
if (mSapProfile != null && ArrayUtils.contains(uuids, BluetoothUuid.SAP)) {
profiles.add(mSapProfile);
removedProfiles.remove(mSapProfile);
diff --git a/services/companion/OWNERS b/services/companion/OWNERS
new file mode 100644
index 0000000..cb4cc56
--- /dev/null
+++ b/services/companion/OWNERS
@@ -0,0 +1,4 @@
+evanxinchen@google.com
+ewol@google.com
+guojing@google.com
+svetoslavganov@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index fdba098..469f465 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -476,7 +476,11 @@
*/
public static void addTombstoneToDropBox(Context ctx, File tombstone, boolean proto) {
final DropBoxManager db = ctx.getSystemService(DropBoxManager.class);
- final String bootReason = SystemProperties.get("ro.boot.bootreason", null);
+ if (db == null) {
+ Slog.e(TAG, "Can't log tombstone: DropBoxManager not available");
+ return;
+ }
+
HashMap<String, Long> timestamps = readTimestamps();
try {
if (proto) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index edf832f..c11c4de 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -385,6 +385,10 @@
private int[] mAllowedNetworkTypeReason;
private long[] mAllowedNetworkTypeValue;
+ private static final List<LinkCapacityEstimate> INVALID_LCE_LIST =
+ new ArrayList<LinkCapacityEstimate>(Arrays.asList(new LinkCapacityEstimate(
+ LinkCapacityEstimate.LCE_TYPE_COMBINED,
+ LinkCapacityEstimate.INVALID, LinkCapacityEstimate.INVALID)));
private List<List<LinkCapacityEstimate>> mLinkCapacityEstimateLists;
/**
@@ -719,7 +723,7 @@
mPhysicalChannelConfigs.add(i, new ArrayList<>());
mAllowedNetworkTypeReason[i] = -1;
mAllowedNetworkTypeValue[i] = -1;
- mLinkCapacityEstimateLists.add(i, new ArrayList<>());
+ mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
}
}
@@ -819,7 +823,7 @@
mPhysicalChannelConfigs.add(i, new ArrayList<>());
mAllowedNetworkTypeReason[i] = -1;
mAllowedNetworkTypeValue[i] = -1;
- mLinkCapacityEstimateLists.add(i, new ArrayList<>());
+ mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 503b3a9..94bf62f 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -1568,17 +1568,23 @@
perm = PackageManager.PERMISSION_DENIED;
}
- if (perm == PackageManager.PERMISSION_GRANTED) {
- skip = true;
- break;
- }
-
int appOp = AppOpsManager.permissionToOpCode(excludedPermission);
if (appOp != AppOpsManager.OP_NONE) {
- if (mService.getAppOpsManager().checkOpNoThrow(appOp,
+ // When there is an app op associated with the permission,
+ // skip when both the permission and the app op are
+ // granted.
+ if ((perm == PackageManager.PERMISSION_GRANTED) && (
+ mService.getAppOpsManager().checkOpNoThrow(appOp,
info.activityInfo.applicationInfo.uid,
info.activityInfo.packageName)
- == AppOpsManager.MODE_ALLOWED) {
+ == AppOpsManager.MODE_ALLOWED)) {
+ skip = true;
+ break;
+ }
+ } else {
+ // When there is no app op associated with the permission,
+ // skip when permission is granted.
+ if (perm == PackageManager.PERMISSION_GRANTED) {
skip = true;
break;
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 38f71ba..c383f51 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -22,6 +22,7 @@
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothLeAudio;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -503,6 +504,18 @@
}
}
+ /*package*/ static final class BleVolumeInfo {
+ final int mIndex;
+ final int mMaxIndex;
+ final int mStreamType;
+
+ BleVolumeInfo(int index, int maxIndex, int streamType) {
+ mIndex = index;
+ mMaxIndex = maxIndex;
+ mStreamType = streamType;
+ }
+ };
+
/*package*/ static final class BtDeviceConnectionInfo {
final @NonNull BluetoothDevice mDevice;
final @AudioService.BtProfileConnectionState int mState;
@@ -711,6 +724,11 @@
sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
}
+ /*package*/ void postSetLeAudioVolumeIndex(int index, int maxIndex, int streamType) {
+ BleVolumeInfo info = new BleVolumeInfo(index, maxIndex, streamType);
+ sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info);
+ }
+
/*package*/ void postSetModeOwnerPid(int pid, int mode) {
sendIIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid, mode);
}
@@ -851,6 +869,10 @@
return mAudioService.getVssVolumeForDevice(streamType, device);
}
+ /*package*/ int getMaxVssVolumeForStream(int streamType) {
+ return mAudioService.getMaxVssVolumeForStream(streamType);
+ }
+
/*package*/ int getDeviceForStream(int streamType) {
return mAudioService.getDeviceForStream(streamType);
}
@@ -962,6 +984,10 @@
sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
}
+ /*package*/ void postDisconnectLeAudio() {
+ sendMsgNoDelay(MSG_DISCONNECT_BT_LE_AUDIO, SENDMSG_QUEUE);
+ }
+
/*package*/ void postDisconnectHeadset() {
sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
}
@@ -983,6 +1009,11 @@
hearingAidProfile);
}
+ /*package*/ void postBtLeAudioProfileConnected(BluetoothLeAudio leAudioProfile) {
+ sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO, SENDMSG_QUEUE,
+ leAudioProfile);
+ }
+
/*package*/ void postCommunicationRouteClientDied(CommunicationRouteClient client) {
sendLMsgNoDelay(MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED, SENDMSG_QUEUE, client);
}
@@ -1321,6 +1352,12 @@
mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2);
}
break;
+ case MSG_II_SET_LE_AUDIO_OUT_VOLUME: {
+ final BleVolumeInfo info = (BleVolumeInfo) msg.obj;
+ synchronized (mDeviceStateLock) {
+ mBtHelper.setLeAudioVolume(info.mIndex, info.mMaxIndex, info.mStreamType);
+ }
+ } break;
case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME:
synchronized (mDeviceStateLock) {
mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
@@ -1384,6 +1421,11 @@
}
}
break;
+ case MSG_DISCONNECT_BT_LE_AUDIO:
+ synchronized(mDeviceStateLock) {
+ mDeviceInventory.disconnectLeAudio();
+ }
+ break;
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP:
synchronized (mDeviceStateLock) {
mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
@@ -1399,6 +1441,12 @@
mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
}
break;
+
+ case MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO:
+ synchronized(mDeviceStateLock) {
+ mBtHelper.onLeAudioProfileConnected((BluetoothLeAudio) msg.obj);
+ }
+ break;
case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
@@ -1586,6 +1634,11 @@
private static final int MSG_IL_SET_LE_AUDIO_IN_CONNECTION_STATE = 43;
private static final int MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT = 44;
private static final int MSG_L_LE_AUDIO_DEVICE_IN_CONNECTION_CHANGE_EXT = 45;
+ // process set volume for Le Audio, obj is BleVolumeInfo
+ private static final int MSG_II_SET_LE_AUDIO_OUT_VOLUME = 46;
+
+ private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_LE_AUDIO = 47;
+ private static final int MSG_DISCONNECT_BT_LE_AUDIO = 48;
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
@@ -1714,10 +1767,12 @@
MESSAGES_MUTE_MUSIC = new HashSet<>();
MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED);
MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED);
+ MESSAGES_MUTE_MUSIC.add(MSG_IL_SET_LE_AUDIO_OUT_CONNECTION_STATE);
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE);
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE);
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION);
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION);
+ MESSAGES_MUTE_MUSIC.add(MSG_L_LE_AUDIO_DEVICE_OUT_CONNECTION_CHANGE_EXT);
MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
MESSAGES_MUTE_MUSIC.add(MSG_REPORT_NEW_ROUTES_A2DP);
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 64e620e..6c3c736 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -887,6 +887,28 @@
}
}
+ /*package*/ void disconnectLeAudio() {
+ synchronized (mDevicesLock) {
+ final ArraySet<String> toRemove = new ArraySet<>();
+ // Disconnect ALL DEVICE_OUT_BLE_HEADSET devices
+ mConnectedDevices.values().forEach(deviceInfo -> {
+ if (deviceInfo.mDeviceType == AudioSystem.DEVICE_OUT_BLE_HEADSET) {
+ toRemove.add(deviceInfo.mDeviceAddress);
+ }
+ });
+ new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
+ .record();
+ if (toRemove.size() > 0) {
+ final int delay = checkSendBecomingNoisyIntentInt(
+ AudioSystem.DEVICE_OUT_BLE_HEADSET, 0, AudioSystem.DEVICE_NONE);
+ toRemove.stream().forEach(deviceAddress ->
+ makeLeAudioDeviceUnavailable(deviceAddress,
+ AudioSystem.DEVICE_OUT_BLE_HEADSET)
+ );
+ }
+ }
+ }
+
// must be called before removing the device from mConnectedDevices
// musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
// from AudioSystem
@@ -1195,6 +1217,10 @@
return;
}
+ final int leAudioVolIndex = mDeviceBroker.getVssVolumeForDevice(streamType,
+ AudioSystem.DEVICE_OUT_BLE_HEADSET);
+ final int maxIndex = mDeviceBroker.getMaxVssVolumeForStream(streamType);
+ mDeviceBroker.postSetLeAudioVolumeIndex(leAudioVolIndex, maxIndex, streamType);
mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "makeLeAudioDeviceAvailable");
}
@@ -1243,6 +1269,7 @@
BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_LINE);
BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_HEARING_AID);
+ BECOMING_NOISY_INTENT_DEVICES_SET.add(AudioSystem.DEVICE_OUT_BLE_HEADSET);
BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
BECOMING_NOISY_INTENT_DEVICES_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index bf5f4c2..8e1b06b 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -334,6 +334,10 @@
return mStreamStates[stream].getIndex(device);
}
+ /*package*/ int getMaxVssVolumeForStream(int stream) {
+ return mStreamStates[stream].getMaxIndex();
+ }
+
private SettingsObserver mSettingsObserver;
private AtomicInteger mMode = new AtomicInteger(AudioSystem.MODE_NORMAL);
@@ -2952,6 +2956,16 @@
mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
}
+ if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
+ && streamType == getBluetoothContextualVolumeStream()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
+ + newIndex + " stream=" + streamType);
+ }
+ mDeviceBroker.postSetLeAudioVolumeIndex(newIndex,
+ mStreamStates[streamType].getMaxIndex(), streamType);
+ }
+
// Check if volume update should be send to Hearing Aid
if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
// only modify the hearing aid attenuation when the stream to modify matches
@@ -3580,6 +3594,16 @@
mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
}
+ if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
+ && streamType == getBluetoothContextualVolumeStream()) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
+ + index + " stream=" + streamType);
+ }
+ mDeviceBroker.postSetLeAudioVolumeIndex(index,
+ mStreamStates[streamType].getMaxIndex(), streamType);
+ }
+
if (device == AudioSystem.DEVICE_OUT_HEARING_AID
&& streamType == getBluetoothContextualVolumeStream()) {
Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index 0eb5a5d..3137fa5 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -155,6 +155,7 @@
static final int VOL_MODE_CHANGE_HEARING_AID = 7;
static final int VOL_SET_GROUP_VOL = 8;
static final int VOL_MUTE_STREAM_INT = 9;
+ static final int VOL_SET_LE_AUDIO_VOL = 10;
final int mOp;
final int mStream;
@@ -310,6 +311,13 @@
.set(MediaMetrics.Property.INDEX, mVal1)
.record();
return;
+ case VOL_SET_LE_AUDIO_VOL:
+ new MediaMetrics.Item(mMetricsId)
+ .set(MediaMetrics.Property.EVENT, "setLeAudioVolume")
+ .set(MediaMetrics.Property.INDEX, mVal1)
+ .set(MediaMetrics.Property.MAX_INDEX, mVal2)
+ .record();
+ return;
case VOL_SET_AVRCP_VOL:
new MediaMetrics.Item(mMetricsId)
.set(MediaMetrics.Property.EVENT, "setAvrcpVolume")
@@ -382,6 +390,11 @@
.append(" index:").append(mVal1)
.append(" gain dB:").append(mVal2)
.toString();
+ case VOL_SET_LE_AUDIO_VOL:
+ return new StringBuilder("setLeAudioVolume:")
+ .append(" index:").append(mVal1)
+ .append(" gain dB:").append(mVal2)
+ .toString();
case VOL_SET_AVRCP_VOL:
return new StringBuilder("setAvrcpVolume:")
.append(" index:").append(mVal1)
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 52e8edf..c924fde 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -25,6 +25,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.media.AudioDeviceAttributes;
@@ -63,6 +64,8 @@
private @Nullable BluetoothHearingAid mHearingAid;
+ private @Nullable BluetoothLeAudio mLeAudio;
+
// Reference to BluetoothA2dp to query for AbsoluteVolume.
private @Nullable BluetoothA2dp mA2dp;
@@ -106,6 +109,8 @@
private static final int SCO_MODE_MAX = 2;
private static final int BT_HEARING_AID_GAIN_MIN = -128;
+ private static final int BT_LE_AUDIO_MIN_VOL = 0;
+ private static final int BT_LE_AUDIO_MAX_VOL = 255;
/**
* Returns a string representation of the scoAudioMode.
@@ -235,6 +240,8 @@
mBluetoothProfileServiceListener, BluetoothProfile.A2DP);
adapter.getProfileProxy(mDeviceBroker.getContext(),
mBluetoothProfileServiceListener, BluetoothProfile.HEARING_AID);
+ adapter.getProfileProxy(mDeviceBroker.getContext(),
+ mBluetoothProfileServiceListener, BluetoothProfile.LE_AUDIO);
}
}
@@ -389,6 +396,26 @@
return requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, SCO_MODE_VIRTUAL_CALL);
}
+ /*package*/ synchronized void setLeAudioVolume(int index, int maxIndex, int streamType) {
+ if (mLeAudio == null) {
+ if (AudioService.DEBUG_VOL) {
+ Log.i(TAG, "setLeAudioVolume: null mLeAudio");
+ }
+ return;
+ }
+ /* leaudio expect volume value in range 0 to 255
+ */
+ int volume = (index * (BT_LE_AUDIO_MAX_VOL - BT_LE_AUDIO_MIN_VOL)) / maxIndex ;
+
+ if (AudioService.DEBUG_VOL) {
+ Log.i(TAG, "setLeAudioVolume: calling mLeAudio.setVolume idx="
+ + index + " volume=" + volume);
+ }
+ AudioService.sVolumeLogger.log(new AudioServiceEvents.VolumeEvent(
+ AudioServiceEvents.VolumeEvent.VOL_SET_LE_AUDIO_VOL, index, maxIndex));
+ mLeAudio.setVolume(volume);
+ }
+
/*package*/ synchronized void setHearingAidVolume(int index, int streamType) {
if (mHearingAid == null) {
if (AudioService.DEBUG_VOL) {
@@ -428,6 +455,7 @@
mDeviceBroker.postDisconnectA2dpSink();
mDeviceBroker.postDisconnectHeadset();
mDeviceBroker.postDisconnectHearingAid();
+ mDeviceBroker.postDisconnectLeAudio();
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@@ -488,6 +516,23 @@
/*eventSource*/ "mBluetoothProfileServiceListener");
}
+ /*package*/ synchronized void onLeAudioProfileConnected(BluetoothLeAudio leAudio) {
+ mLeAudio = leAudio;
+ final List<BluetoothDevice> deviceList = mLeAudio.getConnectedDevices();
+ if (deviceList.isEmpty()) {
+ return;
+ }
+
+ final BluetoothDevice btDevice = deviceList.get(0);
+ final @BluetoothProfile.BtProfileState int state =
+ mLeAudio.getConnectionState(btDevice);
+ mDeviceBroker.postBluetoothLeAudioOutDeviceConnectionState(
+ btDevice, state,
+ /*suppressNoisyIntent*/ false,
+ /*musicDevice android.media.AudioSystem.DEVICE_NONE,*/
+ /*eventSource*/ "mBluetoothProfileServiceListener");
+ }
+
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void onHeadsetProfileConnected(BluetoothHeadset headset) {
@@ -655,6 +700,13 @@
mDeviceBroker.postBtHearingAidProfileConnected(
(BluetoothHearingAid) proxy);
break;
+
+ case BluetoothProfile.LE_AUDIO:
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "BT profile service: connecting LE_AUDIO profile"));
+ mDeviceBroker.postBtLeAudioProfileConnected(
+ (BluetoothLeAudio) proxy);
+ break;
default:
break;
}
@@ -677,6 +729,9 @@
case BluetoothProfile.HEARING_AID:
mDeviceBroker.postDisconnectHearingAid();
break;
+ case BluetoothProfile.LE_AUDIO:
+ mDeviceBroker.postDisconnectLeAudio();
+ break;
default:
break;
@@ -899,6 +954,7 @@
pw.println(prefix + "mScoAudioState: " + scoAudioStateToString(mScoAudioState));
pw.println(prefix + "mScoAudioMode: " + scoAudioModeToString(mScoAudioMode));
pw.println("\n" + prefix + "mHearingAid: " + mHearingAid);
+ pw.println("\n" + prefix + "mLeAudio: " + mLeAudio);
pw.println(prefix + "mA2dp: " + mA2dp);
pw.println(prefix + "mAvrcpAbsVolSupported: " + mAvrcpAbsVolSupported);
}
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index 7afa81a..73de0f8 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -26,6 +26,7 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -56,6 +57,7 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
+ private static final String LE_AUDIO_ROUTE_ID_PREFIX = "LE_AUDIO_";
@SuppressWarnings("WeakerAccess") /* synthetic access */
// Maps hardware address to BluetoothRouteInfo
@@ -66,6 +68,8 @@
BluetoothA2dp mA2dpProfile;
@SuppressWarnings("WeakerAccess") /* synthetic access */
BluetoothHearingAid mHearingAidProfile;
+ @SuppressWarnings("WeakerAccess") /* synthetic access */
+ BluetoothLeAudio mLeAudioProfile;
// Route type -> volume map
private final SparseIntArray mVolumeMap = new SparseIntArray();
@@ -108,6 +112,7 @@
public void start(UserHandle user) {
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
+ mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.LE_AUDIO);
// Bluetooth on/off broadcasts
addEventReceiver(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedReceiver());
@@ -119,6 +124,10 @@
deviceStateChangedReceiver);
addEventReceiver(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED,
deviceStateChangedReceiver);
+ addEventReceiver(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED,
+ deviceStateChangedReceiver);
+ addEventReceiver(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED,
+ deviceStateChangedReceiver);
mContext.registerReceiverAsUser(mBroadcastReceiver, user,
mIntentFilter, null, null);
@@ -240,6 +249,8 @@
| AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
| AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
routeType = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+ } else if ((devices & (AudioManager.DEVICE_OUT_BLE_HEADSET)) != 0) {
+ routeType = MediaRoute2Info.TYPE_BLE_HEADSET;
} else {
return false;
}
@@ -288,6 +299,12 @@
routeId = HEARING_AID_ROUTE_ID_PREFIX + mHearingAidProfile.getHiSyncId(device);
type = MediaRoute2Info.TYPE_HEARING_AID;
}
+ if (mLeAudioProfile != null
+ && mLeAudioProfile.getConnectedDevices().contains(device)) {
+ newBtRoute.connectedProfiles.put(BluetoothProfile.LE_AUDIO, true);
+ routeId = LE_AUDIO_ROUTE_ID_PREFIX + mLeAudioProfile.getGroupId(device);
+ type = MediaRoute2Info.TYPE_BLE_HEADSET;
+ }
// Current volume will be set when connected.
newBtRoute.route = new MediaRoute2Info.Builder(routeId, deviceName)
@@ -358,11 +375,7 @@
}
}
- private void addActiveHearingAidDevices(BluetoothDevice device) {
- if (DEBUG) {
- Log.d(TAG, "Setting active hearing aid devices. device=" + device);
- }
-
+ private void addActiveDevices(BluetoothDevice device) {
// Let the given device be the first active device
BluetoothRouteInfo activeBtRoute = mBluetoothRoutes.get(device.getAddress());
addActiveRoute(activeBtRoute);
@@ -376,6 +389,21 @@
}
}
}
+ private void addActiveHearingAidDevices(BluetoothDevice device) {
+ if (DEBUG) {
+ Log.d(TAG, "Setting active hearing aid devices. device=" + device);
+ }
+
+ addActiveDevices(device);
+ }
+
+ private void addActiveLeAudioDevices(BluetoothDevice device) {
+ if (DEBUG) {
+ Log.d(TAG, "Setting active le audio devices. device=" + device);
+ }
+
+ addActiveDevices(device);
+ }
interface BluetoothRoutesUpdatedListener {
void onBluetoothRoutesUpdated(@NonNull List<MediaRoute2Info> routes);
@@ -392,6 +420,11 @@
if (connectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
return MediaRoute2Info.TYPE_HEARING_AID;
}
+
+ if (connectedProfiles.get(BluetoothProfile.LE_AUDIO, false)) {
+ return MediaRoute2Info.TYPE_BLE_HEADSET;
+ }
+
return MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
}
}
@@ -410,6 +443,10 @@
mHearingAidProfile = (BluetoothHearingAid) proxy;
activeDevices = mHearingAidProfile.getActiveDevices();
break;
+ case BluetoothProfile.LE_AUDIO:
+ mLeAudioProfile = (BluetoothLeAudio) proxy;
+ activeDevices = mLeAudioProfile.getActiveDevices();
+ break;
default:
return;
}
@@ -434,6 +471,9 @@
case BluetoothProfile.HEARING_AID:
mHearingAidProfile = null;
break;
+ case BluetoothProfile.LE_AUDIO:
+ mLeAudioProfile = null;
+ break;
default:
return;
}
@@ -490,12 +530,22 @@
}
notifyBluetoothRoutesUpdated();
break;
+ case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
+ clearActiveRoutesWithType(MediaRoute2Info.TYPE_BLE_HEADSET);
+ if (device != null) {
+ addActiveLeAudioDevices(device);
+ }
+ notifyBluetoothRoutesUpdated();
+ break;
case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
handleConnectionStateChanged(BluetoothProfile.A2DP, intent, device);
break;
case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
handleConnectionStateChanged(BluetoothProfile.HEARING_AID, intent, device);
break;
+ case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
+ handleConnectionStateChanged(BluetoothProfile.LE_AUDIO, intent, device);
+ break;
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 84be7f5..20687c6 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -4073,7 +4073,7 @@
if (hasRestrictedModeAccess(uid)) {
uidBlockedState.allowedReasons |= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
} else {
- uidBlockedState.allowedReasons &= ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
+ uidBlockedState.allowedReasons &= ~ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS;
}
uidBlockedState.updateEffectiveBlockedReasons();
if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
diff --git a/services/core/java/com/android/server/pm/dex/OWNERS b/services/core/java/com/android/server/pm/dex/OWNERS
index 5a4431e..052a4ca 100644
--- a/services/core/java/com/android/server/pm/dex/OWNERS
+++ b/services/core/java/com/android/server/pm/dex/OWNERS
@@ -1,2 +1,3 @@
-calin@google.com
+alanstokes@google.com
+jiakaiz@google.com
ngeoffray@google.com
diff --git a/startop/OWNERS b/startop/OWNERS
index 2d1eb38..11d5ad0 100644
--- a/startop/OWNERS
+++ b/startop/OWNERS
@@ -1,7 +1,2 @@
-# mailing list: startop-eng@google.com
-calin@google.com
-chriswailes@google.com
-eholk@google.com
-iam@google.com
-mathieuc@google.com
-yawanng@google.com
+include platform/art:/OWNERS
+keunyoung@google.com
diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.bp b/tests/DynamicCodeLoggerIntegrationTests/Android.bp
new file mode 100644
index 0000000..448d46f
--- /dev/null
+++ b/tests/DynamicCodeLoggerIntegrationTests/Android.bp
@@ -0,0 +1,60 @@
+//
+// Copyright 2017 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 {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_test_helper_library {
+ name: "DynamicCodeLoggerTestLibrary",
+ srcs: ["src/com/android/dcl/**/*.java"],
+
+}
+
+cc_library_shared {
+ name: "DynamicCodeLoggerNativeTestLibrary",
+ srcs: ["src/cpp/com_android_dcl_Jni.cpp"],
+ header_libs: ["jni_headers"],
+ sdk_version: "28",
+ stl: "c++_static",
+}
+
+cc_binary {
+ name: "DynamicCodeLoggerNativeExecutable",
+ srcs: ["src/cpp/test_executable.cpp"],
+}
+
+android_test {
+ name: "DynamicCodeLoggerIntegrationTests",
+
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+ certificate: "shared",
+ srcs: ["src/com/android/server/pm/**/*.java"],
+
+ static_libs: [
+ "androidx.test.rules",
+ "truth-prebuilt",
+ ],
+
+ compile_multilib: "both",
+ jni_libs: ["DynamicCodeLoggerNativeTestLibrary"],
+
+ java_resources: [
+ ":DynamicCodeLoggerTestLibrary",
+ ":DynamicCodeLoggerNativeExecutable",
+ ],
+}
diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.mk b/tests/DynamicCodeLoggerIntegrationTests/Android.mk
deleted file mode 100644
index dab8304..0000000
--- a/tests/DynamicCodeLoggerIntegrationTests/Android.mk
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# Copyright 2017 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-# Build a tiny library that the test app can dynamically load
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DynamicCodeLoggerTestLibrary
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/dcl)
-
-include $(BUILD_JAVA_LIBRARY)
-
-dynamiccodeloggertest_jar := $(LOCAL_BUILT_MODULE)
-
-
-# Also build a native library that the test app can dynamically load
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DynamicCodeLoggerNativeTestLibrary
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_SRC_FILES := src/cpp/com_android_dcl_Jni.cpp
-LOCAL_HEADER_LIBRARIES := jni_headers
-LOCAL_SDK_VERSION := 28
-LOCAL_NDK_STL_VARIANT := c++_static
-
-include $(BUILD_SHARED_LIBRARY)
-
-# And a standalone native executable that we can exec.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DynamicCodeLoggerNativeExecutable
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_SRC_FILES := src/cpp/test_executable.cpp
-
-include $(BUILD_EXECUTABLE)
-
-dynamiccodeloggertest_executable := $(LOCAL_BUILT_MODULE)
-
-# Build the test app itself
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := DynamicCodeLoggerIntegrationTests
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_CERTIFICATE := shared
-LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/server/pm)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- truth-prebuilt \
-
-# Include both versions of the .so if we have 2 arch
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := \
- DynamicCodeLoggerNativeTestLibrary \
-
-# This gets us the javalib.jar built by DynamicCodeLoggerTestLibrary above as well as the various
-# native binaries.
-LOCAL_JAVA_RESOURCE_FILES := \
- $(dynamiccodeloggertest_jar) \
- $(dynamiccodeloggertest_executable) \
-
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-include $(BUILD_PACKAGE)
diff --git a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
index 883c172..5430dee 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
+++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
@@ -114,7 +114,8 @@
// Obtained via "echo -n copied.jar | sha256sum"
String expectedNameHash =
"1B6C71DB26F36582867432CCA12FB6A517470C9F9AABE9198DD4C5C030D6DC0C";
- String expectedContentHash = copyAndHashResource("/javalib.jar", privateCopyFile);
+ String expectedContentHash = copyAndHashResource(
+ "/DynamicCodeLoggerTestLibrary.jar", privateCopyFile);
// Feed the jar to a class loader and make sure it contains what we expect.
ClassLoader parentClassLoader = sContext.getClass().getClassLoader();
@@ -135,7 +136,8 @@
File privateCopyFile = privateFile("copied2.jar");
String expectedNameHash =
"202158B6A3169D78F1722487205A6B036B3F2F5653FDCFB4E74710611AC7EB93";
- String expectedContentHash = copyAndHashResource("/javalib.jar", privateCopyFile);
+ String expectedContentHash = copyAndHashResource(
+ "/DynamicCodeLoggerTestLibrary.jar", privateCopyFile);
// This time make sure an unknown class loader is an ancestor of the class loader we use.
ClassLoader knownClassLoader = sContext.getClass().getClassLoader();
diff --git a/tests/LockTaskTests/Android.bp b/tests/LockTaskTests/Android.bp
new file mode 100644
index 0000000..dce681e
--- /dev/null
+++ b/tests/LockTaskTests/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_app {
+ name: "LockTaskTests",
+
+ privileged: true,
+
+ sdk_version: "current",
+ certificate: "platform",
+
+ srcs: [
+ "src/**/I*.aidl",
+ "src/**/*.java",
+ ],
+
+}
diff --git a/tests/LockTaskTests/Android.mk b/tests/LockTaskTests/Android.mk
deleted file mode 100644
index 5406ee1..0000000
--- a/tests/LockTaskTests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/priv-app
-
-LOCAL_PACKAGE_NAME := LockTaskTests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-Iaidl-files-under, src) $(call all-java-files-under, src)
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java b/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java
index 7cda977..5d639f6 100644
--- a/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java
+++ b/tests/notification/src/com/android/frameworks/tests/notification/NotificationTests.java
@@ -409,10 +409,10 @@
sleepIfYouCan(500);
L("Parceling notifications...");
- // we want to be able to use this test on older OSes that do not have getBlobAshmemSize
- Method getBlobAshmemSize = null;
+ // we want to be able to use this test on older OSes that do not have getOpenAshmemSize
+ Method getOpenAshmemSize = null;
try {
- getBlobAshmemSize = Parcel.class.getMethod("getBlobAshmemSize");
+ getOpenAshmemSize = Parcel.class.getMethod("getOpenAshmemSize");
} catch (NoSuchMethodException ex) {
}
for (int i=0; i<mNotifications.size(); i++) {
@@ -424,8 +424,8 @@
time = SystemClock.currentThreadTimeMillis() - time;
L(" %s: write parcel=%dms size=%d ashmem=%s",
summarize(n), time, p.dataPosition(),
- (getBlobAshmemSize != null)
- ? getBlobAshmemSize.invoke(p)
+ (getOpenAshmemSize != null)
+ ? getOpenAshmemSize.invoke(p)
: "???");
p.setDataPosition(0);
}