Access to Device Vibrator State
Add API to access vibrator state and vibrator state listener.
Bug: 135949568
Change-Id: I96636b432d581cea03a9fc9fecba4c08045f5006
diff --git a/api/system-current.txt b/api/system-current.txt
index 51cab13..aacd453 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -18,6 +18,7 @@
field public static final String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS";
field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER";
field public static final String ACCESS_TV_TUNER = "android.permission.ACCESS_TV_TUNER";
+ field public static final String ACCESS_VIBRATOR_STATE = "android.permission.ACCESS_VIBRATOR_STATE";
field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
@@ -9092,6 +9093,17 @@
@IntDef(flag=true, prefix={"RESTRICTION_"}, value={android.os.UserManager.RESTRICTION_NOT_SET, android.os.UserManager.RESTRICTION_SOURCE_SYSTEM, android.os.UserManager.RESTRICTION_SOURCE_DEVICE_OWNER, android.os.UserManager.RESTRICTION_SOURCE_PROFILE_OWNER}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface UserManager.UserRestrictionSource {
}
+ public abstract class Vibrator {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void addVibratorStateListener(@NonNull android.os.Vibrator.OnVibratorStateChangedListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void addVibratorStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.Vibrator.OnVibratorStateChangedListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public boolean isVibrating();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void removeVibratorStateListener(@NonNull android.os.Vibrator.OnVibratorStateChangedListener);
+ }
+
+ public static interface Vibrator.OnVibratorStateChangedListener {
+ method public void onVibratorStateChanged(boolean);
+ }
+
public class WorkSource implements android.os.Parcelable {
ctor public WorkSource(int);
ctor public WorkSource(int, @NonNull String);
diff --git a/api/test-current.txt b/api/test-current.txt
index e352cb6..6a61398 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2605,6 +2605,17 @@
field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Waveform> CREATOR;
}
+ public abstract class Vibrator {
+ method @RequiresPermission("android.permission.ACCESS_VIBRATOR_STATE") public void addVibratorStateListener(@NonNull android.os.Vibrator.OnVibratorStateChangedListener);
+ method @RequiresPermission("android.permission.ACCESS_VIBRATOR_STATE") public void addVibratorStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.Vibrator.OnVibratorStateChangedListener);
+ method @RequiresPermission("android.permission.ACCESS_VIBRATOR_STATE") public boolean isVibrating();
+ method @RequiresPermission("android.permission.ACCESS_VIBRATOR_STATE") public void removeVibratorStateListener(@NonNull android.os.Vibrator.OnVibratorStateChangedListener);
+ }
+
+ public static interface Vibrator.OnVibratorStateChangedListener {
+ method public void onVibratorStateChanged(boolean);
+ }
+
public class VintfObject {
method public static String[] getHalNamesAndVersions();
method public static String getSepolicyVersion();
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 83f01a5..a7b6516 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,6 +16,7 @@
package android.hardware.input;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
@@ -51,6 +52,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.concurrent.Executor;
import java.util.List;
/**
@@ -1236,6 +1238,32 @@
}
@Override
+ public boolean isVibrating() {
+ throw new UnsupportedOperationException(
+ "isVibrating not supported in InputDeviceVibrator");
+ }
+
+ @Override
+ public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+ throw new UnsupportedOperationException(
+ "addVibratorStateListener not supported in InputDeviceVibrator");
+ }
+
+ @Override
+ public void addVibratorStateListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnVibratorStateChangedListener listener) {
+ throw new UnsupportedOperationException(
+ "addVibratorStateListener not supported in InputDeviceVibrator");
+ }
+
+ @Override
+ public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+ throw new UnsupportedOperationException(
+ "removeVibratorStateListener not supported in InputDeviceVibrator");
+ }
+
+ @Override
public boolean hasAmplitudeControl() {
return false;
}
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index e201e43..84013e7 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -18,11 +18,15 @@
import android.os.VibrationEffect;
import android.os.VibrationAttributes;
+import android.os.IVibratorStateListener;
/** {@hide} */
interface IVibratorService
{
boolean hasVibrator();
+ boolean isVibrating();
+ boolean registerVibratorStateListener(in IVibratorStateListener listener);
+ boolean unregisterVibratorStateListener(in IVibratorStateListener listener);
boolean hasAmplitudeControl();
boolean[] areEffectsSupported(in int[] effectIds);
boolean[] arePrimitivesSupported(in int[] primitiveIds);
diff --git a/core/java/android/os/IVibratorStateListener.aidl b/core/java/android/os/IVibratorStateListener.aidl
new file mode 100644
index 0000000..5ff18a3
--- /dev/null
+++ b/core/java/android/os/IVibratorStateListener.aidl
@@ -0,0 +1,29 @@
+/*
+** Copyright 2020, 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.
+*/
+
+package android.os;
+
+/**
+ * Listener for vibrator state.
+ * {@hide}
+ */
+oneway interface IVibratorStateListener {
+ /**
+ * Called when a vibrator start/stop vibrating.
+ * @param state the vibrator state.
+ */
+ void onVibrating(in boolean vibrating);
+}
\ No newline at end of file
diff --git a/core/java/android/os/NullVibrator.java b/core/java/android/os/NullVibrator.java
index 1d0f9d3..6d8ab6d 100644
--- a/core/java/android/os/NullVibrator.java
+++ b/core/java/android/os/NullVibrator.java
@@ -39,6 +39,11 @@
}
@Override
+ public boolean isVibrating() {
+ return false;
+ }
+
+ @Override
public boolean hasAmplitudeControl() {
return false;
}
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index faf4a36..da20c7f 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -16,11 +16,17 @@
package android.os;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioAttributes;
+import android.os.IVibratorStateListener;
+import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+import java.util.concurrent.Executor;
+import java.util.Objects;
/**
* Vibrator implementation that controls the main system vibrator.
@@ -32,15 +38,22 @@
private final IVibratorService mService;
private final Binder mToken = new Binder();
+ private final Context mContext;
+
+ @GuardedBy("mDelegates")
+ private final ArrayMap<OnVibratorStateChangedListener,
+ OnVibratorStateChangedListenerDelegate> mDelegates = new ArrayMap<>();
@UnsupportedAppUsage
public SystemVibrator() {
+ mContext = null;
mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
}
@UnsupportedAppUsage
public SystemVibrator(Context context) {
super(context);
+ mContext = context;
mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
}
@@ -57,6 +70,126 @@
return false;
}
+ /**
+ * Check whether the vibrator is vibrating.
+ *
+ * @return True if the hardware is vibrating, otherwise false.
+ */
+ @Override
+ public boolean isVibrating() {
+ if (mService == null) {
+ Log.w(TAG, "Failed to vibrate; no vibrator service.");
+ return false;
+ }
+ try {
+ return mService.isVibrating();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return false;
+ }
+
+ private class OnVibratorStateChangedListenerDelegate extends
+ IVibratorStateListener.Stub {
+ private final Executor mExecutor;
+ private final OnVibratorStateChangedListener mListener;
+
+ OnVibratorStateChangedListenerDelegate(@NonNull OnVibratorStateChangedListener listener,
+ @NonNull Executor executor) {
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onVibrating(boolean isVibrating) {
+ mExecutor.execute(() -> mListener.onVibratorStateChanged(isVibrating));
+ }
+ }
+
+ /**
+ * Adds a listener for vibrator state change. If the listener was previously added and not
+ * removed, this call will be ignored.
+ *
+ * @param listener Listener to be added.
+ * @param executor The {@link Executor} on which the listener's callbacks will be executed on.
+ */
+ @Override
+ public void addVibratorStateListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnVibratorStateChangedListener listener) {
+ Objects.requireNonNull(listener);
+ Objects.requireNonNull(executor);
+ if (mService == null) {
+ Log.w(TAG, "Failed to add vibrate state listener; no vibrator service.");
+ return;
+ }
+
+ synchronized (mDelegates) {
+ // If listener is already registered, reject and return.
+ if (mDelegates.containsKey(listener)) {
+ Log.w(TAG, "Listener already registered.");
+ return;
+ }
+ try {
+ final OnVibratorStateChangedListenerDelegate delegate =
+ new OnVibratorStateChangedListenerDelegate(listener, executor);
+ if (!mService.registerVibratorStateListener(delegate)) {
+ Log.w(TAG, "Failed to register vibrate state listener");
+ return;
+ }
+ mDelegates.put(listener, delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread.
+ * If the listener was previously added and not removed, this call will be ignored.
+ *
+ * @param listener listener to be added
+ */
+ @Override
+ public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+ Objects.requireNonNull(listener);
+ if (mContext == null) {
+ Log.w(TAG, "Failed to add vibrate state listener; no vibrator context.");
+ return;
+ }
+ addVibratorStateListener(mContext.getMainExecutor(), listener);
+ }
+
+ /**
+ * Removes the listener for vibrator state changes. If the listener was not previously
+ * registered, this call will do nothing.
+ *
+ * @param listener Listener to be removed.
+ */
+ @Override
+ public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+ Objects.requireNonNull(listener);
+ if (mService == null) {
+ Log.w(TAG, "Failed to remove vibrate state listener; no vibrator service.");
+ return;
+ }
+ synchronized (mDelegates) {
+ // Check if the listener is registered, otherwise will return.
+ if (mDelegates.containsKey(listener)) {
+ final OnVibratorStateChangedListenerDelegate delegate = mDelegates.get(listener);
+ try {
+ if (!mService.unregisterVibratorStateListener(delegate)) {
+ Log.w(TAG, "Failed to unregister vibrate state listener");
+ return;
+ }
+ mDelegates.remove(listener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+
@Override
public boolean hasAmplitudeControl() {
if (mService == null) {
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index f055c60..d4da7a8 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -16,11 +16,14 @@
package android.os;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -29,6 +32,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
/**
* Class that operates the vibrator on the device.
@@ -395,4 +399,78 @@
*/
@RequiresPermission(android.Manifest.permission.VIBRATE)
public abstract void cancel();
+
+ /**
+ * Check whether the vibrator is vibrating.
+ *
+ * @return True if the hardware is vibrating, otherwise false.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
+ public boolean isVibrating() {
+ return false;
+ }
+
+ /**
+ * Listener for when the vibrator state has changed.
+ *
+ * @see #addVibratorStateListener
+ * @see #removeVibratorStateListener
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public interface OnVibratorStateChangedListener {
+ /**
+ * Called when the vibrator state has changed.
+ *
+ * @param isVibrating If true, the vibrator has started vibrating. If false,
+ * it's stopped vibrating.
+ */
+ void onVibratorStateChanged(boolean isVibrating);
+ }
+
+ /**
+ * Adds a listener for vibrator state changes. Callbacks will be executed on the main thread.
+ * If the listener was previously added and not removed, this call will be ignored.
+ *
+ * @param listener listener to be added
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
+ public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+ }
+
+ /**
+ * Adds a listener for vibrator state change. If the listener was previously added and not
+ * removed, this call will be ignored.
+ *
+ * @param listener listener to be added
+ * @param executor executor of listener
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
+ public void addVibratorStateListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnVibratorStateChangedListener listener) {
+ }
+
+ /**
+ * Removes the listener for vibrator state changes. If the listener was not previously
+ * registered, this call will do nothing.
+ *
+ * @param listener listener to be removed
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
+ public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
+ }
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 71a42e4..e961b74 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1912,6 +1912,15 @@
<permission android:name="android.permission.VIBRATE_ALWAYS_ON"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows access to the vibrator state.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_VIBRATOR_STATE"
+ android:label="@string/permdesc_vibrator_state"
+ android:description="@string/permdesc_vibrator_state"
+ android:protectionLevel="signature|privileged" />
+
<!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
from dimming.
<p>Protection level: normal
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 08c8403..93e73b0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1156,6 +1156,8 @@
<string name="permlab_vibrate">control vibration</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_vibrate">Allows the app to control the vibrator.</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_vibrator_state">Allows the app to access the vibrator state.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_callPhone">directly call phone numbers</string>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index f83fb3f..403e0d1 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -378,6 +378,8 @@
<!-- Permission required for ShortcutManagerUsageTest CTS test. -->
<permission name="android.permission.ACCESS_SHORTCUTS"/>
<permission name="android.permission.REBOOT"/>
+ <!-- Permission required for access VIBRATOR_STATE. -->
+ <permission name="android.permission.ACCESS_VIBRATOR_STATE"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 5946f21..772f6e4 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -139,6 +139,7 @@
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
<uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" />
<uses-permission android:name="android.permission.VIBRATE" />
+ <uses-permission android:name="android.permission.ACCESS_VIBRATOR_STATE" />
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
<uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index f7d7d6c..cdde67d 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -42,11 +42,13 @@
import android.os.IBinder;
import android.os.IExternalVibratorService;
import android.os.IVibratorService;
+import android.os.IVibratorStateListener;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.Process;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -166,7 +168,11 @@
private ExternalVibration mCurrentExternalVibration;
private boolean mVibratorUnderExternalControl;
private boolean mLowPowerMode;
+ @GuardedBy("mLock")
private boolean mIsVibrating;
+ @GuardedBy("mLock")
+ private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners =
+ new RemoteCallbackList<>();
private int mHapticFeedbackIntensity;
private int mNotificationIntensity;
private int mRingIntensity;
@@ -522,6 +528,75 @@
}
@Override // Binder call
+ public boolean isVibrating() {
+ if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) {
+ throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission");
+ }
+ synchronized (mLock) {
+ return mIsVibrating;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void notifyStateListenerLocked(IVibratorStateListener listener) {
+ try {
+ listener.onVibrating(mIsVibrating);
+ } catch (RemoteException | RuntimeException e) {
+ Slog.e(TAG, "Vibrator callback failed to call", e);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void notifyStateListenersLocked() {
+ final int length = mVibratorStateListeners.beginBroadcast();
+ try {
+ for (int i = 0; i < length; i++) {
+ final IVibratorStateListener listener =
+ mVibratorStateListeners.getBroadcastItem(i);
+ notifyStateListenerLocked(listener);
+ }
+ } finally {
+ mVibratorStateListeners.finishBroadcast();
+ }
+ }
+
+ @Override // Binder call
+ public boolean registerVibratorStateListener(IVibratorStateListener listener) {
+ if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) {
+ throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission");
+ }
+ synchronized (mLock) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!mVibratorStateListeners.register(listener)) {
+ return false;
+ }
+ // Notify its callback after new client registered.
+ notifyStateListenerLocked(listener);
+ return true;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ @Override // Binder call
+ @GuardedBy("mLock")
+ public boolean unregisterVibratorStateListener(IVibratorStateListener listener) {
+ if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) {
+ throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission");
+ }
+ synchronized (mLock) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mVibratorStateListeners.unregister(listener);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ @Override // Binder call
public boolean hasAmplitudeControl() {
synchronized (mInputDeviceVibrators) {
// Input device vibrators don't support amplitude controls yet, but are still used over
@@ -1373,7 +1448,10 @@
FrameworkStatsLog.write_non_chained(FrameworkStatsLog.VIBRATOR_STATE_CHANGED, uid, null,
FrameworkStatsLog.VIBRATOR_STATE_CHANGED__STATE__ON, millis);
mCurVibUid = uid;
- mIsVibrating = true;
+ if (!mIsVibrating) {
+ mIsVibrating = true;
+ notifyStateListenersLocked();
+ }
} catch (RemoteException e) {
}
}
@@ -1387,7 +1465,10 @@
} catch (RemoteException e) { }
mCurVibUid = -1;
}
- mIsVibrating = false;
+ if (mIsVibrating) {
+ mIsVibrating = false;
+ notifyStateListenersLocked();
+ }
}
private void setVibratorUnderExternalControl(boolean externalControl) {
@@ -1414,6 +1495,8 @@
pw.print(" mCurrentExternalVibration=" + mCurrentExternalVibration);
pw.println(" mVibratorUnderExternalControl=" + mVibratorUnderExternalControl);
pw.println(" mIsVibrating=" + mIsVibrating);
+ pw.println(" mVibratorStateListeners Count=" +
+ mVibratorStateListeners.getRegisteredCallbackCount());
pw.println(" mLowPowerMode=" + mLowPowerMode);
pw.println(" mHapticFeedbackIntensity=" + mHapticFeedbackIntensity);
pw.println(" mNotificationIntensity=" + mNotificationIntensity);