Loading packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +12 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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 Loading @@ -161,6 +168,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { @Override public void onRequestFailed(int reason) { mCallback.onRouteChanged(); mMetricLogger.logOutputFailure(mMediaDevices, reason); } CharSequence getHeaderTitle() { Loading Loading @@ -311,6 +319,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { } void connectDevice(MediaDevice device) { mMetricLogger.updateOutputEndPoints(getCurrentConnectedMediaDevice(), device); ThreadUtils.postOnBackgroundThread(() -> { mLocalMediaManager.connectDevice(device); }); Loading Loading @@ -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() { Loading packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +24 −1 Original line number Diff line number Diff line Loading @@ -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 com.android.systemui.dagger.SysUISingleton; Loading @@ -31,10 +34,12 @@ import com.android.systemui.dagger.SysUISingleton; */ @SysUISingleton 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); Loading @@ -45,6 +50,7 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mUiEventLogger.log(MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW); } @Override Loading Loading @@ -78,4 +84,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; } } } packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +7 −3 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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. */ Loading packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java 0 → 100644 +221 −0 Original line number Diff line number Diff line /* * 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 ""; } } packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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()); Loading Loading
packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +12 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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 Loading @@ -161,6 +168,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { @Override public void onRequestFailed(int reason) { mCallback.onRouteChanged(); mMetricLogger.logOutputFailure(mMediaDevices, reason); } CharSequence getHeaderTitle() { Loading Loading @@ -311,6 +319,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { } void connectDevice(MediaDevice device) { mMetricLogger.updateOutputEndPoints(getCurrentConnectedMediaDevice(), device); ThreadUtils.postOnBackgroundThread(() -> { mLocalMediaManager.connectDevice(device); }); Loading Loading @@ -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() { Loading
packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +24 −1 Original line number Diff line number Diff line Loading @@ -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 com.android.systemui.dagger.SysUISingleton; Loading @@ -31,10 +34,12 @@ import com.android.systemui.dagger.SysUISingleton; */ @SysUISingleton 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); Loading @@ -45,6 +50,7 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mUiEventLogger.log(MediaOutputEvent.MEDIA_OUTPUT_DIALOG_SHOW); } @Override Loading Loading @@ -78,4 +84,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; } } }
packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt +7 −3 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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. */ Loading
packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java 0 → 100644 +221 −0 Original line number Diff line number Diff line /* * 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 ""; } }
packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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()); Loading