1 /* 2 * Copyright (C) 2020 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.server.vibrator; 18 19 import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY; 20 import static android.os.VibrationAttributes.USAGE_ALARM; 21 import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST; 22 import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK; 23 import static android.os.VibrationAttributes.USAGE_MEDIA; 24 import static android.os.VibrationAttributes.USAGE_NOTIFICATION; 25 import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION; 26 import static android.os.VibrationAttributes.USAGE_RINGTONE; 27 import static android.os.VibrationAttributes.USAGE_TOUCH; 28 import static android.os.VibrationAttributes.USAGE_UNKNOWN; 29 30 import android.annotation.Nullable; 31 import android.app.ActivityManager; 32 import android.app.IUidObserver; 33 import android.content.BroadcastReceiver; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.IntentFilter; 37 import android.content.pm.PackageManagerInternal; 38 import android.content.res.Resources; 39 import android.database.ContentObserver; 40 import android.media.AudioManager; 41 import android.net.Uri; 42 import android.os.Handler; 43 import android.os.PowerManager; 44 import android.os.PowerManagerInternal; 45 import android.os.PowerSaveState; 46 import android.os.Process; 47 import android.os.RemoteException; 48 import android.os.UserHandle; 49 import android.os.VibrationAttributes; 50 import android.os.VibrationEffect; 51 import android.os.Vibrator; 52 import android.os.Vibrator.VibrationIntensity; 53 import android.os.vibrator.VibrationConfig; 54 import android.provider.Settings; 55 import android.util.Slog; 56 import android.util.SparseArray; 57 import android.util.SparseIntArray; 58 import android.util.proto.ProtoOutputStream; 59 import android.view.Display; 60 61 import com.android.internal.annotations.GuardedBy; 62 import com.android.internal.annotations.VisibleForTesting; 63 import com.android.server.LocalServices; 64 import com.android.server.companion.virtual.VirtualDeviceManagerInternal; 65 66 import java.util.ArrayList; 67 import java.util.Arrays; 68 import java.util.HashSet; 69 import java.util.List; 70 import java.util.Set; 71 72 /** Controls all the system settings related to vibration. */ 73 final class VibrationSettings { 74 private static final String TAG = "VibrationSettings"; 75 76 /** 77 * Set of usages allowed for vibrations from background processes. 78 * 79 * <p>Some examples are notification, ringtone or alarm vibrations, that are allowed to vibrate 80 * unexpectedly as they are meant to grab the user's attention. Hardware feedback and physical 81 * emulation are also supported, as the trigger process might still be in the background when 82 * the user interaction wakes the device. 83 */ 84 private static final Set<Integer> BACKGROUND_PROCESS_USAGE_ALLOWLIST = new HashSet<>( 85 Arrays.asList( 86 USAGE_RINGTONE, 87 USAGE_ALARM, 88 USAGE_NOTIFICATION, 89 USAGE_COMMUNICATION_REQUEST, 90 USAGE_HARDWARE_FEEDBACK, 91 USAGE_PHYSICAL_EMULATION)); 92 93 /** 94 * Set of usages allowed for vibrations in battery saver mode (low power). 95 * 96 * <p>Some examples are ringtone or alarm vibrations, that have high priority and should vibrate 97 * even when the device is saving battery. 98 */ 99 private static final Set<Integer> BATTERY_SAVER_USAGE_ALLOWLIST = new HashSet<>( 100 Arrays.asList( 101 USAGE_RINGTONE, 102 USAGE_ALARM, 103 USAGE_COMMUNICATION_REQUEST, 104 USAGE_PHYSICAL_EMULATION, 105 USAGE_HARDWARE_FEEDBACK)); 106 107 /** 108 * Usage allowed for vibrations when {@link Settings.System#VIBRATE_ON} is disabled. 109 * 110 * <p>The only allowed usage is accessibility, which is applied when the user enables talkback. 111 * Other usages that must ignore this setting should use 112 * {@link VibrationAttributes#FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF}. 113 */ 114 private static final int VIBRATE_ON_DISABLED_USAGE_ALLOWED = USAGE_ACCESSIBILITY; 115 116 /** 117 * Set of usages allowed for vibrations from system packages when the screen goes off. 118 * 119 * <p>Some examples are touch and hardware feedback, and physical emulation. When the system is 120 * playing one of these usages during the screen off event then the vibration will not be 121 * cancelled by the service. 122 */ 123 private static final Set<Integer> SYSTEM_VIBRATION_SCREEN_OFF_USAGE_ALLOWLIST = new HashSet<>( 124 Arrays.asList( 125 USAGE_TOUCH, 126 USAGE_PHYSICAL_EMULATION, 127 USAGE_HARDWARE_FEEDBACK)); 128 129 /** 130 * Set of reasons for {@link PowerManager} going to sleep events that allows vibrations to 131 * continue running. 132 * 133 * <p>Some examples are timeout and inattentive, which indicates automatic screen off events. 134 * When a vibration is playing during one of these screen off events then it will not be 135 * cancelled by the service. 136 */ 137 private static final Set<Integer> POWER_MANAGER_SLEEP_REASON_ALLOWLIST = new HashSet<>( 138 Arrays.asList( 139 PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 140 PowerManager.GO_TO_SLEEP_REASON_TIMEOUT)); 141 142 private static final IntentFilter USER_SWITCHED_INTENT_FILTER = 143 new IntentFilter(Intent.ACTION_USER_SWITCHED); 144 private static final IntentFilter INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER = 145 new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); 146 147 /** Listener for changes on vibration settings. */ 148 interface OnVibratorSettingsChanged { 149 /** Callback triggered when any of the vibrator settings change. */ onChange()150 void onChange(); 151 } 152 153 private final Object mLock = new Object(); 154 private final Context mContext; 155 private final String mSystemUiPackage; 156 @VisibleForTesting 157 final SettingsContentObserver mSettingObserver; 158 @VisibleForTesting 159 final UidObserver mUidObserver; 160 @VisibleForTesting 161 final SettingsBroadcastReceiver mSettingChangeReceiver; 162 final VirtualDeviceListener mVirtualDeviceListener; 163 164 @GuardedBy("mLock") 165 private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>(); 166 private final SparseArray<VibrationEffect> mFallbackEffects; 167 168 private final VibrationConfig mVibrationConfig; 169 170 @GuardedBy("mLock") 171 @Nullable 172 private AudioManager mAudioManager; 173 @GuardedBy("mLock") 174 @Nullable 175 private PowerManagerInternal mPowerManagerInternal; 176 177 @GuardedBy("mLock") 178 private boolean mVibrateInputDevices; 179 @GuardedBy("mLock") 180 private SparseIntArray mCurrentVibrationIntensities = new SparseIntArray(); 181 @GuardedBy("mLock") 182 private boolean mBatterySaverMode; 183 @GuardedBy("mLock") 184 private boolean mVibrateOn; 185 @GuardedBy("mLock") 186 private int mRingerMode; 187 VibrationSettings(Context context, Handler handler)188 VibrationSettings(Context context, Handler handler) { 189 this(context, handler, new VibrationConfig(context.getResources())); 190 } 191 192 @VisibleForTesting VibrationSettings(Context context, Handler handler, VibrationConfig config)193 VibrationSettings(Context context, Handler handler, VibrationConfig config) { 194 mContext = context; 195 mVibrationConfig = config; 196 mSettingObserver = new SettingsContentObserver(handler); 197 mUidObserver = new UidObserver(); 198 mSettingChangeReceiver = new SettingsBroadcastReceiver(); 199 mVirtualDeviceListener = new VirtualDeviceListener(); 200 201 mSystemUiPackage = LocalServices.getService(PackageManagerInternal.class) 202 .getSystemUiServiceComponent().getPackageName(); 203 204 VibrationEffect clickEffect = createEffectFromResource( 205 com.android.internal.R.array.config_virtualKeyVibePattern); 206 VibrationEffect doubleClickEffect = createEffectFromResource( 207 com.android.internal.R.array.config_doubleClickVibePattern); 208 VibrationEffect heavyClickEffect = createEffectFromResource( 209 com.android.internal.R.array.config_longPressVibePattern); 210 VibrationEffect tickEffect = createEffectFromResource( 211 com.android.internal.R.array.config_clockTickVibePattern); 212 213 mFallbackEffects = new SparseArray<>(); 214 mFallbackEffects.put(VibrationEffect.EFFECT_CLICK, clickEffect); 215 mFallbackEffects.put(VibrationEffect.EFFECT_DOUBLE_CLICK, doubleClickEffect); 216 mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect); 217 mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, heavyClickEffect); 218 mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK, 219 VibrationEffect.get(VibrationEffect.EFFECT_TICK, false)); 220 221 // Update with current values from settings. 222 update(); 223 } 224 onSystemReady()225 public void onSystemReady() { 226 PowerManagerInternal pm = LocalServices.getService(PowerManagerInternal.class); 227 AudioManager am = mContext.getSystemService(AudioManager.class); 228 int ringerMode = am.getRingerModeInternal(); 229 230 synchronized (mLock) { 231 mPowerManagerInternal = pm; 232 mAudioManager = am; 233 mRingerMode = ringerMode; 234 } 235 236 try { 237 ActivityManager.getService().registerUidObserver(mUidObserver, 238 ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE, 239 ActivityManager.PROCESS_STATE_UNKNOWN, null); 240 } catch (RemoteException e) { 241 // ignored; both services live in system_server 242 } 243 244 pm.registerLowPowerModeObserver( 245 new PowerManagerInternal.LowPowerModeListener() { 246 @Override 247 public int getServiceType() { 248 return PowerManager.ServiceType.VIBRATION; 249 } 250 251 @Override 252 public void onLowPowerModeChanged(PowerSaveState result) { 253 boolean shouldNotifyListeners; 254 synchronized (mLock) { 255 shouldNotifyListeners = result.batterySaverEnabled != mBatterySaverMode; 256 mBatterySaverMode = result.batterySaverEnabled; 257 } 258 if (shouldNotifyListeners) { 259 notifyListeners(); 260 } 261 } 262 }); 263 264 VirtualDeviceManagerInternal vdm = LocalServices.getService( 265 VirtualDeviceManagerInternal.class); 266 if (vdm != null) { 267 vdm.registerVirtualDisplayListener(mVirtualDeviceListener); 268 vdm.registerAppsOnVirtualDeviceListener(mVirtualDeviceListener); 269 } 270 271 registerSettingsChangeReceiver(USER_SWITCHED_INTENT_FILTER); 272 registerSettingsChangeReceiver(INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER); 273 274 // Listen to all settings that might affect the result of Vibrator.getVibrationIntensity. 275 registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES)); 276 registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_ON)); 277 registerSettingsObserver(Settings.System.getUriFor( 278 Settings.System.HAPTIC_FEEDBACK_ENABLED)); 279 registerSettingsObserver( 280 Settings.System.getUriFor(Settings.System.ALARM_VIBRATION_INTENSITY)); 281 registerSettingsObserver( 282 Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_INTENSITY)); 283 registerSettingsObserver( 284 Settings.System.getUriFor(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY)); 285 registerSettingsObserver( 286 Settings.System.getUriFor(Settings.System.MEDIA_VIBRATION_INTENSITY)); 287 registerSettingsObserver( 288 Settings.System.getUriFor(Settings.System.NOTIFICATION_VIBRATION_INTENSITY)); 289 registerSettingsObserver( 290 Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY)); 291 292 // Update with newly loaded services. 293 update(); 294 } 295 296 /** 297 * Add listener to vibrator settings changes. This will trigger the listener with current state 298 * immediately and every time one of the settings change. 299 */ addListener(OnVibratorSettingsChanged listener)300 public void addListener(OnVibratorSettingsChanged listener) { 301 synchronized (mLock) { 302 if (!mListeners.contains(listener)) { 303 mListeners.add(listener); 304 } 305 } 306 } 307 308 /** Remove listener to vibrator settings. */ removeListener(OnVibratorSettingsChanged listener)309 public void removeListener(OnVibratorSettingsChanged listener) { 310 synchronized (mLock) { 311 mListeners.remove(listener); 312 } 313 } 314 315 /** 316 * The duration, in milliseconds, that should be applied to convert vibration effect's 317 * {@link android.os.vibrator.RampSegment} to a {@link android.os.vibrator.StepSegment} on 318 * devices without PWLE support. 319 */ getRampStepDuration()320 public int getRampStepDuration() { 321 return mVibrationConfig.getRampStepDurationMs(); 322 } 323 324 /** 325 * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator 326 * when a vibration is cancelled or finished at non-zero amplitude. 327 */ getRampDownDuration()328 public int getRampDownDuration() { 329 return mVibrationConfig.getRampDownDurationMs(); 330 } 331 332 /** 333 * Return default vibration intensity for given usage. 334 * 335 * @param usageHint one of VibrationAttributes.USAGE_* 336 * @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_* 337 */ getDefaultIntensity(@ibrationAttributes.Usage int usageHint)338 public int getDefaultIntensity(@VibrationAttributes.Usage int usageHint) { 339 return mVibrationConfig.getDefaultVibrationIntensity(usageHint); 340 } 341 342 /** 343 * Return the current vibration intensity set for given usage at the user settings. 344 * 345 * @param usageHint one of VibrationAttributes.USAGE_* 346 * @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_* 347 */ getCurrentIntensity(@ibrationAttributes.Usage int usageHint)348 public int getCurrentIntensity(@VibrationAttributes.Usage int usageHint) { 349 int defaultIntensity = getDefaultIntensity(usageHint); 350 synchronized (mLock) { 351 return mCurrentVibrationIntensities.get(usageHint, defaultIntensity); 352 } 353 } 354 355 /** 356 * Return a {@link VibrationEffect} that should be played if the device do not support given 357 * {@code effectId}. 358 * 359 * @param effectId one of VibrationEffect.EFFECT_* 360 * @return The effect to be played as a fallback 361 */ getFallbackEffect(int effectId)362 public VibrationEffect getFallbackEffect(int effectId) { 363 return mFallbackEffects.get(effectId); 364 } 365 366 /** Return {@code true} if input devices should vibrate instead of this device. */ shouldVibrateInputDevices()367 public boolean shouldVibrateInputDevices() { 368 return mVibrateInputDevices; 369 } 370 371 /** 372 * Check if given vibration should be ignored by the service. 373 * 374 * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored, 375 * null otherwise. 376 */ 377 @Nullable shouldIgnoreVibration(int uid, int displayId, VibrationAttributes attrs)378 public Vibration.Status shouldIgnoreVibration(int uid, int displayId, 379 VibrationAttributes attrs) { 380 final int usage = attrs.getUsage(); 381 synchronized (mLock) { 382 if (!mUidObserver.isUidForeground(uid) 383 && !BACKGROUND_PROCESS_USAGE_ALLOWLIST.contains(usage)) { 384 return Vibration.Status.IGNORED_BACKGROUND; 385 } 386 if (mVirtualDeviceListener.isAppOrDisplayOnAnyVirtualDevice(uid, displayId)) { 387 return Vibration.Status.IGNORED_FROM_VIRTUAL_DEVICE; 388 } 389 390 if (mBatterySaverMode && !BATTERY_SAVER_USAGE_ALLOWLIST.contains(usage)) { 391 return Vibration.Status.IGNORED_FOR_POWER; 392 } 393 394 if (!attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)) { 395 if (!mVibrateOn && (VIBRATE_ON_DISABLED_USAGE_ALLOWED != usage)) { 396 return Vibration.Status.IGNORED_FOR_SETTINGS; 397 } 398 399 if (getCurrentIntensity(usage) == Vibrator.VIBRATION_INTENSITY_OFF) { 400 return Vibration.Status.IGNORED_FOR_SETTINGS; 401 } 402 } 403 404 if (!attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) { 405 if (!shouldVibrateForRingerModeLocked(usage)) { 406 return Vibration.Status.IGNORED_FOR_RINGER_MODE; 407 } 408 } 409 } 410 return null; 411 } 412 413 /** 414 * Check if given vibration should be cancelled by the service when the screen goes off. 415 * 416 * <p>When the system is entering a non-interactive state, we want to cancel vibrations in case 417 * a misbehaving app has abandoned them. However, it may happen that the system is currently 418 * playing haptic feedback as part of the transition. So we don't cancel system vibrations of 419 * usages like touch and hardware feedback, and physical emulation. 420 * 421 * @return true if the vibration should be cancelled when the screen goes off, false otherwise. 422 */ shouldCancelVibrationOnScreenOff(int uid, String opPkg, @VibrationAttributes.Usage int usage, long vibrationStartUptimeMillis)423 public boolean shouldCancelVibrationOnScreenOff(int uid, String opPkg, 424 @VibrationAttributes.Usage int usage, long vibrationStartUptimeMillis) { 425 PowerManagerInternal pm; 426 synchronized (mLock) { 427 pm = mPowerManagerInternal; 428 } 429 if (pm != null) { 430 // The SleepData from PowerManager may refer to a more recent sleep than the broadcast 431 // that triggered this method call. That's ok because only automatic sleeps would be 432 // ignored here and not cancel a vibration, and those are usually triggered by timeout 433 // or inactivity, so it's unlikely that it will override a more active goToSleep reason. 434 PowerManager.SleepData sleepData = pm.getLastGoToSleep(); 435 if ((sleepData.goToSleepUptimeMillis < vibrationStartUptimeMillis) 436 || POWER_MANAGER_SLEEP_REASON_ALLOWLIST.contains(sleepData.goToSleepReason)) { 437 // Ignore screen off events triggered before the vibration started, and all 438 // automatic "go to sleep" events from allowlist. 439 Slog.d(TAG, "Ignoring screen off event triggered at uptime " 440 + sleepData.goToSleepUptimeMillis + " for reason " 441 + PowerManager.sleepReasonToString(sleepData.goToSleepReason)); 442 return false; 443 } 444 } 445 if (!SYSTEM_VIBRATION_SCREEN_OFF_USAGE_ALLOWLIST.contains(usage)) { 446 // Usages not allowed even for system vibrations should always be cancelled. 447 return true; 448 } 449 // Only allow vibrations from System packages to continue vibrating when the screen goes off 450 return uid != Process.SYSTEM_UID && uid != 0 && !mSystemUiPackage.equals(opPkg); 451 } 452 453 /** 454 * Return {@code true} if the device should vibrate for current ringer mode. 455 * 456 * <p>This checks the current {@link AudioManager#getRingerModeInternal()} against user settings 457 * for ringtone and notification usages. All other usages are allowed by this method. 458 */ 459 @GuardedBy("mLock") shouldVibrateForRingerModeLocked(@ibrationAttributes.Usage int usageHint)460 private boolean shouldVibrateForRingerModeLocked(@VibrationAttributes.Usage int usageHint) { 461 if ((usageHint != USAGE_RINGTONE) && (usageHint != USAGE_NOTIFICATION)) { 462 // Only ringtone and notification vibrations are disabled when phone is on silent mode. 463 return true; 464 } 465 return mRingerMode != AudioManager.RINGER_MODE_SILENT; 466 } 467 468 /** Update all cached settings and triggers registered listeners. */ update()469 void update() { 470 updateSettings(); 471 updateRingerMode(); 472 notifyListeners(); 473 } 474 updateSettings()475 private void updateSettings() { 476 synchronized (mLock) { 477 mVibrateInputDevices = loadSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0; 478 mVibrateOn = loadSystemSetting(Settings.System.VIBRATE_ON, 1) > 0; 479 480 int alarmIntensity = toIntensity( 481 loadSystemSetting(Settings.System.ALARM_VIBRATION_INTENSITY, -1), 482 getDefaultIntensity(USAGE_ALARM)); 483 int defaultHapticFeedbackIntensity = getDefaultIntensity(USAGE_TOUCH); 484 int hapticFeedbackIntensity = toIntensity( 485 loadSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, -1), 486 defaultHapticFeedbackIntensity); 487 int positiveHapticFeedbackIntensity = toPositiveIntensity( 488 hapticFeedbackIntensity, defaultHapticFeedbackIntensity); 489 int hardwareFeedbackIntensity = toIntensity( 490 loadSystemSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, -1), 491 positiveHapticFeedbackIntensity); 492 int mediaIntensity = toIntensity( 493 loadSystemSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, -1), 494 getDefaultIntensity(USAGE_MEDIA)); 495 int defaultNotificationIntensity = getDefaultIntensity(USAGE_NOTIFICATION); 496 int notificationIntensity = toIntensity( 497 loadSystemSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, -1), 498 defaultNotificationIntensity); 499 int positiveNotificationIntensity = toPositiveIntensity( 500 notificationIntensity, defaultNotificationIntensity); 501 int ringIntensity = toIntensity( 502 loadSystemSetting(Settings.System.RING_VIBRATION_INTENSITY, -1), 503 getDefaultIntensity(USAGE_RINGTONE)); 504 505 mCurrentVibrationIntensities.clear(); 506 mCurrentVibrationIntensities.put(USAGE_ALARM, alarmIntensity); 507 mCurrentVibrationIntensities.put(USAGE_NOTIFICATION, notificationIntensity); 508 mCurrentVibrationIntensities.put(USAGE_MEDIA, mediaIntensity); 509 mCurrentVibrationIntensities.put(USAGE_UNKNOWN, mediaIntensity); 510 mCurrentVibrationIntensities.put(USAGE_RINGTONE, ringIntensity); 511 512 // Communication request is not disabled by the notification setting. 513 mCurrentVibrationIntensities.put(USAGE_COMMUNICATION_REQUEST, 514 positiveNotificationIntensity); 515 516 // This should adapt the behavior preceding the introduction of this new setting 517 // key, which is to apply HAPTIC_FEEDBACK_INTENSITY, unless it's disabled. 518 mCurrentVibrationIntensities.put(USAGE_HARDWARE_FEEDBACK, hardwareFeedbackIntensity); 519 mCurrentVibrationIntensities.put(USAGE_PHYSICAL_EMULATION, hardwareFeedbackIntensity); 520 521 if (!loadBooleanSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)) { 522 // Make sure deprecated boolean setting still disables touch vibrations. 523 mCurrentVibrationIntensities.put(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_OFF); 524 } else { 525 mCurrentVibrationIntensities.put(USAGE_TOUCH, hapticFeedbackIntensity); 526 } 527 528 // A11y is not disabled by any haptic feedback setting. 529 mCurrentVibrationIntensities.put(USAGE_ACCESSIBILITY, positiveHapticFeedbackIntensity); 530 } 531 } 532 updateRingerMode()533 private void updateRingerMode() { 534 synchronized (mLock) { 535 // If audio manager was not loaded yet then assume most restrictive mode. 536 // This will be loaded again as soon as the audio manager is loaded in onSystemReady. 537 mRingerMode = (mAudioManager == null) 538 ? AudioManager.RINGER_MODE_SILENT 539 : mAudioManager.getRingerModeInternal(); 540 } 541 } 542 543 @Override toString()544 public String toString() { 545 synchronized (mLock) { 546 StringBuilder vibrationIntensitiesString = new StringBuilder("{"); 547 for (int i = 0; i < mCurrentVibrationIntensities.size(); i++) { 548 int usage = mCurrentVibrationIntensities.keyAt(i); 549 int intensity = mCurrentVibrationIntensities.valueAt(i); 550 vibrationIntensitiesString.append(VibrationAttributes.usageToString(usage)) 551 .append("=(").append(intensityToString(intensity)) 552 .append(",default:").append(intensityToString(getDefaultIntensity(usage))) 553 .append("), "); 554 } 555 vibrationIntensitiesString.append('}'); 556 return "VibrationSettings{" 557 + "mVibratorConfig=" + mVibrationConfig 558 + ", mVibrateInputDevices=" + mVibrateInputDevices 559 + ", mBatterySaverMode=" + mBatterySaverMode 560 + ", mVibrateOn=" + mVibrateOn 561 + ", mVibrationIntensities=" + vibrationIntensitiesString 562 + ", mProcStatesCache=" + mUidObserver.mProcStatesCache 563 + '}'; 564 } 565 } 566 567 /** Write current settings into given {@link ProtoOutputStream}. */ dumpProto(ProtoOutputStream proto)568 public void dumpProto(ProtoOutputStream proto) { 569 synchronized (mLock) { 570 proto.write(VibratorManagerServiceDumpProto.VIBRATE_ON, mVibrateOn); 571 proto.write(VibratorManagerServiceDumpProto.LOW_POWER_MODE, mBatterySaverMode); 572 proto.write(VibratorManagerServiceDumpProto.ALARM_INTENSITY, 573 getCurrentIntensity(USAGE_ALARM)); 574 proto.write(VibratorManagerServiceDumpProto.ALARM_DEFAULT_INTENSITY, 575 getDefaultIntensity(USAGE_ALARM)); 576 proto.write(VibratorManagerServiceDumpProto.HARDWARE_FEEDBACK_INTENSITY, 577 getCurrentIntensity(USAGE_HARDWARE_FEEDBACK)); 578 proto.write(VibratorManagerServiceDumpProto.HARDWARE_FEEDBACK_DEFAULT_INTENSITY, 579 getDefaultIntensity(USAGE_HARDWARE_FEEDBACK)); 580 proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY, 581 getCurrentIntensity(USAGE_TOUCH)); 582 proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY, 583 getDefaultIntensity(USAGE_TOUCH)); 584 proto.write(VibratorManagerServiceDumpProto.MEDIA_INTENSITY, 585 getCurrentIntensity(USAGE_MEDIA)); 586 proto.write(VibratorManagerServiceDumpProto.MEDIA_DEFAULT_INTENSITY, 587 getDefaultIntensity(USAGE_MEDIA)); 588 proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_INTENSITY, 589 getCurrentIntensity(USAGE_NOTIFICATION)); 590 proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_DEFAULT_INTENSITY, 591 getDefaultIntensity(USAGE_NOTIFICATION)); 592 proto.write(VibratorManagerServiceDumpProto.RING_INTENSITY, 593 getCurrentIntensity(USAGE_RINGTONE)); 594 proto.write(VibratorManagerServiceDumpProto.RING_DEFAULT_INTENSITY, 595 getDefaultIntensity(USAGE_RINGTONE)); 596 } 597 } 598 notifyListeners()599 private void notifyListeners() { 600 List<OnVibratorSettingsChanged> currentListeners; 601 synchronized (mLock) { 602 currentListeners = new ArrayList<>(mListeners); 603 } 604 for (OnVibratorSettingsChanged listener : currentListeners) { 605 listener.onChange(); 606 } 607 } 608 intensityToString(int intensity)609 private static String intensityToString(int intensity) { 610 switch (intensity) { 611 case Vibrator.VIBRATION_INTENSITY_OFF: 612 return "OFF"; 613 case Vibrator.VIBRATION_INTENSITY_LOW: 614 return "LOW"; 615 case Vibrator.VIBRATION_INTENSITY_MEDIUM: 616 return "MEDIUM"; 617 case Vibrator.VIBRATION_INTENSITY_HIGH: 618 return "HIGH"; 619 default: 620 return "UNKNOWN INTENSITY " + intensity; 621 } 622 } 623 624 @VibrationIntensity toPositiveIntensity(int value, @VibrationIntensity int defaultValue)625 private int toPositiveIntensity(int value, @VibrationIntensity int defaultValue) { 626 if (value == Vibrator.VIBRATION_INTENSITY_OFF) { 627 return defaultValue; 628 } 629 return toIntensity(value, defaultValue); 630 } 631 632 @VibrationIntensity toIntensity(int value, @VibrationIntensity int defaultValue)633 private int toIntensity(int value, @VibrationIntensity int defaultValue) { 634 if ((value < Vibrator.VIBRATION_INTENSITY_OFF) 635 || (value > Vibrator.VIBRATION_INTENSITY_HIGH)) { 636 return defaultValue; 637 } 638 return value; 639 } 640 loadBooleanSetting(String settingKey)641 private boolean loadBooleanSetting(String settingKey) { 642 return Settings.System.getIntForUser(mContext.getContentResolver(), 643 settingKey, 0, UserHandle.USER_CURRENT) != 0; 644 } 645 loadSystemSetting(String settingName, int defaultValue)646 private int loadSystemSetting(String settingName, int defaultValue) { 647 return Settings.System.getIntForUser(mContext.getContentResolver(), 648 settingName, defaultValue, UserHandle.USER_CURRENT); 649 } 650 registerSettingsObserver(Uri settingUri)651 private void registerSettingsObserver(Uri settingUri) { 652 mContext.getContentResolver().registerContentObserver( 653 settingUri, /* notifyForDescendants= */ true, mSettingObserver, 654 UserHandle.USER_ALL); 655 } 656 registerSettingsChangeReceiver(IntentFilter intentFilter)657 private void registerSettingsChangeReceiver(IntentFilter intentFilter) { 658 mContext.registerReceiver(mSettingChangeReceiver, intentFilter); 659 } 660 661 @Nullable createEffectFromResource(int resId)662 private VibrationEffect createEffectFromResource(int resId) { 663 long[] timings = getLongIntArray(mContext.getResources(), resId); 664 return createEffectFromTimings(timings); 665 } 666 667 @Nullable createEffectFromTimings(@ullable long[] timings)668 private static VibrationEffect createEffectFromTimings(@Nullable long[] timings) { 669 if (timings == null || timings.length == 0) { 670 return null; 671 } else if (timings.length == 1) { 672 return VibrationEffect.createOneShot(timings[0], VibrationEffect.DEFAULT_AMPLITUDE); 673 } else { 674 return VibrationEffect.createWaveform(timings, -1); 675 } 676 } 677 getLongIntArray(Resources r, int resid)678 private static long[] getLongIntArray(Resources r, int resid) { 679 int[] ar = r.getIntArray(resid); 680 if (ar == null) { 681 return null; 682 } 683 long[] out = new long[ar.length]; 684 for (int i = 0; i < ar.length; i++) { 685 out[i] = ar[i]; 686 } 687 return out; 688 } 689 690 /** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */ 691 @VisibleForTesting 692 final class SettingsContentObserver extends ContentObserver { SettingsContentObserver(Handler handler)693 SettingsContentObserver(Handler handler) { 694 super(handler); 695 } 696 697 @Override onChange(boolean selfChange)698 public void onChange(boolean selfChange) { 699 updateSettings(); 700 notifyListeners(); 701 } 702 } 703 704 /** 705 * Implementation of {@link BroadcastReceiver} to update settings on current user or ringer 706 * mode change. 707 */ 708 @VisibleForTesting 709 final class SettingsBroadcastReceiver extends BroadcastReceiver { 710 @Override onReceive(Context context, Intent intent)711 public void onReceive(Context context, Intent intent) { 712 String action = intent.getAction(); 713 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 714 // Reload all settings, as they are user-based. 715 update(); 716 } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { 717 updateRingerMode(); 718 notifyListeners(); 719 } 720 } 721 } 722 723 /** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */ 724 @VisibleForTesting 725 final class UidObserver extends IUidObserver.Stub { 726 private final SparseArray<Integer> mProcStatesCache = new SparseArray<>(); 727 isUidForeground(int uid)728 public boolean isUidForeground(int uid) { 729 return mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) 730 <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; 731 } 732 733 @Override onUidGone(int uid, boolean disabled)734 public void onUidGone(int uid, boolean disabled) { 735 mProcStatesCache.delete(uid); 736 } 737 738 @Override onUidActive(int uid)739 public void onUidActive(int uid) { 740 } 741 742 @Override onUidIdle(int uid, boolean disabled)743 public void onUidIdle(int uid, boolean disabled) { 744 } 745 746 @Override onUidStateChanged(int uid, int procState, long procStateSeq, int capability)747 public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { 748 mProcStatesCache.put(uid, procState); 749 } 750 751 @Override onUidCachedChanged(int uid, boolean cached)752 public void onUidCachedChanged(int uid, boolean cached) { 753 } 754 755 @Override onUidProcAdjChanged(int uid)756 public void onUidProcAdjChanged(int uid) { 757 } 758 } 759 760 /** 761 * Implementation of Virtual Device listeners for the changes of virtual displays and of apps 762 * running on any virtual device. 763 */ 764 final class VirtualDeviceListener implements 765 VirtualDeviceManagerInternal.VirtualDisplayListener, 766 VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener { 767 @GuardedBy("mLock") 768 private final Set<Integer> mVirtualDisplays = new HashSet<>(); 769 @GuardedBy("mLock") 770 private final Set<Integer> mAppsOnVirtualDevice = new HashSet<>(); 771 772 773 @Override onVirtualDisplayCreated(int displayId)774 public void onVirtualDisplayCreated(int displayId) { 775 synchronized (mLock) { 776 mVirtualDisplays.add(displayId); 777 } 778 } 779 780 @Override onVirtualDisplayRemoved(int displayId)781 public void onVirtualDisplayRemoved(int displayId) { 782 synchronized (mLock) { 783 mVirtualDisplays.remove(displayId); 784 } 785 } 786 787 788 @Override onAppsOnAnyVirtualDeviceChanged(Set<Integer> allRunningUids)789 public void onAppsOnAnyVirtualDeviceChanged(Set<Integer> allRunningUids) { 790 synchronized (mLock) { 791 mAppsOnVirtualDevice.clear(); 792 mAppsOnVirtualDevice.addAll(allRunningUids); 793 } 794 } 795 796 /** 797 * @param uid: uid of the calling app. 798 * @param displayId: the id of a Display. 799 * @return Returns true if: 800 * <ul> 801 * <li> the displayId is valid, and it's owned by a virtual device.</li> 802 * <li> the displayId is invalid, and the calling app (uid) is running on a virtual 803 * device.</li> 804 * </ul> 805 */ isAppOrDisplayOnAnyVirtualDevice(int uid, int displayId)806 public boolean isAppOrDisplayOnAnyVirtualDevice(int uid, int displayId) { 807 if (displayId == Display.DEFAULT_DISPLAY) { 808 // The default display is the primary physical display on the phone. 809 return false; 810 } 811 812 synchronized (mLock) { 813 if (displayId == Display.INVALID_DISPLAY) { 814 // There is no Display object associated with the Context of calling 815 // {@link SystemVibratorManager}, checking the calling UID instead. 816 return mAppsOnVirtualDevice.contains(uid); 817 } else { 818 // Other valid display IDs representing valid logical displays will be 819 // checked 820 // against the active virtual displays set built with the registered 821 // {@link VirtualDisplayListener}. 822 return mVirtualDisplays.contains(displayId); 823 } 824 } 825 } 826 827 } 828 } 829