blob: 357b234acbbe10f5257138fcf2aef8dbca0e9f91 [file] [log] [blame]
/*
* 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.settings.media;
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.net.Uri;
import android.util.Log;
import com.android.settings.core.instrumentation.SettingsStatsLog;
import com.android.settingslib.media.MediaDevice;
/**
* SliceBackgroundWorker for the MediaOutputSlice class.
* It inherits from MediaDeviceUpdateWorker and add metrics logging.
*/
public class MediaOutputSliceWorker extends MediaDeviceUpdateWorker {
private static final String TAG = "MediaOutputSliceWorker";
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
private MediaDevice mSourceDevice, mTargetDevice;
private int mWiredDeviceCount;
private int mConnectedBluetoothDeviceCount;
private int mRemoteDeviceCount;
private int mAppliedDeviceCountWithinRemoteGroup;
public MediaOutputSliceWorker(Context context, Uri uri) {
super(context, uri);
}
@Override
public void connectDevice(MediaDevice device) {
mSourceDevice = mLocalMediaManager.getCurrentConnectedDevice();
mTargetDevice = device;
if (DBG) {
Log.d(TAG, "connectDevice -"
+ " source:" + mSourceDevice.toString()
+ " target:" + mTargetDevice.toString());
}
super.connectDevice(device);
}
private int getLoggingDeviceType(MediaDevice device, boolean isSourceDevice) {
switch (device.getDeviceType()) {
case MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE:
return isSourceDevice
? SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__BUILTIN_SPEAKER
: SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__BUILTIN_SPEAKER;
case MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE:
return isSourceDevice
? SettingsStatsLog
.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__WIRED_3POINT5_MM_AUDIO
: SettingsStatsLog
.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__WIRED_3POINT5_MM_AUDIO;
case MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE:
return isSourceDevice
? SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__USB_C_AUDIO
: SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__USB_C_AUDIO;
case MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE:
return isSourceDevice
? SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__BLUETOOTH
: SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__BLUETOOTH;
case MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE:
return isSourceDevice
? SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_SINGLE
: SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_SINGLE;
case MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE:
return isSourceDevice
? SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__REMOTE_GROUP
: SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__REMOTE_GROUP;
default:
return isSourceDevice
? SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__UNKNOWN_TYPE
: SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__UNKNOWN_TYPE;
}
}
private int getLoggingSwitchOpSubResult(int reason) {
switch (reason) {
case REASON_REJECTED:
return SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__REJECTED;
case REASON_NETWORK_ERROR:
return SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__NETWORK_ERROR;
case REASON_ROUTE_NOT_AVAILABLE:
return SettingsStatsLog
.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__ROUTE_NOT_AVAILABLE;
case REASON_INVALID_COMMAND:
return SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__INVALID_COMMAND;
case REASON_UNKNOWN_ERROR:
default:
return SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__UNKNOWN_ERROR;
}
}
private String getLoggingPackageName() {
final String packageName = getPackageName();
if (packageName != null && !packageName.isEmpty()) {
try {
final ApplicationInfo applicationInfo = mContext.getPackageManager()
.getApplicationInfo(packageName, /* default flag */ 0);
if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
|| (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
return packageName;
}
} catch (Exception ex) {
Log.e(TAG, packageName + "is invalid.");
}
}
return "";
}
private void updateLoggingDeviceCount() {
mWiredDeviceCount = mConnectedBluetoothDeviceCount = mRemoteDeviceCount = 0;
mAppliedDeviceCountWithinRemoteGroup = 0;
for (MediaDevice mediaDevice : mMediaDevices) {
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 (DBG) {
Log.d(TAG, "connected devices:" + " wired: " + mWiredDeviceCount
+ " bluetooth: " + mConnectedBluetoothDeviceCount
+ " remote: " + mRemoteDeviceCount);
}
}
@Override
public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
if (DBG) {
Log.d(TAG, "onSelectedDeviceStateChanged - " + device.toString());
}
updateLoggingDeviceCount();
SettingsStatsLog.write(
SettingsStatsLog.MEDIAOUTPUT_OP_SWITCH_REPORTED,
getLoggingDeviceType(mSourceDevice, true),
getLoggingDeviceType(mTargetDevice, false),
SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__RESULT__OK,
SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SUBRESULT__NO_ERROR,
getLoggingPackageName(),
mWiredDeviceCount,
mConnectedBluetoothDeviceCount,
mRemoteDeviceCount,
mAppliedDeviceCountWithinRemoteGroup);
super.onSelectedDeviceStateChanged(device, state);
}
@Override
public void onRequestFailed(int reason) {
if (DBG) {
Log.e(TAG, "onRequestFailed - " + reason);
}
updateLoggingDeviceCount();
SettingsStatsLog.write(
SettingsStatsLog.MEDIAOUTPUT_OP_SWITCH_REPORTED,
getLoggingDeviceType(mSourceDevice, true),
getLoggingDeviceType(mTargetDevice, false),
SettingsStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__RESULT__ERROR,
getLoggingSwitchOpSubResult(reason),
getLoggingPackageName(),
mWiredDeviceCount,
mConnectedBluetoothDeviceCount,
mRemoteDeviceCount,
mAppliedDeviceCountWithinRemoteGroup);
super.onRequestFailed(reason);
}
}