【安卓Sensor框架-2】應用注冊Sensor 流程

注冊傳感器的核心流程為如下:應用層調用 SensorManager注冊傳感器,framework層創建SensorEventQueue對象(事件隊列),通過JNI調用Native方法nativeEnableSensor();SensorService服務端createEventQueue()創建SensorEventConnection對象,然后enable使能sensor。
在這里插入圖片描述

這里以監聽光傳感器的流程為例子。

/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController2.java
// 這里設置lightsensor 使能:setLightSensorEnabled

652      private boolean setLightSensorEnabled(boolean enable) {
653          if (enable) {
654              if (!mLightSensorEnabled) {
655                  mLightSensorEnabled = true;
656                  mLightSensorEnableTime = mClock.uptimeMillis();
657                  mCurrentLightSensorRate = mInitialLightSensorRate;
658                  registerForegroundAppUpdater();
// mSensorManager是 SystemSensorManager 是powermanagerservice 設置的
// mLightSensor 是displaycontroller2 在構造的時候設置的
659                  mSensorManager.registerListener(mLightSensorListener, mLightSensor,
660                          mCurrentLightSensorRate * 1000, mHandler);
661                  return true;
662              }

/frameworks/base/services/core/java/com/android/server/display/AutomaticBrightnessController.java

// mLightSensor 是displaycontroller2 在構造的時候設置的
// mSensorManager 是 SystemSensorManager ,繼承了 SensorManager
659 mSensorManager.registerListener(mLightSensorListener, mLightSensor,
660 mCurrentLightSensorRate * 1000, mHandler);

/frameworks/base/core/java/android/hardware/SensorManager.java

852      public boolean registerListener(SensorEventListener listener, Sensor sensor,
853              int samplingPeriodUs, Handler handler) {
854          int delay = getDelay(samplingPeriodUs);
// 在子類中有實現registerListenerImpl
855          return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
856      }

// 在子類中有實現registerListenerImpl

/frameworks/base/core/java/android/hardware/SystemSensorManager.java

240      @Override
241      protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
242              int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
243          if (listener == null || sensor == null) {
244              Log.e(TAG, "sensor or listener is null");
245              return false;
246          }
247          // Trigger Sensors should use the requestTriggerSensor call.
248          if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
249              Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
250              return false;
251          }
252          if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
253              Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
254              return false;
255          }
// 最多觀察者不能大于 128
256          if (mSensorListeners.size() >= MAX_LISTENER_COUNT) {
257              throw new IllegalStateException("register failed, "
258                  + "the sensor listeners size has exceeded the maximum limit "
259                  + MAX_LISTENER_COUNT);
260          }
261  
262          // Invariants to preserve:
263          // - one Looper per SensorEventListener
264          // - one Looper per SensorEventQueue
265          // We map SensorEventListener to a SensorEventQueue, which holds the looper
266          synchronized (mSensorListeners) {
267              SensorEventQueue queue = mSensorListeners.get(listener);
// que 的值為 空
268              if (queue == null) {
269                  Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
270                  final String fullClassName =
271                          listener.getClass().getEnclosingClass() != null
272                              ? listener.getClass().getEnclosingClass().getName()
273                              : listener.getClass().getName();
// 1)創建 SensorEventQueue 對象
274                  queue = new SensorEventQueue(listener, looper, this, fullClassName);
// 2)調用 SensorEventQueue 的 addSensor 方法
275                  if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
276                      queue.dispose();
277                      return false;
278                  }
279                  mSensorListeners.put(listener, queue);
280                  return true;
281              } else {
282                  return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
283              }
284          }
285      }
1)創建 SensorEventQueue 對象
940      static final class SensorEventQueue extends BaseEventQueue {
941          private final SensorEventListener mListener;
942          private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
943  
944          public SensorEventQueue(SensorEventListener listener, Looper looper,
945                  SystemSensorManager manager, String packageName) {
// 調用父類的構造方法
946              super(looper, manager, OPERATING_MODE_NORMAL, packageName);
// 緩存了 mListener  監聽回調
947              mListener = listener;
948          }

// 調用父類的構造方法

802          BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {
803              if (packageName == null) packageName = "";
// mode為 OPERATING_MODE_NORMAL
804              mNativeSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
805                      new WeakReference<>(this), looper.getQueue(),
806                      packageName, mode, manager.mContext.getOpPackageName(),
807                      manager.mContext.getAttributionTag());
808              mCloseGuard.open("BaseEventQueue.dispose");
809              mManager = manager;
810          }

// 初始化 eventqueue

457  static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
458                                          jobject eventQWeak, jobject msgQ, jstring packageName,
459                                          jint mode, jstring opPackageName, jstring attributionTag) {
460      SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
461      ScopedUtfChars packageUtf(env, packageName);
462      String8 clientName(packageUtf.c_str());
463  
464      String16 attributionTagName("");
465      if (attributionTag != nullptr) {
466          ScopedUtfChars attrUtf(env, attributionTag);
467          attributionTagName = String16(attrUtf.c_str());
468      }
// 1-2)createEventQueue 創建 SensorEventQueue
469      sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode, attributionTagName));
470  
471      if (queue == NULL) {
472          jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
473          return 0;
474      }
475  
476      sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
477      if (messageQueue == NULL) {
478          jniThrowRuntimeException(env, "MessageQueue is not initialized.");
479          return 0;
480      }
481  
// 1-3)創建 Receiver 對象,傳入了 SensorEventQueue 對象
482      sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
483      receiver->incStrong((void*)nativeInitSensorEventQueue);
484      return jlong(receiver.get());
485  }

// 1-2)createEventQueue 創建 SensorEventQueue

/frameworks/native/libs/sensor/SensorManager.cpp

286  sp<SensorEventQueue> SensorManager::createEventQueue(
287      String8 packageName, int mode, String16 attributionTag) {
288      sp<SensorEventQueue> queue;
289  
290      Mutex::Autolock _l(mLock);
291      while (assertStateLocked() == NO_ERROR) {
// 1-2-1)createSensorEventConnection創建 ISensorEventConnection
292          sp<ISensorEventConnection> connection = mSensorServer->createSensorEventConnection(
293              packageName, mode, mOpPackageName, attributionTag);
294          if (connection == nullptr) {
295              // SensorService just died or the app doesn't have required permissions.
296              ALOGE("createEventQueue: connection is NULL.");
297              return nullptr;
298          }
// 1-2-2)創建 SensorEventQueue 對象
299          queue = new SensorEventQueue(connection);
300          break;
301      }
302      return queue;
303  }

// 1-2-1)createSensorEventConnection創建 ISensorEventConnection
// 與sensorservice binder通信設置與應用socket 通信

/frameworks/native/services/sensorservice/SensorService.cpp

1495  sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName,
1496          int requestedMode, const String16& opPackageName, const String16& attributionTag) {
1497      // Only 3 modes supported for a SensorEventConnection ... NORMAL, DATA_INJECTION and
1498      // REPLAY_DATA_INJECTION.
1499      if (requestedMode != NORMAL && requestedMode != DATA_INJECTION &&
1500              requestedMode != REPLAY_DATA_INJECTION) {
1501          return nullptr;
1502      }
1503      resetTargetSdkVersionCache(opPackageName);
1504  
1505      Mutex::Autolock _l(mLock);
1506      // To create a client in DATA_INJECTION mode to inject data, SensorService should already be
1507      // operating in DI mode.
1508      if (requestedMode == DATA_INJECTION) {
1509          if (mCurrentOperatingMode != DATA_INJECTION) return nullptr;
1510          if (!isAllowListedPackage(packageName)) return nullptr;
1511      }
1512  
1513      uid_t uid = IPCThreadState::self()->getCallingUid();
1514      pid_t pid = IPCThreadState::self()->getCallingPid();
1515  
1516      String8 connPackageName =
1517              (packageName == "") ? String8::format("unknown_package_pid_%d", pid) : packageName;
1518      String16 connOpPackageName =
1519              (opPackageName == String16("")) ? String16(connPackageName) : opPackageName;
// 創建了 SensorEventConnection 對象,requestedMode  為normal
1520      sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
1521              requestedMode == DATA_INJECTION || requestedMode == REPLAY_DATA_INJECTION,
1522              connOpPackageName, attributionTag));
1523      if (requestedMode == DATA_INJECTION || requestedMode == REPLAY_DATA_INJECTION) {
1524          mConnectionHolder.addEventConnectionIfNotPresent(result);
1525          // Add the associated file descriptor to the Looper for polling whenever there is data to
1526          // be injected.
1527          result->updateLooperRegistration(mLooper);
1528      }
1529      return result;
1530  }

// 創建了 SensorEventConnection 對象,
/frameworks/native/services/sensorservice/SensorEventConnection.cpp

40  SensorService::SensorEventConnection::SensorEventConnection(
41          const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
42          const String16& opPackageName, const String16& attributionTag)
43      : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
44        mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(nullptr),
45        mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),
46        mPackageName(packageName), mOpPackageName(opPackageName), mAttributionTag(attributionTag),
47        mTargetSdk(kTargetSdkUnknown), mDestroyed(false) {
48      mUserId = multiuser_get_user_id(mUid);
// 創建了 BitTube,用于客戶端與sensorservice 進程通信
49      mChannel = new BitTube(mService->mSocketBufferSize);
50  #if DEBUG_CONNECTIONS
51      mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
52      mTotalAcksNeeded = mTotalAcksReceived = 0;
53  #endif
54  }

// 創建了 BitTube,用于客戶端與sensorservice 進程通信
/frameworks/native/libs/sensor/BitTube.cpp

42  BitTube::BitTube(size_t bufsize)
43      : mSendFd(-1), mReceiveFd(-1)
44  {
45      init(bufsize, bufsize);
46  }

// 初始化,在系統進程 sensorservice 初始化 socket 通信

68  void BitTube::init(size_t rcvbuf, size_t sndbuf) {
69      int sockets[2];
70      if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
71          size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
72          setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
73          setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
74          // sine we don't use the "return channel", we keep it small...
75          setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
76          setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
77          fcntl(sockets[0], F_SETFL, O_NONBLOCK);
78          fcntl(sockets[1], F_SETFL, O_NONBLOCK);
// 設置接收的fd,接收客戶端信息
79          mReceiveFd = sockets[0];
// 設置發送的fd
80          mSendFd = sockets[1];
81      } else {
82          mReceiveFd = -errno;
83          ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
84      }
85  }

// 1-2-2)創建 SensorEventQueue 對象

/frameworks/native/libs/sensor/SensorEventQueue.cpp

// 緩存 mSensorEventConnection
40  SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection)
41      : mSensorEventConnection(connection), mRecBuffer(nullptr), mAvailable(0), mConsumed(0),
42        mNumAcksToSend(0) {
// mRecBuffer  用于保存sensor信息
43      mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT];
44  }50  void SensorEventQueue::onFirstRef()
51  {
// 獲取socket通信創建的channel ,BitTube
52      mSensorChannel = mSensorEventConnection->getSensorChannel();
53  }

// 1-3)創建 Receiver 對象,傳入了 SensorEventQueue 對象

// Receiver  繼承了 LooperCallback 
327  class Receiver : public LooperCallback {
328      sp<SensorEventQueue> mSensorQueue;
329      sp<MessageQueue> mMessageQueue;
330      jobject mReceiverWeakGlobal;
331      jfloatArray mFloatScratch;
332      jintArray   mIntScratch;
333  public:
334      Receiver(const sp<SensorEventQueue>& sensorQueue,
335              const sp<MessageQueue>& messageQueue,
336              jobject receiverWeak) {
337          JNIEnv* env = AndroidRuntime::getJNIEnv();
// 緩存 SensorEventQueue  和 MessageQueue
338          mSensorQueue = sensorQueue;
339          mMessageQueue = messageQueue;
340          mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
341  
342          mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
343          mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
344      }

// 初始化方法

359  private:
360      virtual void onFirstRef() {
361          LooperCallback::onFirstRef();
// 從 BitTube獲取到接收端的fd:mReceiveFd;當sensorservice 發送信息的時候,會觸發回調 handleEvent
362          mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
363                  ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
364      }
2)調用 SensorEventQueue 的 addSensor 方法

/frameworks/base/core/java/android/hardware/SystemSensorManager.java

780      private abstract static class BaseEventQueue {
。。。
816          public boolean addSensor(
817                  Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
818              // Check if already present.
819              int handle = sensor.getHandle();
// 將sensor使能,如果使能了,則返回為false
820              if (mActiveSensors.get(handle)) return false;
821  
822              // Get ready to receive events before calling enable.
823              mActiveSensors.put(handle, true);
824              addSensorEvent(sensor);
// enableSensor 使能sensor
825              if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
826                  // Try continuous mode if batching fails.
827                  if (maxBatchReportLatencyUs == 0
828                          || maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
829                      removeSensor(sensor, false);
830                      return false;
831                  }
832              }
833              return true;
834          }

// enableSensor 使能sensor

896          private int enableSensor(
897                  Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
898              if (mNativeSensorEventQueue == 0) throw new NullPointerException();
899              if (sensor == null) throw new NullPointerException();
900              if (mManager.isSensorInCappedSet(sensor.getType())
901                      && rateUs < CAPPED_SAMPLING_PERIOD_US
902                      && mManager.mIsPackageDebuggable
903                      && !mManager.hasHighSamplingRateSensorsPermission()
904                      && Compatibility.isChangeEnabled(CHANGE_ID_SAMPLING_RATE_SENSORS_PERMISSION)) {
905                  throw new SecurityException("To use the sampling rate of " + rateUs
906                          + " microseconds, app needs to declare the normal permission"
907                          + " HIGH_SAMPLING_RATE_SENSORS.");
908              }
// 調用native 層的方法
909              return nativeEnableSensor(mNativeSensorEventQueue, sensor.getHandle(), rateUs,
910                      maxBatchReportLatencyUs);
911          }

/frameworks/base/core/jni/android_hardware_SensorManager.cpp

487  static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
488                                 jint maxBatchReportLatency) {
489      sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
// 通過 SensorEventQueue 去使能sensor
490      return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
491                                                           0);
492  }

// 通過 SensorEventQueue 去使能sensor

/frameworks/native/libs/sensor/SensorEventQueue.cpp

138  status_t SensorEventQueue::enableSensor(int32_t handle, int32_t samplingPeriodUs,
139                                          int64_t maxBatchReportLatencyUs, int reservedFlags) const {
140      return mSensorEventConnection->enableDisable(handle, true, us2ns(samplingPeriodUs),
141                                                   us2ns(maxBatchReportLatencyUs), reservedFlags);
142  }

// mSensorEventConnection 是與sensorservice binder 通信的接口

/frameworks/native/services/sensorservice/SensorEventConnection.cpp

681  status_t SensorService::SensorEventConnection::enableDisable(
682          int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
683          int reservedFlags)
684  {
685      if (mDestroyed) {
686          android_errorWriteLog(0x534e4554, "168211968");
687          return DEAD_OBJECT;
688      }
689  
690      status_t err;
691      if (enabled) {
692          nsecs_t requestedSamplingPeriodNs = samplingPeriodNs;
693          bool isSensorCapped = false;
694          std::shared_ptr<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
695          if (si != nullptr) {
696              const Sensor& s = si->getSensor();
697              if (mService->isSensorInCappedSet(s.getType())) {
698                  isSensorCapped = true;
699              }
700          }
701          if (isSensorCapped) {
702              err = mService->adjustSamplingPeriodBasedOnMicAndPermission(&samplingPeriodNs,
703                                  String16(mOpPackageName));
704              if (err != OK) {
705                  return err;
706              }
707          }
// 如果enable為true,使能的話,則調用sensorservice 的enable方法
708          err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
709                                 reservedFlags, mOpPackageName);
710          if (err == OK && isSensorCapped) {
711              if ((requestedSamplingPeriodNs >= SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) ||
712                  !isRateCappedBasedOnPermission()) {
713                  mMicSamplingPeriodBackup[handle] = requestedSamplingPeriodNs;
714              } else {
715                  mMicSamplingPeriodBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
716              }
717          }
718  
719      } else {
// 不使能,則調用disable方法
720          err = mService->disable(this, handle);
721          mMicSamplingPeriodBackup.erase(handle);
722      }
723      return err;
724  }

// 如果enable為true,使能的話,則調用sensorservice 的anable方法

/frameworks/native/services/sensorservice/SensorService.cpp

1921  status_t SensorService::enable(const sp<SensorEventConnection>& connection,
1922          int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
1923          const String16& opPackageName) {
1924      if (mInitCheck != NO_ERROR)
1925          return mInitCheck;
1926  
// 從sensorlist 中獲取對應handle 傳感器的接口
1927      std::shared_ptr<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
1928      if (sensor == nullptr ||
1929          !canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {
1930          return BAD_VALUE;
1931      }
。。。
// 先調用了 batch 方法;大概率是設置了采樣周期之類的
2018      status_t err = sensor->batch(connection.get(), handle, 0, samplingPeriodNs,
2019                                   maxBatchReportLatencyNs);
。。。。
2040      if (err == NO_ERROR) {
2041          ALOGD_IF(DEBUG_CONNECTIONS, "Calling activate on %d", handle);
// 調用 activate方法
2042          err = sensor->activate(connection.get(), true);
2043      }

// 對應的 SensorInterface 接口為如下:為 HardwareSensor

339                  if (useThisSensor) {
340                      if (list[i].type == SENSOR_TYPE_PROXIMITY) {
341                          auto s = std::make_shared<ProximitySensor>(list[i], *this);
342                          const int handle = s->getSensor().getHandle();
343                          if (registerSensor(std::move(s))) {
344                              mProxSensorHandles.push_back(handle);
345                          }
346                      } else {
// 如下注冊了對應的sensor,對應的 為 HardwareSensor
347                          registerSensor(std::make_shared<HardwareSensor>(list[i]));
348                      }

// 調用HardwareSensor的 activate方法

/frameworks/native/services/sensorservice/SensorInterface.cpp
// 通過 SensorDevice 去使能對應的sensor 的handle,找到對應的sensor

// ident為 SensorEventConnection
62  status_t HardwareSensor::activate(void* ident, bool enabled) {
63      return mSensorDevice.activate(ident, mSensor.getHandle(), enabled);
64  }

/frameworks/native/services/sensorservice/SensorDevice.cpp

437  status_t SensorDevice::activate(void* ident, int handle, int enabled) {
438      if (mHalWrapper == nullptr) return NO_INIT;
439  
440      Mutex::Autolock _l(mLock);
441      return activateLocked(ident, handle, enabled);
442  }
444  status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {
445      bool activateHardware = false;
446  
447      status_t err(NO_ERROR);
448  
449      ssize_t activationIndex = mActivationCount.indexOfKey(handle);
450      if (activationIndex < 0) {
451          ALOGW("Handle %d cannot be found in activation record", handle);
452          return BAD_VALUE;
453      }
454      Info& info(mActivationCount.editValueAt(activationIndex));
455  
456      ALOGD_IF(DEBUG_CONNECTIONS,
457               "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu", ident,
458               handle, enabled, info.batchParams.size());
459  
460      if (enabled) {
461          ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
462  
463          if (isClientDisabledLocked(ident)) {
464              ALOGW("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d", ident,
465                    handle);
466              return NO_ERROR;
467          }
468  
469          if (info.batchParams.indexOfKey(ident) >= 0) {
470              if (info.numActiveClients() > 0 && !info.isActive) {
471                  activateHardware = true;
472              }
。。。。
509      if (activateHardware) {
510          err = doActivateHardwareLocked(handle, enabled);
526  status_t SensorDevice::doActivateHardwareLocked(int handle, bool enabled) {
527      ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
528               enabled);
529      status_t err = mHalWrapper->activate(handle, enabled);
530      ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
531               strerror(-err));
532      return err;
533  }

/frameworks/native/services/sensorservice/AidlSensorHalWrapper.cpp

227  status_t AidlSensorHalWrapper::activate(int32_t sensorHandle, bool enabled) {
228      if (mSensors == nullptr) return NO_INIT;
// 調用aidl binder 通信去激活sensor
229      return convertToStatus(mSensors->activate(sensorHandle, enabled));
230  }

/hardware/interfaces/sensors/aidl/default/multihal/HalProxyAidl.cpp

122  ScopedAStatus HalProxyAidl::activate(int32_t in_sensorHandle, bool in_enabled) {
123    return resultToAStatus(HalProxy::activate(in_sensorHandle, in_enabled));
124  }

/hardware/interfaces/sensors/common/default/2.X/multihal/HalProxy.cpp

161  Return<Result> HalProxy::activate(int32_t sensorHandle, bool enabled) {
162      if (!isSubHalIndexValid(sensorHandle)) {
163          return Result::BAD_VALUE;
164      }
// 下列會通過hal層去設置使能傳感器了
165      return getSubHalForSensorHandle(sensorHandle)
166              ->activate(clearSubHalIndex(sensorHandle), enabled);
167  }

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87339.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87339.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87339.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

新版本沒有docker-desktop-data分發 | docker desktop 鏡像遷移

在新版本的docker desktop中&#xff08;如4.42版本&#xff09;&#xff0c;鏡像遷移只需要更改路徑即可。如下&#xff1a; 打開docker desktop的設置&#xff08;圖1&#xff09;&#xff0c;將圖2的原來的地址C:\Users\用戶\AppData\Local\Docker\wsl修改為你想要的空文件…

EtherCAT SOEM源碼分析 - ec_init

ec_init SOEM主站一切開始的地方始于ec_init, 它是EtherCAT主站初始化的入口。初始化SOEM 主站&#xff0c;并綁定到socket到ifname。 /** Initialise lib in single NIC mode* param[in] ifname Dev name, f.e. "eth0"* return >0 if OK* see ecx_init*/ in…

84、原理解析-SpringApplication創建初始化流程

84、原理解析-SpringApplication初始化流程 # SpringApplication創建初始化流程原理解析 SpringApplication的創建和初始化是Spring Boot應用啟動的關鍵步驟&#xff0c;主要包括以下過程&#xff1a; ## 1. 創建SpringApplication實例 ### 1.1 調用構造函數 - 當調用SpringApp…

【數理邏輯】 選擇公理與集值映射

目錄 選擇公理1. 有限指標集 I I I2. 可數無限指標集 I I I &#xff08;簡稱為 ACC 或 ACω&#xff09;3. 不可數無限指標集 I I I4. 選擇公理的層級與數學應用5. 選擇公理的深層意義 集值映射的選擇函數1. 選擇公理的核心作用2. 不同情況下的依賴性分析3. AC 的必要性證明…

微信小程序使用wx.chooseImage上傳圖片時進行壓縮,并添加時間水印

在微信小程序的開發過程&#xff0c;經常會使用自帶的api(wx.chooseImage)進行圖片拍照或選擇圖片進行上傳&#xff0c;有時圖片太大&#xff0c;造成上傳和下載時過慢&#xff0c;現對圖片進行壓縮后上傳&#xff0c;以下是流程和代碼 一、小程序的版本選擇了3.2.5&#xff0…

RAII簡介

&#x1f4e6; 一、技術原理簡介&#xff1a;RAII是個“托管狂魔” 想象你有個健忘的朋友&#xff0c;每次借東西都會忘記歸還。RAII&#xff08;Resource Acquisition Is Initialization&#xff0c;資源獲取即初始化&#xff09;就是C派來的“超級管家”&#xff1a; “你負…

微信小程序入門實例_____打造你的專屬單詞速記小程序

上次通過天氣查詢小程序&#xff0c;我們初探了微信小程序開發的世界。這次&#xff0c;咱們再挑戰一個有趣又實用的項目 ——“單詞速記小程序”。無論是學生黨備考&#xff0c;還是上班族提升英語&#xff0c;都能用得上&#xff01;接下來就跟著我&#xff0c;一步一步把它做…

gateway白名單存儲nacos,改成存儲數據庫

前言 很久沒寫博客了&#xff0c;csdn都開始ai潤色了&#xff0c;之前都是看相應框架的源碼看了個遍&#xff0c;感覺底層原理都差不多&#xff0c;這陣子著手改造了下gateway中的白名單&#xff0c;之前白名單存儲到nacos&#xff0c;要改成存到數據庫。里面涉及到淺淺的源碼…

ubentu服務器版本安裝Dify

Docker 中安裝Dify 首先安裝Docker 1. 克隆Dify代碼倉庫 從github克隆 Dify 源代碼至要本地環境。 我的ubentu服務器版本&#xff0c;我把源代碼下載到 /var/下 在var文件夾下執行 git clone https://github.com/langgenius/dify.git執行成功后&#xff0c;進入Dify源代碼的…

Redis分布式鎖實戰:從入門到生產級方案

目錄 一、為什么需要分布式鎖&#xff1f; 二、Redis分布式鎖核心特性 三、實現方案與代碼詳解 方案1&#xff1a;基礎版 SETNX EXPIRE 原理 代碼示例 問題 方案2&#xff1a;Redisson框架&#xff08;生產推薦&#xff09; 核心特性 代碼示例 優勢 方案3&#xff…

【Redis】StringRedisTemplate 和 RedisTemplate 的區別

StringRedisTemplate 和 RedisTemplate 是 Spring Data Redis 提供的兩種用于操作 Redis 的模板類&#xff0c;它們的核心區別在于 序列化方式 和 操作的數據類型。以下是兩者的主要區別和使用建議&#xff1a; ? 1. 數據類型支持 類名支持的數據類型說明RedisTemplate支持所…

docker-compose快速搭建redis集群

目錄結構 redis-cluster/ ├── config/ │ ├── master.conf │ ├── slave1.conf │ └── slave2.conf └── docker-compose.yml配置文件內容 1. config/master.conf # Redis主節點配置 port 6379 bind 0.0.0.0 protected-mode no logfile "redis-mas…

SpringCloud系列(39)--SpringCloud Gateway常用的Route Predicate

前言&#xff1a;在上一節中我們實現了SpringCloud Gateway的動態路由 &#xff0c;而在本節中我們將著重介紹各種Route Predicate的作用。 1、可以到官方文檔里查看常用的Route Predicate的種類 https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.REL…

漸變色的進度條控件

近日&#xff0c;用VB.net2003重寫了一個漸變色的進度條控件。主要有以下功能&#xff1a; 支持自定義進度條分段數量&#xff0c;可拆分為多個步驟&#xff1b;每個步驟可獨立顯示完成百分比及漸變色效果。 每個步驟均可配置任務名稱和描述&#xff1b;運行時能實時顯示當前執…

【DICOM后處理】qt+vs 實現DICOM數據四視圖顯示

目錄 1、DICOM四視圖2、vtkImageViewer2 實現二維平面圖顯示3、vtkVolume實現三維體數據顯示4、實現界面圖 1、DICOM四視圖 DICOM四視圖通常指同時顯示醫學影像的四個不同平面或視角&#xff0c;用于全面分析三維數據&#xff08;如CT、MRI等&#xff09;。 標準四視圖布局&a…

Google Maps 安裝使用教程

一、Google Maps 簡介 Google Maps 是谷歌提供的地圖服務&#xff0c;通過其 JavaScript API&#xff0c;開發者可以在網頁中嵌入地圖&#xff0c;添加標記、路徑、地理編碼、路線導航等功能&#xff0c;適用于位置展示、物流追蹤、LBS 應用等場景。 二、獲取 Google Maps API…

Nginx+Keepalived實現前臺服務高可用

現階段項目開發往往采用前后臺分離&#xff0c;前臺常用的技術有vue、react等&#xff0c;前臺代碼部署在nginx中&#xff0c;代碼中配置了后臺服務的網關地址&#xff0c;由網關向后臺分發服務請求&#xff0c;架構示意圖如下&#xff1a; 在上述架構圖中&#xff0c;如果Ngin…

Gradio全解13——MCP協議詳解(5)——Python包命令:uv與uvx實戰

Gradio全解13——MCP協議詳解&#xff08;5&#xff09;——Python包命令&#xff1a;uv與uvx實戰 第13章 MCP協議詳解13.5 Python包命令&#xff1a;uv與uvx實戰13.5.1 uv核心亮點與常用命令1. uv介紹2. 安裝與項目管理3. 腳本與工具4. Python版本與pip接口 13.5.2 uv核心指令…

OD 算法題 B卷【求最小步數】

文章目錄 求最小步數 求最小步數 求從坐標零點到坐標點n的最小步數&#xff0c;一次只能沿著橫坐標軸向左或向右移動2或3&#xff1b;途經的坐標點可以為負數&#xff1b; 輸入描述: 坐標點n 輸出描述: 從坐標零點移動到坐標點n的最小步數 n在【1,10^9】 示例1 輸入&#xf…

Elasticsearch 集群升級實戰指引—7.x 升級到 8.x

升級Elasticsearch集群從7.x到8.x是一項復雜且關鍵的任務&#xff0c;涉及重大版本變更&#xff08;如API調整、配置變更、安全功能強制啟用等&#xff09;&#xff0c;可能影響集群的性能和穩定性。結合您提到的業務量增長導致索引寫入變慢的問題&#xff0c;本指引不僅提供詳…