Android & Vibrator

Android振动器 android.os.Vibrator

1.Java层 frameworks/base/core/java/android/os/Vibrator.java

  Vibrator类的实力可以通过 getSystemService(VIBRATOR_SERVICE)获得实例。
 两个方法:public abstract void vibrate(long milliseconds);/public abstract void vibrate(long[] pattern, int repeat);
               public abstract void cancel();
查找路径:Activity.java-->ContextThemeWrapper.java-->ContextWrapper.java-->Context.java,getSystemService是Context.java类的抽象方法。其实现的类是ContextImpl.java,其中有段静态代码,注册所有context下能使用到的service。
  registerService(VIBRATOR_SERVICE, new ServiceFetcher() { 
                 public Object createService(ContextImpl ctx) { 
                     return new SystemVibrator(); 
                 }});
Vibrator类只是个抽象类,具体实现的代码位于 SystemVibrator。位于\frameworks\base\core\java\android\os\目录下。两个方法的实现代码如下:

 @Override
     public void vibrate(long milliseconds) { 
         if (mService == null) { 
             Log.w(TAG, "Failed to vibrate; no vibrator service."); 

             return; 
         } 
        try { 
             mService.vibrate(milliseconds, mToken); 
         } catch (RemoteException e) { 
            Log.w(TAG, "Failed to vibrate.", e); 
         } 
     }

 @Override
     public void vibrate(long[] pattern, int repeat) { 
         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(pattern, repeat, mToken); 
             } catch (RemoteException e) { 
                 Log.w(TAG, "Failed to vibrate.", e); 
            } 
         } else { 
             throw new ArrayIndexOutOfBoundsException(); 
         } 
     }
还有


 @Override
    public void cancel() { 
         if (mService == null) { 
            return; 
         } 
         try { 
             mService.cancelVibrate(mToken); 
         } catch (RemoteException e) { 
            Log.w(TAG, "Failed to cancel vibration.", e); 
         } 
     }
  查看mService,其声明代码如下:
 

 mService = IVibratorService.Stub.asInterface( 
                 ServiceManager.getService("vibrator"));

 /*这里跟Binder机制有关。。。断片ing*/
 

定义是private final IVibratorService mService;

所以找找这个IVibratorService吧。
查找下\frameworks\base\core\java\android\os\IVibratorService.aidl,这里定义了接口。

 package android.os; 
   
 /** {@hide} */
interface IVibratorService 
 { 
     boolean hasVibrator(); 
     void vibrate(long milliseconds, IBinder token); 
    void vibratePattern(in long[] pattern, int repeat, IBinder token); 
     void cancelVibrate(IBinder token); 
 }

 具体的实现位于VibratorService.java。(\frameworks\base\services\java\com\android\server\)

  public class VibratorService extends IVibratorService.Stub

 然后是vibrate方法:


 public void vibrate(long milliseconds, IBinder token) { 
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 
                 != PackageManager.PERMISSION_GRANTED) { 
             throw new SecurityException("Requires VIBRATE permission"); 
         } 
         int uid = Binder.getCallingUid(); 
         // We're running in the system server so we cannot crash. Check for a 

         // timeout of 0 or negative. This will ensure that a vibration has 
         // either a timeout of > 0 or a non-null pattern. 
         if (milliseconds <= 0 || (mCurrentVibration != null
                 && mCurrentVibration.hasLongerTimeout(milliseconds))) { 
            // Ignore this vibration since the current vibration will play for 
            // longer than milliseconds. 
             return; 
         } 
  
         Vibration vib = new Vibration(token, milliseconds, uid); 
         synchronized (mVibrations) { 
             removeVibrationLocked(token); 
             doCancelVibrateLocked(); 
             mCurrentVibration = vib; 
            startVibrationLocked(vib); 
         } 
     }
         然后是startVibrationLocked方法。

 private void startVibrationLocked(final Vibration vib) { 
         if (vib.mTimeout != 0) { 
            doVibratorOn(vib.mTimeout); 
             mH.postDelayed(mVibrationRunnable, vib.mTimeout); 
         } else { 
             // mThread better be null here. doCancelVibrate should always be 
             // called before startNextVibrationLocked or startVibrationLocked. 
             mThread = new VibrateThread(vib); 
             mThread.start(); 
        } 
     }
       翻看了VibrateThread的run方法,最终还是调用了doVibratorOn方法。
       所以看doVibratorOn方法:

 private void doVibratorOn(long millis) { 
         synchronized (mInputDeviceVibrators) { 
             final int vibratorCount = mInputDeviceVibrators.size(); 
             if (vibratorCount != 0) { 
                for (int i = 0; i < vibratorCount; i++) { 
                     mInputDeviceVibrators.get(i).vibrate(millis); 
                 } 
             } else { 
                 vibratorOn(millis); 
             } 
         } 
     }
          |---------首先是vibratorCount这个,假如这个不为0,那么是调用 Vibrator的vibrate方法。。断片:vibratorCount这个表示什么意义!
          mInputDeviceVibrators的声明如下:

 private final ArrayList mInputDeviceVibrators = new ArrayList();
     里面的每一个元素都是一个Vibrator的实力,Vibrator是个抽闲类。
     mInputDeviceVibrators会在VibratorService.java中的updateInputDeviceVibrators方法添加元素:

 mInputDeviceVibrators.clear(); 
 if (mVibrateInputDevicesSetting) { 
     int[] ids = mIm.getInputDeviceIds(); 
    for (int i = 0; i < ids.length; i++) { 
         InputDevice device = mIm.getInputDevice(ids[i]); 
         Vibrator vibrator = device.getVibrator(); 
         if (vibrator.hasVibrator()) { 
             mInputDeviceVibrators.add(vibrator); 
         } 
     } 
 }
      查看InputDevice类的getVibrator


 public Vibrator getVibrator() { 
         synchronized (mMotionRanges) { 
            if (mVibrator == null) { 
                 if (mHasVibrator) { 
                     mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId); 
                 } else { 
                     mVibrator = NullVibrator.getInstance(); 
                 } 
             } 
            return mVibrator; 
         } 
     }
所以数组 mInputDeviceVibrators中的元素有两种,都是抽象类Vibrator的子类:
        一种是InputDeviceVibrator类,一种就是NullVibrator类了。
      先说说InputDeviceVibrator类。

 private final class InputDeviceVibrator extends Vibrator { 
         private final int mDeviceId; 
         private final Binder mToken; 
   
         public InputDeviceVibrator(int deviceId) { 
             mDeviceId = deviceId; 
             mToken = new Binder(); 
         } 
   
         @Override
        public boolean hasVibrator() { 
            return true; 
         } 
   
         @Override
         public void vibrate(long milliseconds) { 
             vibrate(new long[] { 0, milliseconds}, -1); 
         } 
   
         @Override
         public void vibrate(long[] pattern, int repeat) { 
             if (repeat >= pattern.length) { 
                throw new ArrayIndexOutOfBoundsException(); 
            } 
            try { 
                mIm.vibrate(mDeviceId, pattern, repeat, mToken); 
            } catch (RemoteException ex) { 
                 Log.w(TAG, "Failed to vibrate.", ex); 
             } 
         } 
   
        @Override
         public void cancel() { 
             try { 
                 mIm.cancelVibrate(mDeviceId, mToken); 
             } catch (RemoteException ex) { 
                 Log.w(TAG, "Failed to cancel vibration.", ex); 
             } 
         } 
     }
       这里关注public void vibrate(long[] pattern, int repeat)方法,最终调用mIm.vibrate(mDeviceId, pattern, repeat, mToken)。。坑爹的,mIm是个抽象类,又得去找其实例,然后穿越到InputManagerService.java,放看起vibrate方法:

 public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) { 
         if (repeat >= pattern.length) { 
             throw new ArrayIndexOutOfBoundsException(); 
         } 
  
         VibratorToken v; 
         synchronized (mVibratorLock) { 
             v = mVibratorTokens.get(token); 
             if (v == null) { 
                 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++); 
                 try { 
                     token.linkToDeath(v, 0); 
                 } catch (RemoteException ex) { 
                     // give up 
                     throw new RuntimeException(ex); 
                 } 
                 mVibratorTokens.put(token, v); 
             } 
         } 
   
         synchronized (v) { 
             v.mVibrating = true; 
             nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue); 
         } 
     }
           这里调用了JNI方法nativeVibrate,同样,InputDeviceVibrator的cancel方法也到了这里:

 public void cancelVibrate(int deviceId, IBinder token) { 
         VibratorToken v; 
         synchronized (mVibratorLock) { 
             v = mVibratorTokens.get(token); 
             if (v == null || v.mDeviceId != deviceId) { 
                 return; // nothing to cancel 
             } 
         } 

         cancelVibrateIfNeeded(v); 
     }
              cancelVibrateIfNeeded方法最终调用nativeCancelVibrate方法。到达JNI层。
              |||||||||
              再来看看NullVibrator类。。不过既然是Null。。。那就是Null实现。
              自此,vibrate跟cancel到达的JNI层的接口是:


 private static native void nativeVibrate(int ptr, int deviceId, long[] pattern, 
             int repeat, int token); 
     private static native void nativeCancelVibrate(int ptr, int deviceId, int token);
       |-------然后是vibratorCount为0的情况,直接调用vibratorOn,cancel同理。
       自此,vibrate跟cancel到达的JNI层的接口是:
    native static void vibratorOn(long milliseconds); 
    native static void vibratorOff();

2.JNI层
--对于nativeVibrate/nativeCancelVibrate,其实现位于com_android_server_input_InputManagerService.cpp中.
 static void nativeVibrate(JNIEnv* env, 
         jclass clazz, jint ptr, jint deviceId, jlongArray patternObj, 
         jint repeat, jint token) { 
     NativeInputManager* im = reinterpret_cast(ptr); 
   
     size_t patternSize = env->GetArrayLength(patternObj); 
     if (patternSize > MAX_VIBRATE_PATTERN_SIZE) { 
         ALOGI("Skipped requested vibration because the pattern size is %d "
                 "which is more than the maximum supported size of %d.", 
                 patternSize, MAX_VIBRATE_PATTERN_SIZE); 
         return; // limit to reasonable size 
     } 
   
     jlong* patternMillis = static_cast(env->GetPrimitiveArrayCritical( 
             patternObj, NULL)); 
    nsecs_t pattern[patternSize]; 
     for (size_t i = 0; i < patternSize; i++) { 
         pattern[i] = max(jlong(0), min(patternMillis[i], 
                 MAX_VIBRATE_PATTERN_DELAY_NSECS / 1000000LL)) * 1000000LL; 
     } 
     env->ReleasePrimitiveArrayCritical(patternObj, patternMillis, JNI_ABORT); 
   
     im->getInputManager()->getReader()->vibrate(deviceId, pattern, patternSize, repeat, token); 
 } 
   
 static void nativeCancelVibrate(JNIEnv* env, 
        jclass clazz, jint ptr, jint deviceId, jint token) { 
     NativeInputManager* im = reinterpret_cast(ptr); 
   
     im->getInputManager()->getReader()->cancelVibrate(deviceId, token); 
 }
-- 对于vibratorOn /vibratorOff,其实现位于com_android_server_VibratorService.cpp中 

 static JNINativeMethod method_table[] = { 
     { "vibratorExists", "()Z", (void*)vibratorExists }, 
     { "vibratorOn", "(J)V", (void*)vibratorOn }, 
     { "vibratorOff", "()V", (void*)vibratorOff } 
 };


 static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms) 
 { 
     // ALOGI("vibratorOn\n"); 
     vibrator_on(timeout_ms); 
 } 
   
 static void vibratorOff(JNIEnv *env, jobject clazz) 
 { 
     // ALOGI("vibratorOff\n"); 
     vibrator_off(); 
 }

3.HAL层    
 vib rator_on/vibrator_off的定义位于头文件(\hardware\libhardware_legacy\include\hardware_legacy\)


 /** 
  * Turn on vibrator 
  * 
  * @param timeout_ms number of milliseconds to vibrate 
  * 
  * @return 0 if successful, -1 if error 
  */
 int vibrator_on(int timeout_ms); 
  
 /** 
  * Turn off vibrator 
  * 
  * @return 0 if successful, -1 if error 
  */
 int vibrator_off();
HAL已经完成了实现。 
\hardware\libhardware_legacy\vibrator\vibrator.c

 /* 
  * Copyright (C) 2008 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. 
  */

 #include  
 #include "qemu.h" 
   
 #include  

 #include  
 #include  
 #include  
   
 #define THE_DEVICE "/sys/class/timed_output/vibrator/enable" 
   
 int vibrator_exists() 
 { 
     int fd; 
   
 #ifdef QEMU_HARDWARE 
     if (qemu_check()) { 
         return 1; 
     } 
 #endif 
   
     fd = open(THE_DEVICE, O_RDWR); 
     if(fd < 0) 
         return 0; 
     close(fd); 
     return 1; 
 } 
   
 static int sendit(int timeout_ms) 
 { 
     int nwr, ret, fd; 
     char value[20]; 
   
 #ifdef QEMU_HARDWARE 
     if (qemu_check()) { 
         return qemu_control_command( "vibrator:%d", timeout_ms ); 
     } 
 #endif 
   
     fd = open(THE_DEVICE, O_RDWR); 
    if(fd < 0) 
         return errno; 
   
     nwr = sprintf(value, "%d\n", timeout_ms); 

     ret = write(fd, value, nwr); 
   
     close(fd); 
   
     return (ret == nwr) ? 0 : -1; 
 } 
   
 int vibrator_on(int timeout_ms) 
 { 
     /* constant on, up to maximum allowed time */
     return sendit(timeout_ms); 
 } 
 int vibrator_off() 
 { 
     return sendit(0); 
 }
    这里使用的是Android的timed output机制,通过操纵/sys/class/timed_output/vibrator/enable节点启动或者停止启动器。
4.内核层
先看看timed output的驱动代码,位于Linux_Kernel_3x\drivers\staging\android\下。

 #ifndef _LINUX_TIMED_OUTPUT_H 
 #define _LINUX_TIMED_OUTPUT_H 

 struct timed_output_dev { 
     const char  *name; 
     /* enable the output and set the timer */
     void    (*enable)(struct timed_output_dev *sdev, int timeout); 
     /* returns the current number of milliseconds remaining on the timer */
     int     (*get_time)(struct timed_output_dev *sdev); 
     /* private data */
     struct device   *dev; 
     int     index; 
     int     state; 
 };
extern int timed_output_dev_register(struct timed_output_dev *dev); 
extern void timed_output_dev_unregister(struct timed_output_dev *dev); 
#endif
所有的timed output实现都需要定义在结构体timed_output_dev中。
Timed Output驱动程序框架将为每个设备在/sys/class/timed_output/目录中建立一个子目录,设备子目录中的enable文件就是设备的控制文件。读enable文件表示获得剩余时间,写这个文件表示根据时间振动。
这个具体情况具体实现,参考:
http://tech.it168.com/a2012/0201/1305/000001305847.shtmlhttp://tech.it168.com/a2012/0201/1305/000001305847.shtml

你可能感兴趣的:(android基础知识)