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