Android Camera(三)Camera Service的初始化代码分析(AndroidR)

news2025/6/7 23:17:34

highlight: a11y-dark

1.APP CameraManager初始化

CameraManager初始化代码较少,放在这里进行讲解,CameraManager是一个用来管理相机的系统服务,可以通过此服务获取到相机设备和相机信息,在frameworks/base/core/java/android/app/SystemServiceRegistry.java 注册

image.png
应用层可以通过下面方法获取一个CameraManager实例

CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);

代码实现:/frameworks/base/core/java/android/hardware/camera2/

image.png

2.Native层CameraServer启动

由于CameraServer需要连接CameraProvider,所以一般来说CameraSever后于CameraProvider启动,CameraServer的启动脚本在cameraserver.rc这个文件,文件位置为frameworks/av/camera/cameraserver/cameraserver.rc

service cameraserver/system/bin/camera
       class main
       user   cameraserver
       group audio   camera input drmrpc
         ioprio rt 4
         task_profiles CameraServiceCapacity MaxPerformance
         rlimit rtprio 10 10

2.1 main_cameraserver.cpp

此文件为camerserver的入口,创建CameraService实例,并将其添加到ServiceManager中
路径:frameworks/av/camera/cameraserver/main_cameraserver.cpp

#define LOG_TAG "cameraserver"
   //#define LOG_NDEBUG 0
  
   #include   "CameraService.h"
   #include   <hidl/HidlTransportSupport.h>
    
   using namespace android;
    
   int main(int argc __unused, char** argv   __unused)
   {
         signal(SIGPIPE, SIG_IGN);
    
         // Set 5 threads for HIDL calls.   Now cameraserver will serve HIDL calls in
         // addition to consuming them from   the Camera HAL as well.
         hardware::configureRpcThreadpool(5, /*willjoin*/ false);
    
         sp<ProcessState> proc(ProcessState::self());
         sp<IServiceManager> sm = defaultServiceManager();
         ALOGI("ServiceManager:   %p", sm.get());
         CameraService::instantiate();
         ALOGI("ServiceManager: %p done   instantiate", sm.get());
         ProcessState::self()->startThreadPool();
         IPCThreadState::self()->joinThreadPool();
   }
    
   //路径http://aospxref.com/android-11.0.0_r21/xref/frameworks/native/include/binder/BinderService.h
   template<typename SERVICE>
     class BinderService
     {
     public:
           static status_t publish(bool allowIsolated =   false,
                                 int dumpFlags =   IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT)   {
               sp<IServiceManager> sm(defaultServiceManager());
               return sm->addService(String16(SERVICE::getServiceName()),   new SERVICE(), allowIsolated,
                                   dumpFlags);
         }
     
    
           static void instantiate() { publish(); }
   }
   //http://aospxref.com/android-11.0.0_r21/xref/frameworks/av/services/camera/libcameraservice/CameraService.h
     class CameraService :
         public   BinderService<CameraService>,
         public   virtual ::android::hardware::BnCameraService,
         public   virtual IBinder::DeathRecipient,
         public   virtual CameraProviderManager::StatusListener
     {
       
     static char const* getServiceName(){ return "media.camera"; }
     }
    
   //http://aospxref.com/android-11.0.0_r21/xref/frameworks/native/cmds/servicemanager/ServiceManager.cpp
   inline   virtual status_t addService(const String16 &   name, const   sp<IBinder> & service, bool allowIsolated) {
           。。。。
           };	 

CameraService::instantiate()用来实例化一个CameraService对象,其中CameraService继承BinderService,BinderService为一个模板类,native service通过sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,dumpFlags)这种方式来将服务注册到ServiceManager,所以SERVICE为CameraService,向sp sm注册CameraService服务。调用addService函数时会实例化CameraService并将赋值sp强指针引用,从而调用CameraService的onFirstRef成员函数

2.2 CameraService::onFirstRef

在此函数中,主要调用的函数为enumerateProviders(),用来获取CameraProvider的信息
代码位置:frameworks/av/services/camera/libcameraservice/CameraService.cpp

   151  void CameraService::onFirstRef()
   152  {
   153      ALOGI("CameraService   process starting");
   154  
   155        BnCameraService::onFirstRef();//调用父类的OnFirstRef()函数
   156  
   157      //   Update battery life tracking if service is restarting
   158      BatteryNotifier& notifier(BatteryNotifier::getInstance());
   159      notifier.noteResetCamera();
   160      notifier.noteResetFlashlight();
   161  
   162      status_t res = INVALID_OPERATION;
   163  
   164      res =   enumerateProviders();//获取CameraProvider信息
   165      if (res == OK) {
   166          mInitialized = true;
   167      }
   168  
   169      mUidPolicy = new UidPolicy(this);
   170      mUidPolicy->registerSelf();
   171      mSensorPrivacyPolicy = new   SensorPrivacyPolicy(this);
   172        mSensorPrivacyPolicy->registerSelf();
   173        mAppOps.setCameraAudioRestriction(mAudioRestriction);
   174      sp<HidlCameraService> hcs =   HidlCameraService::getInstance(this);
   175      if (hcs->registerAsService() != android::OK) {
   176          ALOGE("%s: Failed to register default   android.frameworks.cameraservice.service@1.0",
   177                __FUNCTION__);
   178      }
   179  
   180      //   This needs to be last call in this function, so that it's as close to
   181      //   ServiceManager::addService() as possible.
   182        CameraService::pingCameraServiceProxy();
   183      ALOGI("CameraService   pinged cameraservice proxy");
   184  }

2.3 CameraService::enumerateProviders()

在enumerateProviders()中会实例化一个CameraProviderManager对象,并调用CameraProviderManager的initialize函数,将CameraSevice作为一个成员变量传入到initialize
代码位置:frameworks/av/services/camera/libcameraservice/CameraService.cpp#enumerateProviders

   186  status_t CameraService::enumerateProviders() {
   187      status_t res;
   188  
   189      std::vector<std::string> deviceIds;
   190      {
   191          Mutex::Autolock l(mServiceLock);
   192  
   193          if (nullptr == mCameraProviderManager.get()) {
   194                mCameraProviderManager = new CameraProviderManager();//实例化CameraProviderManager,并且调用其initialize函数
   195              res =   mCameraProviderManager->initialize(this);
   196              if (res != OK) {
   197                  ALOGE("%s: Unable to initialize camera provider manager:   %s (%d)",
   198                          __FUNCTION__,   strerror(-res), res);
   199                  return res;
   200              }
   201          }
   202  
   203  
   204          //   Setup vendor tags before we call get_camera_info the first time
   205          //   because HAL might need to setup static vendor keys in get_camera_info
   206          //   TODO:   maybe put this into CameraProviderManager::initialize()?
   207            mCameraProviderManager->setUpVendorTags();
   208  
   209          if (nullptr == mFlashlight.get()) {
   210                mFlashlight = new CameraFlashlight(mCameraProviderManager, this);//创建Flashlight对象
   211          }
   212  
   213          res =   mFlashlight->findFlashUnits();
   214          if (res != OK) {
   215              ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
   216          }
   217  
   218            deviceIds = mCameraProviderManager->getCameraDeviceIds();//获取摄像头ID集合
   219      }
   220  
   221  
   222      for (auto& cameraId : deviceIds) {
   223          String8 id8 =   String8(cameraId.c_str());
   224          if (getCameraState(id8) == nullptr) {
   225                onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);//更新Camera的状态,暂时不理解
   226          }
   227      }
   228  
   229      return OK;
   230  }

2.4 CameraProviderManager::initialize

代码位置:frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp

image.png
initialize主要做三件事情

  1. 将传下来的CameraService对象赋给mListener以此来通知CameraSevice状态的变化,mListener的实现类似于java的回调机制,由于CameraService在调用initialize函数
    时没有传入第二个参数,所以proxy使用默认参数并且将sHardwareServiceInteractionProxy静态变量赋给mServiceProxy,
    代码位置frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.h
    image.png

image.png
2.调用mServiceProxy->registerForNotifications来调用hardware:📷:provider::V2_4::ICameraProvider的静态方法registerForNotifications
代码位置:frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.h

image.png
3.通过this->addProviderLocked来获取当前系统中的CameraProiver对象
代码位置:

frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp#addProviderLocked

image.png
1.调用mServiceProxy->tryGetService(newProvider),会最终调用到一个名为HIDL_FETCH_ICameraProvider 的函数,并且将CameraProvider赋值给
interface
代码位置:hardware/interfaces/camera/provider/2.4/default/CameraProvider_2_4.cpp

template<typename IMPL>
   CameraProvider<IMPL>* getProviderImpl() {
         CameraProvider<IMPL> *provider = new   CameraProvider<IMPL>();
         if   (provider == nullptr) {
             ALOGE("%s: cannot allocate   camera provider!", __FUNCTION__);
             return nullptr;
       }
         if   (provider->isInitFailed()) {
             ALOGE("%s: camera provider   init failed!", __FUNCTION__);
           delete   provider;
             return nullptr;
       }
         return provider;
   }
    
   ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
       using   namespace android::hardware::camera::provider::V2_4::implementation;
         ICameraProvider* provider = nullptr;
         if   (strcmp(name,   kLegacyProviderName) == 0) {
           provider   = getProviderImpl<LegacyCameraProviderImpl_2_4>();
         } else if (strcmp(name, kExternalProviderName) == 0) {
           provider   = getProviderImpl<ExternalCameraProviderImpl_2_4>();
         } else {
             ALOGE("%s: unknown instance   name: %s", __FUNCTION__, name);
       }
    
         return provider;
   }
    
   const   char *kLegacyProviderName = "legacy/0";
   const   char *kExternalProviderName = "external/0";

通过比较名字来初始化对应的CameraProvider,从而调用不同CamerProvider的构造函数,以LegacyCameraProviderImpl_2_4为例,在initialize函数中会调用
camera hal module中的函数,例如原生的camera.v4l2.so
代码位置:hardware/interfaces/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp

image.png

image.png

image.png
2.实例化一个ProviderInfo对象,并传入对应的CameraProvider对象和CameraProviderManager对象,将报错CameraProvider的名字,这里的名字分别为
“legacy/0” 和 “external/0”,也可自行扩展,并将CameraProviderManager对象赋值给mManager,方便后续查找

image.png
3.调用已经实例化的ProviderInfo对象的initialize,在initialize函数中主要调用interface即对应CameraProiver对象的来和Hal层进行通信

 setCallback(this)
    linkToDeath
    getCameraIdList
   isSetTorchModeSupported

填充从Camera Provider中获取到的Camera名字到device向量中和填充Camera id到mProviderPublicCameraIds向量中
代码位置:

frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
status_t   CameraProviderManager::ProviderInfo::initialize(
             sp<provider::V2_4::ICameraProvider>& interface,
             hardware::hidl_bitfield<provider::V2_5::DeviceState>   currentDeviceState) {
       status_t res   = parseProviderName(mProviderName, &mType, &mId);
         if   (res != OK) {
             ALOGE("%s: Invalid provider   name, ignoring", __FUNCTION__);
             return BAD_VALUE;
       }
         ALOGI("Connecting to new   camera provider: %s, isRemote? %d",
                 mProviderName.c_str(), interface->isRemote());
    
         // Determine minor version
         mMinorVersion = 4;
         auto   cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
         sp<provider::V2_6::ICameraProvider> interface2_6 = nullptr;
         if   (cast2_6.isOk()) {
             interface2_6 = cast2_6;
             if   (interface2_6 != nullptr) {
               mMinorVersion = 6;
           }
       }
         // We need to check again since   cast2_6.isOk() succeeds even if the provider
         // version isn't actually 2.6.
         if   (interface2_6 == nullptr){
             auto   cast2_5 =
                     provider::V2_5::ICameraProvider::castFrom(interface);
             sp<provider::V2_5::ICameraProvider> interface2_5 = nullptr;
             if   (cast2_5.isOk()) {
                 interface2_5 = cast2_5;
               if (interface != nullptr) {
                   mMinorVersion = 5;
               }
           }
       }
    
         // cameraDeviceStatusChange   callbacks may be called (and causing new devices added)
         // before setCallback returns
         hardware::Return<Status> status =   interface->setCallback(this);
         if   (!status.isOk()) {
             ALOGE("%s: Transaction error   setting up callbacks with camera provider '%s': %s",
                     __FUNCTION__, mProviderName.c_str(), status.description().c_str());
             return DEAD_OBJECT;
       }
         if   (status != Status::OK) {
             ALOGE("%s: Unable to register   callbacks with camera provider '%s'",
                     __FUNCTION__, mProviderName.c_str());
             return mapToStatusT(status);
       }
    
         hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
         if   (!linked.isOk()) {
             ALOGE("%s: Transaction error   in linking to camera provider '%s' death: %s",
                     __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
             return DEAD_OBJECT;
         } else if (!linked) {
             ALOGW("%s: Unable to link to   provider '%s' death notifications",
                     __FUNCTION__, mProviderName.c_str());
       }
    
         if   (!kEnableLazyHal) {
             // Save HAL reference indefinitely
           mSavedInterface = interface;//保存CameraProvider对象
         } else {
             mActiveInterface = interface;
       }
    
         ALOGV("%s: Setting device   state for %s: 0x%" PRIx64,
                 __FUNCTION__, mProviderName.c_str(), mDeviceState);
         notifyDeviceStateChange(currentDeviceState);
    
       res =   setUpVendorTags();
         if   (res != OK) {
             ALOGE("%s: Unable to set up   vendor tags from provider '%s'",
                     __FUNCTION__, mProviderName.c_str());
             return res;
       }
    
         // Get initial list of camera   devices, if any
         std::vector<std::string> devices;
         hardware::Return<void> ret =   interface->getCameraIdList([&status, this, &devices](
                 Status idStatus,
               const hardware::hidl_vec<hardware::hidl_string>&   cameraDeviceNames) {
           status =   idStatus;
             if   (status == Status::OK) {
               for (auto& name : cameraDeviceNames) {
                     uint16_t major, minor;
                   std::string type, id;
                     status_t res = parseDeviceName(name, &major, &minor,   &type, &id);
                   if (res != OK) {
                       ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
                         status = Status::INTERNAL_ERROR;
                   } else {
                       devices.push_back(name);//填充从Camera Provider中获取到的Camera名字到device向量中
                         mProviderPublicCameraIds.push_back(id);//填充Camera   id到mProviderPublicCameraIds向量中
                     }
               }
           } });
         if   (!ret.isOk()) {
             ALOGE("%s: Transaction error   in getting camera ID list from provider '%s': %s",
                     __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
             return DEAD_OBJECT;
       }
         if   (status != Status::OK) {
             ALOGE("%s: Unable to query for   camera devices from provider '%s'",
                     __FUNCTION__, mProviderName.c_str());
             return mapToStatusT(status);
       }
    
         // Get list of concurrent streaming   camera device combinations
         if   (mMinorVersion >= 6) {
           res =   getConcurrentCameraIdsInternalLocked(interface2_6);
             if   (res != OK) {
               return res;
           }
       }
    
       ret =   interface->isSetTorchModeSupported(
             [this](auto status, bool supported) {
               if (status == Status::OK) {
                     mSetTorchModeSupported = supported;
               }
           });
         if   (!ret.isOk()) {
             ALOGE("%s: Transaction error   checking torch mode support '%s': %s",
                     __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
             return DEAD_OBJECT;
       }
    
       mIsRemote =   interface->isRemote();
    
         sp<StatusListener> listener = mManager->getStatusListener();//CameraSevice
         for   (auto&   device : devices) {
             std::string id;
           status_t   res = addDevice(device, common::V1_0::CameraDeviceStatus::PRESENT, &id);
             if   (res != OK) {
               ALOGE("%s: Unable to enumerate camera device '%s': %s   (%d)",
                         __FUNCTION__, device.c_str(), strerror(-res), res);
               continue;
           }
       }
    
         ALOGI("Camera provider %s   ready with %zu camera devices",
                 mProviderName.c_str(), mDevices.size());
    
         // Process cached status callbacks
         std::unique_ptr<std::vector<CameraStatusInfoT>>   cachedStatus =
               std::make_unique<std::vector<CameraStatusInfoT>>();
       {
             std::lock_guard<std::mutex> lock(mInitLock);
    
             for   (auto&   statusInfo : mCachedStatus) {
               std::string id, physicalId;
                 status_t res = OK;
               if (statusInfo.isPhysicalCameraStatus) {
                     res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
                         statusInfo.cameraId, statusInfo.physicalCameraId, statusInfo.status);
               } else {
                     res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId,   statusInfo.status);
               }
               if (res == OK) {
                     cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
                             id.c_str(), physicalId.c_str(), statusInfo.status);
               }
           }
             mCachedStatus.clear();
    
             mInitialized = true;
       }
    
         // The cached status change   callbacks cannot be fired directly from this
         // function, due to same-thread   deadlock trying to acquire mInterfaceMutex
         // twice.
         if   (listener != nullptr) {
             mInitialStatusCallbackFuture = std::async(std::launch::async,
                     &CameraProviderManager::ProviderInfo::notifyInitialStatusChange,   this,
                   listener, std::move(cachedStatus));
       }
    
         return OK;
   }

并将每一个Camera的信息保存到ProviderInfo对象的mDevices中,并将Camera id插入到mUniqueCameraIds列表中

image.png

image.png
4.addProviderLocked将ProviderInfo信息push到CameraManagerProvider对象中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/334590.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

下载好python后,怎么打开,python怎么进入编程界面

大家好&#xff0c;给大家分享一下python下载安装好后怎么打开&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 1、python第一次怎么打开 python第一次打开方法如下&#xff1a; winr快捷键打开运行窗口&#xff0c;在运行窗口输入栏中输入…

基于C#制作一个飞机大战小游戏

此文主要基于C#制作一个飞机大战游戏&#xff0c;重温经典的同时亦可学习。 实现流程1、创建项目2、界面绘制3、我方飞机4、敌方飞机5、子弹及碰撞检测实现流程 1、创建项目 打开Visual Studio&#xff0c;右侧选择创建新项目。 搜索框输入winform&#xff0c;选择windows窗体…

线程的生命周期和状态中方法的详解

点个关注&#xff0c;必回关 一、线程的生命周期和状态图&#xff1a; 图一&#xff1a; 图二 二、线程状态 1&#xff1a;新建 2&#xff1a;就绪&#xff08;拿到执行权开始运行&#xff09; 3&#xff1a;运行 4&#xff1a;阻塞 5&#xff1a;死亡 三、线程生命周期…

CUDA中的动态并行

CUDA的动态并行 文章目录CUDA的动态并行1. 介绍1.1. 简述警告&#xff1a;与父块的子内核显式同步&#xff08;即在设备代码中使用 cudaDeviceSynchronize()&#xff09;在 CUDA 11.6 中已弃用&#xff0c;并计划在未来的 CUDA 版本中删除。1.2. 术语2. 执行环境和内存模型2.1.…

ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程

ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程 我家里的MAC没这个问题。这个是在windows上发生的。 起因很简单我用ASP.NET CORE 3.1 MVC做个项目做登录将数据从VIEW post到Controller上结果意外的报了错误。 各种百度都说…

不要再问Spring是如何解决循环依赖了

1、什么是循环依赖&#xff1f; 循环依赖主要来次三个方面&#xff0c;第一种A相互依赖&#xff0c;第二种是 A依赖B&#xff0c;B依赖A&#xff0c;第三种是A依赖B&#xff0c;B依赖C&#xff0c;C依赖A。 总结一句话就是对象之间形成环形依赖。 代码如下&#xff1a; 第一…

FPGA时序约束与分析 (1)--- 约束工具及相关命令的使用

注意&#xff1a; 时序约束辅助工具或者相关的TCL命令&#xff0c;都必须在 open synthesis design / open implemention design 后才能有效运行。 1、时序约束辅助工具 2、查看相关时序信息 3、一般的时序约束顺序 1、 时序约束辅助工具&#xff08;1&#xff09;时序约束编辑…

蓝桥杯刷题练习Python(笔记)

# a1 A # a2 A B A # a3 ABA C ABA # a4 ABACABADABACABAnum int(input(N < 26:)) # 26 个字母 str "ABCDEFGHIJKLMNOPQRSTUVWXYZ"if num 1:a A # str[0] else:a Afor i in range(1, num, 1): # b str[i]c a b aa c# print(str[i])# print(a) …

【React】从 0 开始学 React —— 实现井字棋小游戏

目录1 React 简介2 实现井字棋小游戏2.1 初始化2.2 props2.3 setState2.4 状态提升2.5 副本2.6 简化组件2.7 key2.8 小结3 核心概念1 React 简介 React 是一个声明式&#xff0c;高效且灵活的用于构建用户界面的 JavaScript 库 官网提供了两种学习思路 如果你喜欢边做边学&am…

Vue3 组件之间的通信

组件之间的通信 经过前面几章的阅读&#xff0c;相信开发者已经可以搭建一个基础的 Vue 3 项目了&#xff01; 但实际业务开发过程中&#xff0c;还会遇到一些组件之间的通信问题&#xff0c;父子组件通信、兄弟组件通信、爷孙组件通信&#xff0c;还有一些全局通信的场景。 …

【GPLT 二阶题目集】L2-043 龙龙送外卖

参考地址&#xff1a;AcWing 4474. 龙龙送外卖&#xff08;杂题选讲&#xff09; 作者&#xff1a;yxc 感谢y总&#xff01; 龙龙是“饱了呀”外卖软件的注册骑手&#xff0c;负责送帕特小区的外卖。帕特小区的构造非常特别&#xff0c;都是双向道路且没有构成环 —— 你可以…

Spring Cloud Alibaba Sentinel 控制台

简介 Sentinel 控制台是流量控制、熔断降级规则统一配置和管理的入口&#xff0c;它为用户提供了机器自发现、簇点链路自发现、监控、规则配置等功能。在 Sentinel 控制台上&#xff0c;我们可以配置规则并实时查看流量控制效果。 下载 有以下两种方式获取Sentinel控制台 下…

进阶技术:Linux Arm32是如何调用C Main的

前言&#xff1a; Linux x64通过qemu的rdinit方式调用的C Main&#xff0c;实际上是通过load_elf_binary(加载和解析elf)和start_thread(设置Ip和sp)&#xff0c;用缺页异常来调用。关于这点可以看这篇文章&#xff1a;点击查看。那么Arm32里面是如何调用C Main的呢&#xff1f…

Android 进阶——Framework 核心之Binder 相关预备理论(一)

文章大纲引言一、进程的内存空间和进程隔离二、Linux 系统内存的用户空间和内核空间1、用户空间&#xff08;User Space&#xff09;2、内核空间&#xff08;Kernel Space&#xff09;三、Linux IPC 原理1、内核态和用户态2、IPC 步骤四、内核模块和驱动五、Binder1、Binder IP…

优思学院|從《狂飙》高启强爱看的《孙子兵法》到六西格玛项目管理

近期最受人瞩目的&#xff0c;无疑是电视剧《狂飙》中出类拔萃的反派高启强。而在剧中&#xff0c;指引高启强走向顶峰的&#xff0c;正是那部著名的军事经典——《孙子兵法》。 在剧中&#xff0c;高启强在一次村庄改造项目上遇到了困难&#xff0c;但他仍保持冷静&#xff0…

QT开发安卓程序初识

Qt | Qt For Android、Qt5.14.2安卓开发环境搭建详细步骤 测试结果如下&#xff1a;

AcWing 840. 模拟散列表

题目描述 餐前小菜&#xff1a; 在讨论本题目之前先看一个简单的问题&#xff1a;给出 NNN 个正整数 (a1,a2,...,an)(a_1,a_2,...,a_n)(a1​,a2​,...,an​)&#xff0c;再给出 MMM 个正整数 (x1,x2,...,xm)(x_1,x_2,...,x_m)(x1​,x2​,...,xm​)&#xff0c;问这 MMM 个数中…

冷知识|鹤顶红还能用来修长城?

大家好&#xff0c;我是建模助手。 在上篇浅浅地蹭了波热点之后&#xff0c;我灵机一动&#xff0c;倒不如也搞一搞建筑方面的冷知识&#xff1f;冷热搭配&#xff0c;事半功倍... 问问大家&#xff0c;如果谈起古建筑&#xff0c;关键词都有什么&#xff1f;是庄严、震撼、壮…

DHCP实验及配置

DHCP实验配置基于接口拓扑图配置基于全局拓扑图配置基于接口 拓扑图 配置 [Huawei]dhcp enable//在全局下使能DHCP服务 [Huawei]interface GigabitEthernet0/0/0//进入接口 [Huawei-GigabitEthernet0/0/0] ip address 192.168.1.1 255.255.255.0 //配置接口地址 [Huawei-Giga…

什么是QoS?QoS是如何工作的?QoS的实验配置如何进行?

QoS&#xff08;Quality of Service&#xff09;是服务质量的简称。对于网络业务来说&#xff0c;服务质量包括哪些方面呢&#xff1f; 从传统意义上来讲&#xff0c;无非就是传输的带宽、传送的时延、数据的丢包率等&#xff0c;而提高服务质量无非也就是保证传输的带宽&…