Merge "Display notification effects suppressor in the volume panel." into lmp-dev

This commit is contained in:
John Spurlock
2014-08-22 22:09:34 +00:00
committed by Android (Google) Code Review
9 changed files with 173 additions and 8 deletions

View File

@@ -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);

View File

@@ -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;
}

View 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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() {}
}
}

View File

@@ -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();
}
}
};

View File

@@ -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() {

View File

@@ -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) {