Merge "Display notification effects suppressor in the volume panel." into lmp-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
7653a30ea0
@@ -62,6 +62,8 @@ interface INotificationManager
|
||||
void requestHintsFromListener(in INotificationListener token, int hints);
|
||||
int getHintsFromListener(in INotificationListener token);
|
||||
|
||||
ComponentName getEffectsSuppressor();
|
||||
|
||||
ZenModeConfig getZenModeConfig();
|
||||
boolean setZenModeConfig(in ZenModeConfig config);
|
||||
oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package android.app;
|
||||
|
||||
import android.annotation.SdkConstant;
|
||||
import android.app.Notification.Builder;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -72,6 +74,16 @@ public class NotificationManager
|
||||
private static String TAG = "NotificationManager";
|
||||
private static boolean localLOGV = false;
|
||||
|
||||
/**
|
||||
* Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes.
|
||||
* This broadcast is only sent to registered receivers.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
public static final String ACTION_EFFECTS_SUPPRESSOR_CHANGED
|
||||
= "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED";
|
||||
|
||||
private static INotificationManager sService;
|
||||
|
||||
/** @hide */
|
||||
@@ -227,5 +239,17 @@ public class NotificationManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public ComponentName getEffectsSuppressor() {
|
||||
INotificationManager service = getService();
|
||||
try {
|
||||
return service.getEffectsSuppressor();
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
}
|
||||
|
||||
24
packages/SystemUI/res/drawable/ic_ringer_mute.xml
Normal file
24
packages/SystemUI/res/drawable/ic_ringer_mute.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2014 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="48.0"
|
||||
android:viewportHeight="48.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z"/>
|
||||
</vector>
|
||||
@@ -29,14 +29,30 @@
|
||||
android:background="@drawable/btn_borderless_rect"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar"
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingBottom="0dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="0dip" />
|
||||
android:layout_weight="1" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/suppressor"
|
||||
android:visibility="gone"
|
||||
android:textAppearance="@style/TextAppearance.QS.VolumeSuppressor"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="0dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="0dp" />
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
@@ -141,6 +141,11 @@
|
||||
<item name="android:textColor">@color/system_accent_color</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.QS.VolumeSuppressor">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textColor">@color/qs_tile_text</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.QS.DetailButton">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textAllCaps">true</item>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.service.notification.Condition;
|
||||
|
||||
public interface ZenModeController {
|
||||
@@ -29,6 +30,7 @@ public interface ZenModeController {
|
||||
long getNextAlarm();
|
||||
void setUserId(int userId);
|
||||
boolean isZenAvailable();
|
||||
ComponentName getEffectsSuppressor();
|
||||
|
||||
public static class Callback {
|
||||
public void onZenChanged(int zen) {}
|
||||
@@ -36,5 +38,6 @@ public interface ZenModeController {
|
||||
public void onConditionsChanged(Condition[] conditions) {}
|
||||
public void onNextAlarmChanged() {}
|
||||
public void onZenAvailableChanged(boolean available) {}
|
||||
public void onEffectsSupressorChanged() {}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,9 @@ package com.android.systemui.statusbar.policy;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -161,12 +163,23 @@ public class ZenModeControllerImpl implements ZenModeController {
|
||||
mSetupObserver.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName getEffectsSuppressor() {
|
||||
return NotificationManager.from(mContext).getEffectsSuppressor();
|
||||
}
|
||||
|
||||
private void fireNextAlarmChanged() {
|
||||
for (Callback cb : mCallbacks) {
|
||||
cb.onNextAlarmChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void fireEffectsSuppressorChanged() {
|
||||
for (Callback cb : mCallbacks) {
|
||||
cb.onEffectsSupressorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void fireZenChanged(int zen) {
|
||||
for (Callback cb : mCallbacks) {
|
||||
cb.onZenChanged(zen);
|
||||
@@ -219,6 +232,9 @@ public class ZenModeControllerImpl implements ZenModeController {
|
||||
if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) {
|
||||
fireNextAlarmChanged();
|
||||
}
|
||||
if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) {
|
||||
fireEffectsSuppressorChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -19,11 +19,15 @@ package com.android.systemui.volume;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
@@ -57,6 +61,7 @@ import android.view.WindowManager.LayoutParams;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
||||
@@ -109,6 +114,7 @@ public class VolumePanel extends Handler {
|
||||
private static final int MSG_LAYOUT_DIRECTION = 12;
|
||||
private static final int MSG_ZEN_MODE_AVAILABLE_CHANGED = 13;
|
||||
private static final int MSG_USER_ACTIVITY = 14;
|
||||
private static final int MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED = 15;
|
||||
|
||||
// Pseudo stream type for master volume
|
||||
private static final int STREAM_MASTER = -100;
|
||||
@@ -234,8 +240,10 @@ public class VolumePanel extends Handler {
|
||||
ViewGroup group;
|
||||
ImageView icon;
|
||||
SeekBar seekbarView;
|
||||
TextView suppressorView;
|
||||
int iconRes;
|
||||
int iconMuteRes;
|
||||
int iconSuppressedRes;
|
||||
}
|
||||
|
||||
// Synchronize when accessing this
|
||||
@@ -613,8 +621,12 @@ public class VolumePanel extends Handler {
|
||||
toggle(sc);
|
||||
}
|
||||
});
|
||||
sc.iconSuppressedRes = com.android.systemui.R.drawable.ic_ringer_mute;
|
||||
}
|
||||
sc.seekbarView = (SeekBar) sc.group.findViewById(com.android.systemui.R.id.seekbar);
|
||||
sc.suppressorView =
|
||||
(TextView) sc.group.findViewById(com.android.systemui.R.id.suppressor);
|
||||
sc.suppressorView.setVisibility(View.GONE);
|
||||
final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
|
||||
streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
|
||||
sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);
|
||||
@@ -678,6 +690,40 @@ public class VolumePanel extends Handler {
|
||||
sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes);
|
||||
}
|
||||
|
||||
private void updateSliderSupressor(StreamControl sc) {
|
||||
final ComponentName suppressor = isNotificationOrRing(sc.streamType)
|
||||
? mZenController.getEffectsSuppressor() : null;
|
||||
if (suppressor == null) {
|
||||
sc.seekbarView.setVisibility(View.VISIBLE);
|
||||
sc.suppressorView.setVisibility(View.GONE);
|
||||
} else {
|
||||
sc.seekbarView.setVisibility(View.GONE);
|
||||
sc.suppressorView.setVisibility(View.VISIBLE);
|
||||
sc.suppressorView.setText(mContext.getString(com.android.systemui.R.string.muted_by,
|
||||
getSuppressorCaption(suppressor)));
|
||||
sc.icon.setImageResource(sc.iconSuppressedRes);
|
||||
}
|
||||
}
|
||||
|
||||
private String getSuppressorCaption(ComponentName suppressor) {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
try {
|
||||
final ServiceInfo info = pm.getServiceInfo(suppressor, 0);
|
||||
if (info != null) {
|
||||
final CharSequence seq = info.loadLabel(pm);
|
||||
if (seq != null) {
|
||||
final String str = seq.toString().trim();
|
||||
if (str.length() > 0) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Error loading suppressor caption", e);
|
||||
}
|
||||
return suppressor.getPackageName();
|
||||
}
|
||||
|
||||
/** Update the mute and progress state of a slider */
|
||||
private void updateSlider(StreamControl sc) {
|
||||
updateSliderProgress(sc, -1);
|
||||
@@ -686,6 +732,7 @@ public class VolumePanel extends Handler {
|
||||
sc.icon.setImageDrawable(null);
|
||||
updateSliderIcon(sc, muted);
|
||||
updateSliderEnabled(sc, muted, false);
|
||||
updateSliderSupressor(sc);
|
||||
}
|
||||
|
||||
private void updateSliderEnabled(final StreamControl sc, boolean muted, boolean fixedVolume) {
|
||||
@@ -1275,7 +1322,9 @@ public class VolumePanel extends Handler {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_RINGER_MODE_CHANGED: {
|
||||
|
||||
case MSG_RINGER_MODE_CHANGED:
|
||||
case MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED: {
|
||||
if (isShowing()) {
|
||||
updateStates();
|
||||
}
|
||||
@@ -1356,9 +1405,15 @@ public class VolumePanel extends Handler {
|
||||
};
|
||||
|
||||
private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
|
||||
@Override
|
||||
public void onZenAvailableChanged(boolean available) {
|
||||
obtainMessage(MSG_ZEN_MODE_AVAILABLE_CHANGED, available ? 1 : 0, 0).sendToTarget();
|
||||
}
|
||||
@Override
|
||||
public void onEffectsSupressorChanged() {
|
||||
obtainMessage(MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED,
|
||||
mZenController.getEffectsSuppressor()).sendToTarget();
|
||||
}
|
||||
};
|
||||
|
||||
private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.app.IActivityManager;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.ITransientNotification;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.StatusBarManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -56,6 +57,7 @@ import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
@@ -109,6 +111,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
/** {@hide} */
|
||||
public class NotificationManagerService extends SystemService {
|
||||
@@ -173,6 +176,7 @@ public class NotificationManagerService extends SystemService {
|
||||
NotificationRecord mVibrateNotification;
|
||||
|
||||
private final ArraySet<ManagedServiceInfo> mListenersDisablingEffects = new ArraySet<>();
|
||||
private ComponentName mEffectsSuppressor;
|
||||
private int mListenerHints; // right now, all hints are global
|
||||
|
||||
// for enabling and disabling notification pulse behavior
|
||||
@@ -941,6 +945,15 @@ public class NotificationManagerService extends SystemService {
|
||||
scheduleListenerHintsChanged(hints);
|
||||
}
|
||||
|
||||
private void updateEffectsSuppressorLocked() {
|
||||
final ComponentName suppressor = !mListenersDisablingEffects.isEmpty()
|
||||
? mListenersDisablingEffects.valueAt(0).component : null;
|
||||
if (Objects.equals(suppressor, mEffectsSuppressor)) return;
|
||||
mEffectsSuppressor = suppressor;
|
||||
getContext().sendBroadcast(new Intent(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)
|
||||
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
|
||||
}
|
||||
|
||||
private final IBinder mService = new INotificationManager.Stub() {
|
||||
// Toasts
|
||||
// ============================================================================
|
||||
@@ -1299,6 +1312,7 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
mZenModeHelper.requestFromListener(hints);
|
||||
updateListenerHintsLocked();
|
||||
updateEffectsSuppressorLocked();
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
@@ -1384,6 +1398,12 @@ public class NotificationManagerService extends SystemService {
|
||||
|
||||
dumpImpl(pw, DumpFilter.parseFromArguments(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName getEffectsSuppressor() {
|
||||
enforceSystemOrSystemUI("INotificationManager.getEffectsSuppressor");
|
||||
return mEffectsSuppressor;
|
||||
}
|
||||
};
|
||||
|
||||
private String[] getActiveNotificationKeys(INotificationListener token) {
|
||||
|
||||
Reference in New Issue
Block a user