Snap for 6520975 from a18d14ac9e to mainline-release
Change-Id: Iebeedbf17f8c37d87685351e5da8e8916d0f9689
This commit is contained in:
@@ -51,8 +51,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
public class MediaDeviceUpdateWorker extends SliceBackgroundWorker
|
||||
implements LocalMediaManager.DeviceCallback {
|
||||
|
||||
private final Context mContext;
|
||||
private final Collection<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
|
||||
protected final Context mContext;
|
||||
protected final Collection<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
|
||||
private final DevicesChangedBroadcastReceiver mReceiver;
|
||||
private final String mPackageName;
|
||||
|
||||
|
||||
@@ -375,7 +375,7 @@ public class MediaOutputSlice implements CustomSliceable {
|
||||
|
||||
@Override
|
||||
public Class getBackgroundWorkerClass() {
|
||||
return MediaDeviceUpdateWorker.class;
|
||||
return MediaOutputSliceWorker.class;
|
||||
}
|
||||
|
||||
private boolean isVisible() {
|
||||
|
||||
211
src/com/android/settings/media/MediaOutputSliceWorker.java
Normal file
211
src/com/android/settings/media/MediaOutputSliceWorker.java
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public class AppConversationListPreferenceController extends NotificationPrefere
|
||||
ShortcutInfo si = conversation.getShortcutInfo();
|
||||
|
||||
pref.setTitle(si != null
|
||||
? si.getShortLabel()
|
||||
? si.getLabel()
|
||||
: conversation.getNotificationChannel().getName());
|
||||
pref.setSummary(conversation.getNotificationChannel().getGroup() != null
|
||||
? mContext.getString(R.string.notification_conversation_summary,
|
||||
|
||||
@@ -124,7 +124,7 @@ public class ConversationHeaderPreferenceController extends NotificationPreferen
|
||||
@VisibleForTesting
|
||||
CharSequence getLabel() {
|
||||
return mConversationInfo != null
|
||||
? mConversationInfo.getShortLabel()
|
||||
? mConversationInfo.getLabel()
|
||||
: mChannel.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ public abstract class ConversationListPreferenceController extends AbstractPrefe
|
||||
CharSequence getTitle(ConversationChannelWrapper conversation) {
|
||||
ShortcutInfo si = conversation.getShortcutInfo();
|
||||
return si != null
|
||||
? si.getShortLabel()
|
||||
? si.getLabel()
|
||||
: conversation.getNotificationChannel().getName();
|
||||
}
|
||||
|
||||
@@ -154,8 +154,8 @@ public abstract class ConversationListPreferenceController extends AbstractPrefe
|
||||
return o1.getNotificationChannel().getId().compareTo(
|
||||
o2.getNotificationChannel().getId());
|
||||
}
|
||||
return sCollator.compare(o1.getShortcutInfo().getShortLabel(),
|
||||
o2.getShortcutInfo().getShortLabel());
|
||||
return sCollator.compare(o1.getShortcutInfo().getLabel(),
|
||||
o2.getShortcutInfo().getLabel());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ public class NotificationHistoryActivity extends Activity {
|
||||
LinearLayoutManager lm = new LinearLayoutManager(NotificationHistoryActivity.this);
|
||||
mSnoozedRv.setLayoutManager(lm);
|
||||
mSnoozedRv.setAdapter(
|
||||
new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm));
|
||||
new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm));
|
||||
mSnoozedRv.setNestedScrollingEnabled(false);
|
||||
|
||||
if (snoozed == null || snoozed.length == 0) {
|
||||
@@ -280,7 +280,7 @@ public class NotificationHistoryActivity extends Activity {
|
||||
new LinearLayoutManager(NotificationHistoryActivity.this);
|
||||
mDismissedRv.setLayoutManager(dismissLm);
|
||||
mDismissedRv.setAdapter(
|
||||
new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm));
|
||||
new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm, mUm));
|
||||
mDismissedRv.setNestedScrollingEnabled(false);
|
||||
|
||||
if (dismissed == null || dismissed.length == 0) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.content.res.Configuration;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
@@ -47,6 +48,7 @@ import com.android.internal.util.ContrastColorUtil;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -62,8 +64,9 @@ public class NotificationSbnAdapter extends
|
||||
private @ColorInt int mBackgroundColor;
|
||||
private boolean mInNightMode;
|
||||
private @UserIdInt int mCurrentUser;
|
||||
private List<Integer> mEnabledProfiles = new ArrayList<>();
|
||||
|
||||
public NotificationSbnAdapter(Context context, PackageManager pm) {
|
||||
public NotificationSbnAdapter(Context context, PackageManager pm, UserManager um) {
|
||||
mContext = context;
|
||||
mPm = pm;
|
||||
mUserBadgeCache = new HashMap<>();
|
||||
@@ -74,6 +77,12 @@ public class NotificationSbnAdapter extends
|
||||
mInNightMode = (currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
|
||||
== Configuration.UI_MODE_NIGHT_YES;
|
||||
mCurrentUser = ActivityManager.getCurrentUser();
|
||||
int[] enabledUsers = um.getEnabledProfileIds(mCurrentUser);
|
||||
for (int id : enabledUsers) {
|
||||
if (!um.isQuietModeEnabled(UserHandle.of(id))) {
|
||||
mEnabledProfiles.add(id);
|
||||
}
|
||||
}
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
@@ -115,10 +124,9 @@ public class NotificationSbnAdapter extends
|
||||
}
|
||||
|
||||
public void onRebuildComplete(List<StatusBarNotification> notifications) {
|
||||
// summaries are low content; don't bother showing them
|
||||
for (int i = notifications.size() - 1; i >= 0; i--) {
|
||||
StatusBarNotification sbn = notifications.get(i);
|
||||
if (sbn.isGroup() && sbn.getNotification().isGroupSummary()) {
|
||||
if (!shouldShowSbn(sbn)) {
|
||||
notifications.remove(i);
|
||||
}
|
||||
}
|
||||
@@ -127,13 +135,25 @@ public class NotificationSbnAdapter extends
|
||||
}
|
||||
|
||||
public void addSbn(StatusBarNotification sbn) {
|
||||
if (sbn.isGroup() && sbn.getNotification().isGroupSummary()) {
|
||||
if (!shouldShowSbn(sbn)) {
|
||||
return;
|
||||
}
|
||||
mValues.add(0, sbn);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private boolean shouldShowSbn(StatusBarNotification sbn) {
|
||||
// summaries are low content; don't bother showing them
|
||||
if (sbn.isGroup() && sbn.getNotification().isGroupSummary()) {
|
||||
return false;
|
||||
}
|
||||
// also don't show profile notifications if the profile is currently disabled
|
||||
if (!mEnabledProfiles.contains(normalizeUserId(sbn))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private @NonNull CharSequence loadPackageLabel(String pkg) {
|
||||
try {
|
||||
ApplicationInfo info = mPm.getApplicationInfo(pkg,
|
||||
|
||||
@@ -103,10 +103,10 @@ public class ConversationHeaderPreferenceControllerTest {
|
||||
@Test
|
||||
public void testGetLabel() {
|
||||
ShortcutInfo si = mock(ShortcutInfo.class);
|
||||
when(si.getShortLabel()).thenReturn("hello");
|
||||
when(si.getLabel()).thenReturn("hello");
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
mController.onResume(appRow, null, null, null, si, null);
|
||||
assertEquals(si.getShortLabel(), mController.getLabel());
|
||||
assertEquals(si.getLabel(), mController.getLabel());
|
||||
|
||||
NotificationChannel channel = new NotificationChannel("cid", "cname", IMPORTANCE_NONE);
|
||||
mController.onResume(appRow, channel, null, null, null, null);
|
||||
|
||||
@@ -169,12 +169,12 @@ public class ConversationListPreferenceControllerTest {
|
||||
ccw.setPkg("pkg");
|
||||
ccw.setUid(1);
|
||||
ShortcutInfo si = mock(ShortcutInfo.class);
|
||||
when(si.getShortLabel()).thenReturn("conversation name");
|
||||
when(si.getLabel()).thenReturn("conversation name");
|
||||
ccw.setShortcutInfo(si);
|
||||
ccw.setGroupLabel("group");
|
||||
ccw.setParentChannelLabel("parent");
|
||||
|
||||
assertThat(mController.getTitle(ccw).toString()).isEqualTo(si.getShortLabel());
|
||||
assertThat(mController.getTitle(ccw).toString()).isEqualTo(si.getLabel());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user