秦嘉宏 發表於 2022-11-8 14:20:00

Android系统开发 android8之后版本读写Nvram

<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1>
<p><span style="color: rgba(0, 128, 128, 1)">  <span style="color: rgba(0, 0, 0, 1)">此博客讲解</span></span><span style="color: rgba(0, 0, 0, 1)">Android8之后的版本为准,Android8.0以前,是通过AIDL的方式去获取一个名为【NvRAMAgent】的服务。&nbsp;到了Android8.0之后,NVRAM的读写方式已经变更,不再通过AIDL去获取NVRAM服务,然后进行读写。而是通过HIDL的方式去获取服务来进行读写。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">  另外请注意,此博客讲解的是如何使用Android studio上编译的apk工程读写Nvram中的SN与WiFi的Mac地址。如果是系统工程apk请拉到博客最下面。</span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">了解文件位置</span></h1>
<p>在开始实现具体操作流程之前先了解下在系统工程目录里新的NVRAM是怎么生成的。HIDL的是需要依靠系统编译成so与jar形成接口来调用的,类似于AIDL与JNI的组合使用。另外这里只需要了解,并不需要修改这些文件与代码。因为我们需要得到经过系统编译后的so与jar文件,将其导入到后续我们的apk项目里。</p>
<h2><span style="color: rgba(0, 51, 102, 1)">hal文件</span></h2>
<p><span style="color: rgba(0, 0, 0, 1)">路径:</span></p>
<div class="cnblogs_code">
<pre>vendor/mediatek/proprietary/hardware/interfaces/nvram/<span style="color: rgba(128, 0, 128, 1)">1.0</span>/INvram.hal</pre>
</div>
<p>&nbsp;代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      </span><span style="color: rgba(0, 128, 0, 1); text-decoration: underline">http://www.apache.org/licenses/LICENSE-2.0</span><span style="color: rgba(0, 128, 0, 1)">
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

package vendor.mediatek.hardware.nvram@</span><span style="color: rgba(128, 0, 128, 1)">1.0</span><span style="color: rgba(0, 0, 0, 1)">;


</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
* Purpose:
* Nvram hidl interface is used by java layer to access nvram file
* Note:
* Support nvram file list in nvram@1.0 was listed as below
* Please update nvram interface and versoin if new nvram file need to be supported
*
/vendor/nvdata/APCFG/APRDEB/BT_Addr
/vendor/nvdata/APCFG/APRDCL/AUXADC
/vendor/nvdata/media/CAMERA_Para
/vendor/nvdata/media/CAMERA_3A
/vendor/nvdata/media/CAMERA_SHADING
/vendor/nvdata/media/CAMERA_DEFECT
/vendor/nvdata/media/CAMERA_SENSOR
/vendor/nvdata/media/CAMERA_LENS
/vendor/nvdata/APCFG/APRDCL/UART
/vendor/nvdata/APCFG/APRDCL/FACTORY
/vendor/nvdata/APCFG/APRDCL/BWCS
/vendor/nvdata/APCFG/APRDCL/HWMON_ACC
/vendor/nvdata/APCFG/APRDCL/HWMON_GYRO
/vendor/nvdata/media/Voice_Recognize_Param
/vendor/nvdata/media/Audio_AudEnh_Control_Opt
/vendor/nvdata/media/Audio_VOIP_Param
/vendor/nvdata/APCFG/APRDCL/HWMON_PS
/vendor/nvdata/APCFG/APRDCL/MD_Type
/vendor/nvdata/APCFG/APRDCL/EXT_MD_Type
/vendor/nvdata/APCFG/APRDCL/SDIO
/vendor/nvdata/media/CAMERA_VERSION
/vendor/nvdata/media/CAMERA_FEATURE
/vendor/nvdata/media/CAMERA_GEOMETRY
/vendor/nvdata/APCFG/APRDCL/MD_SBP
/vendor/nvdata/media/CAMERA_SHADING2
/vendor/nvdata/media/CAMERA_PLINE
/vendor/nvdata/media/CAMERA_AF
/vendor/nvdata/media/CAMERA_FLASH_CALIBRATION
/vendor/nvdata/media/Audio_Sph
/vendor/nvdata/APCFG/APRDEB/GPS
/vendor/nvdata/media/Audio_CompFlt
/vendor/nvdata/media/Audio_Effect
/vendor/nvdata/APCFG/APRDEB/WIFI
/vendor/nvdata/APCFG/APRDEB/WIFI_CUSTOM
/vendor/nvdata/media/Audio_Sph_Med
/vendor/nvdata/media/Audio_Vol_custom
/vendor/nvdata/media/Sph_Dual_Mic
/vendor/nvdata/media/Audio_Wb_Sph
/vendor/nvdata/APCFG/APRDEB/PRODUCT_INFO
/vendor/nvdata/media/Headphone_CompFlt
/vendor/nvdata/media/Audio_gain_table
/vendor/nvdata/media/Audio_ver1_Vol_custom
/vendor/nvdata/media/Audio_Hd_Record_Param
/vendor/nvdata/media/Audio_Hd_Record_Scene_Table
/vendor/nvdata/media/Audio_Buffer_DC_Calibration_Param
/vendor/nvdata/media/VibSpk_CompFlt
/vendor/nvdata/media/MusicDRC_CompFlt
/vendor/nvdata/media/RingToneDRC_CompFlt
/vendor/nvdata/media/Audio_MAGI_CONFERENCE
/vendor/nvdata/media/Audio_HAC_Param
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>

<span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> INvram {
    readFileByName(</span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> filename, uint32_t size)
            generates (</span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> data);
    writeFileByNamevec(</span><span style="color: rgba(0, 0, 255, 1)">string</span> filename, uint32_t size, vec&lt;uint8_t&gt;<span style="color: rgba(0, 0, 0, 1)"> data)
            generates (int8_t retval);
};</span></pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">.h文件</span></h2>
<p><span style="color: rgba(0, 51, 102, 1)">路径</span></p>
<div class="cnblogs_code">
<pre>vendor/mediatek/proprietary/external/libnvram/nvram_hidl/<span style="color: rgba(128, 0, 128, 1)">1.0</span>/NvRam.h</pre>
</div>
<p>代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">#ifndef VENDOR_MEDIATEK_HARDWARE_NVRAM_V1_0_NVRAM_H
</span><span style="color: rgba(0, 0, 255, 1)">#define</span> VENDOR_MEDIATEK_HARDWARE_NVRAM_V1_0_NVRAM_H<span style="color: rgba(0, 0, 0, 1)">

#include </span>&lt;vendor/mediatek/hardware/nvram/<span style="color: rgba(128, 0, 128, 1)">1.0</span>/INvram.h&gt;<span style="color: rgba(0, 0, 0, 1)">
#include </span>&lt;hidl/MQDescriptor.h&gt;<span style="color: rgba(0, 0, 0, 1)">
#include </span>&lt;hidl/Status.h&gt;

<span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> vendor {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> mediatek {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> hardware {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> nvram {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> V1_0 {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> implementation {

</span><span style="color: rgba(0, 0, 255, 1)">using</span> ::android::hidl::<span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">::V1_0::DebugInfo;
</span><span style="color: rgba(0, 0, 255, 1)">using</span> ::android::hidl::<span style="color: rgba(0, 0, 255, 1)">base</span><span style="color: rgba(0, 0, 0, 1)">::V1_0::IBase;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ::vendor::mediatek::hardware::nvram::V1_0::INvram;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ::android::hardware::hidl_array;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ::android::hardware::hidl_memory;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ::android::hardware::hidl_string;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ::android::hardware::hidl_vec;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ::android::hardware::Return;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ::android::hardware::Void;
</span><span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> ::android::sp;

</span><span style="color: rgba(0, 0, 255, 1)">struct</span> Nvram : <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> INvram {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Methods from ::vendor::mediatek::hardware::nvram::V1_0::INvram follow.</span>
    Return&lt;<span style="color: rgba(0, 0, 255, 1)">void</span>&gt; readFileByName(<span style="color: rgba(0, 0, 255, 1)">const</span> hidl_string&amp; filename, uint32_t size, readFileByName_cb _hidl_cb) <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)">;
    Return</span>&lt;int8_t&gt; writeFileByNamevec(<span style="color: rgba(0, 0, 255, 1)">const</span> hidl_string&amp; filename, uint32_t size, <span style="color: rgba(0, 0, 255, 1)">const</span> hidl_vec&lt;uint8_t&gt;&amp; data) <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Methods from ::android::hidl::base::V1_0::IBase follow.</span>
<span style="color: rgba(0, 0, 0, 1)">
};

</span><span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">C</span><span style="color: rgba(128, 0, 0, 1)">"</span> INvram* HIDL_FETCH_INvram(<span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">char</span>*<span style="color: rgba(0, 0, 0, 1)"> name);

}</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace implementation</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace V1_0</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace nvram</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace hardware</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace mediatek</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace vendor</span>

<span style="color: rgba(0, 0, 255, 1)">#endif</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> VENDOR_MEDIATEK_HARDWARE_NVRAM_V1_0_NVRAM_H</span></pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">.cpp文件</span></h2>
<p><span style="color: rgba(0, 51, 102, 1)">路径</span></p>
<div class="cnblogs_code">
<pre>vendor/mediatek/proprietary/external/libnvram/nvram_hidl/<span style="color: rgba(128, 0, 128, 1)">1.0</span>/NvRam.cpp</pre>
</div>
<p>代码:</p>
<div class="cnblogs_code">
<pre>#include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Nvram.h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
#include </span>&lt;android-<span style="color: rgba(0, 0, 255, 1)">base</span>/logging.h&gt;<span style="color: rgba(0, 0, 0, 1)">
#include </span>&lt;log/log.h&gt;<span style="color: rgba(0, 0, 0, 1)">
#include </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">libnvram.h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
#include </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">libnvram_log.h</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">using</span> std::<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;


</span><span style="color: rgba(0, 0, 255, 1)">#define</span> NVRAM_LOG(...) \
      <span style="color: rgba(0, 0, 255, 1)">do</span><span style="color: rgba(0, 0, 0, 1)"> { \
            ALOGD(__VA_ARGS__); \
      } </span><span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)


</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> vendor {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> mediatek {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> hardware {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> nvram {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> V1_0 {
</span><span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> implementation {
    </span><span style="color: rgba(0, 0, 255, 1)">void</span> covertVector2Array(std::vector&lt;uint8_t&gt; <span style="color: rgba(0, 0, 255, 1)">in</span>, <span style="color: rgba(0, 0, 255, 1)">char</span>* <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">int</span> size = <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)">.size();
      </span><span style="color: rgba(0, 0, 255, 1)">for</span>(<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; size; i++<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">out</span> = <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)">.at(i);
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">void</span> covertArray2Vector(<span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">char</span>* <span style="color: rgba(0, 0, 255, 1)">in</span>, <span style="color: rgba(0, 0, 255, 1)">int</span> len, std::vector&lt;uint8_t&gt;&amp; <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)">.clear();
      </span><span style="color: rgba(0, 0, 255, 1)">for</span>(<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; len; i++<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">out</span>.push_back(<span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)">);
      }
    }

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Methods from ::vendor::mediatek::hardware::nvram::V1_0::INvram follow.</span>
Return&lt;<span style="color: rgba(0, 0, 255, 1)">void</span>&gt; Nvram::readFileByName(<span style="color: rgba(0, 0, 255, 1)">const</span> hidl_string&amp;<span style="color: rgba(0, 0, 0, 1)"> filename, uint32_t size, readFileByName_cb _hidl_cb) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO implement</span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> pRecSize=<span style="color: rgba(128, 0, 128, 1)">0</span>,pRecNum=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">bool</span> IsRead=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">char</span> *buff=<span style="color: rgba(0, 0, 0, 1)">NULL;
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> file_lid = -<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> result;
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">char</span> *nvramstr = (<span style="color: rgba(0, 0, 255, 1)">char</span>*)malloc(<span style="color: rgba(128, 0, 128, 1)">2</span>*size+<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">char</span> *nvramptr =<span style="color: rgba(0, 0, 0, 1)"> nvramstr;
    </span><span style="color: rgba(0, 0, 255, 1)">char</span> *cstr=<span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">char</span>;
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (nvramstr==NULL || size==<span style="color: rgba(128, 0, 128, 1)">0</span> || cstr==<span style="color: rgba(0, 0, 0, 1)">NULL) {
    NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nvramstr==NULL\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(nvramstr!=<span style="color: rgba(0, 0, 0, 1)">NULL)
            free(nvramstr);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(cstr!=<span style="color: rgba(0, 0, 0, 1)">NULL)
            delete[] cstr;
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Void();
    }

    snprintf(cstr, filename.size()</span>+<span style="color: rgba(128, 0, 128, 1)">1</span>,<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">%s</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, filename.c_str());

    file_lid </span>=<span style="color: rgba(0, 0, 0, 1)"> NVM_GetLIDByName(cstr);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(file_lid &lt; <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Get LID by name fail! %s\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,cstr);
      free(nvramstr);
      delete[] cstr;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Void();
    }

    F_ID fd</span>=NVM_GetFileDesc(file_lid,&amp;pRecSize,&amp;<span style="color: rgba(0, 0, 0, 1)">pRecNum,IsRead);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (fd.iFileDesc==-<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      LOG(ERROR) </span>&lt;&lt; <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">open file Error!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
      free(nvramstr);
      delete[] cstr;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Void();
    }
    LOG(ERROR) </span>&lt;&lt; <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">RecNum is </span><span style="color: rgba(128, 0, 0, 1)">"</span>&lt;&lt;<span style="color: rgba(0, 0, 0, 1)">pRecNum;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">size=pRecSize*pRecNum;</span>
    buff=(<span style="color: rgba(0, 0, 255, 1)">char</span> *<span style="color: rgba(0, 0, 0, 1)">)malloc(size);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(buff ==<span style="color: rgba(0, 0, 0, 1)"> NULL)
    {
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Malloc Error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">NVM_CloseFileDesc(fd))
            NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">close File error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      free(nvramstr);
      delete[] cstr;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Void();
    }
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>((ssize_t)size ==<span style="color: rgba(0, 0, 0, 1)"> read(fd.iFileDesc,buff,(ssize_t)size))
    {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(NVM_CloseFileDesc(fd))
      {
            NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Read Done!Size is %d\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,size);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">return buff;</span>
<span style="color: rgba(0, 0, 0, 1)">      }
      </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
      {
            NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Close file error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            free(buff);
            free(nvramstr);
            delete[] cstr;
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Void();
      }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
    {
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">read File error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">NVM_CloseFileDesc(fd))
            NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">close File error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      free(buff);
      free(nvramstr);
      delete[] cstr;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Void();
    }

    NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nvramstr buff%x, buff%x, buff%x, buff%x, buff%x, buff%x, buff%x, buff%x, buff%x \n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
      buff[</span><span style="color: rgba(128, 0, 128, 1)">0</span>],buff[<span style="color: rgba(128, 0, 128, 1)">1</span>],buff[<span style="color: rgba(128, 0, 128, 1)">2</span>],buff[<span style="color: rgba(128, 0, 128, 1)">3</span>],buff[<span style="color: rgba(128, 0, 128, 1)">4</span>],buff[<span style="color: rgba(128, 0, 128, 1)">5</span>],buff[<span style="color: rgba(128, 0, 128, 1)">6</span>],buff[<span style="color: rgba(128, 0, 128, 1)">7</span>],buff[<span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">]);


    </span><span style="color: rgba(0, 0, 255, 1)">for</span>(i=<span style="color: rgba(128, 0, 128, 1)">0</span>; i&lt;(<span style="color: rgba(0, 0, 255, 1)">int</span>)size; i++<span style="color: rgba(0, 0, 0, 1)">)
    {
       nvramptr </span>+= sprintf(nvramptr, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">%02X</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,buff);
    }
    sprintf(nvramptr,</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    </span>*(nvramptr+<span style="color: rgba(128, 0, 128, 1)">1</span>)=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\0</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;


    NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nvramstr %s\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,nvramstr);
    _hidl_cb(nvramstr);
    free(buff);
    delete[] cstr;
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Void();
}

Return</span>&lt;int8_t&gt; Nvram::writeFileByNamevec(<span style="color: rgba(0, 0, 255, 1)">const</span> hidl_string&amp; filename, uint32_t size, <span style="color: rgba(0, 0, 255, 1)">const</span> hidl_vec&lt;uint8_t&gt;&amp;<span style="color: rgba(0, 0, 0, 1)"> data) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO implement</span>
    <span style="color: rgba(0, 0, 255, 1)">char</span> *cstr_filename=<span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">char</span>;
    </span><span style="color: rgba(0, 0, 255, 1)">char</span> *cstr_data=<span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">char</span>;
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (cstr_data==NULL || size==<span style="color: rgba(128, 0, 128, 1)">0</span> || cstr_filename==<span style="color: rgba(0, 0, 0, 1)">NULL) {
    NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">cstr_data==NULL\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(cstr_data!=<span style="color: rgba(0, 0, 0, 1)">NULL)
            delete[] cstr_data;
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(cstr_filename!=<span style="color: rgba(0, 0, 0, 1)">NULL)
            delete[] cstr_filename;
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> int8_t {};
    }
    snprintf(cstr_filename, filename.size()</span>+<span style="color: rgba(128, 0, 128, 1)">1</span>,<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">%s</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, filename.c_str());
    covertVector2Array(data, cstr_data);

    </span><span style="color: rgba(0, 0, 255, 1)">int</span> pRecSize=<span style="color: rgba(128, 0, 128, 1)">0</span>,pRecNum=<span style="color: rgba(128, 0, 128, 1)">0</span>,looptimes=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">bool</span> IsRead=<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> file_lid = -<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;

    file_lid </span>=<span style="color: rgba(0, 0, 0, 1)"> NVM_GetLIDByName(cstr_filename);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(file_lid &lt; <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Get LID by name fail!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      delete[] cstr_data;
      delete[] cstr_filename;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> int8_t {};
    }


    F_ID fd</span>=NVM_GetFileDesc(file_lid,&amp;pRecSize,&amp;<span style="color: rgba(0, 0, 0, 1)">pRecNum,IsRead);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (fd.iFileDesc==-<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">)
    {
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">open file Error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      delete[] cstr_data;
      delete[] cstr_filename;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> int8_t {};
    }
    </span><span style="color: rgba(0, 0, 255, 1)">#if</span> 0
    <span style="color: rgba(0, 0, 255, 1)">if</span>(size !=<span style="color: rgba(0, 0, 0, 1)"> pRecSize)
    {
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Input size (%d) and RecSize (%d) not match!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,size,pRecSize);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">NVM_CloseFileDesc(fd))
            NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">close File error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">return 0;</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> int8_t {};
    }
    </span><span style="color: rgba(0, 0, 255, 1)">#endif</span>

    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> GetFileDesc should return right pos and this would cause pro_info multi lids issue.</span>
    <span style="color: rgba(0, 0, 255, 1)">#if</span> 0
    <span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(128, 0, 128, 1)">0</span> != lseek(fd.iFileDesc,<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">,SEEK_SET)){
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">lseek error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">NVM_CloseFileDesc(fd))
            NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">close File error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
      }
    </span><span style="color: rgba(0, 0, 255, 1)">#endif</span><span style="color: rgba(0, 0, 0, 1)">
    looptimes </span>=<span style="color: rgba(0, 0, 0, 1)"> pRecNum;
    NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">RecNum is :%d\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,pRecNum);
    </span><span style="color: rgba(0, 0, 255, 1)">while</span>(looptimes--<span style="color: rgba(0, 0, 0, 1)">)
    {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>((ssize_t)size !=<span style="color: rgba(0, 0, 0, 1)"> write(fd.iFileDesc,cstr_data,(ssize_t)size))
      {
            NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">write file error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">NVM_CloseFileDesc(fd))
                NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">close File error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
            delete[] cstr_data;
            delete[] cstr_filename;
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> int8_t {};
      }
    }
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(NVM_CloseFileDesc(fd))
    {
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Write file Done!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      delete[] cstr_data;
      delete[] cstr_filename;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> int8_t {};
    }
    </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
    {
      NVRAM_LOG(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">close File error!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      delete[] cstr_data;
      delete[] cstr_filename;
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> int8_t {};
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">return int8_t {};</span>
<span style="color: rgba(0, 0, 0, 1)">}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Methods from ::android::hidl::base::V1_0::IBase follow.</span>
<span style="color: rgba(0, 0, 0, 1)">
INvram</span>* HIDL_FETCH_INvram(<span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">char</span>* <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> name </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Nvram();
}

}</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace implementation</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace V1_0</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace nvram</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace hardware</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace mediatek</span>
}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> namespace vendor</span></pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">经过系统编译后输出的so文件路径与jar文件路径</span></h2>
<p><span style="color: rgba(0, 51, 102, 1)">so路径</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">out</span>\target\product\A8385_JS04\obj\SHARED_LIBRARIES\vendor.mediatek.hardware.nvram@<span style="color: rgba(128, 0, 128, 1)">1.0</span>.vendor_intermediates</pre>
</div>
<p>jar路径</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">out</span>\target\common\obj\JAVA_LIBRARIES\vendor.mediatek.hardware.nvram-V1.<span style="color: rgba(128, 0, 128, 1)">0</span>-java_intermediates</pre>
</div>
<p>其中classes.jar就包含了INvram这个类,这里可以用反编译工具解包后查看</p>
<p><img src="https://img2022.cnblogs.com/blog/1497956/202211/1497956-20221108143408766-1015074942.png" alt=""></p>
<p>&nbsp;如图:</p>
<p><img src="https://img2022.cnblogs.com/blog/1497956/202211/1497956-20221108143903706-942084213.png" alt=""></p>
<h1><span style="color: rgba(0, 128, 128, 1)">读写Nvram中SN号的操作流程</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">这里是Android studio上编译的工程</span></p>
<h2><span style="color: rgba(0, 51, 102, 1)">第一步 导入系统编译Nvram的so与jar</span></h2>
<p><img src="https://img2022.cnblogs.com/blog/1497956/202211/1497956-20221108143625553-1960685561.png" alt=""></p>
<p>&nbsp;在build里添加</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">android {
    compileSdk </span><span style="color: rgba(128, 0, 128, 1)">28</span><span style="color: rgba(0, 0, 0, 1)">

    defaultConfig {
      applicationId </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">com.xxx.xxxx</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
      minSdk </span><span style="color: rgba(128, 0, 128, 1)">26</span><span style="color: rgba(0, 0, 0, 1)">
      targetSdk </span><span style="color: rgba(128, 0, 128, 1)">28</span><span style="color: rgba(0, 0, 0, 1)">
      versionCode </span><span style="color: rgba(128, 0, 128, 1)">11</span><span style="color: rgba(0, 0, 0, 1)">
      versionName </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1.10</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">

      testInstrumentationRunner </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">androidx.test.runner.AndroidJUnitRunner</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    }
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加</span>
<span style="color: rgba(0, 0, 0, 1)">    sourceSets {
      main {
            jniLibs.srcDirs </span>= [<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">libs</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">]
      }
    }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">略...</span>
<span style="color: rgba(0, 0, 0, 1)">}

dependencies {
    implementation fileTree(dir: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">libs</span><span style="color: rgba(128, 0, 0, 1)">'</span>, include: [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">*.jar</span><span style="color: rgba(128, 0, 0, 1)">'</span>])<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加</span>
    implementation files(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">libs\\classes.jar</span><span style="color: rgba(128, 0, 0, 1)">'</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加</span>
}</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">第二步 项目必须是系统权限与系统签名</span></h2>
<p>怎么实现请参考博客:https://www.cnblogs.com/guanxinjing/p/11410915.html</p>
<h2><span style="color: rgba(0, 51, 102, 1)">第三步 项目必须架包framework</span></h2>
<p>怎么实现请参考博客:https://www.cnblogs.com/guanxinjing/p/16613716.html</p>
<p>这里说一下为什么需要架framework,因为Android studio在编译的时候会检查到代码里没有IHwInterface这个类并且抛出编译异常,而这个类在framework中。</p>
<div class="cnblogs_code">
<pre>android.os.IHwInterface;</pre>
</div>
<p>这里在啰嗦一下为什么会检查这个类。因为在调用INvram.getService()方法的时候,INvram的基类是IBase</p>
<p><img src="https://img2022.cnblogs.com/blog/1497956/202211/1497956-20221108143057128-1308081574.png" alt=""></p>
<p>&nbsp;</p>
<p>而IBase继承了IHwInterface</p>
<p>&nbsp;<img src="https://img2022.cnblogs.com/blog/1497956/202211/1497956-20221108143135438-108068402.png" alt=""></p>
<p>&nbsp;</p>
<h2><span style="color: rgba(0, 51, 102, 1)">第四步 修改系统工程里的代码,删除Nv写入保护的代码</span></h2>
<p>系统工程修改文件路径</p>
<div class="cnblogs_code">
<pre>vendor\mediatek\proprietary\bootable\bootloader\lk\platform\mt6765\write_protect.c</pre>
</div>
<p>修改代码位置</p>
<p><img src="https://img2022.cnblogs.com/blog/1497956/202211/1497956-20221108144246384-657102252.png" alt=""></p>
<p>&nbsp;如果不删除写入保护set_write_protect,会出现在写入NV的时候如下报错</p>
<p><img src="https://img2022.cnblogs.com/blog/1497956/202211/1497956-20221108145923965-1470317031.png" alt=""></p>
<h2><span style="color: rgba(0, 51, 102, 1)">第五步 使用下面工具类读写SN号,或者Nv里的其他数据&nbsp;</span></h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.util.Log;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.android.internal.util.HexDump;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.nio.ByteBuffer;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.nio.CharBuffer;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.nio.charset.Charset;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.ArrayList;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Arrays;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> vendor.mediatek.hardware.nvram.V1_0.INvram;

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
*
*   /vendor/nvdata/APCFG/APRDEB/BT_Addr
*   /vendor/nvdata/APCFG/APRDCL/AUXADC
*   /vendor/nvdata/media/CAMERA_Para
*   /vendor/nvdata/media/CAMERA_3A
*   /vendor/nvdata/media/CAMERA_SHADING
*   /vendor/nvdata/media/CAMERA_DEFECT
*   /vendor/nvdata/media/CAMERA_SENSOR
*   /vendor/nvdata/media/CAMERA_LENS
*   /vendor/nvdata/APCFG/APRDCL/UART
*   /vendor/nvdata/APCFG/APRDCL/FACTORY
*   /vendor/nvdata/APCFG/APRDCL/BWCS
*   /vendor/nvdata/APCFG/APRDCL/HWMON_ACC
*   /vendor/nvdata/APCFG/APRDCL/HWMON_GYRO
*   /vendor/nvdata/media/Voice_Recognize_Param
*   /vendor/nvdata/media/Audio_AudEnh_Control_Opt
*   /vendor/nvdata/media/Audio_VOIP_Param
*   /vendor/nvdata/APCFG/APRDCL/HWMON_PS
*   /vendor/nvdata/APCFG/APRDCL/MD_Type
*   /vendor/nvdata/APCFG/APRDCL/EXT_MD_Type
*   /vendor/nvdata/APCFG/APRDCL/SDIO
*   /vendor/nvdata/media/CAMERA_VERSION
*   /vendor/nvdata/media/CAMERA_FEATURE
*   /vendor/nvdata/media/CAMERA_GEOMETRY
*   /vendor/nvdata/APCFG/APRDCL/MD_SBP
*   /vendor/nvdata/media/CAMERA_SHADING2
*   /vendor/nvdata/media/CAMERA_PLINE
*   /vendor/nvdata/media/CAMERA_AF
*   /vendor/nvdata/media/CAMERA_FLASH_CALIBRATION
*   /vendor/nvdata/media/Audio_Sph
*   /vendor/nvdata/APCFG/APRDEB/GPS
*   /vendor/nvdata/media/Audio_CompFlt
*   /vendor/nvdata/media/Audio_Effect
*   /vendor/nvdata/APCFG/APRDEB/WIFI
*   /vendor/nvdata/APCFG/APRDEB/WIFI_CUSTOM
*   /vendor/nvdata/media/Audio_Sph_Med
*   /vendor/nvdata/media/Audio_Vol_custom
*   /vendor/nvdata/media/Sph_Dual_Mic
*   /vendor/nvdata/media/Audio_Wb_Sph
*   /vendor/nvdata/APCFG/APRDEB/PRODUCT_INFO
*   /vendor/nvdata/media/Headphone_CompFlt
*   /vendor/nvdata/media/Audio_gain_table
*   /vendor/nvdata/media/Audio_ver1_Vol_custom
*   /vendor/nvdata/media/Audio_Hd_Record_Param
*   /vendor/nvdata/media/Audio_Hd_Record_Scene_Table
*   /vendor/nvdata/media/Audio_Buffer_DC_Calibration_Param
*   /vendor/nvdata/media/VibSpk_CompFlt
*   /vendor/nvdata/media/MusicDRC_CompFlt
*   /vendor/nvdata/media/RingToneDRC_CompFlt
*   /vendor/nvdata/media/Audio_MAGI_CONFERENCE
*   /vendor/nvdata/media/Audio_HAC_Param
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SNParamUtils {
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String PRODUCT_INFO_FILENAME = "/vendor/nvdata/APCFG/APRDEB/PRODUCT_INFO"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> SN_LENGTH = 32<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> writeSn(String sn) {
      </span><span style="color: rgba(0, 0, 255, 1)">char</span> sn_chars[] =<span style="color: rgba(0, 0, 0, 1)"> sn.toCharArray();
      </span><span style="color: rgba(0, 0, 255, 1)">byte</span> sn_bytes[] =<span style="color: rgba(0, 0, 0, 1)"> getBytes(sn_chars);
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            INvram agent </span>=<span style="color: rgba(0, 0, 0, 1)"> INvram.getService();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (agent != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                ArrayList</span>&lt;Byte&gt; dataArray = <span style="color: rgba(0, 0, 255, 1)">new</span> ArrayList&lt;&gt;<span style="color: rgba(0, 0, 0, 1)">();
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)"> b : sn_bytes) {
                  dataArray.add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Byte(b));
                }
                </span><span style="color: rgba(0, 0, 255, 1)">int</span> ret_1 =<span style="color: rgba(0, 0, 0, 1)"> agent.writeFileByNamevec(PRODUCT_INFO_FILENAME, SN_LENGTH, dataArray);
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (ret_1 == 0<span style="color: rgba(0, 0, 0, 1)">) {
                  Log.e(</span>"zh", "writeSn success " +<span style="color: rgba(0, 0, 0, 1)"> ret_1);
                } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                  Log.e(</span>"zh", "writeSn failed" +<span style="color: rgba(0, 0, 0, 1)"> ret_1);
                }
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                Log.e(</span>"zh", "writeSn: agent null"<span style="color: rgba(0, 0, 0, 1)">);
            }
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
            Log.e(</span>"zh", "writeSn exception:" +<span style="color: rgba(0, 0, 0, 1)"> e.getLocalizedMessage());
            e.printStackTrace();
      }
    }


    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String readSn() {
      </span><span style="color: rgba(0, 0, 255, 1)">int</span> targets = 0<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            String buff </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
            INvram agent </span>=<span style="color: rgba(0, 0, 0, 1)"> INvram.getService();

            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (agent != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                buff </span>=<span style="color: rgba(0, 0, 0, 1)"> agent.readFileByName(PRODUCT_INFO_FILENAME, SN_LENGTH);
                Log.e(</span>"zh", "buff: " +<span style="color: rgba(0, 0, 0, 1)"> buff );
            }
            </span><span style="color: rgba(0, 0, 255, 1)">byte</span>[] buffArr = HexDump.hexStringToByteArray(buff.substring(0, buff.length() - 1<span style="color: rgba(0, 0, 0, 1)">));
            targets </span>= (buffArr &amp; 0xff) | ((buffArr &lt;&lt; 8) &amp; 0xff00) | ((buffArr &lt;&lt; 24) &gt;&gt;&gt; 8) | (buffArr &lt;&lt; 24<span style="color: rgba(0, 0, 0, 1)">);
            Log.e(</span>"zh","readSn: chars=&gt;" + Arrays.toString(getChars(buffArr)) + ", targets == " +<span style="color: rgba(0, 0, 0, 1)"> targets);
            Log.e(</span>"zh","readSn: bytes=&gt;" + Arrays.toString((buffArr)) + ", targets == " +<span style="color: rgba(0, 0, 0, 1)"> targets);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> String.valueOf(getChars(buffArr));
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
            Log.e(</span>"zh","readSn exception:" +<span style="color: rgba(0, 0, 0, 1)"> e.getLocalizedMessage());
            e.printStackTrace();
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> "123456789"<span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">char</span>[] getChars(<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">[] bytes) {
      Charset cs </span>= Charset.forName("UTF-8"<span style="color: rgba(0, 0, 0, 1)">);
      ByteBuffer bb </span>=<span style="color: rgba(0, 0, 0, 1)"> ByteBuffer.allocate(bytes.length);
      bb.put(bytes);
      bb.flip();
      CharBuffer cb </span>=<span style="color: rgba(0, 0, 0, 1)"> cs.decode(bb);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> cb.array();
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">byte</span>[] getBytes(<span style="color: rgba(0, 0, 255, 1)">char</span><span style="color: rgba(0, 0, 0, 1)">[] chars) {
      Charset cs </span>= Charset.forName("UTF-8"<span style="color: rgba(0, 0, 0, 1)">);
      CharBuffer cb </span>=<span style="color: rgba(0, 0, 0, 1)"> CharBuffer.allocate(chars.length);
      cb.put(chars);
      cb.flip();
      ByteBuffer bb </span>=<span style="color: rgba(0, 0, 0, 1)"> cs.encode(cb);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> bb.array();
    }
}</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">假如你是系统</span><span style="color: rgba(0, 128, 128, 1)">工程</span><span style="color: rgba(0, 128, 128, 1)">编译apk</span></h1>
<h3>可以在apk工程的android.mk里直接导入,不需要以上的第一步到第三步,但是依然需要第四步与第五步</h3>
<pre class="highlighter-hljs" data-dark-theme="true"><code>LOCAL_STATIC_JAVA_LIBRARIES := vendor.mediatek.hardware.nvram-V1.0-java</code></pre>
<div class="cnblogs_code">
<pre>LOCAL_PATH:= $(call my-<span style="color: rgba(0, 0, 0, 1)">dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS :</span>=<span style="color: rgba(0, 0, 0, 1)"> optional
LOCAL_CERTIFICATE :</span>=<span style="color: rgba(0, 0, 0, 1)"> platform

# Add </span><span style="color: rgba(0, 0, 255, 1)">static</span> library <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> nvram
# LOCAL_STATIC_JAVA_LIBRARIES :</span>= vendor.mediatek.hardware.nvram-V1.1-java-<span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)">
LOCAL_STATIC_JAVA_LIBRARIES :</span>= vendor.mediatek.hardware.nvram-V1.0-<span style="color: rgba(0, 0, 0, 1)">java
LOCAL_SRC_FILES :</span>= $(call all-subdir-java-<span style="color: rgba(0, 0, 0, 1)">files)
LOCAL_PACKAGE_NAME :</span>=<span style="color: rgba(0, 0, 0, 1)"> JNvRAM_V11
LOCAL_PRIVATE_PLATFORM_APIS :</span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
include $(BUILD_PACKAGE)</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">MTK平台如何用Build.getSerial()方法读取写入的SN号</span></h1>
<p><strong><span style="color: rgba(0, 0, 0, 1)">这里直接复制MTK论坛那边的开发回复(下面提是MTK的写号工具SN Write,但是我们这个写NV的方法同样适用):</span></strong></p>
<p>在/vendor/mediatek/proprietary/bootable/bootloader/lk/app/mt_boot/mt_boot.c<br>中,将&nbsp;#define SERIAL_NUM_FROM_BARCODE&nbsp;&nbsp;宏定义打开<br>这时SN Write工具写Barcode即可,其他无需修改。<br>这是最简单的方式,相当于serial no取Barcode空间的值。</p>
<p><span style="color: rgba(0, 128, 128, 1)"><img src="https://img2023.cnblogs.com/blog/1497956/202212/1497956-20221219114049817-1344626868.png" alt=""></span></p>
<h1><span style="color: rgba(22, 145, 121, 1)">在NV中读写WiFi的Mac地址</span></h1>
<p><strong><span style="color: rgba(186, 55, 42, 1)">请注意!</span>在Android10版本以后,WiFi已经默认使用随机mac地址</strong>,意思是说,哪怕你写到了NV中,在WifiManager中也不会读取到,这需要你手动设置或者修改代码将,下面的选项从随机Mac地址修改成固定设备的Mac地址。如下图位置:</p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202310/1497956-20231020144621293-664473884.png"></p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202310/1497956-20231020144650235-930652558.png"></p>
<p>代码部分:</p>
<p>其他流程与上面一样,这里直接提供读写代码。&nbsp;</p>
<pre class="language-java highlighter-hljs" data-dark-theme="true"><code>import android.app.Application;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.util.Log;
import com.android.internal.util.HexDump;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.StringTokenizer;
import vendor.mediatek.hardware.nvram.V1_0.INvram;

public class MacParamUtils {
    public static final String MAC_ADDRESS_FILENAME = "/vendor/nvdata/APCFG/APRDEB/WIFI";
    private static final int MAC_ADDRESS_OFFSET = 4;
    private static final int MAC_ADDRESS_DIGITS = 6;

    /**
   * 通过WifiManager获取WiFi Mac地址
   */
    public static String getMACAddress(Application application) {
      try {
            WifiManager wifiManager = (WifiManager)application.getSystemService(Context.WIFI_SERVICE);
            Method getFactoryMacAddresses = wifiManager.getClass().getMethod("getFactoryMacAddresses");
            String[] macAddresses= (String[]) getFactoryMacAddresses.invoke(wifiManager);
            String macAddress = "";
            if (macAddresses.length &gt; 0) {
                macAddress = macAddresses;
            }
            return macAddress;
      } catch (Exception e) {
            return null;
      }
    }

    /**
   * 直接从NV中读取Mac地址
   * @return
   */
    public static String getWifiMacFromNvram() {
      StringBuffer nvramBuf = new StringBuffer();
      try {
            int i = 0;
            String buff = null;
            INvram agent = INvram.getService();
            if (agent == null) {
                Log.e("zh", "NvRAMAgent is null");
                return "";            }
            try {
                buff = agent.readFileByName(MAC_ADDRESS_FILENAME, MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS);
            } catch (Exception e) {
                e.printStackTrace();
                return "";
            }
            Log.e("zh", "Raw data:" + buff);
            if (buff.length() &lt; 2 * (MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS)) {
                return "";
            }
            // Remove the \0 special character.
            int macLen = buff.length() - 1;
            for (i = MAC_ADDRESS_OFFSET * 2; i &lt; macLen; i += 2) {
                if ((i + 2) &lt; macLen) {
                  nvramBuf.append(buff.substring(i, i + 2));
                  nvramBuf.append(":");
                } else {
                  nvramBuf.append(buff.substring(i));
                }
            }
      } catch (Exception e) {
            e.printStackTrace();
            return "";
      }
      return nvramBuf.toString();
    }

    /**
   * 更新WiFi Mac地址到NV中
   * @param mac
   * @return
   */
    public static int updateWifiMacToNvram(String mac){
      try {
            int i = 0;
            INvram agent = INvram.getService();
            byte[] macAddr = new byte;
            if (agent == null) {
                Log.e("zh", "NvRAMAgent is null");
                return 0;
            }
            //parse mac address firstly
            StringTokenizer txtBuffer = new StringTokenizer(mac, ":");
            while (txtBuffer.hasMoreTokens()) {
                macAddr = (byte) Integer.parseInt(txtBuffer.nextToken(), 16);
                i++;
            }
            if(i != MAC_ADDRESS_DIGITS){
                Log.e("zh", "Wrong length of macAddr:" + i);
                return 0;
            }
            String buff = null;
            try {
                buff = agent.readFileByName(MAC_ADDRESS_FILENAME, MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
            byte[] buffArr = HexDump.hexStringToByteArray(buff.substring(0, buff.length() - 1));
            for (i = 0; i &lt; MAC_ADDRESS_DIGITS; i ++) {
                buffArr = macAddr;
            }
            ArrayList&lt;Byte&gt; dataArray = new ArrayList&lt;Byte&gt;(MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS);
            for (i = 0; i &lt; MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS; i++) {
                dataArray.add(i, new Byte(buffArr));
            }
            int flag = 0;
            try {
                flag = agent.writeFileByNamevec(MAC_ADDRESS_FILENAME,MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS,dataArray);
                return flag;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
      }catch (Exception e) {
            e.printStackTrace();
      }
      return 0;
    }

    private static char[] getChars(byte[] bytes) {
      Charset cs = Charset.forName("UTF-8");
      ByteBuffer bb = ByteBuffer.allocate(bytes.length);
      bb.put(bytes);
      bb.flip();
      CharBuffer cb = cs.decode(bb);
      return cb.array();
    }

    private static byte[] getBytes(char[] chars) {
      Charset cs = Charset.forName("UTF-8");
      CharBuffer cb = CharBuffer.allocate(chars.length);
      cb.put(chars);
      cb.flip();
      ByteBuffer bb = cs.encode(cb);
      return bb.array();
    }
}</code></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>End</p>

</div>
<div id="MySignature" role="contentinfo">
    <div style="text-align: center">
    <p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/16869583.html </p>
    <div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/16869583.html
頁: [1]
查看完整版本: Android系统开发 android8之后版本读写Nvram