Merge "OPS_MIC refactoring" into main
diff --git a/api/api.go b/api/api.go
index a003aba..e09be03 100644
--- a/api/api.go
+++ b/api/api.go
@@ -146,7 +146,7 @@
metalavaCmd := "$(location metalava)"
// Silence reflection warnings. See b/168689341
metalavaCmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
- metalavaCmd += " --quiet --no-banner --format=v2 "
+ metalavaCmd += " --quiet merge-signatures --format=v2 "
filename := txt.TxtFilename
if txt.Scope != "public" {
@@ -156,7 +156,7 @@
props.Name = proptools.StringPtr(ctx.ModuleName() + "-" + filename)
props.Tools = []string{"metalava"}
props.Out = []string{filename}
- props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --api $(out)")
+ props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --out $(out)")
props.Srcs = append([]string{txt.BaseTxt}, createSrcs(txt.Modules, txt.ModuleTag)...)
props.Dists = []android.Dist{
{
diff --git a/core/java/android/os/PowerMonitor.java b/core/java/android/os/PowerMonitor.java
index ebdd463..5fb0df7 100644
--- a/core/java/android/os/PowerMonitor.java
+++ b/core/java/android/os/PowerMonitor.java
@@ -23,6 +23,10 @@
import java.lang.annotation.RetentionPolicy;
/**
+ * A PowerMonitor represents either a Channel aka ODPM rail (on-device power monitor) or an
+ * EnergyConsumer, as defined in
+ * <a href="https://android.googlesource.com/platform/hardware/interfaces/+/refs/heads/main/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats">android.hardware.power.stats</a>
+ *
* @hide
*/
public final class PowerMonitor implements Parcelable {
@@ -92,6 +96,7 @@
return 0;
}
+ @NonNull
public static final Creator<PowerMonitor> CREATOR = new Creator<>() {
@Override
public PowerMonitor createFromParcel(@NonNull Parcel in) {
diff --git a/core/java/android/os/PowerMonitorReadings.java b/core/java/android/os/PowerMonitorReadings.java
index 3d7f859..e767059 100644
--- a/core/java/android/os/PowerMonitorReadings.java
+++ b/core/java/android/os/PowerMonitorReadings.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import java.util.Arrays;
@@ -43,8 +44,8 @@
* @param powerMonitors array of power monitor (ODPM) rails, sorted by PowerMonitor.index
* @hide
*/
- public PowerMonitorReadings(PowerMonitor[] powerMonitors,
- long[] energyUws, long[] timestampsMs) {
+ public PowerMonitorReadings(@NonNull PowerMonitor[] powerMonitors,
+ @NonNull long[] energyUws, @NonNull long[] timestampsMs) {
mPowerMonitors = powerMonitors;
mEnergyUws = energyUws;
mTimestampsMs = timestampsMs;
@@ -55,7 +56,7 @@
* Does not persist across reboots.
* Represents total energy: both on-battery and plugged-in.
*/
- public long getConsumedEnergyUws(PowerMonitor powerMonitor) {
+ public long getConsumedEnergyUws(@NonNull PowerMonitor powerMonitor) {
int offset = Arrays.binarySearch(mPowerMonitors, powerMonitor, POWER_MONITOR_COMPARATOR);
if (offset >= 0) {
return mEnergyUws[offset];
@@ -64,9 +65,10 @@
}
/**
- * Elapsed realtime when the snapshot was taken.
+ * Elapsed realtime, in milliseconds, when the snapshot was taken.
*/
- public long getTimestampMs(PowerMonitor powerMonitor) {
+ @ElapsedRealtimeLong
+ public long getTimestamp(@NonNull PowerMonitor powerMonitor) {
int offset = Arrays.binarySearch(mPowerMonitors, powerMonitor, POWER_MONITOR_COMPARATOR);
if (offset >= 0) {
return mTimestampsMs[offset];
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index ab30a8b..dfc43f4 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -24,6 +24,8 @@
import android.os.BatteryStats;
import android.os.Build;
import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.os.Handler;
import android.os.IPowerStatsService;
import android.os.PowerMonitor;
import android.os.PowerMonitorReadings;
@@ -36,8 +38,8 @@
import java.util.Arrays;
import java.util.Comparator;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
+import java.util.List;
+import java.util.function.Consumer;
/**
* Provides access to data about how various system resources are used by applications.
@@ -62,7 +64,8 @@
private final IBatteryStats mBatteryStats;
@Nullable
private final IPowerStatsService mPowerStats;
- private PowerMonitor[] mPowerMonitorsInfo;
+ private List<PowerMonitor> mPowerMonitorsInfo;
+ private final Object mPowerMonitorsLock = new Object();
/**
* Construct a new SystemHealthManager object.
@@ -161,53 +164,68 @@
* @hide
*/
@NonNull
- public PowerMonitor[] getSupportedPowerMonitors() {
- synchronized (this) {
+ public List<PowerMonitor> getSupportedPowerMonitors() {
+ synchronized (mPowerMonitorsLock) {
if (mPowerMonitorsInfo != null) {
return mPowerMonitorsInfo;
}
+ }
+ ConditionVariable lock = new ConditionVariable();
+ // Populate mPowerMonitorsInfo by side-effect
+ getSupportedPowerMonitors(null, unused -> lock.open());
+ lock.block();
- CompletableFuture<PowerMonitor[]> future = new CompletableFuture<>();
- getSupportedPowerMonitors(future);
- try {
- return future.get();
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException(e);
- }
+ synchronized (mPowerMonitorsLock) {
+ return mPowerMonitorsInfo;
}
}
/**
- * Retrieves a list of supported power monitors, see {@link #getSupportedPowerMonitors()}
+ * Asynchronously retrieves a list of supported power monitors, see
+ * {@link #getSupportedPowerMonitors()}
+ *
+ * @param handler optional Handler to deliver the callback. If not supplied, the callback
+ * may be invoked on an arbitrary thread.
+ * @param onResult callback for the result
*
* @hide
*/
- public void getSupportedPowerMonitors(@NonNull CompletableFuture<PowerMonitor[]> future) {
- synchronized (this) {
+ public void getSupportedPowerMonitors(@Nullable Handler handler,
+ @NonNull Consumer<List<PowerMonitor>> onResult) {
+ final List<PowerMonitor> result;
+ synchronized (mPowerMonitorsLock) {
if (mPowerMonitorsInfo != null) {
- future.complete(mPowerMonitorsInfo);
- return;
+ result = mPowerMonitorsInfo;
+ } else if (mPowerStats == null) {
+ mPowerMonitorsInfo = List.of();
+ result = mPowerMonitorsInfo;
+ } else {
+ result = null;
}
- try {
- if (mPowerStats == null) {
- mPowerMonitorsInfo = new PowerMonitor[0];
- future.complete(mPowerMonitorsInfo);
- return;
- }
-
- mPowerStats.getSupportedPowerMonitors(new ResultReceiver(null) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- synchronized (this) {
- mPowerMonitorsInfo = resultData.getParcelableArray(
- IPowerStatsService.KEY_MONITORS, PowerMonitor.class);
- }
- future.complete(mPowerMonitorsInfo);
+ }
+ if (result != null) {
+ if (handler != null) {
+ handler.post(() -> onResult.accept(result));
+ } else {
+ onResult.accept(result);
+ }
+ return;
+ }
+ try {
+ mPowerStats.getSupportedPowerMonitors(new ResultReceiver(handler) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ PowerMonitor[] array = resultData.getParcelableArray(
+ IPowerStatsService.KEY_MONITORS, PowerMonitor.class);
+ List<PowerMonitor> result = array != null ? Arrays.asList(array) : List.of();
+ synchronized (mPowerMonitorsLock) {
+ mPowerMonitorsInfo = result;
}
- });
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ onResult.accept(result);
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -215,54 +233,74 @@
* Retrieves the accumulated power consumption reported by the specified power monitors.
*
* @param powerMonitors power monitors to be returned.
+ *
* @hide
*/
@NonNull
- public PowerMonitorReadings getPowerMonitorReadings(@NonNull PowerMonitor[] powerMonitors) {
- CompletableFuture<PowerMonitorReadings> future = new CompletableFuture<>();
- getPowerMonitorReadings(powerMonitors, future);
- try {
- return future.get();
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException(e);
+ public PowerMonitorReadings getPowerMonitorReadings(@NonNull List<PowerMonitor> powerMonitors) {
+ PowerMonitorReadings[] outReadings = new PowerMonitorReadings[1];
+ RuntimeException[] outException = new RuntimeException[1];
+ ConditionVariable lock = new ConditionVariable();
+ getPowerMonitorReadings(powerMonitors, null,
+ pms -> {
+ outReadings[0] = pms;
+ lock.open();
+ },
+ error -> {
+ outException[0] = error;
+ lock.open();
+ }
+ );
+ lock.block();
+ if (outException[0] != null) {
+ throw outException[0];
}
+ return outReadings[0];
}
private static final Comparator<PowerMonitor> POWER_MONITOR_COMPARATOR =
Comparator.comparingInt(pm -> pm.index);
/**
+ * Asynchronously retrieves the accumulated power consumption reported by the specified power
+ * monitors.
+ *
* @param powerMonitors power monitors to be retrieved.
+ * @param handler optional Handler to deliver the callbacks. If not supplied, the callback
+ * may be invoked on an arbitrary thread.
+ * @param onSuccess callback for the result
+ * @param onError callback invoked in case of an error
+ *
* @hide
*/
- public void getPowerMonitorReadings(@NonNull PowerMonitor[] powerMonitors,
- @NonNull CompletableFuture<PowerMonitorReadings> future) {
+ public void getPowerMonitorReadings(@NonNull List<PowerMonitor> powerMonitors,
+ @Nullable Handler handler, @NonNull Consumer<PowerMonitorReadings> onSuccess,
+ @NonNull Consumer<RuntimeException> onError) {
if (mPowerStats == null) {
- future.completeExceptionally(
- new IllegalArgumentException("Unsupported power monitor"));
+ onError.accept(new IllegalArgumentException("Unsupported power monitor"));
return;
}
- Arrays.sort(powerMonitors, POWER_MONITOR_COMPARATOR);
- int[] indices = new int[powerMonitors.length];
- for (int i = 0; i < powerMonitors.length; i++) {
- indices[i] = powerMonitors[i].index;
+ PowerMonitor[] powerMonitorsArray =
+ powerMonitors.toArray(new PowerMonitor[powerMonitors.size()]);
+ Arrays.sort(powerMonitorsArray, POWER_MONITOR_COMPARATOR);
+ int[] indices = new int[powerMonitors.size()];
+ for (int i = 0; i < powerMonitors.size(); i++) {
+ indices[i] = powerMonitorsArray[i].index;
}
try {
- mPowerStats.getPowerMonitorReadings(indices, new ResultReceiver(null) {
+ mPowerStats.getPowerMonitorReadings(indices, new ResultReceiver(handler) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == IPowerStatsService.RESULT_SUCCESS) {
- future.complete(new PowerMonitorReadings(powerMonitors,
+ onSuccess.accept(new PowerMonitorReadings(powerMonitorsArray,
resultData.getLongArray(IPowerStatsService.KEY_ENERGY),
resultData.getLongArray(IPowerStatsService.KEY_TIMESTAMPS)));
} else if (resultCode == IPowerStatsService.RESULT_UNSUPPORTED_POWER_MONITOR) {
- future.completeExceptionally(
- new IllegalArgumentException("Unsupported power monitor"));
+ onError.accept(new IllegalArgumentException("Unsupported power monitor"));
} else {
- future.completeExceptionally(
- new IllegalStateException(
- "Unrecognized result code " + resultCode));
+ onError.accept(new IllegalStateException(
+ "Unrecognized result code " + resultCode));
}
}
});
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index b85cf6d..fce87db 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -285,6 +286,7 @@
private IControlsSubscriber mCs;
private boolean mEnforceStateless;
private Context mContext;
+ private SubscriptionAdapter mSubscription;
SubscriberProxy(boolean enforceStateless, IBinder token, IControlsSubscriber cs) {
mEnforceStateless = enforceStateless;
@@ -300,11 +302,14 @@
public void onSubscribe(Subscription subscription) {
try {
- mCs.onSubscribe(mToken, new SubscriptionAdapter(subscription));
+ SubscriptionAdapter subscriptionAdapter = new SubscriptionAdapter(subscription);
+ mCs.onSubscribe(mToken, subscriptionAdapter);
+ mSubscription = subscriptionAdapter;
} catch (RemoteException ex) {
- ex.rethrowAsRuntimeException();
+ handleRemoteException(ex);
}
}
+
public void onNext(@NonNull Control control) {
Preconditions.checkNotNull(control);
try {
@@ -318,20 +323,36 @@
}
mCs.onNext(mToken, control);
} catch (RemoteException ex) {
- ex.rethrowAsRuntimeException();
+ handleRemoteException(ex);
}
}
+
public void onError(Throwable t) {
try {
mCs.onError(mToken, t.toString());
+ mSubscription = null;
} catch (RemoteException ex) {
- ex.rethrowAsRuntimeException();
+ handleRemoteException(ex);
}
}
+
public void onComplete() {
try {
mCs.onComplete(mToken);
+ mSubscription = null;
} catch (RemoteException ex) {
+ handleRemoteException(ex);
+ }
+ }
+
+ private void handleRemoteException(RemoteException ex) {
+ if (ex instanceof DeadObjectException) {
+ // System UI crashed or is restarting. There is no need to rethrow this
+ SubscriptionAdapter subscriptionAdapter = mSubscription;
+ if (subscriptionAdapter != null) {
+ subscriptionAdapter.cancel();
+ }
+ } else {
ex.rethrowAsRuntimeException();
}
}
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 4464d19..d31f823 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManagerGlobal;
+import android.os.IInputConstants;
import android.util.ArrayMap;
import android.util.Pools.SynchronizedPool;
@@ -53,11 +54,13 @@
public @interface VelocityTrackableMotionEventAxis {}
/**
- * Velocity Tracker Strategy: Invalid.
+ * Use the default Velocity Tracker Strategy. Different axes may use different default
+ * strategies.
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_DEFAULT = -1;
+ public static final int VELOCITY_TRACKER_STRATEGY_DEFAULT =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_DEFAULT;
/**
* Velocity Tracker Strategy: Impulse.
@@ -66,7 +69,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_IMPULSE = 0;
+ public static final int VELOCITY_TRACKER_STRATEGY_IMPULSE =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_IMPULSE;
/**
* Velocity Tracker Strategy: LSQ1.
@@ -77,7 +81,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_LSQ1 = 1;
+ public static final int VELOCITY_TRACKER_STRATEGY_LSQ1 =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_LSQ1;
/**
* Velocity Tracker Strategy: LSQ2.
@@ -88,7 +93,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_LSQ2 = 2;
+ public static final int VELOCITY_TRACKER_STRATEGY_LSQ2 =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_LSQ2;
/**
* Velocity Tracker Strategy: LSQ3.
@@ -98,7 +104,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_LSQ3 = 3;
+ public static final int VELOCITY_TRACKER_STRATEGY_LSQ3 =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_LSQ3;
/**
* Velocity Tracker Strategy: WLSQ2_DELTA.
@@ -106,7 +113,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_WLSQ2_DELTA = 4;
+ public static final int VELOCITY_TRACKER_STRATEGY_WLSQ2_DELTA =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_WLSQ2_DELTA;
/**
* Velocity Tracker Strategy: WLSQ2_CENTRAL.
@@ -114,7 +122,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_WLSQ2_CENTRAL = 5;
+ public static final int VELOCITY_TRACKER_STRATEGY_WLSQ2_CENTRAL =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_WLSQ2_CENTRAL;
/**
* Velocity Tracker Strategy: WLSQ2_RECENT.
@@ -122,7 +131,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_WLSQ2_RECENT = 6;
+ public static final int VELOCITY_TRACKER_STRATEGY_WLSQ2_RECENT =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_WLSQ2_RECENT;
/**
* Velocity Tracker Strategy: INT1.
@@ -134,7 +144,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_INT1 = 7;
+ public static final int VELOCITY_TRACKER_STRATEGY_INT1 =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_INT1;
/**
* Velocity Tracker Strategy: INT2.
@@ -144,7 +155,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_INT2 = 8;
+ public static final int VELOCITY_TRACKER_STRATEGY_INT2 =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_INT2;
/**
* Velocity Tracker Strategy: Legacy.
@@ -155,7 +167,8 @@
*
* @hide
*/
- public static final int VELOCITY_TRACKER_STRATEGY_LEGACY = 9;
+ public static final int VELOCITY_TRACKER_STRATEGY_LEGACY =
+ IInputConstants.VELOCITY_TRACKER_STRATEGY_LEGACY;
/**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 5d1a81f..bb1d5b1 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1302,7 +1302,7 @@
* ratio or orientation specified in the app manifest.
*
* <p>The aspect ratio compatibility override is exposed to users in device
- * settings. A menu in device settings lists all apps that don't opt out of
+ * settings. A menu in device settings lists all apps that have not opted out of
* the compatibility override. Users select apps from the menu and set the
* app aspect ratio on a per-app basis. Typically, the menu is available
* only on large screen devices.
@@ -1347,11 +1347,11 @@
* Application level
* {@link android.content.pm.PackageManager.Property PackageManager.Property}
* tag that (when set to false) informs the system the app has opted out of the
- * full-screen option of the aspect ratio compatibility override. (For
- * background information about the aspect ratio compatibility override, see
+ * full-screen option of the user aspect ratio compatibility override settings. (For
+ * background information about the user aspect ratio compatibility override, see
* {@link #PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE}.)
*
- * <p>When users apply the aspect ratio compatibility override, the orientation
+ * <p>When users apply the full-screen compatibility override, the orientation
* of the activity is forced to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_USER}.
*
* <p>The user override is intended to improve the app experience on devices
diff --git a/core/jni/android_view_VelocityTracker.cpp b/core/jni/android_view_VelocityTracker.cpp
index 05c9f68..03e9a6a 100644
--- a/core/jni/android_view_VelocityTracker.cpp
+++ b/core/jni/android_view_VelocityTracker.cpp
@@ -16,13 +16,14 @@
#define LOG_TAG "VelocityTracker-JNI"
+#include <android-base/logging.h>
#include <android_runtime/AndroidRuntime.h>
#include <cutils/properties.h>
#include <input/Input.h>
#include <input/VelocityTracker.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
-#include <utils/Log.h>
+
#include "android_view_MotionEvent.h"
#include "core_jni_helpers.h"
@@ -102,7 +103,7 @@
jobject eventObj) {
const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
if (!event) {
- ALOGW("nativeAddMovement failed because MotionEvent was finalized.");
+ LOG(WARNING) << "nativeAddMovement failed because MotionEvent was finalized.";
return;
}
diff --git a/core/tests/coretests/src/android/os/health/SystemHealthManagerTest.java b/core/tests/coretests/src/android/os/health/SystemHealthManagerTest.java
index 2232e3a..e1f9523 100644
--- a/core/tests/coretests/src/android/os/health/SystemHealthManagerTest.java
+++ b/core/tests/coretests/src/android/os/health/SystemHealthManagerTest.java
@@ -20,6 +20,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.os.ConditionVariable;
import android.os.PowerMonitor;
import android.os.PowerMonitorReadings;
@@ -29,13 +30,16 @@
import java.util.List;
public class SystemHealthManagerTest {
+ private List<PowerMonitor> mPowerMonitorInfo;
+ private PowerMonitorReadings mReadings;
+ private RuntimeException mException;
@Test
public void getPowerMonitors() {
SystemHealthManager shm = getContext().getSystemService(SystemHealthManager.class);
- PowerMonitor[] powerMonitorInfo = shm.getSupportedPowerMonitors();
+ List<PowerMonitor> powerMonitorInfo = shm.getSupportedPowerMonitors();
assertThat(powerMonitorInfo).isNotNull();
- if (powerMonitorInfo.length == 0) {
+ if (powerMonitorInfo.isEmpty()) {
// This device does not support PowerStats HAL
return;
}
@@ -50,20 +54,73 @@
}
}
- List<PowerMonitor> pmis = new ArrayList<>();
+ List<PowerMonitor> selectedMonitors = new ArrayList<>();
if (consumerMonitor != null) {
- pmis.add(consumerMonitor);
+ selectedMonitors.add(consumerMonitor);
}
if (measurementMonitor != null) {
- pmis.add(measurementMonitor);
+ selectedMonitors.add(measurementMonitor);
}
- PowerMonitor[] selectedMonitors = pmis.toArray(new PowerMonitor[0]);
PowerMonitorReadings readings = shm.getPowerMonitorReadings(selectedMonitors);
for (PowerMonitor monitor : selectedMonitors) {
assertThat(readings.getConsumedEnergyUws(monitor)).isAtLeast(0);
- assertThat(readings.getTimestampMs(monitor)).isGreaterThan(0);
+ assertThat(readings.getTimestamp(monitor)).isGreaterThan(0);
+ }
+ }
+
+ @Test
+ public void getPowerMonitorsAsync() {
+ SystemHealthManager shm = getContext().getSystemService(SystemHealthManager.class);
+ ConditionVariable done = new ConditionVariable();
+ shm.getSupportedPowerMonitors(null, pms -> {
+ mPowerMonitorInfo = pms;
+ done.open();
+ });
+ done.block();
+ assertThat(mPowerMonitorInfo).isNotNull();
+ if (mPowerMonitorInfo.isEmpty()) {
+ // This device does not support PowerStats HAL
+ return;
+ }
+
+ PowerMonitor consumerMonitor = null;
+ PowerMonitor measurementMonitor = null;
+ for (PowerMonitor pmi : mPowerMonitorInfo) {
+ if (pmi.type == PowerMonitor.POWER_MONITOR_TYPE_MEASUREMENT) {
+ measurementMonitor = pmi;
+ } else {
+ consumerMonitor = pmi;
+ }
+ }
+
+ List<PowerMonitor> selectedMonitors = new ArrayList<>();
+ if (consumerMonitor != null) {
+ selectedMonitors.add(consumerMonitor);
+ }
+ if (measurementMonitor != null) {
+ selectedMonitors.add(measurementMonitor);
+ }
+
+ done.close();
+ shm.getPowerMonitorReadings(selectedMonitors, null,
+ readings -> {
+ mReadings = readings;
+ done.open();
+ },
+ exception -> {
+ mException = exception;
+ done.open();
+ }
+ );
+ done.block();
+
+ assertThat(mException).isNull();
+
+ for (PowerMonitor monitor : selectedMonitors) {
+ assertThat(mReadings.getConsumedEnergyUws(monitor)).isAtLeast(0);
+ assertThat(mReadings.getTimestamp(monitor)).isGreaterThan(0);
}
}
}
diff --git a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
index 5fe17ee..4d446901 100644
--- a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
+++ b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -36,6 +37,7 @@
import android.graphics.drawable.Icon;
import android.os.Binder;
import android.os.Bundle;
+import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.RemoteException;
import android.service.controls.actions.CommandAction;
@@ -53,6 +55,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -307,6 +310,18 @@
intent.getParcelableExtra(ControlsProviderService.EXTRA_CONTROL)));
}
+ @Test
+ public void testOnNextDoesntRethrowDeadObjectException() throws RemoteException {
+ doAnswer(invocation -> {
+ throw new DeadObjectException();
+ }).when(mSubscriber).onNext(ArgumentMatchers.any(), ArgumentMatchers.any());
+ Control control = new Control.StatelessBuilder("TEST_ID", mPendingIntent).build();
+
+ sendControlGetControl(control);
+
+ assertTrue(mControlsProviderService.mSubscription.mIsCancelled);
+ }
+
/**
* Sends the control through the publisher in {@code mControlsProviderService}, returning
* the control obtained by the subscriber
@@ -359,6 +374,7 @@
}
private List<Control> mControls;
+ private FakeSubscription mSubscription;
public void setControls(List<Control> controls) {
mControls = controls;
@@ -398,17 +414,35 @@
}
private Subscription createSubscription(Subscriber s, List<Control> controls) {
- return new Subscription() {
- public void request(long n) {
- int i = 0;
- for (Control c : mControls) {
- if (i++ < n) s.onNext(c);
- else break;
- }
- s.onComplete();
- }
- public void cancel() {}
- };
+ FakeSubscription subscription = new FakeSubscription(s, controls);
+ mSubscription = subscription;
+ return subscription;
+ }
+ }
+
+ private static final class FakeSubscription implements Subscription {
+
+ private final Subscriber mSubscriber;
+ private final List<Control> mControls;
+
+ private boolean mIsCancelled = false;
+
+ FakeSubscription(Subscriber s, List<Control> controls) {
+ mSubscriber = s;
+ mControls = controls;
+ }
+
+ public void request(long n) {
+ int i = 0;
+ for (Control c : mControls) {
+ if (i++ < n) mSubscriber.onNext(c);
+ else break;
+ }
+ mSubscriber.onComplete();
+ }
+
+ public void cancel() {
+ mIsCancelled = true;
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 62b0799..0998e71 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -342,6 +342,7 @@
if (!mActiveLetterboxEduLayout.updateCompatInfo(taskInfo, taskListener,
showOnDisplay(mActiveLetterboxEduLayout.getDisplayId()))) {
// The layout is no longer eligible to be shown, clear active layout.
+ mActiveLetterboxEduLayout.release();
mActiveLetterboxEduLayout = null;
}
return;
@@ -371,15 +372,9 @@
ShellTaskOrganizer.TaskListener taskListener) {
return new LetterboxEduWindowManager(context, taskInfo,
mSyncQueue, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId),
- mTransitionsLazy.get(), this::onLetterboxEduDismissed, mDockStateReader,
- mCompatUIConfiguration);
- }
-
- private void onLetterboxEduDismissed(
- Pair<TaskInfo, ShellTaskOrganizer.TaskListener> stateInfo) {
- mActiveLetterboxEduLayout = null;
- // We need to update the UI
- createOrUpdateReachabilityEduLayout(stateInfo.first, stateInfo.second);
+ mTransitionsLazy.get(),
+ stateInfo -> createOrUpdateReachabilityEduLayout(stateInfo.first, stateInfo.second),
+ mDockStateReader, mCompatUIConfiguration);
}
private void createOrUpdateRestartDialogLayout(TaskInfo taskInfo,
@@ -448,6 +443,7 @@
if (!mActiveReachabilityEduLayout.updateCompatInfo(taskInfo, taskListener,
showOnDisplay(mActiveReachabilityEduLayout.getDisplayId()))) {
// The layout is no longer eligible to be shown, remove from active layouts.
+ mActiveReachabilityEduLayout.release();
mActiveReachabilityEduLayout = null;
}
return;
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 8191f5e..a958a09 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -15,6 +15,8 @@
*/
#include "FrameInfo.h"
+#include <gui/TraceUtils.h>
+
#include <cstring>
namespace android {
@@ -51,6 +53,30 @@
void FrameInfo::importUiThreadInfo(int64_t* info) {
memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
+ mSkippedFrameReason.reset();
+}
+
+const char* toString(SkippedFrameReason reason) {
+ switch (reason) {
+ case SkippedFrameReason::DrawingOff:
+ return "DrawingOff";
+ case SkippedFrameReason::ContextIsStopped:
+ return "ContextIsStopped";
+ case SkippedFrameReason::NothingToDraw:
+ return "NothingToDraw";
+ case SkippedFrameReason::NoOutputTarget:
+ return "NoOutputTarget";
+ case SkippedFrameReason::NoBuffer:
+ return "NoBuffer";
+ case SkippedFrameReason::AlreadyDrawn:
+ return "AlreadyDrawn";
+ }
+}
+
+void FrameInfo::setSkippedFrameReason(android::uirenderer::SkippedFrameReason reason) {
+ ATRACE_FORMAT_INSTANT("Frame skipped: %s", toString(reason));
+ addFlag(FrameInfoFlags::SkippedFrame);
+ mSkippedFrameReason = reason;
}
} /* namespace uirenderer */
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index b15b6cb..f7ad139 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -16,15 +16,17 @@
#ifndef FRAMEINFO_H_
#define FRAMEINFO_H_
-#include "utils/Macros.h"
-
#include <cutils/compiler.h>
+#include <memory.h>
#include <utils/Timers.h>
#include <array>
-#include <memory.h>
+#include <optional>
#include <string>
+#include "SkippedFrameInfo.h"
+#include "utils/Macros.h"
+
namespace android {
namespace uirenderer {
@@ -186,8 +188,14 @@
return mFrameInfo[static_cast<int>(index)];
}
+ void setSkippedFrameReason(SkippedFrameReason reason);
+ inline std::optional<SkippedFrameReason> getSkippedFrameReason() const {
+ return mSkippedFrameReason;
+ }
+
private:
int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
+ std::optional<SkippedFrameReason> mSkippedFrameReason;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 687e4dd..59f2169 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -148,7 +148,7 @@
int fast_i = 0, janky_i = 0;
// Set the bottom of all the shapes to the baseline
for (int fi = mFrameSource.size() - 1; fi >= 0; fi--) {
- if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) {
+ if (mFrameSource[fi].getSkippedFrameReason()) {
continue;
}
float lineWidth = baseLineWidth;
@@ -181,7 +181,7 @@
int janky_i = (mNumJankyRects - 1) * 4;
for (size_t fi = 0; fi < mFrameSource.size(); fi++) {
- if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) {
+ if (mFrameSource[fi].getSkippedFrameReason()) {
continue;
}
diff --git a/libs/hwui/SkippedFrameInfo.h b/libs/hwui/SkippedFrameInfo.h
new file mode 100644
index 0000000..de56d9a
--- /dev/null
+++ b/libs/hwui/SkippedFrameInfo.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#pragma once
+
+namespace android::uirenderer {
+
+enum class SkippedFrameReason {
+ DrawingOff,
+ ContextIsStopped,
+ NothingToDraw,
+ NoOutputTarget,
+ NoBuffer,
+ AlreadyDrawn,
+};
+
+} /* namespace android::uirenderer */
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 2bff9cb..ea25f68 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -16,14 +16,16 @@
#pragma once
-#include "Properties.h"
-#include "utils/Macros.h"
-
#include <utils/Timers.h>
-#include "SkSize.h"
+#include <optional>
#include <string>
+#include "Properties.h"
+#include "SkSize.h"
+#include "SkippedFrameInfo.h"
+#include "utils/Macros.h"
+
namespace android {
namespace uirenderer {
@@ -110,13 +112,13 @@
// animate itself, such as if hasFunctors is true
// This is only set if hasAnimations is true
bool requiresUiRedraw = false;
- // This is set to true if draw() can be called this frame
- // false means that we must delay until the next vsync pulse as frame
+ // This is set to nullopt if draw() can be called this frame
+ // A value means that we must delay until the next vsync pulse as frame
// production is outrunning consumption
- // NOTE that if this is false CanvasContext will set either requiresUiRedraw
+ // NOTE that if this has a value CanvasContext will set either requiresUiRedraw
// *OR* will post itself for the next vsync automatically, use this
// only to avoid calling draw()
- bool canDrawThisFrame = true;
+ std::optional<SkippedFrameReason> skippedFrameReason;
// Sentinel for animatedImageDelay meaning there is no need to post such
// a message.
static constexpr nsecs_t kNoAnimatedImageDelay = -1;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2ef7802..2e0de3f 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -357,8 +357,9 @@
return true;
}
-static bool wasSkipped(FrameInfo* info) {
- return info && ((*info)[FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame);
+static std::optional<SkippedFrameReason> wasSkipped(FrameInfo* info) {
+ if (info) return info->getSkippedFrameReason();
+ return std::nullopt;
}
bool CanvasContext::isSwapChainStuffed() {
@@ -407,13 +408,26 @@
// If the previous frame was dropped we don't need to hold onto it, so
// just keep using the previous frame's structure instead
- if (wasSkipped(mCurrentFrameInfo)) {
+ if (const auto reason = wasSkipped(mCurrentFrameInfo)) {
// Use the oldest skipped frame in case we skip more than a single frame
if (!mSkippedFrameInfo) {
- mSkippedFrameInfo.emplace();
- mSkippedFrameInfo->vsyncId =
- mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
- mSkippedFrameInfo->startTime = mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime);
+ switch (*reason) {
+ case SkippedFrameReason::AlreadyDrawn:
+ case SkippedFrameReason::NoBuffer:
+ case SkippedFrameReason::NoOutputTarget:
+ mSkippedFrameInfo.emplace();
+ mSkippedFrameInfo->vsyncId =
+ mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
+ mSkippedFrameInfo->startTime =
+ mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime);
+ break;
+ case SkippedFrameReason::DrawingOff:
+ case SkippedFrameReason::ContextIsStopped:
+ case SkippedFrameReason::NothingToDraw:
+ // Do not report those as skipped frames as there was no frame expected to be
+ // drawn
+ break;
+ }
}
} else {
mCurrentFrameInfo = mJankTracker.startFrame();
@@ -427,7 +441,7 @@
info.damageAccumulator = &mDamageAccumulator;
info.layerUpdateQueue = &mLayerUpdateQueue;
info.damageGenerationId = mDamageId++;
- info.out.canDrawThisFrame = true;
+ info.out.skippedFrameReason = std::nullopt;
mAnimationContext->startFrame(info.mode);
for (const sp<RenderNode>& node : mRenderNodes) {
@@ -447,8 +461,8 @@
mIsDirty = true;
if (CC_UNLIKELY(!hasOutputTarget())) {
- mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
- info.out.canDrawThisFrame = false;
+ info.out.skippedFrameReason = SkippedFrameReason::NoOutputTarget;
+ mCurrentFrameInfo->setSkippedFrameReason(*info.out.skippedFrameReason);
return;
}
@@ -463,23 +477,23 @@
if (vsyncDelta < 2_ms) {
// Already drew for this vsync pulse, UI draw request missed
// the deadline for RT animations
- info.out.canDrawThisFrame = false;
+ info.out.skippedFrameReason = SkippedFrameReason::AlreadyDrawn;
}
} else {
- info.out.canDrawThisFrame = true;
+ info.out.skippedFrameReason = std::nullopt;
}
// TODO: Do we need to abort out if the backdrop is added but not ready? Should that even
// be an allowable combination?
if (mRenderNodes.size() > 2 && !mRenderNodes[1]->isRenderable()) {
- info.out.canDrawThisFrame = false;
+ info.out.skippedFrameReason = SkippedFrameReason::NothingToDraw;
}
- if (info.out.canDrawThisFrame) {
+ if (!info.out.skippedFrameReason) {
int err = mNativeSurface->reserveNext();
if (err != OK) {
- mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
- info.out.canDrawThisFrame = false;
+ info.out.skippedFrameReason = SkippedFrameReason::NoBuffer;
+ mCurrentFrameInfo->setSkippedFrameReason(*info.out.skippedFrameReason);
ALOGW("reserveNext failed, error = %d (%s)", err, strerror(-err));
if (err != TIMED_OUT) {
// A timed out surface can still recover, but assume others are permanently dead.
@@ -488,11 +502,11 @@
}
}
} else {
- mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+ mCurrentFrameInfo->setSkippedFrameReason(*info.out.skippedFrameReason);
}
bool postedFrameCallback = false;
- if (info.out.hasAnimations || !info.out.canDrawThisFrame) {
+ if (info.out.hasAnimations || info.out.skippedFrameReason) {
if (CC_UNLIKELY(!Properties::enableRTAnimations)) {
info.out.requiresUiRedraw = true;
}
@@ -558,9 +572,20 @@
mSyncDelayDuration = 0;
mIdleDuration = 0;
- if (!Properties::isDrawingEnabled() ||
- (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw())) {
- mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+ const auto skippedFrameReason = [&]() -> std::optional<SkippedFrameReason> {
+ if (!Properties::isDrawingEnabled()) {
+ return SkippedFrameReason::DrawingOff;
+ }
+
+ if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) {
+ return SkippedFrameReason::NothingToDraw;
+ }
+
+ return std::nullopt;
+ }();
+ if (skippedFrameReason) {
+ mCurrentFrameInfo->setSkippedFrameReason(*skippedFrameReason);
+
if (auto grContext = getGrContext()) {
// Submit to ensure that any texture uploads complete and Skia can
// free its staging buffers.
@@ -904,7 +929,7 @@
TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
prepareTree(info, frameInfo, systemTime(SYSTEM_TIME_MONOTONIC), node);
- if (info.out.canDrawThisFrame) {
+ if (!info.out.skippedFrameReason) {
draw(info.out.solelyTextureViewUpdates);
} else {
// wait on fences so tasks don't overlap next frame
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 53b43ba..1b333bf 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -104,7 +104,7 @@
info.forceDrawFrame = mForceDrawFrame;
mForceDrawFrame = false;
canUnblockUiThread = syncFrameState(info);
- canDrawThisFrame = info.out.canDrawThisFrame;
+ canDrawThisFrame = !info.out.skippedFrameReason.has_value();
solelyTextureViewUpdates = info.out.solelyTextureViewUpdates;
if (mFrameCommitCallback) {
@@ -192,11 +192,12 @@
if (CC_UNLIKELY(!hasTarget || !canDraw)) {
if (!hasTarget) {
mSyncResult |= SyncResult::LostSurfaceRewardIfFound;
+ info.out.skippedFrameReason = SkippedFrameReason::NoOutputTarget;
} else {
// If we have a surface but can't draw we must be stopped
mSyncResult |= SyncResult::ContextIsStopped;
+ info.out.skippedFrameReason = SkippedFrameReason::ContextIsStopped;
}
- info.out.canDrawThisFrame = false;
}
if (info.out.hasAnimations) {
@@ -204,7 +205,7 @@
mSyncResult |= SyncResult::UIRedrawRequired;
}
}
- if (!info.out.canDrawThisFrame) {
+ if (info.out.skippedFrameReason) {
mSyncResult |= SyncResult::FrameDropped;
}
// If prepareTextures is false, we ran out of texture cache space
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index 9234d37..147412d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -22,6 +22,7 @@
import static android.media.MediaRoute2Info.TYPE_GROUP;
import static android.media.MediaRoute2Info.TYPE_HDMI;
import static android.media.MediaRoute2Info.TYPE_HEARING_AID;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_AUDIO_VIDEO_RECEIVER;
import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
import static android.media.MediaRoute2Info.TYPE_REMOTE_TV;
import static android.media.MediaRoute2Info.TYPE_UNKNOWN;
@@ -82,7 +83,8 @@
MediaDeviceType.TYPE_FAST_PAIR_BLUETOOTH_DEVICE,
MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
MediaDeviceType.TYPE_CAST_DEVICE,
- MediaDeviceType.TYPE_CAST_GROUP_DEVICE})
+ MediaDeviceType.TYPE_CAST_GROUP_DEVICE,
+ MediaDeviceType.TYPE_REMOTE_AUDIO_VIDEO_RECEIVER})
public @interface MediaDeviceType {
int TYPE_UNKNOWN = 0;
int TYPE_PHONE_DEVICE = 1;
@@ -92,6 +94,7 @@
int TYPE_BLUETOOTH_DEVICE = 5;
int TYPE_CAST_DEVICE = 6;
int TYPE_CAST_GROUP_DEVICE = 7;
+ int TYPE_REMOTE_AUDIO_VIDEO_RECEIVER = 8;
}
@Retention(RetentionPolicy.SOURCE)
@@ -161,6 +164,9 @@
case TYPE_BLE_HEADSET:
mType = MediaDeviceType.TYPE_BLUETOOTH_DEVICE;
break;
+ case TYPE_REMOTE_AUDIO_VIDEO_RECEIVER:
+ mType = MediaDeviceType.TYPE_REMOTE_AUDIO_VIDEO_RECEIVER;
+ break;
case TYPE_UNKNOWN:
case TYPE_REMOTE_TV:
case TYPE_REMOTE_SPEAKER:
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java
index 39d4e6e..412d1a3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java
@@ -56,6 +56,7 @@
* Update the endpoints of a content switching operation.
* This method should be called before a switching operation, so the metric logger can track
* source and target devices.
+ *
* @param source the current connected media device
* @param target the target media device for content switching to
*/
@@ -72,37 +73,9 @@
/**
* Do the metric logging of content switching success.
+ *
* @param selectedDeviceType string representation of the target media device
- * @param deviceList media device list for device count updating
- */
- public void logOutputSuccess(String selectedDeviceType, List<MediaDevice> deviceList) {
- if (DEBUG) {
- Log.d(TAG, "logOutputSuccess - selected device: " + selectedDeviceType);
- }
-
- if (mSourceDevice == null && mTargetDevice == null) {
- return;
- }
-
- updateLoggingDeviceCount(deviceList);
-
- SysUiStatsLog.write(
- SysUiStatsLog.MEDIAOUTPUT_OP_SWITCH_REPORTED,
- getLoggingDeviceType(mSourceDevice, true),
- getLoggingDeviceType(mTargetDevice, false),
- SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__RESULT__OK,
- SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__NO_ERROR,
- getLoggingPackageName(),
- mWiredDeviceCount,
- mConnectedBluetoothDeviceCount,
- mRemoteDeviceCount,
- mAppliedDeviceCountWithinRemoteGroup);
- }
-
- /**
- * Do the metric logging of content switching success.
- * @param selectedDeviceType string representation of the target media device
- * @param deviceItemList media item list for device count updating
+ * @param deviceItemList media item list for device count updating
*/
public void logOutputItemSuccess(String selectedDeviceType, List<MediaItem> deviceItemList) {
if (DEBUG) {
@@ -125,11 +98,14 @@
mWiredDeviceCount,
mConnectedBluetoothDeviceCount,
mRemoteDeviceCount,
- mAppliedDeviceCountWithinRemoteGroup);
+ mAppliedDeviceCountWithinRemoteGroup,
+ mTargetDevice.isSuggestedDevice(),
+ mTargetDevice.hasOngoingSession());
}
/**
* Do the metric logging of volume adjustment.
+ *
* @param source the device been adjusted
*/
public void logInteractionAdjustVolume(MediaDevice source) {
@@ -141,7 +117,8 @@
SysUiStatsLog.MEDIAOUTPUT_OP_INTERACTION_REPORT,
SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__INTERACTION_TYPE__ADJUST_VOLUME,
getInteractionDeviceType(source),
- getLoggingPackageName());
+ getLoggingPackageName(),
+ source.isSuggestedDevice());
}
/**
@@ -156,7 +133,8 @@
SysUiStatsLog.MEDIAOUTPUT_OP_INTERACTION_REPORT,
SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__INTERACTION_TYPE__STOP_CASTING,
SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__TARGET__UNKNOWN_TYPE,
- getLoggingPackageName());
+ getLoggingPackageName(),
+ /*isSuggestedDevice = */false);
}
/**
@@ -171,42 +149,15 @@
SysUiStatsLog.MEDIAOUTPUT_OP_INTERACTION_REPORT,
SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__INTERACTION_TYPE__EXPANSION,
getInteractionDeviceType(source),
- getLoggingPackageName());
- }
-
- /**
- * Do the metric logging of content switching failure.
- * @param deviceList media device list for device count updating
- * @param reason the reason of content switching failure
- */
- public void logOutputFailure(List<MediaDevice> deviceList, int reason) {
- if (DEBUG) {
- Log.e(TAG, "logRequestFailed - " + reason);
- }
-
- if (mSourceDevice == null && mTargetDevice == null) {
- return;
- }
-
- updateLoggingDeviceCount(deviceList);
-
- SysUiStatsLog.write(
- SysUiStatsLog.MEDIAOUTPUT_OP_SWITCH_REPORTED,
- getLoggingDeviceType(mSourceDevice, true),
- getLoggingDeviceType(mTargetDevice, false),
- SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__RESULT__ERROR,
- getLoggingSwitchOpSubResult(reason),
getLoggingPackageName(),
- mWiredDeviceCount,
- mConnectedBluetoothDeviceCount,
- mRemoteDeviceCount,
- mAppliedDeviceCountWithinRemoteGroup);
+ source.isSuggestedDevice());
}
/**
* Do the metric logging of content switching failure.
+ *
* @param deviceItemList media item list for device count updating
- * @param reason the reason of content switching failure
+ * @param reason the reason of content switching failure
*/
public void logOutputItemFailure(List<MediaItem> deviceItemList, int reason) {
if (DEBUG) {
@@ -229,7 +180,9 @@
mWiredDeviceCount,
mConnectedBluetoothDeviceCount,
mRemoteDeviceCount,
- mAppliedDeviceCountWithinRemoteGroup);
+ mAppliedDeviceCountWithinRemoteGroup,
+ mTargetDevice.isSuggestedDevice(),
+ mTargetDevice.hasOngoingSession());
}
private void updateLoggingDeviceCount(List<MediaDevice> deviceList) {
@@ -266,7 +219,7 @@
mWiredDeviceCount = mConnectedBluetoothDeviceCount = mRemoteDeviceCount = 0;
mAppliedDeviceCountWithinRemoteGroup = 0;
- for (MediaItem mediaItem: deviceItemList) {
+ for (MediaItem mediaItem : deviceItemList) {
if (mediaItem.getMediaDevice().isPresent()
&& mediaItem.getMediaDevice().get().isConnected()) {
switch (mediaItem.getMediaDevice().get().getDeviceType()) {
@@ -326,6 +279,10 @@
return isSourceDevice
? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_GROUP
: SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_GROUP;
+ case MediaDevice.MediaDeviceType.TYPE_REMOTE_AUDIO_VIDEO_RECEIVER:
+ return isSourceDevice
+ ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__AVR
+ : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__AVR;
default:
return isSourceDevice
? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__UNKNOWN_TYPE
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index e97a12a..6f9b7d6 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -295,6 +295,8 @@
private final PowerManager.WakeLock mDownloadPsdsWakeLock;
@GuardedBy("mLock")
private final Set<Integer> mPendingDownloadPsdsTypes = new HashSet<>();
+ @GuardedBy("mLock")
+ private final Set<Integer> mDownloadInProgressPsdsTypes = new HashSet<>();
/**
* Properties loaded from PROPERTIES_FILE.
@@ -767,8 +769,16 @@
return;
}
synchronized (mLock) {
+ if (mDownloadInProgressPsdsTypes.contains(psdsType)) {
+ if (DEBUG) {
+ Log.d(TAG,
+ "PSDS type " + psdsType + " download in progress. Ignore the request.");
+ }
+ return;
+ }
// hold wake lock while task runs
mDownloadPsdsWakeLock.acquire(DOWNLOAD_PSDS_DATA_TIMEOUT_MS);
+ mDownloadInProgressPsdsTypes.add(psdsType);
}
Log.i(TAG, "WakeLock acquired by handleDownloadPsdsData()");
Executors.newSingleThreadExecutor().execute(() -> {
@@ -818,6 +828,7 @@
Log.e(TAG, "WakeLock expired before release in "
+ "handleDownloadPsdsData()");
}
+ mDownloadInProgressPsdsTypes.remove(psdsType);
}
});
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index dd681aa..d77ceb2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -130,7 +130,8 @@
// Keep system and current user
if (user.id != UserHandle.USER_SYSTEM &&
user.id != currentUser &&
- user.id != communalProfileId) {
+ user.id != communalProfileId &&
+ !user.isMain()) {
removeUser(user.id);
}
}
@@ -1105,16 +1106,16 @@
public void testCreateProfileForUser_disallowAddManagedProfile() throws Exception {
assumeManagedUsersSupported();
final int mainUserId = mUserManager.getMainUser().getIdentifier();
- final UserHandle mainUserHandle = asHandle(mainUserId);
+ final UserHandle currentUserHandle = asHandle(ActivityManager.getCurrentUser());
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
- mainUserHandle);
+ currentUserHandle);
try {
UserInfo userInfo = createProfileForUser("Managed",
UserManager.USER_TYPE_PROFILE_MANAGED, mainUserId);
assertThat(userInfo).isNull();
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
- mainUserHandle);
+ currentUserHandle);
}
}
@@ -1190,6 +1191,7 @@
@Test
public void testGetManagedProfileCreationTime() throws Exception {
assumeManagedUsersSupported();
+ assumeTrue("User does not have access to creation time", mUserManager.isMainUser());
final int mainUserId = mUserManager.getMainUser().getIdentifier();
final long startTime = System.currentTimeMillis();
UserInfo profile = createProfileForUser("Managed 1",