Android Senor Framework (二) Application

本节主要分析的是java层次相关的软件内容

Application开发

谷歌开发者网站 sensors 中提供了AOSP提供的sensor相关的api介绍及demo;

可以参考下相关资源:

App demo 实现

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private SensorManager mSensorManager;
    private Sensor mSensorAcc, mSensorMag;
    private TextView tvAcc, tvMag;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        tvAcc = findViewById(R.id.tvAcc);
        tvMag = findViewById(R.id.tvMag);
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		 //!< 通过getSystemService获得SensorManager实例对象 >!
        mSensorAcc = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		 //!< 通过SensorManager 获取sensor对象 >!
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];
        if(event.sensor == mSensorAcc)
            tvAcc.setText("x:" + x + "\ny:" + y + "\nz:" + z);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, mSensorAcc, SensorManager.SENSOR_DELAY_NORMAL);
    }
	
    @Override
    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }
}

实现的步骤:

  1. 通过调用通过getSystemService获得传感器服务,实现返回的是封装了SensorService的SensorManager对象
  2. 通过SensorManager 来获得指定类型的传感器对象,用来获得传感器的数据
  3. 通过SensorManager.registerListener注册SensorEventListener监听器,监听传感器
  4. 实现对sensor上报数据内容的具体操作

运行demo

以下是在Android Studio中实际demo

SensorManager

通过上面简单的app demo可知,主要过程均是通过SensorManager来完成;

改SensorManager是通过 getSystemService获取系统name 为“sensor” service得到;

/**
 * Use with {@link #getSystemService(String)} to retrieve a {@link
 * android.hardware.SensorManager} for accessing sensors.
 *
 * @see #getSystemService(String)
 * @see android.hardware.SensorManager
 */
public static final String SENSOR_SERVICE = "sensor";

Sensor服务用户程序不能直接访问, android.hardware.SensorManager 是真正用来在java程序中操作sensor的类,它是SensorService提供服务接口的封装。

因为 Manager是应用程序直接面对的接口, Manager里维护对应的Service,应用程序不能直接访问Service;

Service是服务,被所有的应用共享的服务,并非属于某一个特定的进程,也即Sensor application与SensorService不在同一个进程内,App需要使用Sensor

service就需要进程间通信,这显然不利于很高效率的开发程序,为此由manager类操作,隐藏共享操作,把细节实现隐藏封装,app应用程序只需要通过访问被暴

露出来的api接口,所以应用中与之直接交互的是SensorManager;

SensorManager提供了各种方法来访问和列出传感器,注册和取消注册传感器事件监听器,它还提供了几个传感器常量,用于报

告传感器精确度,设置数据采集频率和校准传感器;下面是这个类的定义:

public abstract class SensorManager 
    protected static final String TAG = "SensorManager";
   public static final int RAW_DATA_Z = 5;
   /** Standard gravity (g) on Earth. This value is equivalent to 1G */
   public static final float STANDARD_GRAVITY = 9.80665f;
......
   public SensorManager() {
   }
   protected abstract List<Sensor> getFullSensorList();
   protected abstract List<Sensor> getFullDynamicSensorList();
   @Deprecated
   public int getSensors() {
       return getLegacySensorManager().getSensors();
   }
   public List<Sensor> getSensorList(int type) {
       // cache the returned lists the first time
       List<Sensor> list;
       final List<Sensor> fullList = getFullSensorList();
       synchronized (mSensorListByType) {
           list = mSensorListByType.get(type);
           if (list == null) {
               if (type == Sensor.TYPE_ALL) {
                   list = fullList;
               } else {
                   list = new ArrayList<Sensor>();
                   for (Sensor i : fullList) {
                       if (i.getType() == type)
                           list.add(i);
                   }
               }
               list = Collections.unmodifiableList(list);
               mSensorListByType.append(type, list);
           }
       }
       return list;
   }
   @Deprecated
   public boolean registerListener(SensorListener listener, int sensors) {
       return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
   }
	public boolean registerListener(SensorEventListener listener, Sensor sensor,
	        int samplingPeriodUs, Handler handler) {
	    int delay = getDelay(samplingPeriodUs);
	    return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
	}
   public void unregisterListener(SensorEventListener listener, Sensor sensor) {
       if (listener == null || sensor == null) {
           return;
       }
       unregisterListenerImpl(listener, sensor);
   }
   public boolean flush(SensorEventListener listener) {
       return flushImpl(listener);
   }
.......
}

通过上面的内容可以看出SensorManager是个抽象类,真正完成管理控制sensor的是它的子类SystemSensorManager;

SystemSensorManager继承了它 做具体的实现;

SystemSensorManager.java extends SensorManager
 public class SystemSensorManager extends SensorManager {
    //TODO: disable extra logging before release
    private static boolean DEBUG_DYNAMIC_SENSOR = true;
 
    private static native void nativeClassInit();
    private static native long nativeCreate(String opPackageName);
    private static native boolean nativeGetSensorAtIndex(long nativeInstance,
            Sensor sensor, int index);
    private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
    private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
    private static final Object sLock = new Object();
    @GuardedBy("sLock")
    private static boolean sNativeClassInited = false;
    @GuardedBy("sLock")
    private static InjectEventQueue sInjectEventQueue = null;
 
    private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
    private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
    private boolean mDynamicSensorListDirty = true;
 
    private final HashMap<Integer, Sensor> mHandleToSensor = new HashMap<>();
......
    public SystemSensorManager(Context context, Looper mainLooper) {
        synchronized(sLock) {
            if (!sNativeClassInited) {
                sNativeClassInited = true;
                nativeClassInit();
            }
        }
        mMainLooper = mainLooper;
        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
        mContext = context;
        mNativeInstance = nativeCreate(context.getOpPackageName());
 
        // initialize the sensor list
        for (int index = 0;;++index) {
            Sensor sensor = new Sensor();
            if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
            mFullSensorsList.add(sensor);
            mHandleToSensor.put(sensor.getHandle(), sensor);
        }
    }
......
    @Override
    protected List<Sensor> getFullSensorList() {
        return mFullSensorsList;
......
        private static abstract class BaseEventQueue {
        private static native long nativeInitBaseEventQueue(long nativeManager,
                WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,
                String packageName, int mode, String opPackageName);
        private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
                int maxBatchReportLatencyUs);
        private static native int nativeDisableSensor(long eventQ, int handle);
        private static native void nativeDestroySensorEventQueue(long eventQ);
        private static native int nativeFlushSensor(long eventQ);
        private static native int nativeInjectSensorData(long eventQ, int handle,
    }
......
    }

从这个类中可以本地的native方法,如:

nativeClassInit();
nativeCreate(String opPackageName);
nativeGetSensorAtIndex(long nativeInstance,Sensor sensor, int index);
nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
nativeIsDataInjectionEnabled(long nativeInstance);

通过load到的JNI访问到libc中的native方法,有关jni 和c++ 本地方法实现后面博客介绍;

除了对本地native方法的调用,SystemSensorManager 还在其构造函数中 初始化了对应的sensor list;

        for (int index = 0;;++index) {
            Sensor sensor = new Sensor();
            if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
            mFullSensorsList.add(sensor);
            mHandleToSensor.put(sensor.getHandle(), sensor);
        }

Sensor对象

从app的demo代码中可以看出,一个存在的sensor是由一个Sensor类的对象来标识的,它获取自Sensor Manager,通过给定的参数,获取一个实例sensor对象;该类提供了各种方法来确定传感器的特性。

mSensorAcc = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
public Sensor getDefaultSensor(int type) {
    // TODO: need to be smarter, for now, just return the 1st sensor
    List<Sensor> l = getSensorList(type);
    boolean wakeUpSensor = false;
    // For the following sensor types, return a wake-up sensor. These types are by default
    // defined as wake-up sensors. For the rest of the SDK defined sensor types return a
    // non_wake-up version.
    if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION ||
            type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE ||
            type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE ||
            type == Sensor.TYPE_WRIST_TILT_GESTURE) {
        wakeUpSensor = true;
    }
    for (Sensor sensor : l) {
        if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor;
    }
    return null;
}

Sensor类的内容如下:

public final class Sensor {
    mName
    mVendor
    mVersion
    mHandle
    mType
    mMaxRange
    mResolution
    mPower
    mMinDelay
    mFifoReservedEventCount
    mFifoMaxEventCount
    mStringType
    mRequiredPermission
    mMaxDelay
    mFlags
    mld
// func
    Sensor
    getName
    getVendor
    getType
    getVersion
    getMaximumRange
    getResolution
    getPower
    getMinDelay
    getFifoReservedEventCount
    getFifoMaxEventCount
    getStringType
    getUuid
    getld
    getRequiredPermission
    getHandle
    getMaxDelay
    isWakeUpSensor
    isDynamicSensor
    isAdditionallnfoSupported
    isDatalnjectionSupported
    setRange
    toString
    setType
    setUuid
}

Sensor Event 处理

SensorEventListener

回到app demo中,可以看出,sensor数据的处理是override了onSensorChanged方法,它在有sensor数据上报时被回调,详细的回调过程后面的内容会做分析;暂时只关注demo中的代码实现;

通过activity的定义可知,onSensorChanged方法是来自接口SensorEventListener;

接口类interface SensorEventListener (方法都是public abstract, 变量都是public static final)

用于接收新的sensor 数据上报时回调其中的抽象方法;

code:frameworks\base\core\java\android\hardware\SensorEvent.java
public interface SensorEventListener {
  public void onSensorChanged(SensorEvent event); //sensor数据变化
  public void onAccuracyChanged(Sensor sensor, int accuracy); //精度变化
}

它处理的参数类型是SensorEvent类对象;这个类的对象表示一个SensorEvent事件,并保存诸如传感器类型、时间戳、精度等信息,还有传感器的数据。

values float数组里保存了app需要用到的数据信息;按照固定的格式去读取需要的参数即可; 具体参考android API介绍,拿到event之后,对应固定的格式,拆解出的value即是我们需要的sensor数据;

public class SensorEvent {
public final float[] values;
public Sensor sensor;
public int accuracy;
public long timestamp;
SensorEvent(int valueSize) {
    values = new float[valueSize];
	}
}

registerListener

实现一个sensor监听,是先通过SensorManager.registerListener注册SensorEventListener监听器,监听sensor,注册监听器的方法实现同样是有SensorManager对象来管理,appdemo中使用获取到的mSensorManager,以及设置指定类型获取的sensor对象 acc msensor来注册监听;

mSensorManager.registerListener(this, mSensorAcc, SensorManager.SENSOR_DELAY_NORMAL);

以下是registerListener在SystemSensorManager类中的定义:

SystemSensorManager::registerListener
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
        int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
//......
        // listener 是activity
        // - one Looper per SensorEventListener
        // - one Looper per SensorEventQueue
        //   将SensorEventListener映射到一个SensorEventQueue
    synchronized (mSensorListeners) {
        SensorEventQueue queue = mSensorListeners.get(listener);
        if (queue == null) {
            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
            final String fullClassName = listener.getClass().getEnclosingClass() != null ?
                listener.getClass().getEnclosingClass().getName() :
                listener.getClass().getName();
            queue = new SensorEventQueue(listener, looper, this, fullClassName);
            if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
                queue.dispose();
                return false;
            }
            mSensorListeners.put(listener, queue);
            return true;
        } else {
            return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
        }
    }
 //......
}

将SensorEventListener映射到一个SensorEventQueue,如果SensorEventQueue已经存在,将该sensor(mSensorAcc)添加到queue中去,如果不存在,则创建SensorEventQueue;以下是SensorEventQueue 队列的实现:

SensorEventQueue

prj\frameworks\base\core\java\android\hardware\SystemSensorManager.java
static final class SensorEventQueue extends BaseEventQueue {
    private final SensorEventListener mListener;
    private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
    public SensorEventQueue(SensorEventListener listener, Looper looper,
            SystemSensorManager manager, String packageName) {
        super(looper, manager, OPERATING_MODE_NORMAL, packageName);
        mListener = listener;
    }
    @Override
    public void addSensorEvent(Sensor sensor) {
        SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
                mManager.mTargetSdkLevel));
        synchronized (mSensorsEvents) {
            mSensorsEvents.put(sensor.getHandle(), t);
        }
    }
}
  // Called from native code.
    protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
            long timestamp) {
        final Sensor sensor = mManager.mHandleToSensor.get(handle);
        if (sensor == null) {
            // sensor disconnected
            return;
        }
        SensorEvent t = null;
        synchronized (mSensorsEvents) {
            t = mSensorsEvents.get(handle);
        }
        // Copy from the values array.
        System.arraycopy(values, 0, t.values, 0, t.values.length);
        t.timestamp = timestamp;
        t.accuracy = inAccuracy;
        t.sensor = sensor;
        // call onAccuracyChanged() only if the value changes
        final int accuracy = mSensorAccuracies.get(handle);
        if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
            mSensorAccuracies.put(handle, t.accuracy);
            mListener.onAccuracyChanged(t.sensor, t.accuracy);
        }
        mListener.onSensorChanged(t);
    }

BaseEventQueue

它继承自BaseBaseEventQueue; 以下是 BaseEventQueue的定义:

prj\frameworks\base\core\java\android\hardware\SystemSensorManager.java
private static abstract class BaseEventQueue {
    private static native long nativeInitBaseEventQueue(long nativeManager,
            WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,
            String packageName, int mode, String opPackageName);
    private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
            int maxBatchReportLatencyUs);
    private static native int nativeDisableSensor(long eventQ, int handle);
    private static native void nativeDestroySensorEventQueue(long eventQ);
    private static native int nativeFlushSensor(long eventQ);
    private static native int nativeInjectSensorData(long eventQ, int handle,
            float[] values,int accuracy, long timestamp);
    private long nSensorEventQueue;
    private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
    protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
    private final CloseGuard mCloseGuard = CloseGuard.get();
    protected final SystemSensorManager mManager;
    protected static final int OPERATING_MODE_NORMAL = 0;
    protected static final int OPERATING_MODE_DATA_INJECTION = 1;
    BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {
        if (packageName == null) packageName = "";
        nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
                new WeakReference<>(this), looper.getQueue(),
                packageName, mode, manager.mContext.getOpPackageName());
        mCloseGuard.open("dispose");
        mManager = manager;
    }
    public boolean addSensor(
            Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
        // Check if already present.
        int handle = sensor.getHandle();
        if (mActiveSensors.get(handle)) return false;
        // Get ready to receive events before calling enable.
        mActiveSensors.put(handle, true);
        addSensorEvent(sensor);
        if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
            // Try continuous mode if batching fails.
            if (maxBatchReportLatencyUs == 0 ||
                maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
              removeSensor(sensor, false);
              return false;
            }
        }
        return true;
    }
    @Override
    public void addSensorEvent(Sensor sensor) {
        SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
                mManager.mTargetSdkLevel));
        synchronized (mSensorsEvents) {
            mSensorsEvents.put(sensor.getHandle(), t);
        }
    }

    private int enableSensor(
            Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
        if (nSensorEventQueue == 0) throw new NullPointerException();
        if (sensor == null) throw new NullPointerException();
        return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,
                maxBatchReportLatencyUs);
    }

SensorList获取

前面SensorManager构造函数中,有提过获取sensor list的过程,它在java代码中的实现如下;

public List<Sensor> getSensorList(int type) {
       // cache the returned lists the first time
       List<Sensor> list;
       final List<Sensor> fullList = getFullSensorList();
       synchronized (mSensorListByType) {
           list = mSensorListByType.get(type);
           if (list == null) {
               if (type == Sensor.TYPE_ALL) {
                   list = fullList;
               } else {
                 list = new ArrayList<Sensor>();
                   for (Sensor i : fullList) {
                       if (i.getType() == type)
                           list.add(i);
                   }
               }
               list = Collections.unmodifiableList(list);
               mSensorListByType.append(type, list);
           }
       }
       return list;
   }
protected List<Sensor> getFullSensorList() {
    return mFullSensorsList;
}

实际上是反回了mFullSensorsList 列表,实际的初始化过程是子类SystemSensorManager的构造过程中实现的,如下;

// initialize the sensor list
for (int index = 0;;++index) {
    Sensor sensor = new Sensor();
    if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
    mFullSensorsList.add(sensor);
    mHandleToSensor.put(sensor.getHandle(), sensor);
}

可以看到 每一个sensor都是通过new Sensor对象,再调用本地native方法nativeGetSensorAtIndex去做实例;

本节主要分析的是java层次相关的软件内容,nativeGetSensorAtIndex通过jni访问到C++中的sensor manager,在后续的博客汇总介绍;

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值