Snap for 6864616 from d3d88afee7
to rvc-qpr1-release
Change-Id: I107bc46efdeedeb792cbd03295aa0fd91fb76a3e
This commit is contained in:
@@ -1922,6 +1922,7 @@
|
|||||||
<intent-filter android:priority="1">
|
<intent-filter android:priority="1">
|
||||||
<action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
|
<action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
|
||||||
<action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
|
<action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
|
||||||
|
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES"/>
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:theme="@style/GlifV3Theme.Light"
|
android:theme="@style/GlifV3Theme"
|
||||||
android:icon="@drawable/ic_scan_32dp">
|
android:icon="@drawable/ic_scan_32dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@@ -18,6 +18,10 @@ package com.android.settings;
|
|||||||
|
|
||||||
import static android.content.Intent.EXTRA_USER;
|
import static android.content.Intent.EXTRA_USER;
|
||||||
import static android.content.Intent.EXTRA_USER_ID;
|
import static android.content.Intent.EXTRA_USER_ID;
|
||||||
|
import static android.media.MediaRoute2Info.TYPE_GROUP;
|
||||||
|
import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
|
||||||
|
import static android.media.MediaRoute2Info.TYPE_REMOTE_TV;
|
||||||
|
import static android.media.MediaRoute2Info.TYPE_UNKNOWN;
|
||||||
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
|
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
|
||||||
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
||||||
|
|
||||||
@@ -53,6 +57,8 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.graphics.drawable.VectorDrawable;
|
import android.graphics.drawable.VectorDrawable;
|
||||||
import android.hardware.face.FaceManager;
|
import android.hardware.face.FaceManager;
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.media.MediaRoute2Info;
|
||||||
|
import android.media.MediaRouter2Manager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
@@ -1137,4 +1143,31 @@ public final class Utils extends com.android.settingslib.Utils {
|
|||||||
drawable.draw(canvas);
|
drawable.draw(canvas);
|
||||||
return roundedBitmap;
|
return roundedBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if needed to disable media output, otherwise returns {@code false}.
|
||||||
|
*/
|
||||||
|
public static boolean isMediaOutputDisabled(
|
||||||
|
MediaRouter2Manager router2Manager, String packageName) {
|
||||||
|
boolean isMediaOutputDisabled = false;
|
||||||
|
if (!TextUtils.isEmpty(packageName)) {
|
||||||
|
final List<MediaRoute2Info> infos = router2Manager.getAvailableRoutes(packageName);
|
||||||
|
if (infos.size() == 1) {
|
||||||
|
final MediaRoute2Info info = infos.get(0);
|
||||||
|
final int deviceType = info.getType();
|
||||||
|
switch (deviceType) {
|
||||||
|
case TYPE_UNKNOWN:
|
||||||
|
case TYPE_REMOTE_TV:
|
||||||
|
case TYPE_REMOTE_SPEAKER:
|
||||||
|
case TYPE_GROUP:
|
||||||
|
isMediaOutputDisabled = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
isMediaOutputDisabled = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isMediaOutputDisabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings.development;
|
package com.android.settings.development;
|
||||||
|
|
||||||
|
import static android.service.quicksettings.TileService.ACTION_QS_TILE_PREFERENCES;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.bluetooth.BluetoothA2dp;
|
import android.bluetooth.BluetoothA2dp;
|
||||||
@@ -23,12 +25,14 @@ import android.bluetooth.BluetoothAdapter;
|
|||||||
import android.bluetooth.BluetoothCodecStatus;
|
import android.bluetooth.BluetoothCodecStatus;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -41,6 +45,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsActivity;
|
import com.android.settings.SettingsActivity;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||||
import com.android.settings.development.autofill.AutofillLoggingLevelPreferenceController;
|
import com.android.settings.development.autofill.AutofillLoggingLevelPreferenceController;
|
||||||
import com.android.settings.development.autofill.AutofillResetOptionsPreferenceController;
|
import com.android.settings.development.autofill.AutofillResetOptionsPreferenceController;
|
||||||
@@ -52,6 +57,7 @@ import com.android.settings.development.bluetooth.BluetoothCodecDialogPreference
|
|||||||
import com.android.settings.development.bluetooth.BluetoothHDAudioPreferenceController;
|
import com.android.settings.development.bluetooth.BluetoothHDAudioPreferenceController;
|
||||||
import com.android.settings.development.bluetooth.BluetoothQualityDialogPreferenceController;
|
import com.android.settings.development.bluetooth.BluetoothQualityDialogPreferenceController;
|
||||||
import com.android.settings.development.bluetooth.BluetoothSampleRateDialogPreferenceController;
|
import com.android.settings.development.bluetooth.BluetoothSampleRateDialogPreferenceController;
|
||||||
|
import com.android.settings.development.qstile.DevelopmentTiles;
|
||||||
import com.android.settings.development.storage.SharedDataPreferenceController;
|
import com.android.settings.development.storage.SharedDataPreferenceController;
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
import com.android.settings.widget.SwitchBar;
|
import com.android.settings.widget.SwitchBar;
|
||||||
@@ -199,11 +205,42 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
|||||||
// Restore UI state based on whether developer options is enabled
|
// Restore UI state based on whether developer options is enabled
|
||||||
if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext())) {
|
if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(getContext())) {
|
||||||
enableDeveloperOptions();
|
enableDeveloperOptions();
|
||||||
|
handleQsTileLongPressActionIfAny();
|
||||||
} else {
|
} else {
|
||||||
disableDeveloperOptions();
|
disableDeveloperOptions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Long-pressing a developer options quick settings tile will by default (see
|
||||||
|
* QS_TILE_PREFERENCES in the manifest) take you to the developer options page.
|
||||||
|
* Some tiles may want to go into their own page within the developer options.
|
||||||
|
*/
|
||||||
|
private void handleQsTileLongPressActionIfAny() {
|
||||||
|
Intent intent = getActivity().getIntent();
|
||||||
|
if (intent == null || !TextUtils.equals(ACTION_QS_TILE_PREFERENCES, intent.getAction())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Developer options started from qstile long-press");
|
||||||
|
final ComponentName componentName = (ComponentName) intent.getParcelableExtra(
|
||||||
|
Intent.EXTRA_COMPONENT_NAME);
|
||||||
|
if (componentName == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DevelopmentTiles.WirelessDebugging.class.getName().equals(
|
||||||
|
componentName.getClassName()) && getDevelopmentOptionsController(
|
||||||
|
WirelessDebuggingPreferenceController.class).isAvailable()) {
|
||||||
|
Log.d(TAG, "Long press from wireless debugging qstile");
|
||||||
|
new SubSettingLauncher(getContext())
|
||||||
|
.setDestination(WirelessDebuggingFragment.class.getName())
|
||||||
|
.setSourceMetricsCategory(SettingsEnums.SETTINGS_ADB_WIRELESS)
|
||||||
|
.launch();
|
||||||
|
}
|
||||||
|
// Add other qstiles here
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
@@ -243,7 +243,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
|
|||||||
final MetricsFeatureProvider metricsFeatureProvider =
|
final MetricsFeatureProvider metricsFeatureProvider =
|
||||||
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
|
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
|
||||||
|
|
||||||
//navigate back to the homepage, screen rotate or after card dismissal
|
// navigate back to the homepage, screen rotate or after card dismissal
|
||||||
if (!mIsFirstLaunch) {
|
if (!mIsFirstLaunch) {
|
||||||
onContextualCardUpdated(cardsToKeep.stream()
|
onContextualCardUpdated(cardsToKeep.stream()
|
||||||
.collect(groupingBy(ContextualCard::getCardType)));
|
.collect(groupingBy(ContextualCard::getCardType)));
|
||||||
@@ -266,8 +266,17 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
|
|||||||
SettingsEnums.ACTION_CONTEXTUAL_CARD_LOAD_TIMEOUT,
|
SettingsEnums.ACTION_CONTEXTUAL_CARD_LOAD_TIMEOUT,
|
||||||
SettingsEnums.SETTINGS_HOMEPAGE,
|
SettingsEnums.SETTINGS_HOMEPAGE,
|
||||||
null /* key */, (int) loadTime /* value */);
|
null /* key */, (int) loadTime /* value */);
|
||||||
|
|
||||||
|
// display a card on timeout if the one-card space is pre-allocated
|
||||||
|
if (!cards.isEmpty() && ContextualCardLoader.getCardCount(mContext) == 1) {
|
||||||
|
onContextualCardUpdated(cards.stream()
|
||||||
|
.collect(groupingBy(ContextualCard::getCardType)));
|
||||||
|
metricsFeatureProvider.action(mContext,
|
||||||
|
SettingsEnums.ACTION_CONTEXTUAL_CARD_SHOW,
|
||||||
|
ContextualCardLogUtils.buildCardListLog(cards));
|
||||||
}
|
}
|
||||||
//only log homepage display upon a fresh launch
|
}
|
||||||
|
// only log homepage display upon a fresh launch
|
||||||
final long totalTime = System.currentTimeMillis() - mStartTime;
|
final long totalTime = System.currentTimeMillis() - mStartTime;
|
||||||
metricsFeatureProvider.action(mContext,
|
metricsFeatureProvider.action(mContext,
|
||||||
SettingsEnums.ACTION_CONTEXTUAL_HOME_SHOW, (int) totalTime);
|
SettingsEnums.ACTION_CONTEXTUAL_HOME_SHOW, (int) totalTime);
|
||||||
|
@@ -27,6 +27,7 @@ import android.content.Intent;
|
|||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.media.session.MediaController;
|
import android.media.session.MediaController;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
import androidx.core.graphics.drawable.IconCompat;
|
||||||
@@ -62,8 +63,12 @@ public class MediaOutputIndicatorSlice implements CustomSliceable {
|
|||||||
com.android.internal.R.drawable.ic_settings_bluetooth);
|
com.android.internal.R.drawable.ic_settings_bluetooth);
|
||||||
final CharSequence title = mContext.getString(R.string.media_output_label_title,
|
final CharSequence title = mContext.getString(R.string.media_output_label_title,
|
||||||
Utils.getApplicationLabel(mContext, getWorker().getPackageName()));
|
Utils.getApplicationLabel(mContext, getWorker().getPackageName()));
|
||||||
|
final int requestCode = TextUtils.isEmpty(getWorker().getPackageName())
|
||||||
|
? 0
|
||||||
|
: getWorker().getPackageName().hashCode();
|
||||||
final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext,
|
final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext,
|
||||||
0 /* requestCode */, getMediaOutputSliceIntent(), FLAG_UPDATE_CURRENT);
|
requestCode,
|
||||||
|
getMediaOutputSliceIntent(), FLAG_UPDATE_CURRENT);
|
||||||
final SliceAction primarySliceAction = SliceAction.createDeeplink(
|
final SliceAction primarySliceAction = SliceAction.createDeeplink(
|
||||||
primaryActionIntent, icon, ListBuilder.ICON_IMAGE, title);
|
primaryActionIntent, icon, ListBuilder.ICON_IMAGE, title);
|
||||||
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
|
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
|
||||||
|
@@ -257,9 +257,11 @@ public class MediaOutputSlice implements CustomSliceable {
|
|||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
.putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
|
.putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
|
||||||
getWorker().getPackageName());
|
getWorker().getPackageName());
|
||||||
|
final int requestCode = TextUtils.isEmpty(getWorker().getPackageName())
|
||||||
|
? 0
|
||||||
|
: getWorker().getPackageName().hashCode();
|
||||||
return SliceAction.createDeeplink(
|
return SliceAction.createDeeplink(
|
||||||
PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */),
|
PendingIntent.getActivity(mContext, requestCode, intent, 0 /* flags */),
|
||||||
IconCompat.createWithResource(mContext, R.drawable.ic_add_blue_24dp),
|
IconCompat.createWithResource(mContext, R.drawable.ic_add_blue_24dp),
|
||||||
ListBuilder.ICON_IMAGE,
|
ListBuilder.ICON_IMAGE,
|
||||||
mContext.getText(R.string.add));
|
mContext.getText(R.string.add));
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package com.android.settings.media;
|
package com.android.settings.media;
|
||||||
|
|
||||||
import static android.app.slice.Slice.EXTRA_RANGE_VALUE;
|
import static android.app.slice.Slice.EXTRA_RANGE_VALUE;
|
||||||
|
import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
|
||||||
|
|
||||||
import static com.android.settings.slices.CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI;
|
import static com.android.settings.slices.CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI;
|
||||||
|
|
||||||
@@ -24,11 +25,15 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.media.MediaRouter2Manager;
|
||||||
import android.media.RoutingSessionInfo;
|
import android.media.RoutingSessionInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.text.SpannableString;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
import androidx.core.graphics.drawable.IconCompat;
|
||||||
import androidx.slice.Slice;
|
import androidx.slice.Slice;
|
||||||
import androidx.slice.builders.ListBuilder;
|
import androidx.slice.builders.ListBuilder;
|
||||||
@@ -59,6 +64,9 @@ public class RemoteMediaSlice implements CustomSliceable {
|
|||||||
|
|
||||||
private MediaDeviceUpdateWorker mWorker;
|
private MediaDeviceUpdateWorker mWorker;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
MediaRouter2Manager mRouterManager;
|
||||||
|
|
||||||
public RemoteMediaSlice(Context context) {
|
public RemoteMediaSlice(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
}
|
}
|
||||||
@@ -80,6 +88,9 @@ public class RemoteMediaSlice implements CustomSliceable {
|
|||||||
Log.e(TAG, "Unable to get the slice worker.");
|
Log.e(TAG, "Unable to get the slice worker.");
|
||||||
return listBuilder.build();
|
return listBuilder.build();
|
||||||
}
|
}
|
||||||
|
if (mRouterManager == null) {
|
||||||
|
mRouterManager = MediaRouter2Manager.getInstance(mContext);
|
||||||
|
}
|
||||||
// Only displaying remote devices
|
// Only displaying remote devices
|
||||||
final List<RoutingSessionInfo> infos = getWorker().getActiveRemoteMediaDevice();
|
final List<RoutingSessionInfo> infos = getWorker().getActiveRemoteMediaDevice();
|
||||||
if (infos.isEmpty()) {
|
if (infos.isEmpty()) {
|
||||||
@@ -98,8 +109,10 @@ public class RemoteMediaSlice implements CustomSliceable {
|
|||||||
+ maxVolume);
|
+ maxVolume);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
final CharSequence appName = Utils.getApplicationLabel(
|
||||||
|
mContext, info.getClientPackageName());
|
||||||
final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
|
final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
|
||||||
Utils.getApplicationLabel(mContext, info.getClientPackageName()));
|
appName);
|
||||||
listBuilder.addInputRange(new InputRangeBuilder()
|
listBuilder.addInputRange(new InputRangeBuilder()
|
||||||
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
|
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
|
||||||
.setTitle(castVolume)
|
.setTitle(castVolume)
|
||||||
@@ -107,11 +120,21 @@ public class RemoteMediaSlice implements CustomSliceable {
|
|||||||
.setPrimaryAction(getSoundSettingAction(castVolume, icon, info.getId()))
|
.setPrimaryAction(getSoundSettingAction(castVolume, icon, info.getId()))
|
||||||
.setMax(maxVolume)
|
.setMax(maxVolume)
|
||||||
.setValue(info.getVolume()));
|
.setValue(info.getVolume()));
|
||||||
|
|
||||||
|
final boolean isMediaOutputDisabled =
|
||||||
|
Utils.isMediaOutputDisabled(mRouterManager, info.getClientPackageName());
|
||||||
|
final SpannableString spannableTitle = new SpannableString(
|
||||||
|
TextUtils.isEmpty(appName) ? "" : appName);
|
||||||
|
spannableTitle.setSpan(new ForegroundColorSpan(
|
||||||
|
Utils.getColorAttrDefaultColor(
|
||||||
|
mContext, android.R.attr.textColorSecondary)), 0,
|
||||||
|
spannableTitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
listBuilder.addRow(new ListBuilder.RowBuilder()
|
listBuilder.addRow(new ListBuilder.RowBuilder()
|
||||||
.setTitle(outputTitle)
|
.setTitle(isMediaOutputDisabled ? spannableTitle : outputTitle)
|
||||||
.setSubtitle(info.getName())
|
.setSubtitle(info.getName())
|
||||||
.setTitleItem(emptyIcon, ListBuilder.ICON_IMAGE)
|
.setTitleItem(emptyIcon, ListBuilder.ICON_IMAGE)
|
||||||
.setPrimaryAction(getMediaOutputSliceAction(info.getClientPackageName())));
|
.setPrimaryAction(getMediaOutputSliceAction(
|
||||||
|
info.getClientPackageName(), isMediaOutputDisabled)));
|
||||||
}
|
}
|
||||||
return listBuilder.build();
|
return listBuilder.build();
|
||||||
}
|
}
|
||||||
@@ -144,15 +167,19 @@ public class RemoteMediaSlice implements CustomSliceable {
|
|||||||
return primarySliceAction;
|
return primarySliceAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SliceAction getMediaOutputSliceAction(String packageName) {
|
private SliceAction getMediaOutputSliceAction(
|
||||||
|
String packageName, boolean isMediaOutputDisabled) {
|
||||||
final Intent intent = new Intent()
|
final Intent intent = new Intent()
|
||||||
.setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
|
.setAction(isMediaOutputDisabled
|
||||||
|
? ""
|
||||||
|
: MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
.putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME, packageName);
|
.putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME, packageName);
|
||||||
final IconCompat icon = IconCompat.createWithResource(mContext,
|
final IconCompat icon = IconCompat.createWithResource(mContext,
|
||||||
R.drawable.ic_volume_remote);
|
R.drawable.ic_volume_remote);
|
||||||
|
final int requestCode = TextUtils.isEmpty(packageName) ? 0 : packageName.hashCode();
|
||||||
final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext,
|
final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext,
|
||||||
0 /* requestCode */, intent, 0 /* flags */);
|
requestCode, intent, 0 /* flags */);
|
||||||
final SliceAction primarySliceAction = SliceAction.createDeeplink(
|
final SliceAction primarySliceAction = SliceAction.createDeeplink(
|
||||||
primaryActionIntent, icon, ListBuilder.ICON_IMAGE,
|
primaryActionIntent, icon, ListBuilder.ICON_IMAGE,
|
||||||
mContext.getString(R.string.media_output_label_title,
|
mContext.getString(R.string.media_output_label_title,
|
||||||
|
@@ -55,6 +55,13 @@ public class NrDisabledInDsdsFooterPreferenceController extends BasePreferenceCo
|
|||||||
super.updateState(preference);
|
super.updateState(preference);
|
||||||
|
|
||||||
if (preference != null) {
|
if (preference != null) {
|
||||||
|
// This is necessary to ensure that setting the title to the spannable string returned
|
||||||
|
// by getFooterText will be accepted. Internally, setTitle does an equality check on
|
||||||
|
// the spannable string being set to the text already set on the preference. That
|
||||||
|
// equality check apparently only takes into account the raw text and not and spannables
|
||||||
|
// that are part of the text. So we clear the title before applying the spannable
|
||||||
|
// footer to ensure it is accepted.
|
||||||
|
preference.setTitle("");
|
||||||
preference.setTitle(getFooterText());
|
preference.setTitle(getFooterText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@ package com.android.settings.notification;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.media.MediaRouter2Manager;
|
||||||
import android.media.RoutingSessionInfo;
|
import android.media.RoutingSessionInfo;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
@@ -57,6 +58,8 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
LocalMediaManager mLocalMediaManager;
|
LocalMediaManager mLocalMediaManager;
|
||||||
|
@VisibleForTesting
|
||||||
|
MediaRouter2Manager mRouterManager;
|
||||||
|
|
||||||
public RemoteVolumeGroupController(Context context, String preferenceKey) {
|
public RemoteVolumeGroupController(Context context, String preferenceKey) {
|
||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
@@ -65,6 +68,7 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
|
|||||||
mLocalMediaManager.registerCallback(this);
|
mLocalMediaManager.registerCallback(this);
|
||||||
mLocalMediaManager.startScan();
|
mLocalMediaManager.startScan();
|
||||||
}
|
}
|
||||||
|
mRouterManager = MediaRouter2Manager.getInstance(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -111,8 +115,10 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
|
|||||||
if (mPreferenceCategory.findPreference(info.getId()) != null) {
|
if (mPreferenceCategory.findPreference(info.getId()) != null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
final CharSequence appName = Utils.getApplicationLabel(
|
||||||
|
mContext, info.getClientPackageName());
|
||||||
final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
|
final CharSequence outputTitle = mContext.getString(R.string.media_output_label_title,
|
||||||
Utils.getApplicationLabel(mContext, info.getClientPackageName()));
|
appName);
|
||||||
// Add slider
|
// Add slider
|
||||||
final RemoteVolumeSeekBarPreference seekBarPreference =
|
final RemoteVolumeSeekBarPreference seekBarPreference =
|
||||||
new RemoteVolumeSeekBarPreference(mContext);
|
new RemoteVolumeSeekBarPreference(mContext);
|
||||||
@@ -125,10 +131,13 @@ public class RemoteVolumeGroupController extends BasePreferenceController implem
|
|||||||
seekBarPreference.setIcon(R.drawable.ic_volume_remote);
|
seekBarPreference.setIcon(R.drawable.ic_volume_remote);
|
||||||
mPreferenceCategory.addPreference(seekBarPreference);
|
mPreferenceCategory.addPreference(seekBarPreference);
|
||||||
// Add output indicator
|
// Add output indicator
|
||||||
|
final boolean isMediaOutputDisabled = Utils.isMediaOutputDisabled(
|
||||||
|
mRouterManager, info.getClientPackageName());
|
||||||
final Preference preference = new Preference(mContext);
|
final Preference preference = new Preference(mContext);
|
||||||
preference.setKey(SWITCHER_PREFIX + info.getId());
|
preference.setKey(SWITCHER_PREFIX + info.getId());
|
||||||
preference.setTitle(outputTitle);
|
preference.setTitle(isMediaOutputDisabled ? appName : outputTitle);
|
||||||
preference.setSummary(info.getName());
|
preference.setSummary(info.getName());
|
||||||
|
preference.setEnabled(!isMediaOutputDisabled);
|
||||||
mPreferenceCategory.addPreference(preference);
|
mPreferenceCategory.addPreference(preference);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -40,6 +40,8 @@ import android.graphics.Color;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.VectorDrawable;
|
import android.graphics.drawable.VectorDrawable;
|
||||||
|
import android.media.MediaRoute2Info;
|
||||||
|
import android.media.MediaRouter2Manager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
@@ -299,4 +301,33 @@ public class UtilsTest {
|
|||||||
|
|
||||||
assertThat(Utils.isSettingsIntelligence(mContext)).isFalse();
|
assertThat(Utils.isSettingsIntelligence(mContext)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isMediaOutputDisabled_infosSizeEqual1_returnsTrue() {
|
||||||
|
final MediaRouter2Manager router2Manager = mock(MediaRouter2Manager.class);
|
||||||
|
final MediaRoute2Info info = mock(MediaRoute2Info.class);
|
||||||
|
final List<MediaRoute2Info> infos = new ArrayList<>();
|
||||||
|
infos.add(info);
|
||||||
|
|
||||||
|
when(router2Manager.getAvailableRoutes(anyString())).thenReturn(infos);
|
||||||
|
when(info.getType()).thenReturn(0);
|
||||||
|
|
||||||
|
assertThat(Utils.isMediaOutputDisabled(router2Manager, "test")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isMediaOutputDisabled_infosSizeOverThan1_returnsFalse() {
|
||||||
|
final MediaRouter2Manager router2Manager = mock(MediaRouter2Manager.class);
|
||||||
|
final MediaRoute2Info info = mock(MediaRoute2Info.class);
|
||||||
|
final MediaRoute2Info info2 = mock(MediaRoute2Info.class);
|
||||||
|
final List<MediaRoute2Info> infos = new ArrayList<>();
|
||||||
|
infos.add(info);
|
||||||
|
infos.add(info2);
|
||||||
|
|
||||||
|
when(router2Manager.getAvailableRoutes(anyString())).thenReturn(infos);
|
||||||
|
when(info.getType()).thenReturn(0);
|
||||||
|
when(info2.getType()).thenReturn(0);
|
||||||
|
|
||||||
|
assertThat(Utils.isMediaOutputDisabled(router2Manager, "test")).isFalse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.settings.homepage.contextualcards;
|
package com.android.settings.homepage.contextualcards;
|
||||||
|
|
||||||
|
import static com.android.settings.homepage.contextualcards.ContextualCardLoader.CONTEXTUAL_CARD_COUNT;
|
||||||
import static com.android.settings.homepage.contextualcards.ContextualCardManager.KEY_CONTEXTUAL_CARDS;
|
import static com.android.settings.homepage.contextualcards.ContextualCardManager.KEY_CONTEXTUAL_CARDS;
|
||||||
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH;
|
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH;
|
||||||
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH;
|
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH;
|
||||||
@@ -307,7 +308,7 @@ public class ContextualCardManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onFinishCardLoading_fastLoad_shouldCallOnContextualCardUpdated() {
|
public void onFinishCardLoading_fastLoad_shouldUpdateContextualCard() {
|
||||||
mManager.mStartTime = System.currentTimeMillis();
|
mManager.mStartTime = System.currentTimeMillis();
|
||||||
final ContextualCardManager manager = spy(mManager);
|
final ContextualCardManager manager = spy(mManager);
|
||||||
doNothing().when(manager).onContextualCardUpdated(anyMap());
|
doNothing().when(manager).onContextualCardUpdated(anyMap());
|
||||||
@@ -318,7 +319,7 @@ public class ContextualCardManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onFinishCardLoading_slowLoad_shouldSkipOnContextualCardUpdated() {
|
public void onFinishCardLoading_slowLoadAndNoCard_shouldNotUpdateContextualCard() {
|
||||||
mManager.mStartTime = 0;
|
mManager.mStartTime = 0;
|
||||||
final ContextualCardManager manager = spy(mManager);
|
final ContextualCardManager manager = spy(mManager);
|
||||||
doNothing().when(manager).onContextualCardUpdated(anyMap());
|
doNothing().when(manager).onContextualCardUpdated(anyMap());
|
||||||
@@ -328,6 +329,30 @@ public class ContextualCardManagerTest {
|
|||||||
verify(manager, never()).onContextualCardUpdated(anyMap());
|
verify(manager, never()).onContextualCardUpdated(anyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onFinishCardLoading_slowLoadAndNotPreAllocateSpace_shouldNotUpdateContextualCard() {
|
||||||
|
mManager.mStartTime = 0;
|
||||||
|
Settings.Global.putInt(mContext.getContentResolver(), CONTEXTUAL_CARD_COUNT, 3);
|
||||||
|
final ContextualCardManager manager = spy(mManager);
|
||||||
|
doNothing().when(manager).onContextualCardUpdated(anyMap());
|
||||||
|
|
||||||
|
manager.onFinishCardLoading(Arrays.asList(buildContextualCard(TEST_SLICE_URI)));
|
||||||
|
|
||||||
|
verify(manager, never()).onContextualCardUpdated(anyMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onFinishCardLoading_slowLoadAndPreAllocateSpace_shouldUpdateContextualCard() {
|
||||||
|
mManager.mStartTime = 0;
|
||||||
|
Settings.Global.putInt(mContext.getContentResolver(), CONTEXTUAL_CARD_COUNT, 1);
|
||||||
|
final ContextualCardManager manager = spy(mManager);
|
||||||
|
doNothing().when(manager).onContextualCardUpdated(anyMap());
|
||||||
|
|
||||||
|
manager.onFinishCardLoading(Arrays.asList(buildContextualCard(TEST_SLICE_URI)));
|
||||||
|
|
||||||
|
verify(manager).onContextualCardUpdated(anyMap());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onFinishCardLoading_newLaunch_twoLoadedCards_shouldShowTwoCards() {
|
public void onFinishCardLoading_newLaunch_twoLoadedCards_shouldShowTwoCards() {
|
||||||
mManager.mStartTime = System.currentTimeMillis();
|
mManager.mStartTime = System.currentTimeMillis();
|
||||||
|
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.media.MediaRouter2Manager;
|
||||||
import android.media.RoutingSessionInfo;
|
import android.media.RoutingSessionInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
@@ -87,6 +88,7 @@ public class RemoteMediaSliceTest {
|
|||||||
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
|
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
|
||||||
|
|
||||||
mRemoteMediaSlice = new RemoteMediaSlice(mContext);
|
mRemoteMediaSlice = new RemoteMediaSlice(mContext);
|
||||||
|
mRemoteMediaSlice.mRouterManager = mock(MediaRouter2Manager.class);
|
||||||
sMediaDeviceUpdateWorker = spy(new MediaDeviceUpdateWorker(mContext,
|
sMediaDeviceUpdateWorker = spy(new MediaDeviceUpdateWorker(mContext,
|
||||||
REMOTE_MEDIA_SLICE_URI));
|
REMOTE_MEDIA_SLICE_URI));
|
||||||
sMediaDeviceUpdateWorker.mLocalMediaManager = mLocalMediaManager;
|
sMediaDeviceUpdateWorker.mLocalMediaManager = mLocalMediaManager;
|
||||||
|
@@ -30,6 +30,7 @@ import android.content.SharedPreferences;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageStats;
|
import android.content.pm.PackageStats;
|
||||||
|
import android.media.MediaRouter2Manager;
|
||||||
import android.media.RoutingSessionInfo;
|
import android.media.RoutingSessionInfo;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
@@ -94,6 +95,7 @@ public class RemoteVolumeGroupControllerTest {
|
|||||||
mContext = RuntimeEnvironment.application;
|
mContext = RuntimeEnvironment.application;
|
||||||
mController = new RemoteVolumeGroupController(mContext, KEY_REMOTE_VOLUME_GROUP);
|
mController = new RemoteVolumeGroupController(mContext, KEY_REMOTE_VOLUME_GROUP);
|
||||||
mController.mLocalMediaManager = mLocalMediaManager;
|
mController.mLocalMediaManager = mLocalMediaManager;
|
||||||
|
mController.mRouterManager = mock(MediaRouter2Manager.class);
|
||||||
mPreferenceCategory = spy(new PreferenceCategory(mContext));
|
mPreferenceCategory = spy(new PreferenceCategory(mContext));
|
||||||
mPreferenceCategory.setKey(mController.getPreferenceKey());
|
mPreferenceCategory.setKey(mController.getPreferenceKey());
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user