summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--core/api/system-current.txt8
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java69
-rw-r--r--core/java/android/net/Ikev2VpnProfile.java5
-rw-r--r--core/java/android/nfc/NfcAdapter.java25
-rw-r--r--core/java/android/os/BatteryManager.java112
-rw-r--r--core/jni/android_media_MicrophoneInfo.cpp1
-rw-r--r--core/tests/companiontests/OWNERS1
-rw-r--r--media/java/android/media/RingtoneManager.java2
-rw-r--r--packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java4
-rw-r--r--packages/SettingsLib/res/values/styles.xml4
-rw-r--r--services/core/java/com/android/server/BatteryService.java25
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java15
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java51
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java32
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java72
-rw-r--r--services/core/java/com/android/server/connectivity/VpnIkev2Utils.java4
-rw-r--r--services/core/java/com/android/server/health/HealthServiceWrapperAidl.java17
-rw-r--r--services/robotests/src/com/android/server/media/OWNERS3
-rw-r--r--telephony/java/android/telephony/ims/ImsCallSessionListener.java29
-rw-r--r--telephony/java/android/telephony/ims/feature/MmTelFeature.java1
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java5
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java3
23 files changed, 418 insertions, 72 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 7f35d4a47adf..7d88149abb28 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -30910,6 +30910,8 @@ package android.os {
field public static final int BATTERY_STATUS_NOT_CHARGING = 4; // 0x4
field public static final int BATTERY_STATUS_UNKNOWN = 1; // 0x1
field public static final String EXTRA_BATTERY_LOW = "battery_low";
+ field public static final String EXTRA_CHARGING_STATUS = "android.os.extra.CHARGING_STATUS";
+ field public static final String EXTRA_CYCLE_COUNT = "android.os.extra.CYCLE_COUNT";
field public static final String EXTRA_HEALTH = "health";
field public static final String EXTRA_ICON_SMALL = "icon-small";
field public static final String EXTRA_LEVEL = "level";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 1d3993106a8f..909a3dca3829 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -9152,6 +9152,14 @@ package android.os {
public class BatteryManager {
method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setChargingStateUpdateDelayMillis(int);
+ field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_CHARGING_POLICY = 9; // 0x9
+ field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_FIRST_USAGE_DATE = 8; // 0x8
+ field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_MANUFACTURING_DATE = 7; // 0x7
+ field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10; // 0xa
+ field public static final int CHARGING_POLICY_ADAPTIVE_AC = 3; // 0x3
+ field public static final int CHARGING_POLICY_ADAPTIVE_AON = 2; // 0x2
+ field public static final int CHARGING_POLICY_ADAPTIVE_LONGLIFE = 4; // 0x4
+ field public static final int CHARGING_POLICY_DEFAULT = 1; // 0x1
field public static final String EXTRA_EVENTS = "android.os.extra.EVENTS";
field public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP";
}
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 9235ba15019c..3e509e4d1c2f 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -36,10 +36,12 @@ import android.sysprop.HdmiProperties;
import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ConcurrentUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -69,6 +71,32 @@ public final class HdmiControlManager {
private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
/**
+ * A cache of the current device's physical address. When device's HDMI out port
+ * is not connected to any device, it is set to {@link #INVALID_PHYSICAL_ADDRESS}.
+ *
+ * <p>Otherwise it is updated by the {@link ClientHotplugEventListener} registered
+ * with {@link com.android.server.hdmi.HdmiControlService} by the
+ * {@link #addHotplugEventListener(HotplugEventListener)} and the address is from
+ * {@link com.android.server.hdmi.HdmiControlService#getPortInfo()}
+ */
+ @GuardedBy("mLock")
+ private int mLocalPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
+
+ private void setLocalPhysicalAddress(int physicalAddress) {
+ synchronized (mLock) {
+ mLocalPhysicalAddress = physicalAddress;
+ }
+ }
+
+ private int getLocalPhysicalAddress() {
+ synchronized (mLock) {
+ return mLocalPhysicalAddress;
+ }
+ }
+
+ private final Object mLock = new Object();
+
+ /**
* Broadcast Action: Display OSD message.
* <p>Send when the service has a message to display on screen for events
* that need user's attention such as ARC status change.
@@ -1094,6 +1122,37 @@ public final class HdmiControlManager {
mHasAudioSystemDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
mHasSwitchDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH);
mIsSwitchDevice = HdmiProperties.is_switch().orElse(false);
+ addHotplugEventListener(new ClientHotplugEventListener());
+ }
+
+ private final class ClientHotplugEventListener implements HotplugEventListener {
+
+ @Override
+ public void onReceived(HdmiHotplugEvent event) {
+ List<HdmiPortInfo> ports = new ArrayList<>();
+ try {
+ ports = mService.getPortInfo();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ if (ports.isEmpty()) {
+ Log.e(TAG, "Can't find port info, not updating connected status. "
+ + "Hotplug event:" + event);
+ return;
+ }
+ // If the HDMI OUT port is plugged or unplugged, update the mLocalPhysicalAddress
+ for (HdmiPortInfo port : ports) {
+ if (port.getId() == event.getPort()) {
+ if (port.getType() == HdmiPortInfo.PORT_OUTPUT) {
+ setLocalPhysicalAddress(
+ event.isConnected()
+ ? port.getAddress()
+ : INVALID_PHYSICAL_ADDRESS);
+ }
+ break;
+ }
+ }
+ }
}
private static boolean hasDeviceType(int[] types, int type) {
@@ -1464,11 +1523,7 @@ public final class HdmiControlManager {
* 1.4b 8.7 Physical Address for more details on the address discovery proccess.
*/
public int getPhysicalAddress() {
- try {
- return mService.getPhysicalAddress();
- } catch (RemoteException e) {
- return INVALID_PHYSICAL_ADDRESS;
- }
+ return getLocalPhysicalAddress();
}
/**
@@ -1482,7 +1537,7 @@ public final class HdmiControlManager {
*/
public boolean isDeviceConnected(@NonNull HdmiDeviceInfo targetDevice) {
Objects.requireNonNull(targetDevice);
- int physicalAddress = getPhysicalAddress();
+ int physicalAddress = getLocalPhysicalAddress();
if (physicalAddress == INVALID_PHYSICAL_ADDRESS) {
return false;
}
@@ -1501,7 +1556,7 @@ public final class HdmiControlManager {
@Deprecated
public boolean isRemoteDeviceConnected(@NonNull HdmiDeviceInfo targetDevice) {
Objects.requireNonNull(targetDevice);
- int physicalAddress = getPhysicalAddress();
+ int physicalAddress = getLocalPhysicalAddress();
if (physicalAddress == INVALID_PHYSICAL_ADDRESS) {
return false;
}
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 647514486750..a20191cab774 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -1108,6 +1108,11 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
/**
* Sets the enabled state of the automatic NAT-T keepalive timers
*
+ * Note that if this builder was constructed with a {@link IkeTunnelConnectionParams},
+ * but this is called with {@code true}, the framework will automatically choose the
+ * appropriate keepalive timer and ignore the settings in the session params embedded
+ * in the connection params.
+ *
* @param isEnabled {@code true} to enable automatic keepalive timers, based on internal
* platform signals. Defaults to {@code false}.
* @return this {@link Builder} object to facilitate chaining of method calls
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 6dc80cf4c374..611df0a4ea90 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -26,8 +26,6 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.app.Activity;
-import android.app.ActivityThread;
-import android.app.OnActivityPausedListener;
import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -1570,17 +1568,11 @@ public final class NfcAdapter {
if (activity == null || intent == null) {
throw new NullPointerException();
}
- if (!activity.isResumed()) {
- throw new IllegalStateException("Foreground dispatch can only be enabled " +
- "when your activity is resumed");
- }
try {
TechListParcel parcel = null;
if (techLists != null && techLists.length > 0) {
parcel = new TechListParcel(techLists);
}
- ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
- mForegroundDispatchListener);
sService.setForegroundDispatch(intent, filters, parcel);
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
@@ -1608,25 +1600,8 @@ public final class NfcAdapter {
throw new UnsupportedOperationException();
}
}
- ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
- mForegroundDispatchListener);
- disableForegroundDispatchInternal(activity, false);
- }
-
- OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() {
- @Override
- public void onPaused(Activity activity) {
- disableForegroundDispatchInternal(activity, true);
- }
- };
-
- void disableForegroundDispatchInternal(Activity activity, boolean force) {
try {
sService.setForegroundDispatch(null, null, null);
- if (!force && !activity.isResumed()) {
- throw new IllegalStateException("You must disable foreground dispatching " +
- "while your activity is still resumed");
- }
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 76f857bd91b7..6bc0f6ea947c 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -147,6 +147,18 @@ public class BatteryManager {
public static final String EXTRA_SEQUENCE = "seq";
/**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * Int value representing the battery charging cycle count.
+ */
+ public static final String EXTRA_CYCLE_COUNT = "android.os.extra.CYCLE_COUNT";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * Int value representing the battery charging status.
+ */
+ public static final String EXTRA_CHARGING_STATUS = "android.os.extra.CHARGING_STATUS";
+
+ /**
* Extra for {@link android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED}:
* Contains list of Bundles representing battery events
* @hide
@@ -190,6 +202,35 @@ public class BatteryManager {
/** Power source is dock. */
public static final int BATTERY_PLUGGED_DOCK = OsProtoEnums.BATTERY_PLUGGED_DOCK; // = 8
+ // values for "charge policy" property
+ /**
+ * Default policy (e.g. normal).
+ * @hide
+ */
+ @SystemApi
+ public static final int CHARGING_POLICY_DEFAULT = OsProtoEnums.CHARGING_POLICY_DEFAULT; // = 1
+ /**
+ * Optimized for battery health using static thresholds (e.g stop at 80%).
+ * @hide
+ */
+ @SystemApi
+ public static final int CHARGING_POLICY_ADAPTIVE_AON =
+ OsProtoEnums.CHARGING_POLICY_ADAPTIVE_AON; // = 2
+ /**
+ * Optimized for battery health using adaptive thresholds.
+ * @hide
+ */
+ @SystemApi
+ public static final int CHARGING_POLICY_ADAPTIVE_AC =
+ OsProtoEnums.CHARGING_POLICY_ADAPTIVE_AC; // = 3
+ /**
+ * Optimized for battery health, devices always connected to power.
+ * @hide
+ */
+ @SystemApi
+ public static final int CHARGING_POLICY_ADAPTIVE_LONGLIFE =
+ OsProtoEnums.CHARGING_POLICY_ADAPTIVE_LONGLIFE; // = 4
+
/** @hide */
public static final int BATTERY_PLUGGED_ANY =
BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS
@@ -254,6 +295,76 @@ public class BatteryManager {
*/
public static final int BATTERY_PROPERTY_STATUS = 6;
+ /**
+ * Battery manufacturing date is reported in epoch. The 0 timepoint
+ * begins at midnight Coordinated Universal Time (UTC) on January 1, 1970.
+ * It is a long integer in seconds.
+ *
+ * <p class="note">
+ * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * Example: <code>
+ * // The value returned from the API can be used to create a Date, used
+ * // to set the time on a calendar and coverted to a string.
+ * import java.util.Date;
+ *
+ * mBatteryManager = mContext.getSystemService(BatteryManager.class);
+ * final long manufacturingDate =
+ * mBatteryManager.getLongProperty(BatteryManager.BATTERY_PROPERTY_MANUFACTURING_DATE);
+ * Date date = new Date(manufacturingDate);
+ * Calendar calendar = Calendar.getInstance();
+ * calendar.setTime(date);
+ * // Convert to yyyy-MM-dd HH:mm:ss format string
+ * SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ * String dateString = sdf.format(date);
+ * </code>
+ * @hide
+ */
+ @RequiresPermission(permission.BATTERY_STATS)
+ @SystemApi
+ public static final int BATTERY_PROPERTY_MANUFACTURING_DATE = 7;
+
+ /**
+ * The date of first usage is reported in epoch. The 0 timepoint
+ * begins at midnight Coordinated Universal Time (UTC) on January 1, 1970.
+ * It is a long integer in seconds.
+ *
+ * <p class="note">
+ * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * {@link BATTERY_PROPERTY_MANUFACTURING_DATE for sample code}
+ * @hide
+ */
+ @RequiresPermission(permission.BATTERY_STATS)
+ @SystemApi
+ public static final int BATTERY_PROPERTY_FIRST_USAGE_DATE = 8;
+
+ /**
+ * Battery charging policy from a CHARGING_POLICY_* value..
+ *
+ * <p class="note">
+ * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * @hide
+ */
+ @RequiresPermission(permission.BATTERY_STATS)
+ @SystemApi
+ public static final int BATTERY_PROPERTY_CHARGING_POLICY = 9;
+
+ /**
+ *
+ * Percentage representing the measured battery state of health (remaining
+ * estimated full charge capacity relative to the rated capacity in %).
+ *
+ * <p class="note">
+ * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * @hide
+ */
+ @RequiresPermission(permission.BATTERY_STATS)
+ @SystemApi
+ public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10;
+
private final Context mContext;
private final IBatteryStats mBatteryStats;
private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
@@ -307,7 +418,6 @@ public class BatteryManager {
try {
BatteryProperty prop = new BatteryProperty();
-
if (mBatteryPropertiesRegistrar.getProperty(id, prop) == 0)
ret = prop.getLong();
else
diff --git a/core/jni/android_media_MicrophoneInfo.cpp b/core/jni/android_media_MicrophoneInfo.cpp
index 65e30d8b1ea3..18f81254af7d 100644
--- a/core/jni/android_media_MicrophoneInfo.cpp
+++ b/core/jni/android_media_MicrophoneInfo.cpp
@@ -92,6 +92,7 @@ jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
env->DeleteLocalRef(jFrequencyResponse);
}
// Create a list of Pair for channel mapping.
+ jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor);
const auto &channelMapping = micInfo.channel_mapping;
for (size_t i = 0; i < std::size(channelMapping); i++) {
int channelMappingType = channelMapping[i];
diff --git a/core/tests/companiontests/OWNERS b/core/tests/companiontests/OWNERS
new file mode 100644
index 000000000000..734d8b6c5f43
--- /dev/null
+++ b/core/tests/companiontests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/companion/OWNERS \ No newline at end of file
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 27db41cb9f4e..171349a26569 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -841,7 +841,7 @@ public class RingtoneManager {
if (ringtoneUri != null) {
final Uri cacheUri = getCacheForType(type, context.getUserId());
try (InputStream in = openRingtone(context, ringtoneUri);
- OutputStream out = resolver.openOutputStream(cacheUri)) {
+ OutputStream out = resolver.openOutputStream(cacheUri, "wt")) {
FileUtils.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to cache ringtone: " + e);
diff --git a/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java b/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
index 2db0a8f4f911..33fc37ea0e6d 100644
--- a/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
+++ b/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
@@ -25,7 +25,7 @@ import android.text.TextUtils;
import android.util.Log;
import androidx.core.os.BuildCompat;
-import androidx.window.embedding.SplitController;
+import androidx.window.embedding.ActivityEmbeddingController;
import com.android.settingslib.utils.BuildCompatUtils;
@@ -86,7 +86,7 @@ public final class ActivityEmbeddingUtils {
* @param activity Activity that needs the check
*/
public static boolean isActivityEmbedded(Activity activity) {
- return SplitController.getInstance().isActivityEmbedded(activity);
+ return ActivityEmbeddingController.getInstance(activity).isActivityEmbedded(activity);
}
/**
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
index 5237b4fa1c3d..172aff76d481 100644
--- a/packages/SettingsLib/res/values/styles.xml
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -14,7 +14,7 @@
~ limitations under the License
-->
-<resources>
+<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearanceSmall">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
</style>
@@ -73,7 +73,7 @@
</style>
<style name="TextAppearanceBroadcastDialogButton" parent="@android:TextAppearance.DeviceDefault.Headline">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
<item name="android:textSize">@dimen/broadcast_dialog_btn_text_size</item>
</style>
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 379fe2ae713b..7634c58fd74d 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -149,6 +149,8 @@ public final class BatteryService extends SystemService {
private int mLastMaxChargingCurrent;
private int mLastMaxChargingVoltage;
private int mLastChargeCounter;
+ private int mLastBatteryCycleCount;
+ private int mLastCharingState;
private int mSequence = 1;
@@ -503,7 +505,9 @@ public final class BatteryService extends SystemService {
|| mHealthInfo.maxChargingCurrentMicroamps != mLastMaxChargingCurrent
|| mHealthInfo.maxChargingVoltageMicrovolts != mLastMaxChargingVoltage
|| mHealthInfo.batteryChargeCounterUah != mLastChargeCounter
- || mInvalidCharger != mLastInvalidCharger)) {
+ || mInvalidCharger != mLastInvalidCharger
+ || mHealthInfo.batteryCycleCount != mLastBatteryCycleCount
+ || mHealthInfo.chargingState != mLastCharingState)) {
if (mPlugType != mLastPlugType) {
if (mLastPlugType == BATTERY_PLUGGED_NONE) {
@@ -677,6 +681,8 @@ public final class BatteryService extends SystemService {
mLastChargeCounter = mHealthInfo.batteryChargeCounterUah;
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
+ mLastBatteryCycleCount = mHealthInfo.batteryCycleCount;
+ mLastCharingState = mHealthInfo.chargingState;
}
}
@@ -708,6 +714,8 @@ public final class BatteryService extends SystemService {
BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE,
mHealthInfo.maxChargingVoltageMicrovolts);
intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounterUah);
+ intent.putExtra(BatteryManager.EXTRA_CYCLE_COUNT, mHealthInfo.batteryCycleCount);
+ intent.putExtra(BatteryManager.EXTRA_CHARGING_STATUS, mHealthInfo.chargingState);
if (DEBUG) {
Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. scale:" + BATTERY_SCALE
+ ", info:" + mHealthInfo.toString());
@@ -731,6 +739,8 @@ public final class BatteryService extends SystemService {
event.putInt(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.batteryTemperatureTenthsCelsius);
event.putInt(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounterUah);
event.putLong(BatteryManager.EXTRA_EVENT_TIMESTAMP, now);
+ event.putInt(BatteryManager.EXTRA_CYCLE_COUNT, mHealthInfo.batteryCycleCount);
+ event.putInt(BatteryManager.EXTRA_CHARGING_STATUS, mHealthInfo.chargingState);
boolean queueWasEmpty = mBatteryLevelsEventQueue.isEmpty();
mBatteryLevelsEventQueue.add(event);
@@ -1241,11 +1251,20 @@ public final class BatteryService extends SystemService {
}
}
- // Reduced IBatteryPropertiesRegistrar that only implements getProperty for usage
- // in BatteryManager.
+ // Reduced IBatteryPropertiesRegistrar that implements getProperty for usage
+ // in BatteryManager and enforce permissions.
private final class BatteryPropertiesRegistrar extends IBatteryPropertiesRegistrar.Stub {
@Override
public int getProperty(int id, final BatteryProperty prop) throws RemoteException {
+ switch (id) {
+ case BatteryManager.BATTERY_PROPERTY_MANUFACTURING_DATE:
+ case BatteryManager.BATTERY_PROPERTY_FIRST_USAGE_DATE:
+ case BatteryManager.BATTERY_PROPERTY_CHARGING_POLICY:
+ case BatteryManager.BATTERY_PROPERTY_STATE_OF_HEALTH:
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ break;
+ }
return mHealthServiceWrapper.getProperty(id, prop);
}
@Override
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 730c4108220a..e1ae8d93e091 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1147,6 +1147,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
}
+ /*package*/ void setLeAudioTimeout(String address, int device, int delayMs) {
+ sendILMsg(MSG_IL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, address, delayMs);
+ }
+
/*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
synchronized (mDeviceStateLock) {
mBtHelper.setAvrcpAbsoluteVolumeSupported(supported);
@@ -1351,6 +1355,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1);
}
break;
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
+ // msg.obj == address of LE Audio device
+ synchronized (mDeviceStateLock) {
+ mDeviceInventory.onMakeLeAudioDeviceUnavailableNow(
+ (String) msg.obj, msg.arg1);
+ }
+ break;
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
synchronized (mDeviceStateLock) {
@@ -1577,11 +1588,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
// 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_IL_BTLEAUDIO_TIMEOUT = 49;
+
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_IL_BTA2DP_TIMEOUT:
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
case MSG_TOGGLE_HDMI:
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
@@ -1672,6 +1686,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_IL_BTA2DP_TIMEOUT:
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
if (sLastDeviceConnectMsgTime >= time) {
// add a little delay to make sure messages are ordered as expected
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 35da73ef58c0..a74f4154eb85 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -374,7 +374,7 @@ public class AudioDeviceInventory {
case BluetoothProfile.LE_AUDIO:
case BluetoothProfile.LE_AUDIO_BROADCAST:
if (switchToUnavailable) {
- makeLeAudioDeviceUnavailable(address, btInfo.mAudioSystemDevice);
+ makeLeAudioDeviceUnavailableNow(address, btInfo.mAudioSystemDevice);
} else if (switchToAvailable) {
makeLeAudioDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
streamType, btInfo.mVolume == -1 ? -1 : btInfo.mVolume * 10,
@@ -486,6 +486,12 @@ public class AudioDeviceInventory {
}
}
+ /*package*/ void onMakeLeAudioDeviceUnavailableNow(String address, int device) {
+ synchronized (mDevicesLock) {
+ makeLeAudioDeviceUnavailableNow(address, device);
+ }
+ }
+
/*package*/ void onReportNewRoutes() {
int n = mRoutesObservers.beginBroadcast();
if (n > 0) {
@@ -883,10 +889,11 @@ public class AudioDeviceInventory {
new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
.record();
if (toRemove.size() > 0) {
- final int delay = checkSendBecomingNoisyIntentInt(device, 0,
+ final int delay = checkSendBecomingNoisyIntentInt(device,
+ AudioService.CONNECTION_STATE_DISCONNECTED,
AudioSystem.DEVICE_NONE);
toRemove.stream().forEach(deviceAddress ->
- makeLeAudioDeviceUnavailable(deviceAddress, device)
+ makeLeAudioDeviceUnavailableLater(deviceAddress, device, delay)
);
}
}
@@ -1187,9 +1194,21 @@ public class AudioDeviceInventory {
*/
mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
- AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(device, address, name),
+ final int res = AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
+ device, address, name),
AudioSystem.DEVICE_STATE_AVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM failed to make available LE Audio device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: connection failed, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "LE Audio device addr=" + address + " now available").printLog(TAG));
+ }
+
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
@@ -1210,11 +1229,23 @@ public class AudioDeviceInventory {
}
@GuardedBy("mDevicesLock")
- private void makeLeAudioDeviceUnavailable(String address, int device) {
+ private void makeLeAudioDeviceUnavailableNow(String address, int device) {
if (device != AudioSystem.DEVICE_NONE) {
- AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(device, address),
+ final int res = AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
+ device, address),
AudioSystem.DEVICE_STATE_UNAVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM failed to make unavailable LE Audio device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: failed to disconnect, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+ "LE Audio device addr=" + address + " made unavailable")).printLog(TAG));
+ }
mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
}
@@ -1222,6 +1253,14 @@ public class AudioDeviceInventory {
}
@GuardedBy("mDevicesLock")
+ private void makeLeAudioDeviceUnavailableLater(String address, int device, int delayMs) {
+ // the device will be made unavailable later, so consider it disconnected right away
+ mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
+ // send the delayed message to make the device unavailable later
+ mDeviceBroker.setLeAudioTimeout(address, device, delayMs);
+ }
+
+ @GuardedBy("mDevicesLock")
private void setCurrentAudioRouteNameIfPossible(String name, boolean fromA2dp) {
synchronized (mCurAudioRoutes) {
if (TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 05915d964eb7..acfde9a4cfbb 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4005,7 +4005,8 @@ public class AudioService extends IAudioService.Stub
}
}
- private void setLeAudioVolumeOnModeUpdate(int mode, int device) {
+ private void setLeAudioVolumeOnModeUpdate(int mode, int device, int streamType, int index,
+ int maxIndex) {
switch (mode) {
case AudioSystem.MODE_IN_COMMUNICATION:
case AudioSystem.MODE_IN_CALL:
@@ -4023,16 +4024,15 @@ public class AudioService extends IAudioService.Stub
// (like the outgoing call) the value of 'device' is not DEVICE_OUT_BLE_*
// even when BLE is connected.
if (!AudioSystem.isLeAudioDeviceType(device)) {
+ Log.w(TAG, "setLeAudioVolumeOnModeUpdate got unexpected device=" + device
+ + ", forcing to device=" + AudioSystem.DEVICE_OUT_BLE_HEADSET);
device = AudioSystem.DEVICE_OUT_BLE_HEADSET;
}
- final int streamType = getBluetoothContextualVolumeStream(mode);
- final int index = mStreamStates[streamType].getIndex(device);
- final int maxIndex = mStreamStates[streamType].getMaxIndex();
-
if (DEBUG_VOL) {
- Log.d(TAG, "setLeAudioVolumeOnModeUpdate postSetLeAudioVolumeIndex index="
- + index + " maxIndex=" + maxIndex + " streamType=" + streamType);
+ Log.d(TAG, "setLeAudioVolumeOnModeUpdate postSetLeAudioVolumeIndex device="
+ + device + ", mode=" + mode + ", index=" + index + " maxIndex=" + maxIndex
+ + " streamType=" + streamType);
}
mDeviceBroker.postSetLeAudioVolumeIndex(index, maxIndex, streamType);
mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "setLeAudioVolumeOnModeUpdate");
@@ -5403,10 +5403,18 @@ public class AudioService extends IAudioService.Stub
mModeLogger.log(new PhoneStateEvent(requesterPackage, requesterPid,
requestedMode, pid, mode));
- int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
- int device = getDeviceForStream(streamType);
- int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
- setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true,
+ final int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
+ final int device = getDeviceForStream(streamType);
+ final int streamAlias = mStreamVolumeAlias[streamType];
+
+ if (DEBUG_MODE) {
+ Log.v(TAG, "onUpdateAudioMode: streamType=" + streamType
+ + ", streamAlias=" + streamAlias);
+ }
+
+ final int index = mStreamStates[streamAlias].getIndex(device);
+ final int maxIndex = mStreamStates[streamAlias].getMaxIndex();
+ setStreamVolumeInt(streamAlias, index, device, true,
requesterPackage, true /*hasModifyAudioSettings*/);
updateStreamVolumeAlias(true /*updateVolumes*/, requesterPackage);
@@ -5414,7 +5422,7 @@ public class AudioService extends IAudioService.Stub
// change of mode may require volume to be re-applied on some devices
updateAbsVolumeMultiModeDevices(previousMode, mode);
- setLeAudioVolumeOnModeUpdate(mode, device);
+ setLeAudioVolumeOnModeUpdate(mode, device, streamAlias, index, maxIndex);
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO
// connections not started by the application changing the mode when pid changes
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c15e419c073c..ab2c002c2b24 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -25,6 +25,8 @@ import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_AUTO;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO;
import static android.os.PowerWhitelistManager.REASON_VPN;
import static android.os.UserHandle.PER_USER_RANGE;
@@ -251,6 +253,14 @@ public class Vpn {
*/
private static final int STARTING_TOKEN = -1;
+ // TODO : read this from carrier config instead of a constant
+ @VisibleForTesting
+ public static final int AUTOMATIC_KEEPALIVE_DELAY_SECONDS = 30;
+
+ // Default keepalive timeout for carrier config is 5 minutes. Mimic this.
+ @VisibleForTesting
+ static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60;
+
// TODO: create separate trackers for each unique VPN to support
// automated reconnection
@@ -3071,6 +3081,7 @@ public class Vpn {
prepareStatusIntent();
}
agentConnect(this::onValidationStatus);
+ mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork());
return; // Link properties are already sent.
} else {
// Underlying networks also set in agentConnect()
@@ -3179,6 +3190,7 @@ public class Vpn {
if (!removedAddrs.isEmpty()) {
startNewNetworkAgent(
mNetworkAgent, "MTU too low for IPv6; restarting network agent");
+ mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork());
for (LinkAddress removed : removedAddrs) {
mTunnelIface.removeAddress(
@@ -3251,14 +3263,22 @@ public class Vpn {
private IkeSessionParams getIkeSessionParams(@NonNull Network underlyingNetwork) {
final IkeTunnelConnectionParams ikeTunConnParams =
mProfile.getIkeTunnelConnectionParams();
+ final IkeSessionParams.Builder builder;
if (ikeTunConnParams != null) {
- final IkeSessionParams.Builder builder =
- new IkeSessionParams.Builder(ikeTunConnParams.getIkeSessionParams())
- .setNetwork(underlyingNetwork);
- return builder.build();
+ builder = new IkeSessionParams.Builder(ikeTunConnParams.getIkeSessionParams())
+ .setNetwork(underlyingNetwork);
} else {
- return VpnIkev2Utils.buildIkeSessionParams(mContext, mProfile, underlyingNetwork);
+ builder = VpnIkev2Utils.makeIkeSessionParamsBuilder(mContext, mProfile,
+ underlyingNetwork);
}
+ if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) {
+ builder.setNattKeepAliveDelaySeconds(guessNattKeepaliveTimerForNetwork());
+ }
+ if (mProfile.isAutomaticIpVersionSelectionEnabled()) {
+ builder.setIpVersion(guessEspIpVersionForNetwork());
+ builder.setEncapType(guessEspEncapTypeForNetwork());
+ }
+ return builder.build();
}
@NonNull
@@ -3322,6 +3342,23 @@ public class Vpn {
startIkeSession(underlyingNetwork);
}
+ private int guessEspIpVersionForNetwork() {
+ // TODO : guess the IP version based on carrier if auto IP version selection is enabled
+ return ESP_IP_VERSION_AUTO;
+ }
+
+ private int guessEspEncapTypeForNetwork() {
+ // TODO : guess the ESP encap type based on carrier if auto IP version selection is
+ // enabled
+ return ESP_ENCAP_TYPE_AUTO;
+ }
+
+ private int guessNattKeepaliveTimerForNetwork() {
+ // TODO : guess the keepalive delay based on carrier if auto keepalive timer is
+ // enabled
+ return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+ }
+
boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) {
if (mSession == null || !mMobikeEnabled) return false;
@@ -3331,7 +3368,20 @@ public class Vpn {
+ mCurrentToken
+ " to network "
+ underlyingNetwork);
- mSession.setNetwork(underlyingNetwork);
+ final int ipVersion = mProfile.isAutomaticIpVersionSelectionEnabled()
+ ? guessEspIpVersionForNetwork() : ESP_IP_VERSION_AUTO;
+ final int encapType = mProfile.isAutomaticIpVersionSelectionEnabled()
+ ? guessEspEncapTypeForNetwork() : ESP_ENCAP_TYPE_AUTO;
+ final int keepaliveDelaySeconds;
+ if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) {
+ keepaliveDelaySeconds = guessNattKeepaliveTimerForNetwork();
+ } else if (mProfile.getIkeTunnelConnectionParams() != null) {
+ keepaliveDelaySeconds = mProfile.getIkeTunnelConnectionParams()
+ .getIkeSessionParams().getNattKeepAliveDelaySeconds();
+ } else {
+ keepaliveDelaySeconds = DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
+ }
+ mSession.setNetwork(underlyingNetwork, ipVersion, encapType, keepaliveDelaySeconds);
return true;
}
@@ -4661,8 +4711,14 @@ public class Vpn {
}
/** Update the underlying network of the IKE Session */
- public void setNetwork(@NonNull Network network) {
- mImpl.setNetwork(network);
+ public void setNetwork(@NonNull Network network, int ipVersion, int encapType,
+ int keepaliveDelaySeconds) {
+ mImpl.setNetwork(network, ipVersion, encapType, keepaliveDelaySeconds);
+ }
+
+ /** Set the underpinned network */
+ public void setUnderpinnedNetwork(@NonNull Network underpinnedNetwork) {
+ mImpl.setUnderpinnedNetwork(underpinnedNetwork);
}
/** Forcibly terminate the IKE Session */
diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
index 857c86de57ca..a48c9fcd4181 100644
--- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
+++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
@@ -99,7 +99,7 @@ import java.util.concurrent.Executor;
public class VpnIkev2Utils {
private static final String TAG = VpnIkev2Utils.class.getSimpleName();
- static IkeSessionParams buildIkeSessionParams(
+ static IkeSessionParams.Builder makeIkeSessionParamsBuilder(
@NonNull Context context, @NonNull Ikev2VpnProfile profile, @NonNull Network network) {
final IkeIdentification localId = parseIkeIdentification(profile.getUserIdentity());
final IkeIdentification remoteId = parseIkeIdentification(profile.getServerAddr());
@@ -117,7 +117,7 @@ public class VpnIkev2Utils {
ikeOptionsBuilder.addSaProposal(ikeProposal);
}
- return ikeOptionsBuilder.build();
+ return ikeOptionsBuilder;
}
static ChildSessionParams buildChildSessionParams(List<String> allowedAlgorithms) {
diff --git a/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java b/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
index c4113198ae1d..1153cc37e3da 100644
--- a/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
+++ b/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
@@ -18,6 +18,7 @@ package com.android.server.health;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.hardware.health.BatteryHealthData;
import android.hardware.health.HealthInfo;
import android.hardware.health.IHealth;
import android.os.BatteryManager;
@@ -113,6 +114,7 @@ class HealthServiceWrapperAidl extends HealthServiceWrapper {
private int getPropertyInternal(int id, BatteryProperty prop) throws RemoteException {
IHealth service = mLastService.get();
if (service == null) throw new RemoteException("no health service");
+ BatteryHealthData healthData;
try {
switch (id) {
case BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER:
@@ -133,6 +135,21 @@ class HealthServiceWrapperAidl extends HealthServiceWrapper {
case BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER:
prop.setLong(service.getEnergyCounterNwh());
break;
+ case BatteryManager.BATTERY_PROPERTY_MANUFACTURING_DATE:
+ healthData = service.getBatteryHealthData();
+ prop.setLong(healthData.batteryManufacturingDateSeconds);
+ break;
+ case BatteryManager.BATTERY_PROPERTY_FIRST_USAGE_DATE:
+ healthData = service.getBatteryHealthData();
+ prop.setLong(healthData.batteryFirstUsageSeconds);
+ break;
+ case BatteryManager.BATTERY_PROPERTY_CHARGING_POLICY:
+ prop.setLong(service.getChargingPolicy());
+ break;
+ case BatteryManager.BATTERY_PROPERTY_STATE_OF_HEALTH:
+ healthData = service.getBatteryHealthData();
+ prop.setLong(healthData.batteryStateOfHealth);
+ break;
}
} catch (UnsupportedOperationException e) {
// Leave prop untouched.
diff --git a/services/robotests/src/com/android/server/media/OWNERS b/services/robotests/src/com/android/server/media/OWNERS
new file mode 100644
index 000000000000..c74c9ac98b13
--- /dev/null
+++ b/services/robotests/src/com/android/server/media/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 137631
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
+
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index db99acfd9a35..3533c0907fac 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -31,6 +31,7 @@ import com.android.ims.internal.IImsCallSession;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.Executor;
/**
* Listener interface for notifying the Framework's {@link ImsCallSession} for updates to an ongoing
@@ -44,8 +45,8 @@ import java.util.Set;
// ImsCallSessionListenerConverter is also changed.
@SystemApi
public class ImsCallSessionListener {
-
private final IImsCallSessionListener mListener;
+ private Executor mExecutor = null;
/** @hide */
public ImsCallSessionListener(IImsCallSessionListener l) {
@@ -243,6 +244,9 @@ public class ImsCallSessionListener {
public void callSessionMergeStarted(ImsCallSessionImplBase newSession, ImsCallProfile profile)
{
try {
+ if (newSession != null && mExecutor != null) {
+ newSession.setDefaultExecutor(mExecutor);
+ }
mListener.callSessionMergeStarted(newSession != null ?
newSession.getServiceImpl() : null, profile);
} catch (RemoteException e) {
@@ -274,6 +278,9 @@ public class ImsCallSessionListener {
*/
public void callSessionMergeComplete(ImsCallSessionImplBase newSession) {
try {
+ if (newSession != null && mExecutor != null) {
+ newSession.setDefaultExecutor(mExecutor);
+ }
mListener.callSessionMergeComplete(newSession != null ?
newSession.getServiceImpl() : null);
} catch (RemoteException e) {
@@ -361,6 +368,9 @@ public class ImsCallSessionListener {
public void callSessionConferenceExtended(ImsCallSessionImplBase newSession,
ImsCallProfile profile) {
try {
+ if (newSession != null && mExecutor != null) {
+ newSession.setDefaultExecutor(mExecutor);
+ }
mListener.callSessionConferenceExtended(
newSession != null ? newSession.getServiceImpl() : null, profile);
} catch (RemoteException e) {
@@ -406,6 +416,9 @@ public class ImsCallSessionListener {
public void callSessionConferenceExtendReceived(ImsCallSessionImplBase newSession,
ImsCallProfile profile) {
try {
+ if (newSession != null && mExecutor != null) {
+ newSession.setDefaultExecutor(mExecutor);
+ }
mListener.callSessionConferenceExtendReceived(newSession != null
? newSession.getServiceImpl() : null, profile);
} catch (RemoteException e) {
@@ -808,5 +821,19 @@ public class ImsCallSessionListener {
e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Set default Executor from ImsService.
+ * @param executor The default executor to use when executing the methods by the vendor
+ * implementation of {@link ImsCallSessionImplBase} for conference call.
+ * This executor is dedicated to set vendor CallSessionImpl
+ * only when conference call is established.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ if (mExecutor == null) {
+ mExecutor = executor;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index fb0e659ec77b..ebe11e938c39 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -644,6 +644,7 @@ public class MmTelFeature extends ImsFeature {
throw new IllegalStateException("Session is not available.");
}
try {
+ c.setDefaultExecutor(MmTelFeature.this.mExecutor);
listener.onIncomingCall(c.getServiceImpl(), extras);
} catch (RemoteException e) {
throw new RuntimeException(e);
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index e8100957517f..25bf7d6af9ca 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -173,8 +173,9 @@ public class ImsCallSessionImplBase implements AutoCloseable {
@Override
public void setListener(IImsCallSessionListener listener) {
- executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener(
- new ImsCallSessionListener(listener)), "setListener");
+ ImsCallSessionListener iCSL = new ImsCallSessionListener(listener);
+ iCSL.setDefaultExecutor(mExecutor);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener(iCSL), "setListener");
}
@Override
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 90ddb6ffb34a..d2a6bf288be4 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -31,6 +31,7 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -299,6 +300,8 @@ public final class BackgroundDexOptServiceIntegrationTests {
// Test that background dexopt under low storage conditions downgrades unused packages.
@Test
+ @Ignore("b/251438180: This test has been failing for a long time; temporarily disable it while"
+ + " we investigate this issue.")
public void testBackgroundDexOptDowngradeSuccessful() throws IOException {
// Should be more than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS + 1;