【安卓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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;本指引不仅提供详…