diff options
34 files changed, 407 insertions, 156 deletions
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index ee8abf1c1894..9349770ee4fd 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -8,6 +8,20 @@ package android.app { } +package android.net { + + public final class TcpRepairWindow { + ctor public TcpRepairWindow(int, int, int, int, int, int); + field public final int maxWindow; + field public final int rcvWnd; + field public final int rcvWndScale; + field public final int rcvWup; + field public final int sndWl1; + field public final int sndWnd; + } + +} + package android.os { public class Binder implements android.os.IBinder { diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 0676ad4e2322..6780167fa63e 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -51,7 +51,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * An agent manages the life cycle of a network. A network starts its * life cycle when {@link register} is called on NetworkAgent. The network * is then connecting. When full L3 connectivity has been established, - * the agent shoud call {@link markConnected} to inform the system that + * the agent should call {@link markConnected} to inform the system that * this network is ready to use. When the network disconnects its life * ends and the agent should call {@link unregister}, at which point the * system will clean up and free resources. @@ -94,12 +94,6 @@ public abstract class NetworkAgent { @Nullable private volatile Network mNetwork; - // Whether this NetworkAgent is using the legacy (never unhidden) API. The difference is - // that the legacy API uses NetworkInfo to convey the state, while the current API is - // exposing methods to manage it and generate it internally instead. - // TODO : remove this as soon as all agents have been converted. - private final boolean mIsLegacy; - private final Handler mHandler; private volatile AsyncChannel mAsyncChannel; private final String LOG_TAG; @@ -110,8 +104,6 @@ public abstract class NetworkAgent { private static final long BW_REFRESH_MIN_WIN_MS = 500; private boolean mBandwidthUpdateScheduled = false; private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false); - // Not used by legacy agents. Non-legacy agents use this to convert the NetworkAgent system API - // into the internal API of ConnectivityService. @NonNull private NetworkInfo mNetworkInfo; @NonNull @@ -337,35 +329,6 @@ public abstract class NetworkAgent { */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; - /** @hide TODO: remove and replace usage with the public constructor. */ - public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score) { - this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); - // Register done by the constructor called in the previous line - } - - /** @hide TODO: remove and replace usage with the public constructor. */ - public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { - this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); - // Register done by the constructor called in the previous line - } - - /** @hide TODO: remove and replace usage with the public constructor. */ - public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score, int providerId) { - this(looper, context, logTag, ni, nc, lp, score, null, providerId); - // Register done by the constructor called in the previous line - } - - /** @hide TODO: remove and replace usage with the public constructor. */ - public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, - int providerId) { - this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */); - register(); - } - private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { // The subtype can be changed with (TODO) setLegacySubtype, but it starts // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description. @@ -393,7 +356,7 @@ public abstract class NetworkAgent { @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { this(looper, context, logTag, nc, lp, score, config, provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), - getLegacyNetworkInfo(config), false /* legacy */); + getLegacyNetworkInfo(config)); } private static class InitialConfiguration { @@ -418,11 +381,9 @@ public abstract class NetworkAgent { private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni, - boolean legacy) { + @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; - mIsLegacy = legacy; mNetworkInfo = new NetworkInfo(ni); this.providerId = providerId; if (ni == null || nc == null || lp == null) { @@ -696,11 +657,6 @@ public abstract class NetworkAgent { * Call {@link #unregister} to disconnect. */ public void markConnected() { - if (mIsLegacy) { - throw new UnsupportedOperationException( - "Legacy agents can't call markConnected."); - } - // |reason| cannot be used by the non-legacy agents mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */, mNetworkInfo.getExtraInfo()); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); @@ -713,9 +669,6 @@ public abstract class NetworkAgent { * the network is torn down and this agent can no longer be used. */ public void unregister() { - if (mIsLegacy) { - throw new UnsupportedOperationException("Legacy agents can't call unregister."); - } // When unregistering an agent nobody should use the extrainfo (or reason) any more. mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */, null /* extraInfo */); @@ -735,9 +688,6 @@ public abstract class NetworkAgent { */ @Deprecated public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) { - if (mIsLegacy) { - throw new UnsupportedOperationException("Legacy agents can't call setLegacySubtype."); - } mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); } @@ -760,9 +710,6 @@ public abstract class NetworkAgent { */ @Deprecated public void setLegacyExtraInfo(@Nullable final String extraInfo) { - if (mIsLegacy) { - throw new UnsupportedOperationException("Legacy agents can't call setLegacyExtraInfo."); - } mNetworkInfo.setExtraInfo(extraInfo); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); } @@ -773,9 +720,6 @@ public abstract class NetworkAgent { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public final void sendNetworkInfo(NetworkInfo networkInfo) { - if (!mIsLegacy) { - throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo."); - } queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo)); } diff --git a/core/java/android/net/TcpRepairWindow.java b/core/java/android/net/TcpRepairWindow.java index 86034f0a76ed..f062fa9034ea 100644 --- a/core/java/android/net/TcpRepairWindow.java +++ b/core/java/android/net/TcpRepairWindow.java @@ -16,12 +16,15 @@ package android.net; +import android.annotation.SystemApi; + /** * Corresponds to C's {@code struct tcp_repair_window} from * include/uapi/linux/tcp.h * * @hide */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public final class TcpRepairWindow { public final int sndWl1; public final int sndWnd; diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index 017f40521a81..6ef9e7e3d9b8 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -16,18 +16,18 @@ package android.security.keymaster; -import android.hardware.security.keymint.Algorithm; -import android.hardware.security.keymint.BlockMode; -import android.hardware.security.keymint.Digest; -import android.hardware.security.keymint.ErrorCode; -import android.hardware.security.keymint.HardwareAuthenticatorType; -import android.hardware.security.keymint.KeyFormat; -import android.hardware.security.keymint.KeyOrigin; -import android.hardware.security.keymint.KeyPurpose; -import android.hardware.security.keymint.PaddingMode; -import android.hardware.security.keymint.SecurityLevel; -import android.hardware.security.keymint.Tag; -import android.hardware.security.keymint.TagType; +import android.hardware.keymint.Algorithm; +import android.hardware.keymint.BlockMode; +import android.hardware.keymint.Digest; +import android.hardware.keymint.ErrorCode; +import android.hardware.keymint.HardwareAuthenticatorType; +import android.hardware.keymint.KeyFormat; +import android.hardware.keymint.KeyOrigin; +import android.hardware.keymint.KeyPurpose; +import android.hardware.keymint.PaddingMode; +import android.hardware.keymint.SecurityLevel; +import android.hardware.keymint.Tag; +import android.hardware.keymint.TagType; import java.util.HashMap; import java.util.Map; diff --git a/keystore/java/android/security/KeyStoreOperation.java b/keystore/java/android/security/KeyStoreOperation.java index 7ea9e1438845..49a48871fd30 100644 --- a/keystore/java/android/security/KeyStoreOperation.java +++ b/keystore/java/android/security/KeyStoreOperation.java @@ -17,7 +17,7 @@ package android.security; import android.annotation.NonNull; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java index 3ef4aa5b7ec3..7c3de8bee475 100644 --- a/keystore/java/android/security/KeyStoreSecurityLevel.java +++ b/keystore/java/android/security/KeyStoreSecurityLevel.java @@ -18,7 +18,7 @@ package android.security; import android.annotation.NonNull; import android.app.compat.CompatChanges; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.security.keystore.BackendBusyException; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java index 0775a1a99886..69c7a2589d6f 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java @@ -17,7 +17,7 @@ package android.security.keystore2; import android.annotation.NonNull; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.keymaster.KeymasterDefs; import android.security.keystore.ArrayUtils; import android.security.keystore.KeyProperties; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java index bc56f015f3bd..2b5f6c31607b 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java @@ -18,7 +18,7 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java index a3b04abfba3f..18d26922f1ae 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java @@ -19,7 +19,7 @@ package android.security.keystore2; import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java index d1ef1df817e6..2250c89aac41 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java @@ -17,7 +17,7 @@ package android.security.keystore2; import android.annotation.NonNull; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java index 8475ad9fd57b..eea45c287622 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java @@ -16,7 +16,7 @@ package android.security.keystore2; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java index 233f352989ab..479fd8a6a73a 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java @@ -16,8 +16,8 @@ package android.security.keystore2; -import android.hardware.security.keymint.KeyParameter; -import android.hardware.security.keymint.SecurityLevel; +import android.hardware.keymint.KeyParameter; +import android.hardware.keymint.SecurityLevel; import android.security.KeyStore2; import android.security.KeyStoreSecurityLevel; import android.security.keymaster.KeymasterArguments; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index df0e1462a492..61725e3e8c24 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -18,8 +18,8 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.security.keymint.KeyParameter; -import android.hardware.security.keymint.SecurityLevel; +import android.hardware.keymint.KeyParameter; +import android.hardware.keymint.SecurityLevel; import android.os.Build; import android.security.KeyPairGeneratorSpec; import android.security.KeyStore2; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java index 951f91887894..2686ddc20c1d 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java @@ -18,7 +18,7 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.keymaster.KeymasterDefs; import android.security.keystore.KeyProperties; import android.security.keystore.KeymasterUtils; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java index ab7559116a41..444dad4cffbe 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java @@ -17,7 +17,7 @@ package android.security.keystore2; import android.annotation.NonNull; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.keymaster.KeymasterDefs; import android.security.keystore.KeyProperties; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java index 9b4f01e744f7..a168f8feb3db 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java @@ -18,7 +18,7 @@ package android.security.keystore2; import android.annotation.CallSuper; import android.annotation.NonNull; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index aca531458382..9790a4ae5b65 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -18,9 +18,9 @@ package android.security.keystore2; import android.annotation.NonNull; import android.hardware.biometrics.BiometricManager; -import android.hardware.security.keymint.HardwareAuthenticatorType; -import android.hardware.security.keymint.KeyParameter; -import android.hardware.security.keymint.SecurityLevel; +import android.hardware.keymint.HardwareAuthenticatorType; +import android.hardware.keymint.KeyParameter; +import android.hardware.keymint.SecurityLevel; import android.security.GateKeeper; import android.security.KeyStore2; import android.security.KeyStoreParameter; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java index 4d4b0d8f183b..a2d4528b99fd 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java @@ -18,7 +18,7 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.security.keymint.KeyParameter; +import android.hardware.keymint.KeyParameter; import android.security.keymaster.KeymasterDefs; import android.security.keystore.ArrayUtils; import android.security.keystore.KeyProperties; diff --git a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java index 18c786aa3093..8fa532b6e188 100644 --- a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java +++ b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java @@ -18,8 +18,8 @@ package android.security.keystore2; import android.annotation.NonNull; import android.hardware.biometrics.BiometricManager; -import android.hardware.security.keymint.KeyParameter; -import android.hardware.security.keymint.SecurityLevel; +import android.hardware.keymint.KeyParameter; +import android.hardware.keymint.SecurityLevel; import android.security.GateKeeper; import android.security.keymaster.KeymasterDefs; import android.security.keystore.KeyProperties; diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 451bd42bd053..eb86128a82a5 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -37,6 +37,7 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.drawable.IconCompat; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.BluetoothUtils; @@ -84,11 +85,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { @VisibleForTesting LocalMediaManager mLocalMediaManager; + private MediaOutputMetricLogger mMetricLogger; + private UiEventLogger mUiEventLogger; + @Inject public MediaOutputController(@NonNull Context context, String packageName, boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager lbm, ShadeController shadeController, ActivityStarter starter, - NotificationEntryManager notificationEntryManager) { + NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger) { mContext = context; mPackageName = packageName; mMediaSessionManager = mediaSessionManager; @@ -98,6 +102,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { mNotificationEntryManager = notificationEntryManager; InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); + mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); + mUiEventLogger = uiEventLogger; } void start(@NonNull Callback cb) { @@ -151,6 +157,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { public void onSelectedDeviceStateChanged(MediaDevice device, @LocalMediaManager.MediaDeviceState int state) { mCallback.onRouteChanged(); + mMetricLogger.logOutputSuccess(device.toString(), mMediaDevices); } @Override @@ -161,6 +168,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { @Override public void onRequestFailed(int reason) { mCallback.onRouteChanged(); + mMetricLogger.logOutputFailure(mMediaDevices, reason); } CharSequence getHeaderTitle() { @@ -311,6 +319,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { } void connectDevice(MediaDevice device) { + mMetricLogger.updateOutputEndPoints(getCurrentConnectedMediaDevice(), device); + ThreadUtils.postOnBackgroundThread(() -> { mLocalMediaManager.connectDevice(device); }); @@ -439,7 +449,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { void launchMediaOutputDialog() { mCallback.dismissDialog(); - new MediaOutputDialog(mContext, mAboveStatusbar, this); + new MediaOutputDialog(mContext, mAboveStatusbar, this, mUiEventLogger); } void launchMediaOutputGroupDialog() { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index c0138f0e200a..fedeceabe73a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -23,6 +23,9 @@ import android.view.WindowManager; import androidx.core.graphics.drawable.IconCompat; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import javax.inject.Singleton; @@ -32,10 +35,12 @@ import javax.inject.Singleton; */ @Singleton public class MediaOutputDialog extends MediaOutputBaseDialog { + final UiEventLogger mUiEventLogger; MediaOutputDialog(Context context, boolean aboveStatusbar, MediaOutputController - mediaOutputController) { + mediaOutputController, UiEventLogger uiEventLogger) { super(context, mediaOutputController); + mUiEventLogger = uiEventLogger; mAdapter = new MediaOutputAdapter(mMediaOutputController); if (!aboveStatusbar) { getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); @@ -46,6 +51,7 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mUiEventLogger.log(MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW); } @Override @@ -79,4 +85,21 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { return mMediaOutputController.isActiveRemoteDevice( mMediaOutputController.getCurrentConnectedMediaDevice()) ? View.VISIBLE : View.GONE; } + + @VisibleForTesting + public enum MediaOutputEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "The MediaOutput dialog became visible on the screen.") + MEDIA_OUTPUT_DIALOG_SHOW(655); + + private final int mId; + + MediaOutputEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt index 7d1a7ced7472..0f340a5cedaa 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt @@ -18,6 +18,7 @@ package com.android.systemui.media.dialog import android.content.Context import android.media.session.MediaSessionManager +import com.android.internal.logging.UiEventLogger import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.notification.NotificationEntryManager @@ -33,7 +34,8 @@ class MediaOutputDialogFactory @Inject constructor( private val lbm: LocalBluetoothManager?, private val shadeController: ShadeController, private val starter: ActivityStarter, - private val notificationEntryManager: NotificationEntryManager + private val notificationEntryManager: NotificationEntryManager, + private val uiEventLogger: UiEventLogger ) { companion object { var mediaOutputDialog: MediaOutputDialog? = null @@ -43,8 +45,10 @@ class MediaOutputDialogFactory @Inject constructor( fun create(packageName: String, aboveStatusBar: Boolean) { mediaOutputDialog?.dismiss() mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar, - mediaSessionManager, lbm, shadeController, starter, notificationEntryManager).run { - MediaOutputDialog(context, aboveStatusBar, this) } + mediaSessionManager, lbm, shadeController, starter, notificationEntryManager, + uiEventLogger).run { + MediaOutputDialog(context, aboveStatusBar, this, uiEventLogger) + } } /** dismiss [MediaOutputDialog] if exist. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java new file mode 100644 index 000000000000..ac0295ed6d14 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media.dialog; + +import static android.media.MediaRoute2ProviderService.REASON_INVALID_COMMAND; +import static android.media.MediaRoute2ProviderService.REASON_NETWORK_ERROR; +import static android.media.MediaRoute2ProviderService.REASON_REJECTED; +import static android.media.MediaRoute2ProviderService.REASON_ROUTE_NOT_AVAILABLE; +import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.util.Log; + +import com.android.settingslib.media.MediaDevice; +import com.android.systemui.shared.system.SysUiStatsLog; + +import java.util.List; + +/** + * Metric logger for media output features + */ +public class MediaOutputMetricLogger { + + private static final String TAG = "MediaOutputMetricLogger"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private final Context mContext; + private final String mPackageName; + private MediaDevice mSourceDevice, mTargetDevice; + private int mWiredDeviceCount; + private int mConnectedBluetoothDeviceCount; + private int mRemoteDeviceCount; + private int mAppliedDeviceCountWithinRemoteGroup; + + public MediaOutputMetricLogger(Context context, String packageName) { + mContext = context; + mPackageName = packageName; + } + + /** + * 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 + */ + public void updateOutputEndPoints(MediaDevice source, MediaDevice target) { + mSourceDevice = source; + mTargetDevice = target; + + if (DEBUG) { + Log.d(TAG, "updateOutputEndPoints -" + + " source:" + mSourceDevice.toString() + + " target:" + mTargetDevice.toString()); + } + } + + /** + * 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); + } + + 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 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); + } + + 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); + } + + private void updateLoggingDeviceCount(List<MediaDevice> deviceList) { + mWiredDeviceCount = mConnectedBluetoothDeviceCount = mRemoteDeviceCount = 0; + mAppliedDeviceCountWithinRemoteGroup = 0; + + for (MediaDevice mediaDevice : deviceList) { + if (mediaDevice.isConnected()) { + switch (mediaDevice.getDeviceType()) { + case MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE: + case MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE: + mWiredDeviceCount++; + break; + case MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE: + mConnectedBluetoothDeviceCount++; + break; + case MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE: + case MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE: + mRemoteDeviceCount++; + break; + default: + } + } + } + + if (DEBUG) { + Log.d(TAG, "connected devices:" + " wired: " + mWiredDeviceCount + + " bluetooth: " + mConnectedBluetoothDeviceCount + + " remote: " + mRemoteDeviceCount); + } + } + + private int getLoggingDeviceType(MediaDevice device, boolean isSourceDevice) { + switch (device.getDeviceType()) { + case MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__BUILTIN_SPEAKER + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__BUILTIN_SPEAKER; + case MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE: + return isSourceDevice + ? SysUiStatsLog + .MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__WIRED_3POINT5_MM_AUDIO + : SysUiStatsLog + .MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__WIRED_3POINT5_MM_AUDIO; + case MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__USB_C_AUDIO + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__USB_C_AUDIO; + case MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__BLUETOOTH + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__BLUETOOTH; + case MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_SINGLE + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_SINGLE; + case MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_GROUP + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_GROUP; + default: + return isSourceDevice + ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__UNKNOWN_TYPE + : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__UNKNOWN_TYPE; + } + } + + private int getLoggingSwitchOpSubResult(int reason) { + switch (reason) { + case REASON_REJECTED: + return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__REJECTED; + case REASON_NETWORK_ERROR: + return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__NETWORK_ERROR; + case REASON_ROUTE_NOT_AVAILABLE: + return SysUiStatsLog + .MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__ROUTE_NOT_AVAILABLE; + case REASON_INVALID_COMMAND: + return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__INVALID_COMMAND; + case REASON_UNKNOWN_ERROR: + default: + return SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__UNKNOWN_ERROR; + } + } + + private String getLoggingPackageName() { + if (mPackageName != null && !mPackageName.isEmpty()) { + try { + final ApplicationInfo applicationInfo = mContext.getPackageManager() + .getApplicationInfo(mPackageName, /* default flag */ 0); + if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 + || (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { + return mPackageName; + } + } catch (Exception ex) { + Log.e(TAG, mPackageName + " is invalid."); + } + } + + return ""; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java index c897d8a53e20..fd5d99667e0c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java @@ -35,6 +35,7 @@ import android.widget.TextView; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -61,6 +62,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { private ActivityStarter mStarter = mock(ActivityStarter.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); + private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl; private MediaOutputController mMediaOutputController; @@ -73,7 +75,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase { public void setUp() { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mMediaOutputController); mMediaOutputBaseDialogImpl.onCreate(new Bundle()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index 0d352c1b42d9..d1a617bcc0cb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -42,6 +42,7 @@ import android.text.TextUtils; import androidx.core.graphics.drawable.IconCompat; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; @@ -89,6 +90,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { private ActivityStarter mStarter = mock(ActivityStarter.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); + private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private Context mSpyContext; private MediaOutputController mMediaOutputController; @@ -111,7 +113,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; MediaDescription.Builder builder = new MediaDescription.Builder(); @@ -155,7 +157,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void start_withoutPackageName_verifyMediaControllerInit() { mMediaOutputController = new MediaOutputController(mSpyContext, null, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputController.start(mCb); @@ -176,7 +178,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void stop_withoutPackageName_verifyMediaControllerDeinit() { mMediaOutputController = new MediaOutputController(mSpyContext, null, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputController.start(mCb); @@ -200,8 +202,10 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onSelectedDeviceStateChanged_verifyCallback() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); mMediaOutputController.start(mCb); reset(mCb); + mMediaOutputController.connectDevice(mMediaDevice1); mMediaOutputController.onSelectedDeviceStateChanged(mMediaDevice1, LocalMediaManager.MediaDeviceState.STATE_CONNECTED); @@ -221,8 +225,10 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onRequestFailed_verifyCallback() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); mMediaOutputController.start(mCb); reset(mCb); + mMediaOutputController.connectDevice(mMediaDevice2); mMediaOutputController.onRequestFailed(0 /* reason */); @@ -268,6 +274,8 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void connectDevice_verifyConnect() { + when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2); + mMediaOutputController.connectDevice(mMediaDevice1); // Wait for background thread execution @@ -441,7 +449,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { public void getNotificationLargeIcon_withoutPackageName_returnsNull() { mMediaOutputController = new MediaOutputController(mSpyContext, null, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); assertThat(mMediaOutputController.getNotificationIcon()).isNull(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java index de8ce55ddcbb..92fcf936a0b2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java @@ -19,6 +19,8 @@ package com.android.systemui.media.dialog; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.media.MediaRoute2Info; @@ -29,6 +31,7 @@ import android.view.View; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; @@ -52,26 +55,28 @@ public class MediaOutputDialogTest extends SysuiTestCase { private static final String TEST_PACKAGE = "test_package"; // Mock - private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); - private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); - private ShadeController mShadeController = mock(ShadeController.class); - private ActivityStarter mStarter = mock(ActivityStarter.class); - private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); - private MediaDevice mMediaDevice = mock(MediaDevice.class); - private NotificationEntryManager mNotificationEntryManager = + private final MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class); + private final LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class); + private final ShadeController mShadeController = mock(ShadeController.class); + private final ActivityStarter mStarter = mock(ActivityStarter.class); + private final LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class); + private final MediaDevice mMediaDevice = mock(MediaDevice.class); + private final NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); + private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private MediaOutputDialog mMediaOutputDialog; private MediaOutputController mMediaOutputController; - private List<String> mFeatures = new ArrayList<>(); + private final List<String> mFeatures = new ArrayList<>(); @Before public void setUp() { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; - mMediaOutputDialog = new MediaOutputDialog(mContext, false, mMediaOutputController); + mMediaOutputDialog = new MediaOutputDialog(mContext, false, + mMediaOutputController, mUiEventLogger); when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice); when(mMediaDevice.getFeatures()).thenReturn(mFeatures); @@ -106,4 +111,16 @@ public class MediaOutputDialogTest extends SysuiTestCase { assertThat(mMediaOutputDialog.getStopButtonVisibility()).isEqualTo(View.GONE); } + @Test + // Check the visibility metric logging by creating a new MediaOutput dialog, + // and verify if the calling times increases. + public void onCreate_ShouldLogVisibility() { + MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false, + mMediaOutputController, mUiEventLogger); + + testDialog.dismissDialog(); + + verify(mUiEventLogger, times(2)) + .log(MediaOutputDialog.MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java index 581335027671..c296ff5cf19a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java @@ -28,6 +28,7 @@ import android.view.View; import androidx.test.filters.SmallTest; +import com.android.internal.logging.UiEventLogger; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; @@ -62,6 +63,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { private MediaDevice mMediaDevice1 = mock(MediaDevice.class); private NotificationEntryManager mNotificationEntryManager = mock(NotificationEntryManager.class); + private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class); private MediaOutputGroupDialog mMediaOutputGroupDialog; private MediaOutputController mMediaOutputController; @@ -71,7 +73,7 @@ public class MediaOutputGroupDialogTest extends SysuiTestCase { public void setUp() { mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false, mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter, - mNotificationEntryManager); + mNotificationEntryManager, mUiEventLogger); mMediaOutputController.mLocalMediaManager = mLocalMediaManager; mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mMediaOutputController); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index a42c86474460..d86744268662 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5579,11 +5579,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) { - final PackageManager pm = mContext.getPackageManager(); - final int userId = UserHandle.getCallingUserId(); + final UserHandle user = UserHandle.getUserHandleForUid(Binder.getCallingUid()); + final PackageManager pm = + mContext.createContextAsUser(user, 0 /* flags */).getPackageManager(); try { - final int callingVersion = pm.getApplicationInfoAsUser( - callingPackageName, 0 /* flags */, userId).targetSdkVersion; + final int callingVersion = pm.getApplicationInfo( + callingPackageName, 0 /* flags */).targetSdkVersion; if (callingVersion < version) return false; } catch (PackageManager.NameNotFoundException e) { } return true; diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index 75ebe70591df..655d8abf3e84 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -61,9 +61,8 @@ import java.util.concurrent.atomic.AtomicInteger; /** @hide */ class TestNetworkService extends ITestNetworkManager.Stub { - @NonNull private static final String TAG = TestNetworkService.class.getSimpleName(); @NonNull private static final String TEST_NETWORK_LOGTAG = "TestNetworkAgent"; - @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = TAG; + @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = "TestNetworkProvider"; @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger(); @NonNull private final Context mContext; @@ -168,17 +167,15 @@ class TestNetworkService extends ITestNetworkManager.Stub { private TestNetworkAgent( @NonNull Context context, @NonNull Looper looper, - @NonNull NetworkAgentConfig config, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, + @NonNull NetworkAgentConfig config, int uid, @NonNull IBinder binder, @NonNull NetworkProvider np) throws RemoteException { super(context, looper, TEST_NETWORK_LOGTAG, nc, lp, NETWORK_SCORE, config, np); - mUid = uid; - synchronized (mBinderLock) { mBinder = binder; // Binder null-checks in create() @@ -286,8 +283,8 @@ class TestNetworkService extends ITestNetworkManager.Stub { lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface)); } - final TestNetworkAgent agent = new TestNetworkAgent(context, looper, - new NetworkAgentConfig.Builder().build(), nc, lp, callingUid, binder, + final TestNetworkAgent agent = new TestNetworkAgent(context, looper, nc, lp, + new NetworkAgentConfig.Builder().build(), callingUid, binder, mNetworkProvider); agent.register(); agent.markConnected(); diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index 4c63eb488118..d507b5f82bd0 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -35,7 +35,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; -import android.content.pm.UserInfo; import android.net.INetd; import android.net.UidRange; import android.os.Build; @@ -174,11 +173,9 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); } - List<UserInfo> users = mUserManager.getAliveUsers(); - if (users != null) { - for (UserInfo user : users) { - mUsers.add(user.id); - } + final List<UserHandle> users = mUserManager.getUserHandles(true /* excludeDying */); + for (UserHandle user : users) { + mUsers.add(user.getIdentifier()); } final SparseArray<ArraySet<String>> systemPermission = diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS index 0862c05e0ee4..f35a318acbf7 100644 --- a/tests/FlickerTests/OWNERS +++ b/tests/FlickerTests/OWNERS @@ -1 +1,2 @@ include /services/core/java/com/android/server/wm/OWNERS +natanieljr@google.com
\ No newline at end of file diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 2a24d1ac22d2..3d4dc4d67dcc 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -29,7 +29,7 @@ import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyT import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.fail; import android.content.Context; import android.net.ConnectivityManager; @@ -38,7 +38,6 @@ import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; -import android.net.NetworkInfo; import android.net.NetworkProvider; import android.net.NetworkSpecifier; import android.net.SocketKeepalive; @@ -53,9 +52,9 @@ import com.android.testutils.HandlerUtils; import com.android.testutils.TestableNetworkCallback; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { - private final NetworkInfo mNetworkInfo; private final NetworkCapabilities mNetworkCapabilities; private final HandlerThread mHandlerThread; private final Context mContext; @@ -63,6 +62,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { private final ConditionVariable mDisconnected = new ConditionVariable(); private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); + private final AtomicBoolean mConnected = new AtomicBoolean(false); private int mScore; private NetworkAgent mNetworkAgent; private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED; @@ -76,7 +76,6 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { NetworkCapabilities ncTemplate, Context context) throws Exception { final int type = transportToLegacyType(transport); final String typeName = ConnectivityManager.getNetworkTypeName(type); - mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities(); mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED); mNetworkCapabilities.addTransportType(transport); @@ -108,22 +107,29 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { mHandlerThread = new HandlerThread(mLogTag); mHandlerThread.start(); - mNetworkAgent = makeNetworkAgent(linkProperties); + mNetworkAgent = makeNetworkAgent(linkProperties, type, typeName); } - protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties) + protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties, + final int type, final String typeName) throws Exception { - return new InstrumentedNetworkAgent(this, linkProperties); + return new InstrumentedNetworkAgent(this, linkProperties, type, typeName); } public static class InstrumentedNetworkAgent extends NetworkAgent { private final NetworkAgentWrapper mWrapper; - - public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) { - super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag, - wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore, - new NetworkAgentConfig(), NetworkProvider.ID_NONE); + private static final String PROVIDER_NAME = "InstrumentedNetworkAgentProvider"; + + public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, + final int type, final String typeName) { + super(wrapper.mContext, wrapper.mHandlerThread.getLooper(), wrapper.mLogTag, + wrapper.mNetworkCapabilities, lp, wrapper.mScore, + new NetworkAgentConfig.Builder() + .setLegacyType(type).setLegacyTypeName(typeName).build(), + new NetworkProvider(wrapper.mContext, wrapper.mHandlerThread.getLooper(), + PROVIDER_NAME)); mWrapper = wrapper; + register(); } @Override @@ -212,10 +218,12 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { } public void connect() { - assertNotEquals("MockNetworkAgents can only be connected once", - mNetworkInfo.getDetailedState(), NetworkInfo.DetailedState.CONNECTED); - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); + if (!mConnected.compareAndSet(false /* expect */, true /* update */)) { + // compareAndSet returns false when the value couldn't be updated because it did not + // match the expected value. + fail("Test NetworkAgents can only be connected once"); + } + mNetworkAgent.markConnected(); } public void suspend() { @@ -227,8 +235,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { } public void disconnect() { - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); + mNetworkAgent.unregister(); } @Override diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index bb7505be1435..9d308c5825c8 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -646,8 +646,8 @@ public class ConnectivityServiceTest { } @Override - protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties) - throws Exception { + protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties, + final int type, final String typeName) throws Exception { mNetworkMonitor = mock(INetworkMonitor.class); final Answer validateAnswer = inv -> { @@ -666,7 +666,8 @@ public class ConnectivityServiceTest { any() /* name */, nmCbCaptor.capture()); - final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) { + final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties, + type, typeName) { @Override public void networkStatus(int status, String redirectUrl) { mRedirectUrl = redirectUrl; diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index de35f910d53a..3556c72776dc 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -58,7 +58,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; -import android.content.pm.UserInfo; import android.net.INetd; import android.net.UidRange; import android.os.Build; @@ -123,10 +122,10 @@ public class PermissionMonitorTest { MockitoAnnotations.initMocks(this); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); - when(mUserManager.getAliveUsers()).thenReturn( - Arrays.asList(new UserInfo[] { - new UserInfo(MOCK_USER1, "", 0), - new UserInfo(MOCK_USER2, "", 0), + when(mUserManager.getUserHandles(eq(true))).thenReturn( + Arrays.asList(new UserHandle[] { + new UserHandle(MOCK_USER1), + new UserHandle(MOCK_USER2), })); mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); |