• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.notification;
18 
19 import android.app.PendingIntent;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.graphics.drawable.Drawable;
23 import android.media.AudioManager;
24 import android.net.Uri;
25 import android.text.TextUtils;
26 import android.util.Log;
27 
28 import androidx.core.graphics.drawable.IconCompat;
29 import androidx.slice.builders.ListBuilder;
30 import androidx.slice.builders.SliceAction;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.settings.R;
34 import com.android.settings.Utils;
35 import com.android.settings.bluetooth.BluetoothBroadcastDialog;
36 import com.android.settings.media.MediaOutputIndicatorWorker;
37 import com.android.settings.slices.CustomSliceRegistry;
38 import com.android.settings.slices.SliceBackgroundWorker;
39 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
40 import com.android.settingslib.flags.Flags;
41 import com.android.settingslib.media.BluetoothMediaDevice;
42 import com.android.settingslib.media.MediaDevice;
43 import com.android.settingslib.media.MediaOutputConstants;
44 
45 // LINT.IfChange
46 public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceController {
47     private static final String TAG = "MediaVolumePreCtrl";
48     private static final String KEY_MEDIA_VOLUME = "media_volume";
49 
50     private MediaOutputIndicatorWorker mWorker;
51     private MediaDevice mMediaDevice;
52     private static final String ACTION_LAUNCH_BROADCAST_DIALOG =
53             "android.settings.MEDIA_BROADCAST_DIALOG";
54 
MediaVolumePreferenceController(Context context)55     public MediaVolumePreferenceController(Context context) {
56         super(context, KEY_MEDIA_VOLUME);
57         mVolumePreferenceListener = this::updateContentDescription;
58     }
59 
60     @Override
getAvailabilityStatus()61     public int getAvailabilityStatus() {
62         return mContext.getResources().getBoolean(R.bool.config_show_media_volume)
63                 ? AVAILABLE
64                 : UNSUPPORTED_ON_DEVICE;
65     }
66 
67     @Override
isSliceable()68     public boolean isSliceable() {
69         return TextUtils.equals(getPreferenceKey(), KEY_MEDIA_VOLUME);
70     }
71 
72     @Override
isPublicSlice()73     public boolean isPublicSlice() {
74         return true;
75     }
76 
77     @Override
useDynamicSliceSummary()78     public boolean useDynamicSliceSummary() {
79         return true;
80     }
81 
82     @Override
getPreferenceKey()83     public String getPreferenceKey() {
84         return KEY_MEDIA_VOLUME;
85     }
86 
87     @Override
getAudioStream()88     public int getAudioStream() {
89         return AudioManager.STREAM_MUSIC;
90     }
91 
92     @Override
getMuteIcon()93     public int getMuteIcon() {
94         return R.drawable.ic_media_stream_off;
95     }
96 
97     @VisibleForTesting
isSupportEndItem()98     boolean isSupportEndItem() {
99         return Flags.legacyLeAudioSharing()
100                 && getWorker() != null
101                 && getWorker().isBroadcastSupported()
102                 && (getWorker().isDeviceBroadcasting() || isConnectedBLEDevice());
103     }
104 
isConnectedBLEDevice()105     private boolean isConnectedBLEDevice() {
106         if (getWorker() == null) {
107             Log.d(TAG, "The Worker is null");
108             return false;
109         }
110         mMediaDevice = getWorker().getCurrentConnectedMediaDevice();
111         if (mMediaDevice != null) {
112             return mMediaDevice.isBLEDevice();
113         }
114         return false;
115     }
116 
updateContentDescription()117     private void updateContentDescription() {
118         if (mPreference != null) {
119             if (mPreference.isMuted()) {
120                 mPreference.updateContentDescription(
121                         mContext.getString(
122                                 R.string.volume_content_description_silent_mode,
123                                 mPreference.getTitle()));
124             } else {
125                 mPreference.updateContentDescription(mPreference.getTitle());
126             }
127         }
128     }
129 
130     @Override
getSliceEndItem(Context context)131     public SliceAction getSliceEndItem(Context context) {
132         if (!isSupportEndItem()) {
133             Log.d(TAG, "The slice doesn't support end item");
134             return null;
135         }
136 
137         final Intent intent = new Intent();
138         PendingIntent pi = null;
139         if (getWorker().isDeviceBroadcasting()) {
140             intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
141             intent.setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
142             intent.putExtra(
143                     MediaOutputConstants.EXTRA_PACKAGE_NAME,
144                     getWorker().getActiveLocalMediaController().getPackageName());
145 
146             pi =
147                     PendingIntent.getBroadcast(
148                             context,
149                             0 /* requestCode */,
150                             intent,
151                             PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
152         } else {
153             final CachedBluetoothDevice bluetoothDevice =
154                     ((BluetoothMediaDevice) mMediaDevice).getCachedDevice();
155             if (bluetoothDevice == null) {
156                 Log.d(TAG, "The bluetooth device is null");
157                 return null;
158             }
159             intent.setAction(ACTION_LAUNCH_BROADCAST_DIALOG);
160             intent.putExtra(
161                     BluetoothBroadcastDialog.KEY_APP_LABEL,
162                     Utils.getApplicationLabel(mContext, getWorker().getPackageName()));
163             intent.putExtra(
164                     BluetoothBroadcastDialog.KEY_DEVICE_ADDRESS, bluetoothDevice.getAddress());
165             intent.putExtra(
166                     BluetoothBroadcastDialog.KEY_MEDIA_STREAMING,
167                     getWorker() != null && getWorker().getActiveLocalMediaController() != null);
168 
169             pi =
170                     PendingIntent.getActivity(
171                             context,
172                             0 /* requestCode */,
173                             intent,
174                             PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
175         }
176 
177         final IconCompat icon = getBroadcastIcon(context);
178 
179         return SliceAction.createDeeplink(pi, icon, ListBuilder.ICON_IMAGE, getPreferenceKey());
180     }
181 
getBroadcastIcon(Context context)182     private IconCompat getBroadcastIcon(Context context) {
183         final Drawable drawable =
184                 context.getDrawable(com.android.settingslib.R.drawable.settings_input_antenna);
185         if (drawable != null) {
186             drawable.setTint(Utils.getColorAccentDefaultColor(context));
187             return Utils.createIconWithDrawable(drawable);
188         }
189         return null;
190     }
191 
getWorker()192     private MediaOutputIndicatorWorker getWorker() {
193         if (mWorker == null) {
194             mWorker = SliceBackgroundWorker.getInstance(getUri());
195         }
196         return mWorker;
197     }
198 
getUri()199     private Uri getUri() {
200         return CustomSliceRegistry.VOLUME_MEDIA_URI;
201     }
202 
203     @Override
getBackgroundWorkerClass()204     public Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
205         return MediaOutputIndicatorWorker.class;
206     }
207 }
208 // LINT.ThenChange(MediaVolumePreference.kt)
209