Merge "Prevent apps without DND access from toggling DND via AudioService." into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
af56824e35
@@ -913,10 +913,6 @@ public class NotificationManager
|
||||
* (e.g. via sound & vibration) and is applied globally.
|
||||
* @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
|
||||
* unavailable.
|
||||
*
|
||||
* <p>
|
||||
* Only available if policy access is granted to this package.
|
||||
* See {@link #isNotificationPolicyAccessGranted}.
|
||||
*/
|
||||
public final @InterruptionFilter int getCurrentInterruptionFilter() {
|
||||
final INotificationManager service = getService();
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.annotation.SystemApi;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.ComponentName;
|
||||
@@ -1004,6 +1005,9 @@ public class AudioManager {
|
||||
* according to user settings.
|
||||
* <p>This method has no effect if the device implements a fixed volume policy
|
||||
* as indicated by {@link #isVolumeFixed()}.
|
||||
* * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
|
||||
* unless the app has been granted Do Not Disturb Access.
|
||||
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
|
||||
* @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
|
||||
* {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
|
||||
* @see #getRingerMode()
|
||||
@@ -1025,6 +1029,9 @@ public class AudioManager {
|
||||
* Sets the volume index for a particular stream.
|
||||
* <p>This method has no effect if the device implements a fixed volume policy
|
||||
* as indicated by {@link #isVolumeFixed()}.
|
||||
* <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless
|
||||
* the app has been granted Do Not Disturb Access.
|
||||
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
|
||||
* @param streamType The stream whose volume index should be set.
|
||||
* @param index The volume index to set. See
|
||||
* {@link #getStreamMaxVolume(int)} for the largest valid value.
|
||||
@@ -1069,6 +1076,9 @@ public class AudioManager {
|
||||
* <p>
|
||||
* This method has no effect if the device implements a fixed volume policy
|
||||
* as indicated by {@link #isVolumeFixed()}.
|
||||
* <p>From N onward, stream mute changes that would toggle Do Not Disturb are not allowed unless
|
||||
* the app has been granted Do Not Disturb Access.
|
||||
* See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
|
||||
* <p>
|
||||
* This method was deprecated in API level 22. Prior to API level 22 this
|
||||
* method had significantly different behavior and should be used carefully.
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.app.ActivityManagerInternal;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.bluetooth.BluetoothA2dp;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothClass;
|
||||
@@ -40,6 +41,7 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
@@ -105,9 +107,6 @@ import android.util.MathUtils;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.OrientationEventListener;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import com.android.internal.util.XmlUtils;
|
||||
@@ -557,6 +556,7 @@ public class AudioService extends IAudioService.Stub {
|
||||
|
||||
private static Long mLastDeviceConnectMsgTime = new Long(0);
|
||||
|
||||
private NotificationManager mNm;
|
||||
private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
|
||||
private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
|
||||
private long mLoweredFromNormalToVibrateTime;
|
||||
@@ -751,6 +751,8 @@ public class AudioService extends IAudioService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
sendMsg(mAudioHandler,
|
||||
MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
|
||||
SENDMSG_REPLACE,
|
||||
@@ -1293,7 +1295,7 @@ public class AudioService extends IAudioService.Stub {
|
||||
// Check if the ringer mode handles this adjustment. If it does we don't
|
||||
// need to adjust the volume further.
|
||||
final int result = checkForRingerModeChange(aliasIndex, direction, step,
|
||||
streamState.mIsMuted);
|
||||
streamState.mIsMuted, caller);
|
||||
adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
|
||||
// If suppressing a volume adjustment in silent mode, display the UI hint
|
||||
if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
|
||||
@@ -1309,7 +1311,6 @@ public class AudioService extends IAudioService.Stub {
|
||||
&& (mRingerModeMutedStreams & (1 << AudioSystem.STREAM_MUSIC)) != 0) {
|
||||
adjustVolume = false;
|
||||
}
|
||||
|
||||
int oldIndex = mStreamStates[streamType].getIndex(device);
|
||||
|
||||
if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
|
||||
@@ -1453,10 +1454,7 @@ public class AudioService extends IAudioService.Stub {
|
||||
}
|
||||
};
|
||||
|
||||
private void onSetStreamVolume(int streamType, int index, int flags, int device,
|
||||
String caller) {
|
||||
final int stream = mStreamVolumeAlias[streamType];
|
||||
setStreamVolumeInt(stream, index, device, false, caller);
|
||||
private int getNewRingerMode(int stream, int index, int flags) {
|
||||
// setting volume on ui sounds stream type also controls silent mode
|
||||
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
|
||||
(stream == getUiSoundsStreamType())) {
|
||||
@@ -1464,11 +1462,49 @@ public class AudioService extends IAudioService.Stub {
|
||||
if (index == 0) {
|
||||
newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
|
||||
: mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
|
||||
: AudioManager.RINGER_MODE_NORMAL;
|
||||
: AudioManager.RINGER_MODE_NORMAL;
|
||||
} else {
|
||||
newRingerMode = AudioManager.RINGER_MODE_NORMAL;
|
||||
}
|
||||
setRingerMode(newRingerMode, TAG + ".onSetStreamVolume", false /*external*/);
|
||||
return newRingerMode;
|
||||
}
|
||||
return getRingerModeExternal();
|
||||
}
|
||||
|
||||
private boolean isAndroidNPlus(String caller) {
|
||||
try {
|
||||
final ApplicationInfo applicationInfo =
|
||||
mContext.getPackageManager().getApplicationInfoAsUser(
|
||||
caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
|
||||
if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean wouldToggleZenMode(int newMode) {
|
||||
if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
|
||||
&& newMode != AudioManager.RINGER_MODE_SILENT) {
|
||||
return true;
|
||||
} else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
|
||||
&& newMode == AudioManager.RINGER_MODE_SILENT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void onSetStreamVolume(int streamType, int index, int flags, int device,
|
||||
String caller) {
|
||||
final int stream = mStreamVolumeAlias[streamType];
|
||||
setStreamVolumeInt(stream, index, device, false, caller);
|
||||
// setting volume on ui sounds stream type also controls silent mode
|
||||
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
|
||||
(stream == getUiSoundsStreamType())) {
|
||||
setRingerMode(getNewRingerMode(stream, index, flags),
|
||||
TAG + ".onSetStreamVolume", false /*external*/);
|
||||
}
|
||||
// setting non-zero volume for a muted stream unmutes the stream and vice versa
|
||||
mStreamStates[stream].mute(index == 0);
|
||||
@@ -1509,6 +1545,12 @@ public class AudioService extends IAudioService.Stub {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAndroidNPlus(callingPackage)
|
||||
&& wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
|
||||
&& !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
|
||||
throw new SecurityException("Not allowed to change Do Not Disturb state");
|
||||
}
|
||||
|
||||
synchronized (mSafeMediaVolumeState) {
|
||||
// reset any pending volume command
|
||||
mPendingVolumeCommand = null;
|
||||
@@ -2005,6 +2047,11 @@ public class AudioService extends IAudioService.Stub {
|
||||
}
|
||||
|
||||
public void setRingerModeExternal(int ringerMode, String caller) {
|
||||
if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
|
||||
&& !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
|
||||
throw new SecurityException("Not allowed to change Do Not Disturb state");
|
||||
}
|
||||
|
||||
setRingerMode(ringerMode, caller, true /*external*/);
|
||||
}
|
||||
|
||||
@@ -3328,7 +3375,8 @@ public class AudioService extends IAudioService.Stub {
|
||||
* adjusting volume. If so, this will set the proper ringer mode and volume
|
||||
* indices on the stream states.
|
||||
*/
|
||||
private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
|
||||
private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
|
||||
String caller) {
|
||||
final boolean isTv = mPlatformType == AudioSystem.PLATFORM_TELEVISION;
|
||||
int result = FLAG_ADJUST_VOLUME;
|
||||
int ringerMode = getRingerModeInternal();
|
||||
@@ -3417,6 +3465,11 @@ public class AudioService extends IAudioService.Stub {
|
||||
break;
|
||||
}
|
||||
|
||||
if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
|
||||
&& !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
|
||||
throw new SecurityException("Not allowed to change Do Not Disturb state");
|
||||
}
|
||||
|
||||
setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
|
||||
|
||||
mPrevVolDirection = direction;
|
||||
|
||||
@@ -1807,6 +1807,16 @@ public class NotificationManagerService extends SystemService {
|
||||
message);
|
||||
}
|
||||
|
||||
private void enforceSystemOrSystemUIOrSamePackage(String pkg, String message) {
|
||||
try {
|
||||
checkCallerIsSystemOrSameApp(pkg);
|
||||
} catch (SecurityException e) {
|
||||
getContext().enforceCallingPermission(
|
||||
android.Manifest.permission.STATUS_BAR_SERVICE,
|
||||
message);
|
||||
}
|
||||
}
|
||||
|
||||
private void enforcePolicyAccess(int uid, String method) {
|
||||
if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission(
|
||||
android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
|
||||
@@ -1933,8 +1943,9 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
|
||||
enforceSystemOrSystemUI("request policy access status for another package");
|
||||
public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {;
|
||||
enforceSystemOrSystemUIOrSamePackage(pkg,
|
||||
"request policy access status for another package");
|
||||
return checkPackagePolicyAccess(pkg);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user