通过adb可以查看系统服务
adb shell
shell@CHT80A:/ $ service list
Found 105 services:
0 media.widi.uibc: [intel.widi.IUibcServer]
1 oemtelephony: [com.intel.internal.telephony.OemTelephony.IOemTelephony]
2 phone: [com.android.internal.telephony.ITelephony]
3 isms: [com.android.internal.telephony.ISms]
4 iphonesubinfo: [com.android.internal.telephony.IPhoneSubInfo]
5 simphonebook: [com.android.internal.telephony.IIccPhoneBook]
6 isub: [com.android.internal.telephony.ISub]
7 telecom: [com.android.internal.telecom.ITelecomService]
8 imms: [com.android.internal.telephony.IMms]
9 media_projection: [android.media.projection.IMediaProjectionManager]
10 launcherapps: [android.content.pm.ILauncherApps]
......
看vibrator: [android.os.IVibratorService]这个服务。
/frameworks/base/core/java/android/content/Context.java
/**
* Use with {@link #getSystemService} to retrieve a {@link
* android.os.Vibrator} for interacting with the vibration hardware.
*
* @see #getSystemService
* @see android.os.Vibrator
*/
public static final String VIBRATOR_SERVICE = "vibrator";
/frameworks/base/core/java/android/app/ContextImpl.java
//在静态块中注册这个服务
registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new SystemVibrator(ctx);
}});
frameworks/base/services/java/com/android/server/SystemServer.java
将vibrate Service 加入到SystemServer 启动进程。
在 startOtherServices() 函数 的try模块中增加以下代码
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
/frameworks/base/core/java/android/os/IVibratorService.aidl 通过aidl通信
interface IVibratorService
{
boolean hasVibrator();
void vibrate(int uid, String opPkg, long milliseconds, int usageHint, IBinder token);
void vibratePattern(int uid, String opPkg, in long[] pattern, int repeat, int usageHint, IBinder token);
void cancelVibrate(IBinder token);
}
编译要加入到make file 中:/frameworks/base/Android.mk:207: core/java/android/os/IVibratorService.aidl
/frameworks/base/services/core/java/com/android/server/VibratorService.java 服务本身,实现IVibratorService中定义的接口
public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
native static boolean vibratorExists();
@Override // Binder call
public boolean hasVibrator() {
return doVibratorExists();
}
private boolean doVibratorExists() {
// For now, we choose to ignore the presence of input devices that have vibrators
// when reporting whether the device has a vibrator. Applications often use this
// information to decide whether to enable certain features so they expect the
// result of hasVibrator() to be constant. For now, just report whether
// the device has a built-in vibrator.
//synchronized (mInputDeviceVibrators) {
// return !mInputDeviceVibrators.isEmpty() || vibratorExists();
//}
return vibratorExists();
}
}
通过JNI与C++交互:
/frameworks/base/services/core/jni/com_android_server_VibratorService.cpp
static jboolean vibratorExists(JNIEnv, jobject)
{
if (gVibraModule && gVibraDevice) {
return JNI_TRUE;
} else {
return JNI_FALSE;
}
}
编译的时候:
./frameworks/base/services/core/jni/Android.mk:26: $(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp
Manager如下:
/frameworks/base/core/java/android/os/Vibrator.java
public abstract class Vibrator {
private final String mPackageName;
/**
* @hide to prevent subclassing from outside of the framework
*/
public Vibrator() {
mPackageName = ActivityThread.currentPackageName();
}
/**
* @hide to prevent subclassing from outside of the framework
*/
protected Vibrator(Context context) {
mPackageName = context.getOpPackageName();
}
/**
* Check whether the hardware has a vibrator.
*
* @return True if the hardware has a vibrator, else false.
*/
public abstract boolean hasVibrator();
/**
* Vibrate constantly for the specified period of time.
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#VIBRATE}.
*
* @param milliseconds The number of milliseconds to vibrate.
*/
public void vibrate(long milliseconds) {
vibrate(milliseconds, null);
}
/**
* Vibrate constantly for the specified period of time.
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#VIBRATE}.
*
* @param milliseconds The number of milliseconds to vibrate.
* @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
* specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
* {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
* vibrations associated with incoming calls.
*/
public void vibrate(long milliseconds, AudioAttributes attributes) {
vibrate(Process.myUid(), mPackageName, milliseconds, attributes);
}
/**
* Vibrate with a given pattern.
*
* <p>
* Pass in an array of ints that are the durations for which to turn on or off
* the vibrator in milliseconds. The first value indicates the number of milliseconds
* to wait before turning the vibrator on. The next value indicates the number of milliseconds
* for which to keep the vibrator on before turning it off. Subsequent values alternate
* between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
* </p><p>
* To cause the pattern to repeat, pass the index into the pattern array at which
* to start the repeat, or -1 to disable repeating.
* </p>
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#VIBRATE}.
*
* @param pattern an array of longs of times for which to turn the vibrator on or off.
* @param repeat the index into pattern at which to repeat, or -1 if
* you don't want to repeat.
*/
public void vibrate(long[] pattern, int repeat) {
vibrate(pattern, repeat, null);
}
/**
* Vibrate with a given pattern.
*
* <p>
* Pass in an array of ints that are the durations for which to turn on or off
* the vibrator in milliseconds. The first value indicates the number of milliseconds
* to wait before turning the vibrator on. The next value indicates the number of milliseconds
* for which to keep the vibrator on before turning it off. Subsequent values alternate
* between durations in milliseconds to turn the vibrator off or to turn the vibrator on.
* </p><p>
* To cause the pattern to repeat, pass the index into the pattern array at which
* to start the repeat, or -1 to disable repeating.
* </p>
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#VIBRATE}.
*
* @param pattern an array of longs of times for which to turn the vibrator on or off.
* @param repeat the index into pattern at which to repeat, or -1 if
* you don't want to repeat.
* @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
* specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
* {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
* vibrations associated with incoming calls.
*/
public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) {
vibrate(Process.myUid(), mPackageName, pattern, repeat, attributes);
}
/**
* @hide
* Like {@link #vibrate(long, AudioAttributes)}, but allowing the caller to specify that
* the vibration is owned by someone else.
*/
public abstract void vibrate(int uid, String opPkg, long milliseconds,
AudioAttributes attributes);
/**
* @hide
* Like {@link #vibrate(long[], int, AudioAttributes)}, but allowing the caller to specify that
* the vibration is owned by someone else.
*/
public abstract void vibrate(int uid, String opPkg, long[] pattern, int repeat,
AudioAttributes attributes);
/**
* Turn the vibrator off.
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#VIBRATE}.
*/
public abstract void cancel();
}
/frameworks/base/core/java/android/os/SystemVibrator.java
public class SystemVibrator extends Vibrator {
private static final String TAG = "Vibrator";
private final IVibratorService mService;
private final Binder mToken = new Binder();
public SystemVibrator() {
mService = IVibratorService.Stub.asInterface(
ServiceManager.getService("vibrator"));
}
public SystemVibrator(Context context) {
super(context);
mService = IVibratorService.Stub.asInterface(
ServiceManager.getService("vibrator"));
}
@Override
public boolean hasVibrator() {
if (mService == null) {
Log.w(TAG, "Failed to vibrate; no vibrator service.");
return false;
}
try {
return mService.hasVibrator();
} catch (RemoteException e) {
}
return false;
}
/**
* @hide
*/
@Override
public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {
if (mService == null) {
Log.w(TAG, "Failed to vibrate; no vibrator service.");
return;
}
try {
mService.vibrate(uid, opPkg, milliseconds, usageForAttributes(attributes), mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
}
/**
* @hide
*/
@Override
public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
AudioAttributes attributes) {
if (mService == null) {
Log.w(TAG, "Failed to vibrate; no vibrator service.");
return;
}
// catch this here because the server will do nothing. pattern may
// not be null, let that be checked, because the server will drop it
// anyway
if (repeat < pattern.length) {
try {
mService.vibratePattern(uid, opPkg, pattern, repeat, usageForAttributes(attributes),
mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
} else {
throw new ArrayIndexOutOfBoundsException();
}
}
private static int usageForAttributes(AudioAttributes attributes) {
return attributes != null ? attributes.getUsage() : AudioAttributes.USAGE_UNKNOWN;
}
@Override
public void cancel() {
if (mService == null) {
return;
}
try {
mService.cancelVibrate(mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to cancel vibration.", e);
}
}
}
应用层去调用
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(sVibratePattern, 0, VIBRATION_ATTRIBUTES);
还需要天机SE权限