天天看點

setting中打開自動旋轉功能和接收sensor資料分析

在設定中,有個自動旋轉螢幕的開關功能。 随系統選裝的話,我們先要在手機設定中選擇顯示項,裝置旋轉時自動旋轉。最終會調用RotationPolicy.setRotationLockForAccessibility函數,我們先來看下這個函數: public static void setRotationLock(Context context, final boolean enabled) { Settings.System.putIntForUser(context.getContentResolver(), Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0, UserHandle.USER_CURRENT);

final int rotation = areAllRotationsAllowed(context) ? CURRENT_ROTATION : NATURAL_ROTATION; setRotationLock(enabled, rotation); }

private static void setRotationLock(final boolean enabled, final int rotation) { AsyncTask.execute(new Runnable() { @Override public void run() { try { IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); if (enabled) { wm.freezeRotation(rotation);//關閉自動旋轉 } else { wm.thawRotation();//打開自動旋轉 } } catch (RemoteException exc) { Log.w(TAG, "Unable to save auto-rotate setting"); } } }); } 接下來需要到WM中看下 thawRotation的實作了:

@Override public void thawRotation() { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, "thawRotation()")) { throw new SecurityException("Requires SET_ORIENTATION permission"); }

if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);

long origId = Binder.clearCallingIdentity(); try { mPolicy. setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used } finally { Binder.restoreCallingIdentity(origId); }

updateRotationUnchecked(false, false); } 繼續跟進 setUserRotationMode函數,它的實作在phonwindowmanger中實作的: public void setUserRotationMode(int mode, int rot) { ContentResolver res = mContext.getContentResolver();

// mUserRotationMode and mUserRotation will be assigned by the content observer if (mode == WindowManagerPolicy. USER_ROTATION_LOCKED) { Settings.System.putIntForUser(res, Settings.System.USER_ROTATION, rot, UserHandle.USER_CURRENT); Settings.System.putIntForUser(res, Settings.System. ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT); } else { Settings.System.putIntForUser(res, Settings.System. ACCELEROMETER_ROTATION, 1, UserHandle.USER_CURRENT); } } 這裡隻是改變了setting中開關的值。當setting中監聽到這個值有變化的時候: class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler) { super(handler); }

void observe() { // Observe all users' changes ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.END_BUTTON_BEHAVIOR), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.WAKE_GESTURE_ENABLED), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System. ACCELEROMETER_ROTATION), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.USER_ROTATION), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_OFF_TIMEOUT), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.POINTER_LOCATION), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.DEFAULT_INPUT_METHOD), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.POLICY_CONTROL), false, this, UserHandle.USER_ALL); updateSettings(); }

@Override public void onChange(boolean selfChange) { updateSettings(); updateRotation(false); } } 在 updateSettings中: // Configure rotation lock. int userRotation = Settings.System.getIntForUser(resolver, Settings.System.USER_ROTATION, Surface.ROTATION_0, UserHandle.USER_CURRENT); if (mUserRotation != userRotation) { mUserRotation = userRotation; updateRotation = true; } int userRotationMode = Settings.System.getIntForUser(resolver, Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? WindowManagerPolicy.USER_ROTATION_FREE : WindowManagerPolicy.USER_ROTATION_LOCKED; if (mUserRotationMode != userRotationMode) { mUserRotationMode = userRotationMode; updateRotation = true; updateOrientationListenerLp(); } 在看看 updateOrientationListenerLp它的實作: void updateOrientationListenerLp() { if (!mOrientationListener.canDetectOrientation()) { // If sensor is turned off or nonexistent for some reason return; } //Could have been invoked due to screen turning on or off or //change of the currently visible window's orientation if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled); boolean disable = true; if (mScreenOnFully && mAwake) { if (needSensorRunningLp()) { disable = false; //enable listener if not already enabled if (!mOrientationSensorEnabled) { mOrientationListener.enable();//打開sensor if(localLOGV) Slog.v(TAG, "Enabling listeners"); mOrientationSensorEnabled = true; } } } //check if sensors need to be disabled if (disable && mOrientationSensorEnabled) { mOrientationListener.disable();//關閉sensor if(localLOGV) Slog.v(TAG, "Disabling listeners"); mOrientationSensorEnabled = false; } } 首先看下這個 mOrientationListener是個啥東西呢 ? 在PhoneWindowManager中的init中: mOrientationListener = new MyOrientationListener(mContext, mHandler);

繼續看 MyOrientationListener: class MyOrientationListener extends WindowOrientationListener { MyOrientationListener(Context context, Handler handler) { super(context, handler); } 是以需要到 WindowOrientationListener 中看它的enable和disable的實作: public void enable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Not enabled"); return; } if (mEnabled == false) { if (LOG) { Log.d(TAG, "WindowOrientationListener enabled"); } mSensorEventListener. resetLocked(); mSensorManager. registerListener(mSensorEventListener, mSensor, mRate, mHandler); mEnabled = true; } } }

public void disable() { synchronized (mLock) { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Invalid disable"); return; } if (mEnabled == true) { if (LOG) { Log.d(TAG, "WindowOrientationListener disabled"); } mSensorManager. unregisterListener(mSensorEventListener); mEnabled = false; } } } 這裡先看下enable的流程: mSensorManager就是 SensorManager,現在到SensorManager中看下 registerListener:、 public boolean registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, Handler handler) { int delay = getDelay(samplingPeriodUs); return registerListenerImpl(listener, sensor, delay, handler, 0, 0); } 需要繼續跟進 registerListenerImpl: protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags); 空的,需要到它的子類中找答案了: 在 SystemSensorManager中: @Override protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) { if (listener == null || sensor == null) { Log.e(TAG, "sensor or listener is null"); return false; } // Trigger Sensors should use the requestTriggerSensor call. if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor."); return false; } if (maxBatchReportLatencyUs < 0 || delayUs < 0) { Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative"); return false; }

// Invariants to preserve: // - one Looper per SensorEventListener // - one Looper per SensorEventQueue // We map SensorEventListener to a SensorEventQueue, which holds the looper synchronized (mSensorListeners) { SensorEventQueue queue = mSensorListeners.get(listener); if (queue == null) { Looper looper = (handler != null) ? handler.getLooper() : mMainLooper; queue = new SensorEventQueue(listener, looper, this);//第一次必須是null if (! queue. addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) { queue.dispose(); return false; } mSensorListeners.put(listener, queue); return true; } else { return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags); } } } 是以接下來需要分析下 SensorEventQueue:作用就是建立一個底層到上層的資料傳輸通道: public SensorEventQueue(SensorEventListener listener, Looper looper, SystemSensorManager manager) { super(looper, manager); mListener = listener; } 它的父類是: BaseEventQueue(Looper looper, SystemSensorManager manager) { nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch); mCloseGuard.open("dispose"); mManager = manager; } 是以需要到jni中分析了 nativeInitBaseEventQueue: static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, jfloatArray scratch) { //1 :建立SensorEventQueue,首先拿到 SensorManager SensorManager& mgr( SensorManager::getInstance()); sp<SensorEventQueue> queue( mgr. createEventQueue()); //建立一個 messageQueue sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ); if (messageQueue == NULL) { jniThrowRuntimeException(env, "MessageQueue is not initialized."); return 0; } //2:建立資料接收者 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch); //3: 調用onfirstRef receiver->incStrong((void*) nativeInitSensorEventQueue); return jlong(receiver.get()); } 先看下第一步:隻看 createEventQueue的過程: sp<SensorEventQueue> SensorManager:: createEventQueue() { sp<SensorEventQueue> queue;

Mutex::Autolock _l(mLock); while (assertStateLocked() == NO_ERROR) { sp<ISensorEventConnection> connection = mSensorServer-> createSensorEventConnection(); if (connection == NULL) { // SensorService just died. ALOGE("createEventQueue: connection is NULL. SensorService died."); continue; } queue = new SensorEventQueue(connection); break; } return queue; } 先看下 createSensorEventConnection,這裡是binder調用,直接到SensorService中看下實作: sp<ISensorEventConnection> SensorService::createSensorEventConnection() { uid_t uid = IPCThreadState::self()->getCallingUid(); sp<SensorEventConnection> result(new SensorEventConnection(this, uid)); return result; } SensorService:: SensorEventConnection::SensorEventConnection( const sp<SensorService>& service, uid_t uid) : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false), mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0) { //最重要是建立了一個 BitTube用于通信 mChannel = new BitTube(mService->mSocketBufferSize); #if DEBUG_CONNECTIONS mEventsReceived = mEventsSentFromCache = mEventsSent = 0; mTotalAcksNeeded = mTotalAcksReceived = 0; #endif } 回到 createEventQueue中,最下面是建立了一個 SensorEventQueue: SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection) : mSensorEventConnection(connection), mRecBuffer(NULL), mAvailable(0), mConsumed(0), mNumAcksToSend(0) { mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT]; }

再看下第二步: Receiver(const sp<SensorEventQueue>& sensorQueue, const sp<MessageQueue>& messageQueue, jobject receiverObject, jfloatArray scratch) { JNIEnv* env = AndroidRuntime::getJNIEnv(); mSensorQueue = sensorQueue; mMessageQueue = messageQueue; mReceiverObject = env->NewGlobalRef(receiverObject); mScratch = (jfloatArray)env->NewGlobalRef(scratch); } 在看下它的一個 onFirstRef:添加到looper中去的監聽 virtual void onFirstRef() { LooperCallback::onFirstRef(); mMessageQueue-> getLooper()-> addFd( mSensorQueue->getFd(), 0, ALOOPER_EVENT_INPUT, this, mSensorQueue.get()); } 既然有looper的 addFd,必然有 handleEvent:下面來看下它的實作: virtual int handleEvent(int fd, int events, void* data) { JNIEnv* env = AndroidRuntime::getJNIEnv(); sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data); ssize_t n; ASensorEvent buffer[16]; while ((n = q->read(buffer, 16)) > 0) { for (int i=0 ; i<n ; i++) { if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) { // step-counter returns a uint64, but the java API only deals with floats float value = float(buffer[i].u64.step_counter); env->SetFloatArrayRegion(mScratch, 0, 1, &value); } else { env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data); }

if (buffer[i].type == SENSOR_TYPE_META_DATA) { // This is a flush complete sensor event. Call dispatchFlushCompleteEvent // method. env->CallVoidMethod(mReceiverObject, gBaseEventQueueClassInfo. dispatchFlushCompleteEvent, buffer[i].meta_data.sensor); } else { int8_t status; switch (buffer[i].type) { case SENSOR_TYPE_ORIENTATION: case SENSOR_TYPE_MAGNETIC_FIELD: case SENSOR_TYPE_ACCELEROMETER: case SENSOR_TYPE_GYROSCOPE: status = buffer[i].vector.status; break; case SENSOR_TYPE_HEART_RATE: status = buffer[i].heart_rate.status; break; default: status = SENSOR_STATUS_ACCURACY_HIGH; break; } //回調Java層 BaseEventQueue的 dispatchSensorEvent方法 env->CallVoidMethod(mReceiverObject, gBaseEventQueueClassInfo. dispatchSensorEvent, buffer[i].sensor, mScratch, status, buffer[i].timestamp); } if (env->ExceptionCheck()) { mSensorQueue->sendAck(buffer, n); ALOGE("Exception dispatching input event."); return 1; } } mSensorQueue-> sendAck(buffer, n); } if (n<0 && n != -EAGAIN) { // FIXME: error receiving events, what to do in this case? } return 1; } 接下來,需要到java層看下資料是怎麼分發的: protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy, long timestamp) { final Sensor sensor = sHandleToSensor.get(handle); SensorEvent t = null; synchronized (mSensorsEvents) { t = mSensorsEvents.get(handle); }

if (t == null) { // This may happen if the client has unregistered and there are pending events in // the queue waiting to be delivered. Ignore. return; } // 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);//是以最終會調用 onSensorChanged的方法; }