<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Soul Of Free Loop &#187; Atom</title>
	<atom:link href="https://zohead.com/archives/tag/atom/feed" rel="self" type="application/rss+xml" />
	<link>https://zohead.com</link>
	<description>Uranus Zhou&#039;s Blog</description>
	<lastBuildDate>Sat, 19 Jul 2025 15:42:46 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>酷走Android行车记录仪研究</title>
		<link>https://zohead.com/archives/kuzo-android-internal/</link>
		<comments>https://zohead.com/archives/kuzo-android-internal/#comments</comments>
		<pubDate>Wed, 03 Jul 2019 17:04:56 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[ADB]]></category>
		<category><![CDATA[Atom]]></category>
		<category><![CDATA[baksmali]]></category>
		<category><![CDATA[oat2dex]]></category>
		<category><![CDATA[Vysor]]></category>
		<category><![CDATA[行车记录仪]]></category>
		<category><![CDATA[酷走]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1586</guid>
		<description><![CDATA[还是之前用的酷走 Android 行车记录仪，最近放在车上使用倒挺顺畅，不过也有一些明显的问题（例如 SIM 卡未联网时系统时间不正确等），因此想着最好能找到调试这款 Android 行车记录仪的途径。 ADB 调试 最开始想到这款行车记录仪既然是用的 Android 系统，应该是支持 ADB 调试功能的，将行车记录仪的 USB 接口直接用数据线接到我的笔记本电脑上，却没有找到 ADB 设备。以为记录仪内部是不是有一个专用的调试串口之类的，为此找到硬件同事把记录仪拆解了一番： 不过并没有找到除 USB 之外其它的调试接口，这时无意将记录仪通过 USB 接到另一台主机上，却认到 ADB 设备了。 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>还是之前用的<a href="https://zohead.com/archives/kuzo-recorder/">酷走 Android 行车记录仪</a>，最近放在车上使用倒挺顺畅，不过也有一些明显的问题（例如 SIM 卡未联网时系统时间不正确等），因此想着最好能找到调试这款 Android 行车记录仪的途径。</p>
<h2 id="adb-debug">ADB 调试</h2>
<p>最开始想到这款行车记录仪既然是用的 Android 系统，应该是支持 ADB 调试功能的，将行车记录仪的 USB 接口直接用数据线接到我的笔记本电脑上，却没有找到 ADB 设备。以为记录仪内部是不是有一个专用的调试串口之类的，为此找到硬件同事把记录仪拆解了一番：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737372135/kuzo-teardown.jpg" alt="酷走行车记录仪拆解" title="酷走行车记录仪拆解"></p>
<p>不过并没有找到除 USB 之外其它的调试接口，这时无意将记录仪通过 USB 接到另一台主机上，却认到 ADB 设备了。无奈地认识到自己犯蠢没有用别的机器验证是否和 USB 接口有关系，毕竟把记录仪拆解了上面的样子也基本不可能装回去咯 -_-#。初步估计我的老笔记本 USB 接口供电有问题，记录仪通过 USB 插到 PC 机之后没有独立供电也只能从 PC 机 USB 接口取电。</p>
<p>比较好的消息是我日常使用的 Chromebook 接记录仪也能认到 ADB 设备，这样就能直接通过 <a href="https://chrome.google.com/webstore/detail/vysor/gidgenkbbabolejbgbpnhbimgjbffefm" target="_blank">Vysor</a> 这个 Chrome 应用来访问行车记录仪了，<a href="http://vysor.io/" target="_blank">Vysor</a> 官网上也有 Windows、Mac、Linux 系统下的桌面版本。另外为了方便通过 ADB 访问行车记录仪的 shell 以及上传下载文件之类的，我还在 Chromebook 的 <a href="https://github.com/dnschneid/crouton" target="_blank">crouton</a> 环境中安装了 adb 支持。</p>
<p>启动 Vysor Chrome 应用，授权允许访问 ADB 设备之后，应该就能看到记录仪设备了：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442964/vysor-devices.png" alt="行车记录仪 ADB 设备" title="行车记录仪 ADB 设备"></p>
<p>上图中的 <code>Full AOSP on Sofia</code> 就是行车记录仪设备，点击 Vysor 上的 <code>View</code> 按钮会自动通过 ADB 在设备上安装 Vysor 受控端 App，稍等片刻就可以看到记录仪的 Android 系统主界面咯：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737371940/kuzo-android-ui.png" alt="行车记录仪 Android 主界面" title="行车记录仪 Android 主界面"></p>
<blockquote>
<p><strong>注意</strong></p>
<p>由于通过 USB 数据线将行车记录仪连接到电脑时功率一般达不到要求的 5V / 2A，记录仪自带的 250 mAh 电池续航时间也有限，因此 ADB 调试操作前最好先使用标准 5V / 2A 充电器将记录仪充满电。</p>
</blockquote>
<h2 id="system-hardware">系统和硬件信息</h2>
<p>解锁进入系统之后，可以先看看我这台行车记录仪的系统版本信息，看起来比较明显用的是 Android 5.1.1 AOSP 版本，内核版本为 3.14.0，版本号为 2.1.5：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737371891/kuzo-android-about.png" alt="行车记录仪 Android 版本" title="行车记录仪 Android 版本"></p>
<p>值得一提的是另外一台同样型号的酷走行车记录仪，通过 Vysor Chrome 应用能找到 ADB 设备，但是自动安装 Vysor App 之后无法正确显示 Android 系统主界面，这样只能通过 ADB Shell 来获取系统版本信息了：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ adb shell getprop | grep 'ro\.build\.'
[ro.build.characteristics]: [tablet]
[ro.build.date.utc]: [1473825617]
[ro.build.date]: [Wed Sep 14 12:00:17 CST 2016]
[ro.build.description]: [Sf3gr_mrd6_p2_720-userdebug 5.1.1 LMY47V eng.softteam.20160914.115752 release-keys]
[ro.build.display.id]: [2.2.3]
[ro.build.fingerprint]: [Intel/Sf3gr_mrd6_p2_720/5.1.1/LMY47V/softteam09141159:userdebug/release-keys]
[ro.build.flavor]: [Sf3gr_mrd6_p2_720-userdebug]
[ro.build.host]: [pdd-build]
[ro.build.id]: [LMY47V]
[ro.build.product]: [Sf3gr_mrd6_p2_720]
[ro.build.tags]: [release-keys]
[ro.build.type]: [userdebug]
[ro.build.user]: [softteam]
[ro.build.version.all_codenames]: [REL]
[ro.build.version.base_os]: []
[ro.build.version.codename]: [REL]
[ro.build.version.incremental]: [eng.softteam.20160914.115752]
[ro.build.version.release]: [5.1.1]
[ro.build.version.sdk]: [22]
[ro.build.version.security_patch]: [2015-11-01]
</pre>
<p>可以看到这台记录仪的版本号是新一点的 2.2.3，进入 Shell 查看内核版本：</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ $ uname -a
Linux localhost 3.14.0 #1 SMP PREEMPT Wed Sep 14 12:14:50 CST 2016 i686 GNU/Linux
</pre>
<p>记录仪使用的是 Intel SOFIA Atom x3 超低功耗 x86 处理器，下面的 <code>/proc/cpuinfo</code> 输出只列出了 4 个核中第一个核的信息，从核数和缓存大小来看具体处理器型号估计是最大频率 1.1 GHz 的 <a href="https://ark.intel.com/content/www/us/en/ark/products/87461/intel-atom-x3-c3230rk-processor-1m-cache-up-to-1-10-ghz.html" target="_blank">x3-C3230RK</a>。</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ $ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 93
model name      : Genuine Intel(R) CPU         @ 728
stepping        : 1
microcode       : 0x102
cpu MHz         : 416.000
cache size      : 512 KB
physical id     : 0
siblings        : 4
core id         : 1
cpu cores       : 4
apicid          : 2
initial apicid  : 2
fdiv_bug        : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 11
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush mmx fxsr sse sse2 ss ht nx rdtscp lm constant_tsc arch_perfmon xtopology pni pclmulqdq monitor ssse3 cx16 xtpr pdcm sse4_1 sse4_2 movbe popcnt aes lahf_lm 3dnowprefetch tsc_adjust smep erms
bogomips        : 892.92
clflush size    : 64
cache_alignment : 64
address sizes   : 32 bits physical, 48 bits virtual
power management:
</pre>
<p>x3-C3230RK 处理器集成了 A-GOLD 620 射频收发器，支持 3G、Wi-Fi（802.11 B/G/N）、蓝牙 4.0、GPS 以及 FM 功能，这几项功能记录仪基本都用上了。GPU 则是 600 MHz 的 Mali-450 MP4。处理器最大支持 2 GB 内存，不过这款行车记录仪上只带了 1 GB 内存：</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ $ cat /proc/meminfo
MemTotal:         948616 kB
MemFree:           26592 kB
MemAvailable:     498968 kB
Buffers:            3696 kB
Cached:           498580 kB
</pre>
<p>我们也可以使用 <code>dumpsys</code> 命令查询记录仪电池信息：</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ $ dumpsys battery
Current Battery Service state:
  AC powered: false
  USB powered: true
  Wireless powered: false
  status: 2
  health: 2
  present: true
  level: 0
  scale: 100
  voltage: 3289
  temperature: 240
  technology: Li-ion
</pre>
<h2 id="system-app">系统 App</h2>
<p>上面的 Android 主界面里可以看到 Tong-server 和 VideoRecorderService 这两个服务在运行，分别对应记录仪的整体管理功能和录像功能，使用老版本系统的记录仪上可以打开 VideoServer 录像的系统 App 界面：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737372135/kuzo-video-server.png" alt="行车记录仪录像 App" title="行车记录仪录像 App"></p>
<p>对于 Vysor 不能打开图形界面的新系统可以用命令列举系统 App 列表（下面只列出了关键的几个）：</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ $ pm list packages -f
package:/system/app/KuzoInstaller/KuzoInstaller.apk=com.hpyl.kuzo.installer
package:/system/app/ArcCamera/ArcCamera.apk=com.arcsoft.camera2
package:/system/app/KuzoLauncher/KuzoLauncher.apk=com.hpyl.kuzolauncher
package:/system/app/TongTermManager/TongTermManager.apk=com.kh.tong.termmanager
package:/system/app/VideoServer/VideoServer.apk=com.kh.videoserver
</pre>
<p>然后使用 <code>dumpsys</code> 命令查看相应 App 的信息：</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ $ dumpsys package com.kh.tong.termmanager
  Package [com.kh.tong.termmanager] (24d3573f):
    userId=10016 gids=[3003, 1028, 1015, 1023, 3002, 3001]
    pkg=Package{c4b880c com.kh.tong.termmanager}
    codePath=/system/app/TongTermManager
    resourcePath=/system/app/TongTermManager
    legacyNativeLibraryDir=/system/app/TongTermManager/lib
    primaryCpuAbi=armeabi-v7a
    secondaryCpuAbi=null
    versionCode=1000027 targetSdk=23
    versionName=1.0.27
shell@Sf3gr_mrd6_p2_720:/ $ dumpsys package com.kh.videoserver
  Package [com.kh.videoserver] (31228436):
    userId=10018 gids=[3003, 1028, 1015, 1023]
    pkg=Package{27beef37 com.kh.videoserver}
    codePath=/system/app/VideoServer
    resourcePath=/system/app/VideoServer
    legacyNativeLibraryDir=/system/app/VideoServer/lib
    primaryCpuAbi=null
    secondaryCpuAbi=null
    versionCode=1000027 targetSdk=22
    versionName=1.0.27
</pre>
<p>可以看到新版本系统下 <code>Tong-server</code> 和 <code>VideoServer</code> App 都是 1.0.27 版本，如果把系统 App 的 apk 文件拷贝出来了也能用 <code>aapt</code> 命令查看：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ aapt dump badging TongTermManager.apk | grep &quot;VersionName&quot;
package: name='com.kh.tong.termmanager' versionCode='1000027' versionName='1.0.27' platformBuildVersionName='5.1.1-1819727'
(xenial)zzm@localhost:~$ aapt dump badging VideoServer.apk | grep &quot;VersionName&quot;
package: name='com.kh.videoserver' versionCode='1000027' versionName='1.0.27' platformBuildVersionName='5.1.1-1819727'
</pre>
<p>老版本系统下这两个 App 也是低一些的 1.0.23 版本：</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ $ dumpsys package com.kh.tong.termmanager
  Package [com.kh.tong.termmanager] (2d37c5ca):
    userId=10017 gids=[3003, 1028, 1015, 1023, 3002, 3001]
    pkg=Package{33ef33b com.kh.tong.termmanager}
    codePath=/system/app/TongTermManager
    resourcePath=/system/app/TongTermManager
    legacyNativeLibraryDir=/system/app/TongTermManager/lib
    primaryCpuAbi=x86
    secondaryCpuAbi=null
    versionCode=1000023 targetSdk=22
    versionName=1.0.23
</pre>
<h2 id="mod-system">修改系统</h2>
<p>记录仪 Android AOSP 系统自带了 root 权限，如果需要修改系统，可以先关闭系统分区保护：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ adb disable-verity
Verity disabled on /system
Now reboot your device for settings to take effect
</pre>
<p>运行 <code>adb reboot</code> 命令重启记录仪之后，就可以直接 <code>su</code> 切换为 root 用户，重新挂载修改系统分区了：</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ # mount -o remount,rw /dev/block/platform/soc0/e0000000.noc/by-name/ImcPartID068 /system
</pre>
<h2 id="update-system-app">尝试升级系统 App</h2>
<p>经过测试我发现 2.1.5 老版本系统相比新的 2.2.3 版本存在以下问题：</p>
<ul>
<li>音乐播放的暂停状态无法保存，记录仪重新开机时始终恢复播放上次的歌曲，这个时候只能使用蓝牙按键或者手机酷走 App 暂停播放；</li>
<li>记录仪录的视频画面中没有当前车速和时间 OSD 显示。</li>
</ul>
<p>因此我想着将 2.1.5 版本系统里的 <code>Tong-server</code> 和 <code>VideoServer</code> App 升级为 2.2.3 里自带的新版本，是不是就能解决这些问题。</p>
<p>不过由于这两个系统 App 的 apk 文件是不完整的，apk 中不包含 <code>classes.dex</code> 并且有单独的 odex 文件，这样的 apk 文件也无法直接安装，最好能先将 odex 反编译出来。</p>
<p>我先试了常用的 <a href="https://github.com/JesusFreke/smali" target="_blank">smali/baksmali</a> 来反编译 <code>VideoServer</code> 的 odex，注意 <code>baksmali</code> 更新之后命令的使用方式和网上很多文章不太一样了：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ java -jar baksmali-2.2.7.jar x VideoServer/x86/VideoServer.odex
Exception in thread &quot;main&quot; org.jf.dexlib2.DexFileFactory$UnsupportedOatVersionException: Unsupported oat version: 48
        at org.jf.dexlib2.DexFileFactory.loadDexFile(DexFileFactory.java:120)
        at org.jf.baksmali.DexInputCommand.loadDexFile(DexInputCommand.java:149)
        at org.jf.baksmali.DisassembleCommand.run(DisassembleCommand.java:162)
        at org.jf.baksmali.Main.main(Main.java:102)
</pre>
<p>额，原来 <code>baksmali</code> 并不支持比较老的 Android 5.1 版本。</p>
<p>看起来我只能使出 <a href="https://github.com/testwhat/SmaliEx" target="_blank">oat2dex</a> 工具来反编译试试了，<code>oat2dex</code> 使用上比 <code>baksmali</code> 复杂一些：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~/Downloads/tmp$ java -jar oat2dex.jar
Easy oat2dex 0.90
Usage:
 java -jar oat2dex.jar [options] &lt;action&gt;
[options]
 Api level: -a &lt;integer&gt;
 Output folder: -o &lt;folder path&gt;
 Print detail : -v
&lt;action&gt;
 Get dex of boot(.oat) : boot &lt;boot.oat/boot-folder&gt;
 Get dex (de-optimize) : &lt;oat/odex file&gt; &lt;boot-class-folder&gt;
                         &lt;vdex file&gt;
 Get raw odex          : odex &lt;oat/odex/vdex file&gt;
 Get raw odex smali    : smali &lt;oat/odex/vdex file&gt;
 Deodex framework (exp): devfw [empty or path of /system/framework/]
</pre>
<p>首先需要将新系统上的 <code>boot.oat</code> 文件拷贝出来：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ adb pull /data/dalvik-cache/x86/system@framework@boot.oat .
2063 KB/s (57823168 bytes in 27.362s)
</pre>
<p>使用 <code>oat2dex</code> 将 <code>boot.oat</code> 反优化为 dex 文件，默认会输出到当前目录下的 <code>boot.oat-dex</code> 子目录：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~/Downloads/tmp$ java -jar oat2dex.jar boot boot.oat
06-28 22:07:36:757 Art version=48 (boot.oat)
06-28 22:07:36:890 De-optimizing /system/framework/core-libart.jar
06-28 22:07:48:650 Output to /home/zzm/boot.oat-dex/core-libart.dex
06-28 22:07:48:651 De-optimizing /system/framework/conscrypt.jar
06-28 22:07:50:095 Output to /home/zzm/boot.oat-dex/conscrypt.dex
06-28 22:07:50:096 De-optimizing /system/framework/okhttp.jar
06-28 22:07:50:750 Output to /home/zzm/boot.oat-dex/okhttp.dex
06-28 22:07:50:751 De-optimizing /system/framework/core-junit.jar
06-28 22:07:50:801 Output to /home/zzm/boot.oat-dex/core-junit.dex
06-28 22:07:50:802 De-optimizing /system/framework/bouncycastle.jar
06-28 22:07:53:226 Output to /home/zzm/boot.oat-dex/bouncycastle.dex
06-28 22:07:53:228 De-optimizing /system/framework/ext.jar
06-28 22:07:55:777 Output to /home/zzm/boot.oat-dex/ext.dex
06-28 22:07:55:777 De-optimizing /system/framework/framework.jar
06-28 22:08:13:350 Output to /home/zzm/boot.oat-dex/framework.dex
06-28 22:08:13:351 De-optimizing /system/framework/framework.jar:classes2.dex
06-28 22:08:15:468 Analysis error in class=Landroid/widget/NumberPicker; method=&lt;init&gt;
Method: Landroid/widget/NumberPicker;-&gt;&lt;init&gt;(Landroid/content/Context;Landroid/util/AttributeSet;II)V
Near line: 604 (address 75)
Instructions: 
 [36] const/4 regA=15
 [37] move-object/from16 regA=0 regB=19
 [38] iput-boolean-quick regA=15 regB=0 &lt;-----
 [39] const/16 regA=15
 [40] const/16 regA=16

06-28 22:08:15:470 org.jf.dexlib2.analysis.AnalysisException: Could not resolve the field in class (Reference,Landroid/content/Context;) at offset 778 in &lt;init&gt;
        at org.jf.dexlib2.analysis.MethodAnalyzer.analyzeIputIgetQuick(MethodAnalyzer.java:2422)
        at org.jf.dexlib2.analysis.MethodAnalyzer.analyzeInstruction(MethodAnalyzer.java:1269)
        at org.jf.dexlib2.analysis.MethodAnalyzer.analyze(MethodAnalyzer.java:259)
        at org.jf.dexlib2.analysis.MethodAnalyzer.&lt;init&gt;(MethodAnalyzer.java:190)
        at org.rh.smaliex.deopt.OdexRewriter$OdexRewriterModule$1$1.getInstructions(OdexRewriter.java:232)
        ...(Skip 24 traces)
        at org.rh.smaliex.OatUtil.convertToDex(OatUtil.java:271)
        at org.rh.smaliex.OatUtil.convertDexFromBootOat(OatUtil.java:192)
        at org.rh.smaliex.OatUtil.bootOat2Dex(OatUtil.java:75)
        at org.rh.smaliex.Main.mainImpl(Main.java:106)
        at org.rh.smaliex.Main.main(Main.java:43)

06-28 22:08:15:471 Failed to re-construct dex java.lang.ClassCastException: org.jf.dexlib2.analysis.UnresolvedOdexInstruction (in module: Unnamed Module) cannot be cast to org.jf.dexlib2.iface.instruction.formats.Instruction22cs (in module: Unnamed Module)
06-28 22:08:15:471 convertToDex: skip /system/framework/framework.jar:classes2.dex
06-28 22:08:15:472 De-optimizing /system/framework/telephony-common.jar
06-28 22:08:18:110 Output to /home/zzm/boot.oat-dex/telephony-common.dex
06-28 22:08:18:111 De-optimizing /system/framework/voip-common.jar
06-28 22:08:18:313 Output to /home/zzm/boot.oat-dex/voip-common.dex
06-28 22:08:18:314 De-optimizing /system/framework/ims-common.jar
06-28 22:08:18:503 Output to /home/zzm/boot.oat-dex/ims-common.dex
06-28 22:08:18:519 De-optimizing /system/framework/mms-common.jar
06-28 22:08:18:579 Output to /home/zzm/boot.oat-dex/mms-common.dex
06-28 22:08:18:599 De-optimizing /system/framework/android.policy.jar
06-28 22:08:19:007 Output to /home/zzm/boot.oat-dex/android.policy.dex
06-28 22:08:19:008 De-optimizing /system/framework/apache-xml.jar
06-28 22:08:20:770 Output to /home/zzm/boot.oat-dex/apache-xml.dex
</pre>
<p>处理 <code>boot.oat</code> 文件有些报错我们先忽略，接着我们可以用 <code>oat2dex</code> 反优化系统 App 的 odex 文件，这里用到了刚才 <code>boot.oat</code> 反优化出来的 dex 文件，类似的会输出到当前目录的子目录：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ java -jar oat2dex.jar VideoServer.odex boot.oat-dex/
06-28 22:13:09:212 Art version=48 (VideoServer.odex)
06-28 22:13:09:250 De-optimizing /system/app/VideoServer/VideoServer.apk
06-28 22:13:27:979 Output to /home/zzm/VideoServer.odex-dex/VideoServer.dex
</pre>
<p>反编译得到的 dex 文件，并重新编译成 <code>classes.dex</code>：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ java -jar baksmali-2.2.7.jar disassemble VideoServer.odex-dex/VideoServer.dex -o video
(xenial)zzm@localhost:~$ java -jar smali-2.2.7.jar assemble video -o classes.dex
</pre>
<p>然后将 <code>classes.dex</code> 打包添加到原来的 apk 文件中：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ aapt add VideoServer.apk classes.dex
</pre>
<p>安装新的 apk 文件存在报错：</p>
<pre class="brush: plain; title: ; notranslate">
W/PackageManager(  584): Package com.kh.videoserver signatures do not match the previously installed version; ignoring!
</pre>
<p>原来是没有签名，这里我使用 <a href="https://github.com/patrickfav/uber-apk-signer" target="_blank">Uber Apk Signer</a> 工具对 apk 进行重新签名：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ java -jar uber-apk-signer-1.0.0.jar -a VideoServer.apk
</pre>
<p>初步测试新编译出来的 <code>VideoServer</code> apk 可以正常安装启动，不过 <code>oat2dex</code> 处理 <code>Tong-server</code> 新版本 App 的时候就有问题了：</p>
<pre class="brush: bash; title: ; notranslate">
(xenial)zzm@localhost:~$ java -jar oat2dex.jar TongTermManager.odex boot.oat-dex/
06-29 23:02:32:138 Art version=48 (TongTermManager.odex)
06-29 23:02:32:203 De-optimizing /system/app/TongTermManager/TongTermManager.apk
06-29 23:02:58:217 Output to /home/zzm/TongTermManager.odex-dex/TongTermManager.dex
06-29 23:02:58:217 De-optimizing /system/app/TongTermManager/TongTermManager.apk:classes2.dex
06-29 23:03:04:420 Analysis error in class=Lorg/jsoup/parser/Tag; method=&lt;clinit&gt;
Method: Lorg/jsoup/parser/Tag;-&gt;&lt;clinit&gt;()V
Near line: 295 (address 1223)
Instructions: 
 [624] check-cast regA=0
 [625] invoke-static regC=0
 [626] iput-boolean-quick regA=7 regB=0 &lt;-----
 [627] add-int/lit8 regA=3 regB=3
 [628] goto

06-29 23:03:04:433 org.jf.dexlib2.analysis.AnalysisException: Could not resolve the field in class (Reference,Lorg/jsoup/parser/Tag;) at offset 15 in &lt;clinit&gt;
        at org.jf.dexlib2.analysis.MethodAnalyzer.analyzeIputIgetQuick(MethodAnalyzer.java:2422)
        at org.jf.dexlib2.analysis.MethodAnalyzer.analyzeInstruction(MethodAnalyzer.java:1269)
        at org.jf.dexlib2.analysis.MethodAnalyzer.analyze(MethodAnalyzer.java:259)
        at org.jf.dexlib2.analysis.MethodAnalyzer.&lt;init&gt;(MethodAnalyzer.java:190)
        at org.rh.smaliex.deopt.OdexRewriter$OdexRewriterModule$1$1.getInstructions(OdexRewriter.java:232)
        ...(Skip 24 traces)
        at org.rh.smaliex.OatUtil.convertToDex(OatUtil.java:271)
        at org.rh.smaliex.OatUtil.convertDexFromBootOat(OatUtil.java:192)
        at org.rh.smaliex.OatUtil.oat2dex(OatUtil.java:81)
        at org.rh.smaliex.Main.mainImpl(Main.java:127)
        at org.rh.smaliex.Main.main(Main.java:43)

06-29 23:03:04:437 Failed to re-construct dex java.lang.ClassCastException: org.jf.dexlib2.analysis.UnresolvedOdexInstruction (in module: Unnamed Module) cannot be cast to org.jf.dexlib2.iface.instruction.formats.Instruction22cs (in module: Unnamed Module)
06-29 23:03:04:437 convertToDex: skip /system/app/TongTermManager/TongTermManager.apk:classes2.dex
</pre>
<p>这个问题目前还没有找到好的解决方法，由于担心整个系统升级也会碰到 Vysor 主界面无法显示的问题，而且酷走记录仪的生产厂家也不提供支持没有单独的升级包，老版本系统的管理和录像 App 也就继续使用了。</p>
<h2 id="mod-app-config">修改系统 App 配置</h2>
<h3 id="tong-server">Tong-server</h3>
<p>前面说的 2.1.5 版本系统音乐播放的暂停状态问题，可以看看 <code>Tong-server</code> 系统 App 的配置文件 <code>/data/data/com.kh.tong.termmanager/shared_prefs/KUZOConfig.xml</code>，例如我的记录仪配置：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version='1.0' encoding='utf-8' standalone='yes' ?&gt;
&lt;map&gt;
    &lt;string name=&quot;LOCAL_SAVE_MUSIC_INFO_KEY2F06A8D7CA314388B58DC46719702844&quot;&gt;{&amp;quot;des&amp;quot;:null,&amp;quot;id&amp;quot;:0,&amp;quot;md5&amp;quot;:&amp;quot;bdb368fe-b568-4157-9b17-818104295f57&amp;quot;,&amp;quot;seekProgress&amp;quot;:5418,&amp;quot;title&amp;quot;:null,&amp;quot;url&amp;quot;:&amp;quot;/storage/sdcard1/Kuzo/Music/2F06A8D7CA314388B58DC46719702844/15/15/bdb368fe-b568-4157-9b17-818104295f57.mp3&amp;quot;}&lt;/string&gt;
    &lt;string name=&quot;USER_TERM_MUSIC_LIST_KEY&quot;&gt;[{&amp;quot;fileSize&amp;quot;:4008624,&amp;quot;id&amp;quot;:0,&amp;quot;length&amp;quot;:0,&amp;quot;md5&amp;quot;:&amp;quot;bdb368fe-b568-4157-9b17-818104295f57&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;?? ?? - ?????&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/storage/sdcard1/Kuzo/Music/2F06A8D7CA314388B58DC46719702844/0/0/bdb368fe-b568-4157-9b17-818104295f57.mp3&amp;quot;,&amp;quot;singer&amp;quot;:null,&amp;quot;userUuid&amp;quot;:&amp;quot;2F06A8D7CA314388B58DC46719702844&amp;quot;,&amp;quot;uuid&amp;quot;:&amp;quot;bdb368fe-b568-4157-9b17-818104295f57&amp;quot;},{&amp;quot;fileSize&amp;quot;:6749379,&amp;quot;id&amp;quot;:0,&amp;quot;length&amp;quot;:0,&amp;quot;md5&amp;quot;:&amp;quot;b49b55b0-ae7c-47d5-9cb4-6cf03249efdc&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;????? - ???&amp;quot;,&amp;quot;path&amp;quot;:&amp;quot;/storage/sdcard1/Kuzo/Music/2F06A8D7CA314388B58DC46719702844/1/0/b49b55b0-ae7c-47d5-9cb4-6cf03249efdc.mp3&amp;quot;,&amp;quot;singer&amp;quot;:null,&amp;quot;userUuid&amp;quot;:&amp;quot;2F06A8D7CA314388B58DC46719702844&amp;quot;,&amp;quot;uuid&amp;quot;:&amp;quot;b49b55b0-ae7c-47d5-9cb4-6cf03249efdc&amp;quot;}]&lt;/string&gt;
    &lt;string name=&quot;userUUID&quot;&gt;2F06A8D7CA314388B58DC46719702844&lt;/string&gt;
    &lt;string name=&quot;LOCAL_SAVE_RADIO_INFO_KEY2F06A8D7CA314388B58DC46719702844&quot;&gt;{&amp;quot;coverUrlLarge&amp;quot;:null,&amp;quot;coverUrlSmall&amp;quot;:null,&amp;quot;id&amp;quot;:-1,&amp;quot;isCollected&amp;quot;:false,&amp;quot;kind&amp;quot;:null,&amp;quot;programName&amp;quot;:null,&amp;quot;radioDesc&amp;quot;:null,&amp;quot;radioName&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;radioPlayCount&amp;quot;:null,&amp;quot;rate24AacUrl&amp;quot;:&amp;quot;http://live.xmcdn.com/live/536/24.m3u8&amp;quot;,&amp;quot;rate24TsUrl&amp;quot;:&amp;quot;http://live.xmcdn.com/live/536/24.m3u8&amp;quot;,&amp;quot;rate64AacUrl&amp;quot;:&amp;quot;http://live.xmcdn.com/live/536/24.m3u8&amp;quot;,&amp;quot;rate64TsUrl&amp;quot;:&amp;quot;http://live.xmcdn.com/live/536/24.m3u8&amp;quot;,&amp;quot;scheduleID&amp;quot;:null,&amp;quot;supportBitRates&amp;quot;:null,&amp;quot;updatedAt&amp;quot;:null}&lt;/string&gt;
    &lt;boolean name=&quot;LOCAL_SAVE_MUSIC_IS_PAUSE_KEY&quot; value=&quot;false&quot; /&gt;
    &lt;string name=&quot;USER_TERM_TONG_SESSION_LIST_KEY&quot;&gt;[]&lt;/string&gt;
    &lt;int name=&quot;com.kh.tong.term.statemachine.TermMenuSM.LAST_SAVED_MENU_KEY&quot; value=&quot;0&quot; /&gt;
    &lt;int name=&quot;com.kh.tong.term.statemachine.TermAudioVolumeSM.PrefKeyVolumn&quot; value=&quot;7&quot; /&gt;
    &lt;boolean name=&quot;LOCAL_SAVE_RADIO_IS_PAUSE_KEY&quot; value=&quot;false&quot; /&gt;
    &lt;string name=&quot;Password&quot;&gt;8888&lt;/string&gt;
&lt;/map&gt;
</pre>
<p>主要配置项如下：</p>
<ul>
<li><code>userUUID</code> 应该是酷走 App 的用户 ID；</li>
<li><code>USER_TERM_MUSIC_LIST_KEY</code> 是通过酷走 App 收藏上传的歌曲列表；</li>
<li><code>LOCAL_SAVE_MUSIC_INFO_KEYxxx</code> 是当前用户的歌曲播放信息；</li>
<li><code>LOCAL_SAVE_RADIO_INFO_KEYxxx</code> 是通过酷走 App 收藏添加的在线电台列表；</li>
<li><code>LOCAL_SAVE_MUSIC_IS_PAUSE_KEY</code> 表示保存的音乐播放暂停状态；</li>
<li><code>LOCAL_SAVE_RADIO_IS_PAUSE_KEY</code> 表示保存的电台播放暂停状态；</li>
<li><code>com.kh.tong.term.statemachine.TermMenuSM.LAST_SAVED_MENU_KEY</code> 表示保存的菜单键状态（0：音乐，1：点播，2：电台）；</li>
<li><code>com.kh.tong.term.statemachine.TermAudioVolumeSM.PrefKeyVolumn</code> 为系统音量值；</li>
<li><code>Password</code> 为记录仪的管理密码。</li>
</ul>
<p>对于老版本系统音乐播放的暂停状态得不到保存的问题，可以修改系统脚本强制设为暂停状态，需要播放音乐时通过蓝牙按键启动，我是在 <code>/system/bin/load_iwlwifi.sh</code> 文件后附加操作命令的：</p>
<pre class="brush: bash; title: ; notranslate">
shell@Sf3gr_mrd6_p2_720:/ # cat &gt;&gt; /system/bin/load_iwlwifi.sh
KUZO_CFG=&quot;/data/data/com.kh.tong.termmanager/shared_prefs/KUZOConfig.xml&quot;

busybox sed -i '/LOCAL_SAVE_MUSIC_IS_PAUSE_KEY/s/value=&quot;.*&quot;/value=&quot;true&quot;/' $KUZO_CFG
busybox sed -i '/LOCAL_SAVE_RADIO_IS_PAUSE_KEY/s/value=&quot;.*&quot;/value=&quot;true&quot;/' $KUZO_CFG
</pre>
<h3 id="videoserver">VideoServer</h3>
<p>录像 App 的配置文件 <code>/data/data/com.kh.videoserver/shared_prefs/com.kh.videoserver_preferences.xml</code> 比较简单：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version='1.0' encoding='utf-8' standalone='yes' ?&gt;
&lt;map&gt;
    &lt;string name=&quot;rtsp_port&quot;&gt;8886&lt;/string&gt;
&lt;/map&gt;
</pre>
<p>可以通过 <code>rtsp_port</code> 参数修改视频服务器的 RTSP 端口号。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/kuzo-android-internal/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>入手华硕Zenfone 2旗舰版</title>
		<link>https://zohead.com/archives/zenfone2/</link>
		<comments>https://zohead.com/archives/zenfone2/#comments</comments>
		<pubDate>Fri, 22 Apr 2016 15:15:45 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[手机]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Atom]]></category>
		<category><![CDATA[PadFone]]></category>
		<category><![CDATA[Zenfone 2]]></category>
		<category><![CDATA[华硕]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1218</guid>
		<description><![CDATA[最近发现使用了两年多的华硕 New PadFone Infinity A86 手机在稍微多安装了一些国产 Android App 之后已经有点力不从心了，启动完成之后一般情况下可用运行内存在 400MB 左右，经常出现开了一个 Chrome 页面再退出之后启动器就要重新加载的情况，而且最多也只能保留两个后台应用，看来 2GB RAM 的 Android 手机已经跟不上这个手机 App 体积奋起直追桌面端程序的时代了。这两个月看到国内外好多厂商都发布了新机，果断准备挑选一款合适的手机升级。 目前我对手机的要求也算比较简单了： Android 手机，作为一个伪谷粉还是受不了水果机的诸多限制； 3G [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>最近发现使用了两年多的华硕 New PadFone Infinity A86 手机在稍微多安装了一些国产 Android App 之后已经有点力不从心了，启动完成之后一般情况下可用运行内存在 400MB 左右，经常出现开了一个 Chrome 页面再退出之后启动器就要重新加载的情况，而且最多也只能保留两个后台应用，看来 2GB RAM 的 Android 手机已经跟不上这个手机 App 体积奋起直追桌面端程序的时代了。这两个月看到国内外好多厂商都发布了新机，果断准备挑选一款合适的手机升级。</p>
<p>目前我对手机的要求也算比较简单了：</p>
<ul>
<li>Android 手机，作为一个伪谷粉还是受不了水果机的诸多限制；</li>
<li>3GB 或者更大的运行内存；</li>
<li>1080p 屏幕，对 2k 屏没有什么兴趣；</li>
<li>必须支持联通 4G，能顺带支持移动 4G 双网通更好；</li>
<li>屏幕最小 5 寸，表示小屏手机完全回不去了；</li>
<li>支持 NFC，指纹解锁倒不是特别在乎；</li>
<li>接近原生 Android 的体验，比较抵触国内各种修改版的广告机；</li>
<li>最好能支持外接存储卡；</li>
<li>能支持快充那是最好不过了；</li>
<li>root 方便，能自带或者很方便的安装 Google 套件；</li>
<li>bootloader 最好能够直接解锁。</li>
</ul>
<p>初步考虑的是华为 Nexus 6P 和一加 2 这两款手机，看到 Nexus 6P 的价格再想想海淘的路稍微有点犹豫。本来一直对海外销量挺好的一加手机感兴趣，但看了参数发现一加 2 直接没有 NFC 功能，后来看到其创始人谈到 NFC 功能被删除的原因只是觉得用的人少而且功能被夸大，只能说这种明明目光短视却死不承认的态度还真是有点小醉呢。</p>
<p>最后经过一番搜寻对比还是找到了基本都能满足我要求的华硕 Zenfone 2 手机（我还真的谈不上是华硕的粉丝哦 -_-#），刚好最近华硕的天猫官方店铺搞促销活动， 4GB RAM 64GB ROM 的 Zenfone 2 从 2399 元降到了 1599 元，而且还能领优惠券继续减价，这样就不用考虑什么了，直接下单购买。</p>
<p>从上海到南京快递走了一天之后手机到手发现华硕天猫店还是比较厚道的，在这种促销力度下还是送了不少赠品：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442992/zenfone2-packages.jpg" alt="Zenfone2 全套" title="Zenfone2 全套"></p>
<p>分别送了充电宝、原装耳机、自拍杆、贴膜、手机壳，而且没有像某些网友评价的那样国行版本默认不给快充充电器。</p>
<blockquote>
<p><strong>福利</strong></p>
<p>现在购买的华硕 Zenfone 2 手机在首次使用时会提示激活两年 100GB 的 Google Drive 奖励,我的 Google Drive 空间又成功扩容了，而且似乎用 Zenfone2 手机注册新的 ASUS WebStorage 云存储账户也是有空间奖励的。</p>
</blockquote>
<p>至于手机的外观实在没有什么好说的 — 因为看起来这款 Zenfone 2 就算和我之前用的 PadFone Infinity 相比也似乎没有什么太好的设计元素在里面。</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442986/zenfone2-front.jpg" alt="Zenfone2 正面" title="Zenfone2 正面"></p>
<p>Zenfone 2 是全塑料机身，正面还是延续了华硕之前众多老机型用的 3 个触控按键，除了最上面的电源键，手机正面以及左右两边就没有其它按键了，音量键被挪到了背面：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442982/zenfone2-back.jpg" alt="Zenfone2 背面" title="Zenfone2 背面"></p>
<p>背面上方还是有 ASUS 的 LOGO，下面的 intel inside 标志表示这是一款使用 Intel Atom 处理器的手机。初看起来是不是觉得这土豪金的配色应该质感还不错?背面倒是一直沿用了华硕之前一些手机的弧形后盖，而且表面还是华硕用了一万年的金属拉丝效果，但比较悲剧的是这用在纯塑料后盖上的结果就是手摸上去触感比较差（赶紧套上赠送的手机壳压压惊 ^_^）。</p>
<p>值得一提的是华硕把电源键放在最顶端似乎是考虑到 5.5 寸的尺寸下用户能更好的按到，但实际上不管是否套上手机壳，这个电源键的手感都是很差的，还好 Zenfone 2 支持 ZenMotion 双击亮屏和息屏一定程序上可以缓解这个问题。</p>
<blockquote>
<p><strong>提示</strong></p>
<p>华硕 ZenMotion 功能还可以支持在锁屏状态下以特定的触控手势启动指定的 App，例如我就设置了锁屏状态下在屏幕上划一个 <code>V</code> 字就启动微信，划一个 <code>Z</code> 字就启动支付宝。</p>
</blockquote>
<p>好吧，其实我写这篇博文最主要的关注点还是手机里附带的这颗 Intel Atom Z3580 处理器了，可以到 Intel 官网上看到其技术参数：</p>
<table>
<thead>
<tr>
<th>规格</th>
<th>参数</th>
</tr>
</thead>
<tbody>
<tr>
<td>发行日期</td>
<td>Q2’14</td>
</tr>
<tr>
<td>缓存</td>
<td>2 MB</td>
</tr>
<tr>
<td>指令集</td>
<td>64-bit</td>
</tr>
<tr>
<td>指令集扩展</td>
<td>SSE4.1/4.2, SSSE3, SSE3, SSE2, AES-NI</td>
</tr>
<tr>
<td>光刻</td>
<td>22 nm</td>
</tr>
<tr>
<td>内核数</td>
<td>4</td>
</tr>
<tr>
<td>线程数</td>
<td>4</td>
</tr>
<tr>
<td>脉冲频率</td>
<td>2.33 GHz</td>
</tr>
<tr>
<td>最大内存大小</td>
<td>4 GB</td>
</tr>
<tr>
<td>内存类型</td>
<td>LPDDR3 1600</td>
</tr>
<tr>
<td>最大内存通道数</td>
<td>2</td>
</tr>
<tr>
<td>最大内存带宽</td>
<td>12.8 GB/s</td>
</tr>
<tr>
<td>物理地址扩展</td>
<td>32-bit</td>
</tr>
<tr>
<td>显卡基本频率</td>
<td>457 MHz</td>
</tr>
<tr>
<td>色同步脉冲频率</td>
<td>533 MHz</td>
</tr>
<tr>
<td>英特尔® 无线显示技术</td>
<td>Yes</td>
</tr>
<tr>
<td>英特尔® 虚拟化技术</td>
<td>Yes</td>
</tr>
<tr>
<td>英特尔® 64</td>
<td>Yes</td>
</tr>
<tr>
<td>空闲状态</td>
<td>Yes</td>
</tr>
<tr>
<td>增强型英特尔 SpeedStep® 技术</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p>看起来处理器频率也够用了，我所关注的无线显示、虚拟化和 64 位都是支持的，虽然用雷兔兔之类的跑分可能和现在新出的高通 820 之类的 CPU 会有些差距，但日常使用肯定是没有太大问题的。</p>
<p>上手开机之后发现 Zenfone 2 国行版系统（CN 版本，现在仍然是 5.0 系统）里预装了好多个国产 App，例如手机百度、UC 浏览器之类的（当然 Google 套件是没有的）。正当我想直接下载一个 Google Apps 安装器来先试试的时候，我又发现国行 Android 系统的位置信息服务也是由百度提供的，这个就不好忍了，立马下载国际版 WW 版本固件并进行刷机。</p>
<p>得益于 4GB 的运行内存，Zenfone 2 实际运行起来还是非常流畅的，刚刷完机之后系统里看到的空闲内存有 2.8GB 左右，把我原来手机上安装的 100 多个 App 还原之后发现正常运行时 Android 系统的空闲内存也在 2GB 左右，这样必须能很欢畅的使用各种 App 后台了。</p>
<p>至于 Android x86 的兼容问题，由于前几年我也用过联想 K800、XOLO X900 这两款使用 Intel Atom Z2460 处理器的手机，知道这些使用 x86 CPU 的手机在某些 Android App 的兼容性上会有些坑。</p>
<p>华硕 Zenfone 2 这几天用下来发现应用的兼容性相比以前来说确实也有不小的提升了，可能由于我比较少装游戏 App 的关系，我在 Zenfone 2 上暂时还没遇到直接不兼容的程序（像 MX Player 之类的 App 是可以安装 x86 专用版本的）。另外我在开启 root 并安装 x86 版本的 xposed 框架之后再尝试之前用的一些 xposed App 看起来也是没有什么问题的。</p>
<p>说到 Zenfone 2 的续航表现，比较可惜的是华硕在这么硕大的机身里却只塞进去了一个 3000 mAh 的电池，看看我这两天使用下来的电池曲线：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442983/zenfone2-battery.jpg" alt="Zenfone2 续航" title="Zenfone2 续航"></p>
<p>一般正常使用的话 Zenfone 2 差不多能顶上一天多一点（我在住处和公司都是连接 WiFi，其它则是使用联通 4G 网络），比较轻度的使用可能才能接近两天，和百度里看到的其它网友写的续航表现基本相符，虽然我都已经完全习惯了 Android 手机的一天甚至半天一充，但由于这款手机的外形完全谈不上轻薄，所以我还是略有点失望的，还是希望华硕后续的 5.1 或者 6.0 系统版本升级能优化续航表现呢。</p>
<p>最后还是总结说下 Zenfone 2 作为一款拥有 4GB 大内存而且性价比挺高的手机，一般的用户使用起来应该还是非常顺手的，另外 x86 的 Android 手机现在其实可玩性也是很高的哦，祝大家玩的开心。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/zenfone2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>在XOLO X900上实现Ubuntu for Android</title>
		<link>https://zohead.com/archives/ubuntu-for-xolo-x900/</link>
		<comments>https://zohead.com/archives/ubuntu-for-xolo-x900/#comments</comments>
		<pubDate>Sun, 06 Jan 2013 19:19:49 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[手机]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[12.04]]></category>
		<category><![CDATA[Atom]]></category>
		<category><![CDATA[DisplayLink]]></category>
		<category><![CDATA[HDMI]]></category>
		<category><![CDATA[Intel]]></category>
		<category><![CDATA[LapDock]]></category>
		<category><![CDATA[Lava]]></category>
		<category><![CDATA[Motorola]]></category>
		<category><![CDATA[OTG]]></category>
		<category><![CDATA[Ubuntu for Android]]></category>
		<category><![CDATA[udlfb]]></category>
		<category><![CDATA[USB]]></category>
		<category><![CDATA[X11]]></category>
		<category><![CDATA[x86]]></category>
		<category><![CDATA[X900]]></category>
		<category><![CDATA[XOLO]]></category>
		<category><![CDATA[Xorg]]></category>
		<category><![CDATA[显卡]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=378</guid>
		<description><![CDATA[本文同步自（最佳显示效果请点击）：https://zohead.com/archives/ubuntu-for-xolo-x900/ 由于 Lava XOLO X900 使用的 Intel Atom Z2460 这一 x86 的 CPU，我们就可以做一些改动，让其实现初步的 Ubuntu for Android 效果，而且运行的是 x86 版本的 Ubuntu，相对于 ARM 版本（不能运行私有软件，没有源代码的话啥都干不了）来说实用性要好很多的。 先看看实际的效果图： 现在我在这个 Android 手机里的 Ubuntu 上已经开始正常运行 Skype、Ubuntu One、sopcast  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自（最佳显示效果请点击）：<a href="https://zohead.com/archives/ubuntu-for-xolo-x900/" target="_blank">https://zohead.com/archives/ubuntu-for-xolo-x900/</a></p>
<p>由于 Lava XOLO X900 使用的 Intel Atom Z2460 这一 x86 的 CPU，我们就可以做一些改动，让其实现初步的 Ubuntu for Android 效果，而且运行的是 x86 版本的 Ubuntu，相对于 ARM 版本（不能运行私有软件，没有源代码的话啥都干不了）来说实用性要好很多的。</p>
<p>先看看实际的效果图：</p>
<p><a href="http://zohead.com/wp-content/uploads/ubuntu-android-x900.jpg" target="_blank"><img class="alignnone" title="Ubuntu for Android on XOLO X900" src="http://zohead.com/wp-content/uploads/ubuntu-android-x900.jpg" alt="Ubuntu for Android on XOLO X900" width="690" height="523" /></a></p>
<p>现在我在这个 Android 手机里的 Ubuntu 上已经开始正常运行 Skype、Ubuntu One、sopcast 等应用，而且 Ubuntu 和 Android 系统是共存同时运行的，Ubuntu 是运行在外部屏幕上的，对 Android 完全没有影响，不需要 VNC 登录之类的。</p>
<p>Canonical 公司提出的 Ubuntu for Android 请参考这里：</p>
<p><a href="http://www.ubuntu.com/devices/android" target="_blank">http://www.ubuntu.com/devices/android</a></p>
<p>这里提到的 Canonical 的 Ubuntu for Android 的要求有：</p>
<ul>
<li>双核手机，内存最少 512MB；</li>
<li>支持 secondary frame buffer；</li>
<li>支持 USB OTG</li>
</ul>
<p>对于 XOLO X900 来说，第二点要求 secondary frame buffer 暂时无法满足，因为官方的 kernel 只注册了 <strong>/dev/graphics/fb0</strong> 一个 frame buffer 设备。但由于支持 USB OTG，我们这里暂时用支持 Linux frame buffer 的外置 USB 显卡来实现。</p>
<p>需要的设备及配件：</p>
<ul>
<li>Motorola LapDock 100（做显示器及键盘鼠标输入，同时接 USB 外置显卡，你完全可以用自己的显示器）</li>
<li>DisplayLink USB 显卡</li>
<li>USB OTG 线</li>
<li>HDMI 线</li>
</ul>
<p><strong><span style="color: #0000ff;">1、准备 x86 Ubuntu 环境：</span></strong></p>
<p>由于 XOLO X900 只有 16GB 的 ROM 空间，为了速度和扩展考虑，最好可以将 Ubuntu 安装在隐藏未启用的 microSD 插槽上，最好使用 Class 10 的 microSD，这样不会对 Ubuntu 的性能造成影响。</p>
<p>你可以参考这个视频（只有 Youtube 哈）查看如果启用隐藏的 microSD 插槽：</p>
<p><a href="http://www.youtube.com/watch?v=6-FkK7Htohs" target="_blank">http://www.youtube.com/watch?v=6-FkK7Htohs</a></p>
<p>下面是找一个合适的 Ubuntu 系统，如果你有时间的话，完全可以用 VMware 安装一个虚拟机到 SD 卡上。如果你像我一样不想浪费时间安装，可以到网上下载现成的 VMware vmdk 映像并直接拷贝到 SD 卡上。</p>
<p>我选择的是下面这个 Lubuntu 12.04 系统，因为使用 LXDE 桌面，速度比较快，这个网站也有完整的 Unity 桌面环境的 Ubuntu 12.04 系统哦：</p>
<p><a href="http://www.trendsigma.net/vmware/lubuntu1204.html" target="_blank">http://www.trendsigma.net/vmware/lubuntu1204.html</a></p>
<p>你可能需要另一个 Linux 虚拟机来将 Lubuntu 映像里的所有文件拷贝到 SD 卡里（最好能对 SD 卡进行分区，我是建立了一个 ext4 的分区）。</p>
<p><strong><span style="color: #0000ff;">2、准备需要的 DisplayLink USB 显卡驱动：</span></strong></p>
<p>由于 XOLO X900 官方 kernel 对 frame buffer 支持并不完整（缺少 defio 等支持），官方 3.0.8 kernel 源代码里的 DisplayLink USB 显卡驱动 udlfb 无法正常编译。</p>
<p>我基于下面的 udlfb 项目的 0.4 版本修改了一个新的可直接用于 XOLO X900 官方 kernel 的 udlfb 驱动（默认代码加载之后无法正常显示图像）：</p>
<p><a href="http://git.plugable.com/gitphp/index.php?p=udlfb" target="_blank">http://git.plugable.com/gitphp/index.php?p=udlfb</a></p>
<p>我修改过的 udlfb 0.4 驱动的下载地址：</p>
<p><a href="http://miseal.googlecode.com/files/udlfb-v0.4.tar.bz2" target="_blank">http://miseal.googlecode.com/files/udlfb-v0.4.tar.bz2</a></p>
<p>相对默认 0.4 版本的主要改进为：</p>
<ul>
<li>解决在 Linux 3.0.8 中无法正常编译的问题；</li>
<li>解决 kzalloc 分配内存失败的问题，以 vmalloc 替代；</li>
<li>增加卸载驱动时的释放内存处理；</li>
<li>自动根据 EDID 判断显示器分辨率，默认使用 EDID 得到的分辨率；</li>
<li>如果 EDID 无法得到合适的分辨率，使用默认 1280x1024 分辨率；</li>
<li>增加模块参数，加载模块时可以指定初始分辨率</li>
</ul>
<p>编译方法请参考之前写的编译 XOLO X900 自定义 kernel 的文章：</p>
<p><a href="https://zohead.com/archives/xolo-x900-kernel/" target="_blank">https://zohead.com/archives/xolo-x900-kernel/</a></p>
<p>如果你想直接用我编译好的，请访问此链接下载：</p>
<p><a href="http://miseal.googlecode.com/files/x900-kernel-config-modules.7z" target="_blank">http://miseal.googlecode.com/files/x900-kernel-config-modules.7z</a></p>
<p>编译好的 <strong>udlfb.ko</strong> 在解压缩出来的 <strong>modules</strong> 目录中，建议将 <strong>modules</strong> 目录拷贝到 <strong>/system/lib</strong> 目录中。</p>
<p><strong><span style="color: #0000ff;">3、测试 udlfb 驱动是否可用：</span></strong></p>
<p>通过外置带电源的 USB HUB 接上 DisplayLink USB 显卡（Motorola Lapdock 就是一个带电源的 USB HUB 哈），并将显卡接到外置显示器上，root 过之后，在 shell 中运行 <strong>su</strong> 然后运行：</p>
<p><strong>insmod /system/lib/modules/udlfb.ko</strong></p>
<p>如果一切正常的话，驱动将自动判断你的显示器分辨率，并在显示器中显示绿屏。</p>
<p>然后运行下面的命令检查 frame buffer 设备是否正常，一般应有正常的设备节点信息输出：</p>
<p><strong>ls -l /dev/graphics/fb1</strong></p>
<p>如果你的显示器不支持 EDID 或者默认的 1280x1024 分辨率不支持，也可以加载驱动时手工指定分辨率，例如：</p>
<p><strong>insmod /system/lib/modules/udlfb.ko init_xres=1024 init_yres=768</strong></p>
<p>上面的命令即将初始分辨率设置为 1024x768。</p>
<p><strong><span style="color: #0000ff;">4、屏蔽 Android 本身对 USB 键盘鼠标的支持：</span></strong></p>
<p>由于 XOLO X900 默认支持 USB OTG，通过 OTG 接上 USB 键盘鼠标之后，可以直接对 Android 进行操作，而且任何对键盘和鼠标的操作都会解锁手机，这对于我们运行 Ubuntu for Android 是毫无益处的，而且会导致重复的 input event 发到 Android 界面上。因此我们需要屏蔽 Android 本身对 USB 输入设备的支持。</p>
<p>首先接上 USB 键盘和鼠标（通过 USB HUB），并确定是哪个 input 设备，同样在 root 中 su 运行：</p>
<p><strong>ls /dev/input/event*</strong></p>
<p>你会看到很多个 event 设备，一一用下面的命令（把 X 换为具体的设备名）确定到底哪个是你所插上的 USB 键盘和鼠标，cat 之后在键盘上敲键或者移动鼠标，正确的设备将会有输出：</p>
<p><strong>cat /dev/input/eventX</strong></p>
<p>假设确定好鼠标和键盘分别为：<strong>/dev/input/event10</strong> 和 <strong>/dev/input/event11</strong>。</p>
<p>然后运行 <strong>dmesg</strong> 确定 USB 键盘和鼠标的设备名，你可以看到类似这样的输出：</p>
<pre class="brush: bash; title: ; notranslate">
usb 1-1: new high speed USB device number 2 using penwell_otg
hub 1-1:1.0: USB hub found
hub 1-1:1.0: 7 ports detected
usb 1-1.1: new full speed USB device number 3 using penwell_otg
input: Motorola Mobility Motorola HD Dock as /devices/pci0000:00/0000:00:02.3/usb1/1-1/1-1.1/1-1.1:1.0/input/input11
generic-usb 0003:22B8:0938.0003: input,hidraw0: USB HID v1.01 Keyboard [Motorola Mobility Motorola HD Dock] on usb-0000:00:02.3-1.1/input0
usb 1-1.3: new low speed USB device number 4 using penwell_otg
input: BTC USB Cordless Mouse as /devices/pci0000:00/0000:00:02.3/usb1/1-1/1-1.3/1-1.3:1.0/input/input12
generic-usb 0003:1241:0003.0004: input,hidraw1: USB HID v1.10 Keyboard [BTC USB Cordless Mouse] on usb-0000:00:02.3-1.3/input0
input: BTC USB Cordless Mouse as /devices/pci0000:00/0000:00:02.3/usb1/1-1/1-1.3/1-1.3:1.1/input/input13
generic-usb 0003:1241:0003.0005: input,hidraw2: USB HID v1.10 Mouse [BTC USB Cordless Mouse] on usb-0000:00:02.3-1.3/input1
usb 1-1.6: new high speed USB device number 5 using penwell_otg
</pre>
<p>上面的 <strong>Motorola Mobility Motorola HD Dock</strong> 和 <strong>BTC USB Cordless Mouse</strong> 即为 USB 键盘和鼠标设备的设备名，记下这些。</p>
<p>编译 <strong>/system/etc/excluded-input-devices.xml</strong> 配置文件，将上面的 USB 键盘和鼠标设备名加入进来，然后重启手机，在 USB 输入设备上的操作就不会影响 Android 系统。</p>
<p>例如我的配置文件内容如下：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;devices&gt;
&lt;device name=&quot;Unipoint HID&quot;/&gt;
&lt;device name=&quot;RMI4 Unipoint&quot;/&gt;
&lt;device name=&quot;Motorola Mobility Motorola HD Dock&quot;/&gt;
&lt;device name=&quot;BTC USB Cordless Mouse&quot;/&gt;
&lt;/devices&gt;
</pre>
<p><strong><span style="color: #0000ff;">5、在 Android 中切换到 Ubuntu 环境：</span></strong></p>
<p>首先 su 运行 shell 创建一个目录作为 Ubuntu 分区的挂载点（这里假设为 /system/sd）：</p>
<p><strong>mount -o remount,rw /dev/block/mmcblk0p2 /system</strong><br />
<strong> busybox mkdir -m 777 /system/sd</strong><br />
<strong> mount -o remount,ro /dev/block/mmcblk0p2 /system</strong></p>
<p>你可以使用我写好的这个切换到 Ubuntu 的脚本 <strong>startubuntu</strong>（我这里是挂载了 SD 卡第一个 ext4 分区，请根据需要自行修改）：</p>
<p><a href="http://pastebin.com/raw.php?i=9r21dR7L" target="_blank">http://pastebin.com/raw.php?i=9r21dR7L</a></p>
<p>我在脚本中将 Android 中的 /mnt/sdcard 目录挂载到了 Ubuntu 里的 /sdcard 目录，Android 系统的 /system 目录挂载到了 /android/system 目录，这样可以很方便的在 Ubuntu 中访问 Android 系统中的数据。</p>
<p><strong><span style="color: #0000ff;">6、准备运行 X 的环境：</span></strong></p>
<p>假设你已经切换到 Ubuntu，首先安装 DisplayLink 的 X 驱动：</p>
<p><strong>apt-get install xserver-xorg-video-displaylink</strong></p>
<p>然后安装输入模块：</p>
<p><strong>apt-get install xserver-xorg-input-evdev</strong></p>
<p>安装成功之后，修改 <strong>/etc/X11/xorg.conf</strong> X11 配置文件（Ubuntu 12.04 中没有这个配置文件，需要在 <strong>/usr/share/X11/xorg.conf.d</strong> 目录中自己增加新的配置文件，我的为：<strong>52-displaylink.conf</strong>），内容为下面的链接：</p>
<p><a href="http://pastebin.com/raw.php?i=WjcfFWc2" target="_blank">http://pastebin.com/raw.php?i=WjcfFWc2</a></p>
<p>注意请将其中的 input 设备和分辨率改为自己需要的。</p>
<p><strong><span style="color: #0000ff;">7、运行 X - 最终的 Ubuntu for Android：</span></strong></p>
<p>产生 X 的初始配置文件 <strong>/root/.xinitrc</strong>：</p>
<p><strong>#!/bin/sh</strong><br />
<strong> xrandr -o 0</strong><br />
<strong> startlubuntu</strong></p>
<p>第二行的 <strong>xrandr</strong> 命令是专门为 DisplayLink udlfb 驱动修改的，没有这个的话可能会导致 X 环境中的菜单项不能正确显示。第三行的 <strong>startlubuntu</strong> 你可以替换成你需要的 X 命令（例如：xinit lxsession）。</p>
<p>然后运行 <strong>startx</strong> 就可以启动 X 桌面环境了。</p>
<p>某些情况下如果这样运行 startx 还是有问题，可以在 <strong>startx</strong> 时增加参数：</p>
<p><strong>startx -- :0 vt1</strong></p>
<p>如果这样可以的话表示 X 使用的 VT 不正确，这时你可能需要将 <strong>/etc/X11/xinit/xserverrc</strong> 改为下面这样以强制指定 X 使用的 VT：</p>
<p><strong>#!/bin/sh</strong><br />
<strong> exec /usr/bin/X -nolisten tcp vt1 "$@"</strong></p>
<p>8、总结：</p>
<p>这样实现的 Ubuntu for Android 实际还是有一些不足的：</p>
<ul>
<li>必须要有外置的 USB 显卡太不方便，而且热插拔 USB 显卡会导致 X server 直接挂掉，最好的解决方案是启用 HDMI frame buffer；</li>
<li>暂时没有声音输出，可能可以用 USB 声卡，或者将声音输出至手机（能想象的到的丑陋）；</li>
<li>不支持通过 USB HUB 进行充电，应该是要修改 kernel 才能支持</li>
</ul>
<p>本文的内容均为我根据实际使用所写，没有考虑到通用的情况，其中有任何问题欢迎提出指正哦 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/ubuntu-for-xolo-x900/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>构建Lava XOLO X900非官方kernel</title>
		<link>https://zohead.com/archives/xolo-x900-kernel/</link>
		<comments>https://zohead.com/archives/xolo-x900-kernel/#comments</comments>
		<pubDate>Thu, 20 Dec 2012 13:38:43 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[手机]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[Atom]]></category>
		<category><![CDATA[cifs]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[Intel]]></category>
		<category><![CDATA[K800]]></category>
		<category><![CDATA[Lava]]></category>
		<category><![CDATA[OTG]]></category>
		<category><![CDATA[U盘]]></category>
		<category><![CDATA[x86]]></category>
		<category><![CDATA[X900]]></category>
		<category><![CDATA[XOLO]]></category>
		<category><![CDATA[Z2460]]></category>
		<category><![CDATA[印度]]></category>
		<category><![CDATA[模块]]></category>
		<category><![CDATA[联想]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=371</guid>
		<description><![CDATA[本文同步自（最佳显示效果请点击）：https://zohead.com/archives/xolo-x900-kernel/ 本文目标为 Lava XOLO X900 这一印度咖喱味手机，同样 Intel Atom Z2460 的芯，移植 kernel 的方法和之前的联想 K800 手机基本一致，具体请移步下面的链接： https://zohead.com/archives/k800-kernel-otg-udisk/ 经过确认 XOLO X900 默认也是 Android 4.0.4 ROM，同样 3.0.8 kernel，当然硬件会有所不同，不过 OTG U盘所需要使用的 usb-stor [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自（最佳显示效果请点击）：<a href="https://zohead.com/archives/xolo-x900-kernel/" target="_blank">https://zohead.com/archives/xolo-x900-kernel/</a></p>
<p>本文目标为 Lava XOLO X900 这一印度咖喱味手机，同样 Intel Atom Z2460 的芯，移植 kernel 的方法和之前的联想 K800 手机基本一致，具体请移步下面的链接：</p>
<p><a href="https://zohead.com/archives/k800-kernel-otg-udisk/" target="_blank">https://zohead.com/archives/k800-kernel-otg-udisk/</a></p>
<p>经过确认 XOLO X900 默认也是 Android 4.0.4 ROM，同样 3.0.8 kernel，当然硬件会有所不同，不过 OTG U盘所需要使用的 usb-storage 模块也是和 K800 一样默认没有开启的。</p>
<p>基于基本相同的 kernel source，先使用 Medfield 默认的配置 i386_mfld_defconfig，发现与现有的 kernel 差距比较多，然后用 Moto 的 i386_mfld_moto_defconfig 编译出的模块加载依然 panic。没办法，硬着头皮与实际运行中 kernel 情况进行对比，发现基于默认配置 i386_mfld_defconfig 进行修改是比较好的方法，而且看得出 XOLO 相对联想还是做了一定的优化，去掉了像 CONFIG_DEBUG_KERNEL 之类的很多调试选项，默认允许了 tun 驱动等。另外声卡相关的配置不同的地方也比较多，经过最终改动和确认，编译之后，先已能成功加载并使用之前在 K800 上编译的那些模块。</p>
<p>XOLO X900 的内核模块和配置文件的下载地址：</p>
<p><a href="http://miseal.googlecode.com/files/x900-kernel-config-modules.7z" target="_blank">http://miseal.googlecode.com/files/x900-kernel-config-modules.7z</a></p>
<p>使用方法和 K800 的基本一致，只是 CIFS 文件系统的使用上有变动：</p>
<p>insmod des_generic.ko<br />
insmod md4.ko<br />
insmod cifs.ko</p>
<p>ASIX Electronics 的 USB 以太网卡的驱动 asix.ko 也已经更新到官方最新的版本（kernel 自带的版本无法使用）。</p>
<p>现已基本可以确认我改动之后的 kernel 和 X900 现有 kernel 的相似性已有 90% 或以上了，不过由于 X900 手机悲剧滴将 bootloader 给锁了，无法刷未签名的 kernel，暂时还没有太好的办法来直接替换 kernel 进行测试哦。</p>
<p>另外有一些需要说明的地方：</p>
<ol>
<li>XOLO X900 现有 kernel 中支持 Kineto GAN 虚拟网卡驱动（支持 VOIP 网络电话的），Moto Razr i 公开的 kernel source 中却并没有这个的支持，为此我手工增加了这个的驱动（上面下载的 kernel configuration 中也有的）；</li>
<li>目前还有 apwr3_0、pax、sep3_7 这三个非免费开源的内核模块没有源代码，暂时也没有办法在网上找到，不过从现在来看，似乎 X900 实际运行时也未使用这三个模块。</li>
</ol>
<p>同样我不对任何导致你的手机 panic 挂掉的后果承担责任，有任何问题欢迎提出指正哦 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/xolo-x900-kernel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
