Quantcast
Channel: 英特尔开发人员专区文章
Viewing all 172 articles
Browse latest View live

英特尔® 硬件加速执行管理器终端用户许可协议 - Windows*

$
0
0

版权所有© 2013 英特尔公司。
所有权利受到保护。

再次分发。在满足以下条件的情况下,允许以二进制的形式进行再次分发或使用(不作修改):

1. 再次分发必须在文档和/或其他随分发提供的材料中保留上述版权通知以及下述免责声明。

2. 未经英特尔事先明确书面许可,不可使用英特尔公司的名称或其供应商的名称进行背书或者促销从该软件派生的产品。

3. 不准对本软件进行逆向工程、反向编译或反汇编。有限的专利许可。英特尔公司针对它现在或今后拥有或控制的专利授予全球性的、免版税的、非独家的许可,被许可方可以制作、已经制作、使用、进口、要约出售和出售(“利用”)本软件,但是其范围仅限于有必要借助任何此类专利利用该软件。不准将该专利许可用于任何包含本软件的组合。任何硬件本身并不在本许可范围之内。

免责条款。
此软件由版权持有者和献助者按“原样”提供,绝不提供其他任何明确或隐含的担保(包括,但不限于,商品适销性和或适用于特定目的适用性的担保)。在任何情况下,版权持有者或 献助者对使用本软件而以任何方式产生之直接的、间接的、事故性的、特殊的、惩罚性的或后果性的损失(包括,但不限于,购买替代产品或服务,使用、数据或利润的减少,或者业务中断)概不承担责任,不论损失是如何造成的及根据任何责任理论(无论是按合同法、严格责任或侵权 - 包括疏忽或其它 -),即使事先被告知这种损失的可能性。

点击以接受《最终用户许可协议》并下载 haxm-windows_r03.zip


在英特尔架构 Android* 设备上使用 HTML5 游戏中的触控屏

$
0
0

随着智能手机和平板电脑的迅速普及,在这些触控设备上提供自然体验的方式也发生了巨大变化。 原生应用开发人员已经整合了触控事件来提升用户体验并改变用户与内容交互的方式。 智能手机和平板电脑等移动设备通常采用敏感的电容式触控屏采集用户手指操作。 随着移动网络开始支持更加先进的应用,web 开发人员需要处理这些事件的解决方案。 例如,几乎任何快速游戏都需要同时按下多个按钮的操作,从触控屏的角度来说就是多触控操作。

使用 HTML5 中的画布元素

本文将详细介绍基于设备 Android* 设备、使用 HTML5 的触控事件 API。 另外,我们还将探讨开发哪些应用,并介绍开发触控应用的技巧与策略。 直到最近移动应用才能使用 HTML5 跨平台技术处理触控事件。 这是让移动应用变得更加原生自然的全新方法。 由于我们能够整合触控事件处理和 HTML5 的新画布组件,我们能够采集用户的活动并支持用户利用画布组件。 HTML5 对<画布>组件的定义是:独立于分辨率的位图画布,可用来渲染图形、游戏图形或其它动态视觉图片。 根据 web 定义,画布包含以 HTML 代码定义的可画区域并且带有属性。 JavaScript* 代码可通过丰富的会话功能集访问这一区域。

使用 HTML5 触控事件,应用可为用户提供与原生应用同样出色的体验。 通过提供触控和各种手势控制,开发人员可帮助用户迅速穿越应用或构建精彩的交互式游戏。

开发人员指南

让我们深入探讨如何使用 HTML5 画布组件采集用户触控事件。

正如万维网联盟(W3C)指出:“本规范定义了第五个主要版本,首次改动了万维网的核心语言: 超文本标记语言(HTML)。”

有四类触控事件:

  • touchstart
  • touchmove
  • touchend
  • touchcancel

下面分别详细介绍。

touchstart

当用户在触控表面放置一个触控焦点就会激活该事件;该事件的焦点必须是一个组件。

touchmove

当用户在触控表面上移动一个触控点时就会激活该事件。

该事件的焦点必须是当触控焦点放在表面时创建 touchstart 事件的同一元素,无论该触控焦点是否曾经移至目标组件的智能范围之外。

请注意:发送 touchmove 事件的速度取决于应用执行速度,而应用执行速度又取决于硬件。

touchend

当用户在触控表面上删除一个触控点时就会激活该事件。另外,当触控点离开触控表面时也会激活该事件,例如,从屏幕上拖开。

该事件的焦点必须是当触控焦点放在表面时创建 touchstart 事件的同一元素,无论该触控焦点是否曾经移至目标组件的智能范围之外。

touchcancel

当在特定实施过程中触控焦点被干扰时就会激活该事件。 例如,同步事件或活动在 UI 上开始,取消触控,或触控焦点离开存档窗口进入可处理用户交互的非报告区域。 当客户端在触控表面放置的触控焦点多于设备或执行的设计存储数量时,我们可能分配这一事件类型。 在这种情况下,触控列表中之前存储的触控对象应清空。

为了采集触控事件并在画布组件上解释,我们首先应了解画布组件的使用方法。 当使用画布进行标准 HTML 输入时必须注意两个方面。

  • 文本信息字段提高移动设备上的控制台(键区),覆盖屏幕的 50%。 为了避免这种情况,我们需要确保控制台不要覆盖画布太多,或者选择其它输入类型。
  • 默认设置下,移动设备上的按钮有可能很小。 为了便于手指操控按钮,使用<元>标签将视口设置小一些,或者引导比例设置大一些,或者将按钮字体设置得大于 CSS 字体。

让我们看一下显式画布 API。 首先,我们从画布 API 介绍以下方法:

  • Context getContext(String contextId);
  • addEventListener()

getcontext() 方法可获取渲染上下文及其绘画功能。addeventlistener() 可在所调用的 EventTarget 上注册指定的收听者。 事件目标可能是存档中的元素,文档本身、窗口、或者增强事件的任何项目。

句法


target.addEvenListener(type,listener,Boolean)

类型

串代表收听的事件类型(touchstart, touchmove, touchend, touchcancel)。

收听者

当特定类型的事件发生时接收告警。 这必须是在 eventlistener 界面中执行的对象,或者 JavaScript 函数。

boolean

如果值为真,则表示用户希望开始采集触控事件。 采集开始以后,所有指定的事件在分配至 DOM 树下的事件的任何 EventTarget 之前必须分配至列表指定的收听者。

我们来一些代码:

<canvas id= ”touch” width=”150” height=”150”> 

对不起,您的浏览器不支持 HTML5 元素画布。

</canvas>

这与<img>组件十分相似;主要差别是它不具备<src>和<alt>质量。 <画布>组件仅有两个方面:宽和高。 如果出现渲染错误,请尝试在画布特性中指明宽高属性,而不要使用 CSS。 宽高分别默认为 300 和 150。 调整 id 以便使用 JavaScript 初始化画布,其内容需要在浏览器不支持时使用。


var cans= document.getElementById(“touch); 
var canctx = canvas.getContect(‘2d’); 

这一变量可采集画布并绘画图形对象,canctx 包含渲染上下文。 本案例中是二维图形对象。

上下文包含在画布上进行绘画的基本方法,例如,arc(),lineto(),和 fill()。


document.addEventListener("touchstart", startTouchDrawing, true); 
document.addEventListener("touchmove", startMoveDrawing, false); 
document.addEventListener("touchend", endDrawing, false); 
document.addEventListener("touchcancel", cancelDrawing, false); 

当用户的手指在手机屏幕上触摸/移动时,就会创建独立事件。 我们必须处理事件并绘画相应线条。 例如下面的 startMoveDrawing (x, y)函数:


	function startMoveDrawing (event)

	{ event.preventDefault();//To prevent default behavior

	var eventTouch, x, y;

	eventTouch = event.changedTouches[0];// Array to store previous touch cords,0 is the initial one.

	x = eventTouch.pageX;//The first touch for x co-ordinate

	 y = eventTouch.pageY;// The first touch for y co-ordinate

OnTouchMoveDraw(x, y);

	}

	function OnTouchMoveDraw (x, y)

	{

	    

	    if (x || y)

	    {

	        if ((start_x === -1) || start_y === -1)

	        {

	            start_x = x;

	            starty_y = y;

	        }

	        drawLine(x, y);

	

Here, the first contention, that is, "starttouch," is the framework event that calls the user-defined function startTouchDrawing. In the code above preventDefault method anticipates the program’s default behavior and initiates the drawing. start_x and start_y are the previous touch positions. The drawLine(x, y) method draws the line.


	function drawLine(x, y) {

	    ctx.beginPath();

	    ctx.moveTo(start_x, start_y);

	    ctx.lineTo(x, y);

	    ctx.stroke();

	}

	

这里首先一点,“starttouch”是框架事件,它调用由用户定义的函数 startTouchDrawing。 在上述代码中,preventDefault 方法预测程序的默认行为并启动绘画。start_x 和 start_y 是之前的触控位置。 drawLine(x, y)方法绘画线条。

 
function drawLine(x, y) { ctx.beginPath(); ctx.moveTo(start_x, start_y); ctx.lineTo(x, y); ctx.stroke(); } 

beginpath() 方法确保我们开始一个新路径。 开始的新路径擦除现有路径(如有)。 您从路径的结尾到开始绘画界面线条时如果发现动画,可能是因为您一开始就没有使用 beginpath() 功能。 为了使用 HTML5 画布生成路径,我们可以关联不同的子路径。 每条新的子路径的最终目标是变为新的设置焦点。 为了完善我们的绘画而开发子路径,我们可使用 lineto()、arcto()、quadraticcurveto() 和 beziercurveto()。 每当我们开始绘画另一条路径(圆圈、线条、矩形、等等)时,我们也可使用 beginpath()。

该线条从 moveTo 函数中的 x, y 坐标起,到线条函数中的 x, y 坐标止。

总之,触控屏革新了计算领域。通过使用 HTML5 中的画布元素,触控事件可轻松处理,为开发人员带来极大便利。

HTML5 是应用开发领域的未来趋势,英特尔相信它可有力推动经验丰富的开发人员采纳这一跨平台方法,并推动新手开发人员快速掌握这一崭新方法从而在所有现代计算平台上部署应用与游戏。 请访问Intel HTML5Intel Android获取更多项目资源。

其它相关文章与资源

为英特尔® 架构 Android* 设备上的 HTML5 游戏添加声音
使用 HTML5 画布绘画应用
使用 HTML5 构建跨平台应用
HTML5 主页

如需深入了解面向安卓开发人员的英特尔工具,请访问:面向安卓的英特尔® 开发人员专区

 

英特尔和 Intel 标识是英特尔公司在美国和/或其他国家的商标。
版权所有 © 2013 年英特尔公司。 保留所有权利。
*其他的名称和品牌可能是其他所有者的资产。

为英特尔® 架构 Android* 设备上的 HTML5 游戏添加声音

$
0
0

介绍

声音是构建交互式游戏最为重要的组件之一。 一个完美的游戏不仅需要高清图形和故事情节,声音效果也要给玩家惊喜。 为游戏/应用添加音效不仅能够提高娱乐价值,还可提高游戏/应用的整体质量。

音频标记

HTML5 的惊喜特性之一是声音和视频标记。 长期来看,它有望取代今天的主流视频技术。 为了使用 HTML5 音频或视频,首先创建<音频>元素,为音频指明源 URL,包括控制属性。

<audio controls>
 <source src="horse.ogg" type="audio/ogg">
 <source src="horse.mp3" type="audio/mpeg"> 
Your browser does not support the audio element. 
</audio> 

控制特性包括声音控制,例如,播放,停止,和音量。 <音频>组件包括不同的<源>组件。 <源>组件可连接至多个<音频>记录。 MIME 类型(亦称互联网媒体类型)是标记文件格式的方法之一,以便您的框架进行管理。 除了源,我们还指定类型属性。 该属性在下载之前告诉程序 MIME 类型以及配套媒体的编码解码器。 如果不提供属性,浏览器将尝试使用经验方法识别媒体类型。 浏览器将使用最初识别的配置,如果无法识别格式,就采用默认格式。

canPlayType 方法

幸运的是,声音 API 为我们提供了一个识别移动浏览器支持的格式的方法。 我们可通过在 HTML 中标记元素来识别<音频>元素,方法如下:


var audio = document.getElementById('myaudio'); 

另外,我们还可在 JavaScript* 中生成元素:


var audio = new Audio(); 

一旦有了声音组件,其后就是方法和属性了。 为了测试格式支持,我们利用 canplaytype 技术;该技术采用 MIME 类型作为参数:


audio.canPlayType('audio/mpeg’); 

canPlayType 生成三个值:

  1. 有可能
  2. 不确定
  3. “” (空串)

返回类型为奇数是因为编码解码器的异常。 移动浏览器无需试播就可识别编码解码器是否能够播放。

面向音频格式的 MIME 类型

特性

HTML 标记包含一个或多个属性/特性。 属性回加至标记以便为浏览器提供关于标记如何显示或表现的数据。 特性包含一个名称和一个值,用等号(=)区分,值加双引号。 这里是一个示例:风格“颜色: 蓝色”;

以下章节介绍关于<音频>标记/元素的属性。

src: 指明音频文件的位置。 其值必须是音频文件的 URL。预加载: 播放大型文件时,最好缓存记录。 因此,使用预加载属性。 该属性可帮助我们提示浏览器:我们计划在播放之前缓存记录,并提升客户端体验。 可能的值有:

  • 元数据
  • 自动

自动播放:

指明对象加载以后是否开始播放音频。

这是一个布尔属性。 因此,该属性相当于真值。 我们还可指明对场景不敏感的值以匹配属性的规范名称,前后均无空格(也就是自动播放或 autoplay=“autoplay”)。

可能的值有:

  • [空串]
  • 自动播放

媒体组:

该属性用来同步音频文件(或媒体元素)的播放。 它帮助我们指明链接在一起的媒体元素。 该值是文本串,例如: mediagroup=album. 与该值相同的音频文件/媒体元素都在被用户代理/浏览器自动链接在一起。

可使用媒体组属性的一个示例是:从一个视频向另一个视频叠加符号语言转换器轨道。

循环:

该属性表明音频播放结束后是否重复播放。

该属性是布尔属性。 因此,该属性相当于真值。 我们还可指明对场景不敏感的值以匹配属性的规范名称,前后均无空格(也就是循环或 loop=“loop”)。

可能的值有:

  • [空串]
  • 循环

控制:

自动播放音频不可取,您最好让浏览器提供一些控制,例如,音量和播放/暂停。 这可通过向标签添加控制属性即可实现。

该属性是布尔属性。 因此,该属性相当于真值。 我们还可指明对场景不敏感的值以匹配属性的规范名称,前后均无空格(也就是控制或 controls=“controls”)。

可能的值有:

  • [空串]
  • 控制

控制媒体回放

一旦我们使用新组件在 HTML 文档中插入媒体,我们就能够从 JavaScript 代码自动控制它们。 例如,开始(或重新)回放的代码是:


var v = document.getElementsByTagName(“myaudio”); 
v.play(); 

第一行获取存档中的首个音频组件,第二个调用组件的播放策略,用于激活媒体组件。 使用 JavaScript 代码控制 HTML5 音频播放器的播放、停止、音量增减十分简单:


document.getElementById('demo').play() //Play the Audio 
document.getElementById('demo').pause() //Pause the Audio 
document.getElementById('demo').volume+=0.1 // Increase Volume document.getElementById('demo').volume-=0.1 // Decrease Volume 

媒体搜索

媒体组件支持将当前播放位置移至媒体库中的特定位置。 为此,可设置组件中的 currenttime 属性的值。 基本上是将时间设置为您希望播放执行的秒数。

我们可利用组件的搜索属性获取媒体播放的起止时间。 这返回 TimeRanges 对象,列出您希望搜索的时间范围。


var audioElement = document.getElementById(“myaudio”); 
audioElement.seekable.start(); // Returns the starting time (in seconds) 
audioElement.seekable.end(); // Returns the ending time (in seconds) 
audioElement.currentTime = 122; // Seek to 122 seconds 
audioElement.played.end(); // Returns the number of seconds the browser has played 

简单游戏库

简单游戏库(simpleGame)可方便地添加声音对象而构建新声音。 简单游戏库中的声音对象是基于 HTML5 <声音>标记。

<script type="text/javascript" 
  src = "simpleGame.js"></script> 
 <script type="text/javascript"> 

使用简单游戏库您可轻松管理音效:

  1. 创建音效。 最佳格式是 mp3 和 ogg。
  2. 为您的音效创建参数。 务必在函数之外定义变量。
  3. 简单游戏库有声音对象。 为声音构建创建实例。 声音对象需要参数。 您可在 init 函数中设置参数。
  4. 声音可使用声音对象的 play()method 播放。

AppMobi 的直接画布

为了增强 HTML5 的功能,开发人员希望利用 AppMobi 的开发工具与环境构建强大应用。 借助 AppMobi 提供的应用游戏界面(AGI)技术,混合型 HTML5 应用可提升其画面标记命令。 AGI 技术由 AppMobi 开发(http://www.appmobi.com/),该公司是一家 HTML5 服务公司,之前称为 directCanvas。

为了使用 AGI,我们首先了解其结构。 AGI 加速的画布命令需要堆栈为与 HTML 框架相同的“视角”,然后在更高级别转换,以更快速度执行。 另外,这分为两个视图而且不支持访问完全存档对象模式(DOM),标准 Web 视图和加速视图之间的信息传递需要付费。

加速“视角”的代码显示在 HTML5 Web 视图中,它表明 AGI API 规定的 HTML 文档或其它文档中的任何图形组件的渲染都高于加速图形。

使用 AGI 声音特性

应用游戏界面(AGI)技术通过多音效升级弥补了 HTML5 的声音弱点。 HTML5 的最初设计目标不是以低延迟播放各种非传统声音,而这正是游戏和各种应用所需要的。 AGI 多音效创新可支持游戏中的每个元素按照应有的效果播放声音,不受同步声音的限制。 AppMobi API 均可通过 Appmobi.context 对象访问,可增强执行和易用性。

独立背景声音可通过三种策略实现:

开启背景声音:

该方法可开启在后台不断播放的声音。

独立背景声音可由加速画布应用游戏界面提供支持。 使用该方法可开启背景声音或音乐。 该命令结合音频对象可增强性能和易用性。

句法


AppMobi.context.startBackgroundSound("sounds/music_main.mp3",true) 

第一个参数是需要播放的背景声音的路径和文件名,第二个参数是可选的布尔值,它表示背景声音是否间歇性回放。

切换背景声音

 

使用该命令可切换背景声音的开启或关闭状态。 独立背景声音可由加速画布应用游戏界面提供支持。 使用该方法可切换背景声音或音乐。 该命令结合音频对象可增强性能和易用性。

句法


AppMobi.context.toggleBackgroundSound(); 

停止背景声音

使用该命令可停止背景声音。 独立背景声音可由加速画布应用游戏界面提供支持。 使用该方法可停止背景声音或音乐。 该命令结合音频对象可增强性能和易用性。

句法


AppMobi.context.stopBackgroundSound() 

结论

尽管浏览器存在不可预测的行为,HTML5 绝对是令人振奋、开发新型强大应用的技术。 本文讨论了如何将声音集成至带 HTML5 音频组件的应用中,以及 AppMobi 提供的 AGI 技术为什么是开发精彩应用的得力助手。 结合使用 JavaScript、phonegap 和 appmobi 等技术/工具,HTML5 有望开发原本需要原生代码的应用。

更多资源

HTML5 是应用开发领域的未来趋势,英特尔相信它可有力推动经验丰富的开发人员采纳这一跨平台方法,并推动新手开发人员快速掌握这一崭新方法从而在所有现代计算平台上部署应用与游戏。 请访问Intel HTML5 和Intel Android 获取更多资源。

HTML5 声音使用精彩演示:
http://www.createjs.com/#!/SoundJS/demos/visualizer
http://www.createjs.com/#!/SoundJS/demos/game
http://www.createjs.com/#!/SoundJS/demos/explosion

其它相关文章与资源

为英特尔架构安卓设备中的 HTML5 应用开发劲酷动画和切换
在英特尔架构安卓设备上的 HTML5 游戏中使用触控屏
在 HTML5 中使用音频标记
HTML5 新标记
HDMI 音频案例研究: Denon AV 接收器

如需深入了解面向安卓开发人员的英特尔工具,请访问:面向安卓的英特尔® 开发人员专区
 

英特尔和 Intel 标识是英特尔公司在美国和/或其他国家的商标。
版权所有 © 2013 年英特尔公司。 保留所有权利。
*其他的名称和品牌可能是其他所有者的资产。

在英特尔® 凌动™ 平台上进行 Android* 应用开发和优化

$
0
0

摘要

本文介绍了开发和导入 Android 应用至英特尔凌动平台的详细方法,以及使用 Android 原生开发套件(NDK)和优化性能开发应用的最佳设计方案。 安卓开发人员在构建适合英特尔架构的高质量应用时可以参考本文档。

1. 安卓应用分类

如图 1 所示,安卓应用可以分为两种类型。

  • 包含 Java* 代码和仅使用安卓官方 SDK API 和必要资源文件(诸如 xml 和 png)的 Dalvik 应用,可编译成一个 APK 文件。
  • 包含 Java 代码、资源文件、C/C++ 源代码(有时也包含汇编码)的 Android NDK 应用。 所有原生代码被编译成一个动态链接库 (.so 文件),然后在主程序中通过使用 JNI 机制的 Java 进行调用。


图 1:两种安卓应用

2. 安卓原生开发套件

2.1 简介

安卓原生开发套件(NDK)是 Android SDK 的附带工具。 NDK 是强大的安卓应用开发工具,理由如下:

  • 以原生代码的形式构建应用中对性能要求极高的部分。 在使用 Java 代码时,基于 Java 的源代码需要使用一台虚拟机解释成机器语言。 相比之下,原生代码可以在执行之前直接编译和优化成二进制的形式。 正确使用原生代码,您就能在您的应用中构建出高性能的代码,如硬件视频编码和解码、图形处理和算术运算。
  • 重复使用传统的原生代码。 C/C++ 代码可以编译成一个动态库,然后通过使用 JNI 机制的 Java 代码进行调用。

2.2 工具概述

在开发期间,您可以使用英特尔® 硬件执行管理器(HAXM)改善安卓模拟器的性能。 HAXM 是一个硬件辅助虚拟化引擎(管理程序),该引擎可以使用英特尔® 虚拟化技术(Intel®VT)加快主机上的安卓应用模拟速度。 配合英特尔提供的 Android x86 模拟器图像和官方的 Android SDK 管理器一起使用时,HAXM 可以在支持英特尔虚拟化技术的系统上提供更快的安卓模拟体验。 如欲了解更多有关 HAXM 的信息,请访问: http://software.intel.com/zh-cn/android/articles/intel-hardware-accelerated-execution-manager.

2.3 安装 HAXM

使用 Android SDK 管理器安装 HAXM (推荐),或者从英特尔网站下载安装程序以后手动安装 HAXM。 如果您希望它可以自动更新,请如图 2 所示使用 Android SDK 管理器进行安装。[1]


图 2:使用 Android SDK 管理器安装英特尔 HAXM

您也可以访问 http://www.intel.com/software/android,找到正确的安装包后将其下载到您的主机平台上, 然后根据说明逐步安装。

2.3.1 设置 HAXM

运行 HAXM 时需要使用英特尔提供的 Android x86 系统图像。 您可以使用 Android SDK 管理器下载该系统图像,或者从 英特尔® 开发人员专区网站手动下载。

图像成功安装之后,英特尔® x86 Android 模拟器图像将通过与 Android SDK 一同提供的 “模拟器-x86” 二进制代码自动执行。 安卓模拟器被英特尔 VT 加速之后可以加快您的开发进程。

3. 为英特尔凌动架构开发并移植 NDK 应用

3.1 为搭载英特尔凌动处理器的设备开发 NDK 应用

成功安装完 NDK 之后,请花费几分钟的时间阅读 <ndk>/docs/ 目录下的文件,尤其是 OVERVIEW.html 和 CPU-X86.html,以便您能完全了解 NDK 机制及使用方法。

如图 3 所示,NDK 应用开发可分为五个步骤:


图 3: NDK 应用开发流程

其中,hello-jni 演示用于说明这五个步骤。 您可以通过您的 NDK Root\samples\hello-jni 文件夹找到该演示 [5]。 Hello-jni 演示是 NDK 中的一个简单应用,该应用可以从共享库中的一个本地方法中获取一个字符串,然后将它用在应用 UI 中。

3.1.1. 创建原生代码

创建一个新的安卓项目并将您的原生源代码放在 <project>/jni/ 下。 项目内容显示在图 4 中。该演示在原生代码中包含了一个名为 Java_com_example_hellojni_HelloJni_stringFromJNI() 的简单函数。 如源代码所示,它能从 JNI 中返回一个简单字符串。


图 4:创建原生代码

3.1.2 创建 MakeFile ‘Android.mk’

默认情况下,构建的 NDK 应用仅用于 ARM 平台。 要想构建用于英特尔凌动平台的 NDK 应用,您需要把 APP_ABI := x86 添加到 MakeFile 中。


图 5:创建 Makefile

3.1.3 编译原生代码

通过运行该项目目录的 'ndk-build'脚本构建原生代码。 该脚本位于顶级 NDK 目录中。 结果如图 6 所示。


图 6:已编译的原生代码

构建工具将把剥离的共享库自动拷贝到应用的项目目录中的正确位置上。

3.1.4 从 Java 调用原生代码

成功部署完共享库之后,您可以从 Java 端调用函数。 代码如图 7 所示。一个名为 stringFromJNI() 的公用原生函数在 Java 代码中创建出来,该函数可以使用 System.loadlibrary() 加载共享库。


图 7:从 Java 调用原生代码

3.1.5 通过 GDB 调试

如果您想要通过 GDB 调试 NDK 应用,必须满足以下条件:

  • 通过“ndk-build”构建 NDK 应用
  • 在 Android.manifest 中将 NDK 应用设置为“debuggable”
  • 在 Android 2.2 (或更高版本) 上运行 NDK 应用
  • 只运行一个目标
  • 将 adb 的目录添加到 PATH 上

使用 ndk-gdb 命令调试应用。 如图 8 所示,您可以设置一个端点或者通过逐步调试的方法跟踪一个变量值的变化记录。


图 8:通过 GDB 调试 NDK 应用

3.2 将现有的 NDK 应用移植到搭载英特尔凌动处理器的设备上

在本节中,假定您有一个可用于 ARM 平台的安卓应用,您需要首先移植该应用然后将其部署到英特尔凌动平台上。

将安卓应用移植到英特尔凌动平台上类似于开发流程。 步骤如图 9 所示。


图 9:将安卓应用移植到英特尔凌动平台上

3.2.1 移植 Dalvik 应用

Dalvik 应用可以直接运行在搭载英特尔凌动处理器的设备上。 用户界面需要根据目标设备进行调整。 就高分辨率设备而言,诸如分辨率为 1280*800 或更高的平板电脑,默认的内存分配可能不会满足应用的要求,此时可能会导致无法启动应用。 此时建议您为高分辨率设备增加默认内存分配。

3.2.2 移植 Android NDK 应用

与移植 Dalvik 应用相比,移植 NDK 应用会稍微复杂一些。 根据以下的原生代码属性,所有的 NDK 应用都能分成三种类型:

  • 仅包含与硬件无关的 C/C++ 代码
  • 使用第三方动态链接库
  • 包含与非 IA 平台高度相关的汇编码

仅包含与硬件无关的 C/C++ 代码的原生代码

  1. 重新编译原生代码,使其可以成功运行英特尔凌动平台上的应用。
  2. 打开 NDK 项目并搜索 Android.mk 文件,将 APP_ABI := armeabi armeabi-v7a x86添加到 Android.mk 中然后使用 ndk-build 重新构建原生代码。
  3. 如果未发现 Android.mk 文件,请使用 ndk-build APP_ABI="armeabi armeabi-v7a x86"命令构建项目。
  4. 使用支持的 x86 平台再次打包应用。

如果原生代码使用的是一个第三方动态链接库,共享库必须被重新编译成适合英特尔凌动平台的 x86 版本。

如果原生代码包含与非 IA 平台高度相关的汇编码,必须使用 IA 汇编或 C/C++ 重写代码。

4. 原生代码开发的最佳设计方案

4.1 强制性内存对齐

由于各种架构、平台和编译器间存在差异,同一种数据结构在不同的平台上可能会具备不同的数据大小。 如果不使用强制性内存对齐,不一致的数据大小就可能会导致加载错误。 [2]

以下例子对不同平台上的同一种数据结构的数据大小进行解释:

struct TestStruct {
int mVar1;
long long mVar2;
int mVar3;
};

这个简单的结构中包含三个变量,分别为 mVar1、mVar2 和 mVar3。

mVar1 是一个整数,占用 4 个字节
mVar2 是双长整数,占用 8 个字节
mVar3 也是个整数,占用 4 个字节。

在 ARM 和英特尔凌动平台上需要多少空间?

图 10 中显示了为 ARM 和带有一个默认的编译器开关的英特尔凌动平台编译的数据大小。ARM 自动使用双重对齐并占用 24 个字节,而 x86 则占用 16 个字节。


图 10:通过默认编译标识分配内存

由于 ARM 要求对诸如 mVar2 等 64 位变量执行 8 字节对齐,因此 8 字节(64 位) mVar2 在 TestStruct 中会具备一个不同的布局。 在大多数情况下,这不会导致问题,因为与构建 ARM 相比,构建 x86 需要完全重新构建。

然而,如果应用对类或结构执行了序列化,则会导致大小不匹配。 例如,如果您在一个 ARM 应用中创建了一个文件,ARM 应用会将 TestStruct 写入该文件。 如果您稍后将该文件中的数据加载到一个 x86 平台中,该应用中的类大小将与文件中的不同。 类似的内存对齐问题也会出现在具有特定内存布局的网络流量上。

GCC 编译器选项“-malign-double”将在 x86 和 ARM 上实现相同的内存对齐。


图 11:添加 -malign-double 标识时分配内存

4.2 将 NEON* 指令移植到 SSE [3]

4.2.1 NEON

ARM NEON* 技术主要用于诸如智能手机和 HDTV 应用等多媒体。 ARM 文档显示其基于 128 位 SIMD 引擎的技术 — ARM Cortex*(一种串行扩展)可提供比 ARMv5 架构至少高 3 倍的性能,以及比 ARMv6 至少高 2 倍的性能。 如欲了解有关 NEON 技术的更多信息,请访问: http://www.arm.com/products/processors/technologies/neon.php.

4.2.2 SSE: 英特尔推出的类似工具

SSE 指面向英特尔架构(IA)的 SIMD 流指令扩展。 英特尔凌动处理器目前支持 SSSE3 (补充 SIMD 流指令扩展 3)和更早的版本,但还不支持 SSE4.x。SSE 是一个可以处理浮点数据打包的 128 位引擎。 这一执行模式开始于 MMX 技术。SSx 是较新的技术,取代了 MMX。 如欲了解详细信息,请参阅“第一卷: 基础架构”部分 — 英特尔 64 和 IA-32 架构软件开发人员手册。 章节 5.5 中的 SSE 概述针对 SSE、SSE2、SSE3 和 SSSE3 提供了说明。 这些数据运算会在 XMM 寄存器之间或者在 XMM 寄存器和内存之间移动基于精度的打包浮点数值。 XMM 寄存器主要用于取代 MMX 寄存器。

4.2.3 NEON 与 SSE 在汇编级的比较

在推荐使用《英特尔架构软件开发人员手册》来了解所有单个 SSE(x) 助记符的同时,我们也鼓励开发人员通过以下链接了解各种 SSE 汇编级指令,网址为: http://neilkemp.us/src/sse_tutorial/sse_tutorial.html. 使用目录访问示例代码或详细了解背景信息。

此外,以下由 ARM 提供的手册也提供了有关 NEON 的信息,同时在章节 1.4 — “NEON 开发”中包含了一些汇编小片段: http://infocenter.arm.com/help/topic/com.arm.doc.dht0002a/DHT0002A_introducing_neon.pdf.

NEON 和 SSE 汇编代码间的主要差异:

  • 字节存储次序。 英特尔仅支持低位优先汇编,而 ARM 则同时支持高位或低位优先顺序(ARM 支持两种顺序)。 在提供的代码示例中,同英特尔一样,ARM 代码采用的也是低位优先顺序。 注:在 ARM 中可能会存在一些编译器影响。 例如,使用 GCC 为 ARM 进行编译时包含 mlittle-endian 和 –mbig-endian 标记。 更多信息请访问:http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html.
  • 粒度。 如果引用的是简单的汇编代码示例,对 SSE (英特尔) 的 ADDPS 指令与 NEON 的 VADD.ix 指令进行比较,例如 x = 8 或 16。注意,后者在作为部分引用助记符处理的数据上放入一些粒度。

注:这些差异并未涵盖所有内容。 您可能会发现 NEON 和 SSE 间的一些其他差异。

4.2.4 NEON 与 SSE 在 C/C++ 层面的比较

在将 C/C++ 代码和 NEON 代码移植到 SSE 时,可能会出现很多 API 问题。 此处请注意本文的一个假设,即这里未使用内嵌汇编,而使用的是真正的 C/C++ 代码。 NEON 指令也提供一些原生 C 库。 尽管这些指令是 C 代码,它们并不能在英特尔凌动平台上执行,因此必须重写。

5. 优化应用性能

5.1 性能优化

在编码的过程中,请使用以下方法对英特尔凌动平台上的应用进行性能优化。

5.1.1 使用内联函数代替频繁使用的短函数

内联函数最好用在小函数上,例如访问专用数据成员。 短函数对函数调用的开销十分敏感。 较长的函数在调用和返回序列上花费的时间相应减少,同时几乎很少从代码嵌入中受益。 [4]

内联函数节省了以下方面的开销:

  • 函数调用(包含参数传递和把对象的地址放置在堆栈上)
  • 保存调用程序的堆栈帧
  • 新堆栈帧设置
  • 返回值通信
  • 原堆栈帧恢复
  • 返回

5.1.2 使用浮点代替二重点

浮点运算单元是计算机系统的一部分,专门设计用来执行浮点数上的运算,诸如: 加、减、乘、除和平方根。 一些系统(尤其是基于微码的较老架构)也可以执行各种超越函数,诸如指数计算或三角计算。 当前的处理器通过软件库例程执行这些计算。 在大多数的现代通用计算机架构中,通常有一个或多个浮点运算单元和 CPU 集成在一起[6]

英特尔凌动平台支持使用浮点运算单元。 在大多数情况下,使用浮点代替二重点会加快数据计算处理速度并为搭载英特尔凌动处理器的设备节省内存带宽。

5.1.3 多线程编码

借助多线程编码,您可以使用英特尔凌动处理器的超线程功能提高吞吐率和整体性能。 更多有关多线程技术的信息,请参见: http://www.intel.cn/content/www/cn/zh/architecture-and-technology/hyper-threading/hyper-threading-technology.html.

5.2 使用编译器标识构建高性能应用

如您所知,原生代码是由安卓应用中的 GCC 构建而成的。 然而,您是否知道 GCC 的默认目标设备呢? 它就是奔腾® 专业处理器。 如果您在编译原生代码时没有添加任何标识,目标二进制代码最好运行在奔腾专业平台上。 大多数安卓应用运行在英特尔凌动平台上,而不是奔腾专业平台。 我们建议您根据自己使用的目标平台添加特定的标识。 您在编译的过程中可以在英特尔凌动平台上添加以下建议标识:

-march=atom
-msse4
-mavx
-maes

更多有关编译器参数的信息,请参见: http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html

6. 结论

本文讨论了如何在英特尔凌动平台上开发和优化安卓应用,以及如何开发和移植 NDK 应用。

要点总结:

  • 大多数安卓应用可以直接在英特尔凌动平台上执行。 NDK 应用需要重新编译原生代码。 如果应用中包含了汇编码,这部分代码必须重写。
  • 充分利用 IA ( 英特尔架构)特性提升您的安卓应用性能。
  • 添加面向特定平台的编译开关,使 GCC 构建代码更加有效。

参考资料

  1. http://software.intel.com/en-us/articles/installation-instructions-for-intel-hardware-accelerated-execution-manager-windows/
  2. http://software.intel.com/en-us/blogs/2011/08/18/understanding-x86-vs-arm-memory-alignment-on-android/
  3. http://software.intel.com/zh-cn/android/articles/ndk-android-application-porting-methodologies
  4. http://msdn.microsoft.com/en-us/library/1w2887zk.aspx
  5. http://developer.android.com/sdk/ndk/index.html
  6. http://en.wikipedia.org/wiki/Floating-point_unit

关于作者

Dawei 是一名专注于移动应用支持的应用工程师,负责为 x86 设备进行安卓应用开发和优化以及 Web HTML5 应用开发。 此外,Dawei 在移动应用 UI 和 UX 设计方面也拥有着丰富的经验。

声明

本文件中包含关于英特尔产品的信息。 本文件不构成对任何知识产权的授权,包括明示的、暗示的,也无论是基于禁止反言的原则或其他。 除相关产品的英特尔销售条款与条件中列明之担保条件以外,英特尔公司不对销售和/或使用英特尔产品做出其他任何明确或隐含的担保,包括对适用于特定用途、适销性,或不侵犯任何专利、版权或其他知识产权的担保。

除非经过英特尔的书面同意认可,英特尔的产品无意被设计用于或被用于以下应用:即在这样的应用中可因英特尔产品的故障而导致人身伤亡。

英特尔有权随时更改产品的规格和描述而毋需发出通知。 设计者不应信赖任何英特产品所不具有的特性,设计者亦不应信赖任何标有“保留权利”或“未定义”的说明或特性描述。 对此,英特尔保留将来对其进行定义的权利,同时,英特尔不应为因其日后更改该等说明或特性描述而产生的冲突和不相容承担任何责任。 本文信息可能随时更改,恕不另行通知。 请勿使用本信息来对某个设计做出最终决定。

本文件所描述的产品可能包含使其与宣称的规格不符的设计缺陷或失误。 这些缺陷或失误已收录于勘误表中,可索取获得。

在发出订单之前,请联系当地的英特尔营业部或分销商以获取最新的产品规格。

如欲获得本文涉及的带编号文档的副本或其他英特尔文献,可致电 1-800-548-4725,或访问: http://www.intel.com/design/literature.htm。性能测试中使用的软件和工作量可能专为英特尔微处理器进行了优化。 诸如SYSmark和MobileMark等测试均系基于特定计算机系统、硬件、软件、操作系统及功能。 上述任何要素的变动都有可能导致测试结果的变化。 请参考其他信息及性能测试(包括结合其他产品使用时的运行性能)以对目标产品进行全面评估。

对本文件中包含的软件源代码的提供均依据相关软件许可而做出,任何对该等源代码的使用和复制均应按照相关软件许可的条款执行。

英特尔、Atom、凌动、Pentium、奔腾和 Intel 标识是英特尔在美国和/或其他国家的商标。

英特尔公司 © 2012 年版权所有。 所有权利受到保护。

*其他的名称和品牌可能是其他所有者的资产。

** 该示例源代码根据英特尔示例源代码许可协议发布

Android* 上的 NFC 应用开发与案例研究

$
0
0

介绍

NFC(近场通信)是一种基于标准的短距离无线连接技术,支持在电子设备间进行简单、直观的双向互动。 触摸 NFC 设备,并在两台 NFC 设备之间通信非常方便。 例如,借助智能手机集成的 NFC 技术,您可以轻松触控手机来购买物品、分享名片、下载打折券等。 您将会看到许多基于 NFC 的新用法在未来开发。

本文介绍了当前市场基于 NFC 的技术和使用模式。 接着介绍了如何在 android 应用中使用 NFC。 最后介绍了两个案例研究,以帮助了解如何开发基于 NFC 的读/写应用。

NFC 技术架构

NFC 基于 RFID 技术,频率为 13.56 MHz,并采用 10 cm 的典型操作距离。数据交换速率为 424 比特/秒。与其他的通信技术相比,NFC 的最大优势是速度快且易于使用。 下图对 NFC 与其他通信技术进行了比较。

图 1: 短距离通信技术比较

 

NFC 技术有三种模式: NFC 卡仿真模式,对等模式和读/写模式,如下图所示。

图 2: NFC 协议家族

 

在卡仿真模式中,NFC 可模拟 RFID 集成电路(IC)卡并带有一个安全模块 — 支持用户安全购买。 在对等模式中,您可以通过 NFC 连接在不同的 NFC 设备之间共享信息,如名片。 此外,您也可以通过 NFC 连接快速设置 WiFi* 或蓝牙* 连接,并通过 WiFi 或蓝牙连接传输大型文件。 在读/写模式中,您可以使用启用了 NFC 的设备来读取 NFC 标签和启动智能任务。

以下将对每种模式分别进行详细介绍。

NFC 卡仿真模式

NFC 模式通常包括两部分: NFC 控制器和安全组件(SE)。 NFC 控制器负责通信。 SE 负责加密和解密敏感数据。

图 3: NFC 硬件组件

 

SE 通过 SWP(单线路协议)或 DCLB(数字非接触式桥)总线与 NFC 控制器进行连接。 NFC 标准为主机和控制器之间的逻辑接口下定义,以便允许它们通过射频场(RF-field)通信。 内置应用或小型操作系统执行 SE,后者负责加密和解密敏感数据。

执行 SE 的三种解决方案:

  • 嵌入 SIM 卡
  • 嵌入 SD 卡
  • 嵌入 NFC 芯片

图 4: 三种 NFC SE 解决方案

通常电信运行商,如 CMCC(中国移动)、Vodafone 和 AT&T,更倾向于使用基于 SIM 卡的解决方案,它们鼓励其用户用全新的启用了 NFC 的 SIM 卡免费替换旧 SIM 卡。

NFC 对等模式

使用 NFC 的两台设备可直接通信并轻松分享小型文件,如名片。 此外,启用 NFC 的两台设备也可以彼此共享 configured .xml 文件,并建立蓝牙/WiFi 连接来共享大型文件。 在该模式中,无需 SE 模块。

NFC 读/写模式

在该模式中,NFC 主机可以读/写 NFC 标签。 从智能海报读取有用信息

就是一个好例子。 用户可以访问链接来查看广告和下载打折券。

图 5: NFC 读/写模式

Android NFC 开发介绍

Android 可为 NFC 提供两个文件包: android.nfc 和 android.nfc.tech。

android.nfc 包中的主类是:

NfcManager: 用户可以使用 Android 设备来管理所有显示的 NFC 适配器,但是因为大部分 Android 设备仅支持一个 NFC 适配器,一般直接使用 getDefaultAdapter 调用 NfcManager 来获取特定的手机适配器。

NfcAdapter: 它起到 NFC 代理的作用,类似于电脑中安装的网络适配器;手机可以通过它使用 NFC 硬件以初始化 NFC 通信。

NDEF: NFC 标准可定义名为“NFC 数据交换格式(NFC Data Exchange Format,NDEF)”的通用数据格式,它可存储和传输各种项目,从 MIME 类型的对象到极短的 RTD 文档,如 URL。 NdefMessage 和 NdefRecord 是面向 NFC 论坛定义的数据格式的两种 NDEF,将用于样本代码。

标签: Android 定义其代表被动对象,如标签、卡等。 当设备检查出一个标签时, Android 将创建一个标签对象,然后将其放至 Intent 对象,最后将其发送至适当的 Activity。

android.nfc.tech 程序包还包括许多重要的子类。该子类可提供对标签技术特性的访问,包括读写操作。 根据使用的技术类型,这些子类可划分为不同的类别,如: NfcA、NfcB、NfcF、MifareClassic 等。

当手机开启 NFC 时,检测到 TAG 后,TAG 分配系统将自动创建意向 NFC TAG 信息软件包。 如果手机有一个以上的应用可以处理该意向,弹出文本框将会要求用户选择要执行的 TAG 活动。 TAG 分配系统可定义三种类型的意向。 它按照降序排列:

NDEF_DISCOVERED, TECH_DISCOVERED, TAG_DISCOVERED

此处,我们使用了操作意向过滤器类型处理从 TECH_DISCOVERED 至 ACTION_TECH_DISCOVERED 的所有类型。 文件 nfc_tech_filter.xml 用于文件 TAG 中定义的类型。 如欲了解更多详细信息,请参见 Android 文档。 下图展示了手机检测到 TAG 时的匹配流程 Activity。

图 6: 检测到 NFC 标签的流程

案例研究: 开发基于 NFC 的读/写应用

以下演示展示了 NFC 标签的读/写功能。 在访问设备的 NFC 硬件并正确处理 NFC 意图之前,请在您的 AndroidManifest.xml 文件中声明这些项目:

<uses-permission android:name="android.permission.NFC" />

应用必须支持的最低 SDK 版本是级别 10,因此请在您的 AndroidManifest.xml 文件中声明这些项目:

<uses-sdk android:minSdkVersion="10"/>

In the onCreate function,you can apply the NfcAdapter:

public void onCreate(Bundle savedInstanceState) {

	……

	adapter = NfcAdapter.getDefaultAdapter(this);

	……

	}  

	

下列的意图回调展示了读功能。 如果系统广播意图与 NfcAdapter.ACTION_TAG_DISCOVERED 对等,那么您可以在标签中读取并展示该信息。


	@Override

	    protected void onNewIntent(Intent intent){

	        if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){

	        mytag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  // get the detected tag

	        Parcelable[] msgs =

	intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);

	            NdefRecord firstRecord = ((NdefMessage)msgs[0]).getRecords()[0];

	            byte[] payload = firstRecord.getPayload();

	            int payloadLength = payload.length;

	            int langLength = payload[0];

	            int textLength = payloadLength - langLength - 1;

	            byte[] text = new byte[textLength];

	            System.arraycopy(payload, 1+langLength, text, 0, textLength);

	            Toast.makeText(this, this.getString(R.string.ok_detection)+new String(text), Toast.LENGTH_LONG).show();

	                    }

	    }

下列代码展示了写入功能。 在确认 mytag 的值之前,您必须知道是否检测到标签,然后才能将信息写入 mytag。


	If (mytag==Null){

	    ……

	}

	else{

	……

	write(message.getText().toString(),mytag);

	……

	}

	    private void write(String text, Tag tag) throws IOException, FormatException {

	        NdefRecord[] records = { createRecord(text) };

	        NdefMessage  message = new NdefMessage(records);

	// Get an instance of Ndef for the tag.

	        Ndef ndef = Ndef.get(tag); // Enable I/O

	        ndef.connect(); // Write the message

	        ndef.writeNdefMessage(message); // Close the connection

	        ndef.close();

	    }

根据从标签中读取到的信息,您可以执行更多操作,如启动智能任务、访问网站等。

案例研究: 开发使用 MifareClassic 卡的基于 NFC 的应用

在该演示中,我们在数据读取测试中使用了 Mifare 卡并使用了卡的 TAG 类型 — MifareClassic。 MifareClassic 卡可在许多场景中通用,如 ID 卡、总线卡等。 传统 MifareClassic 卡的存储空间可分为 16 个区域(Sector),每个区域有四个数据块(Block),每个数据块可以存储 16 字节的数据。

每个区域的最后一个数据块称 Trailer,主要用于为数据的读和写存储本地数据块密钥。 它有两种密钥: A 和 B,每种密钥的长度为 6 字节,其默认值通常是由 MifareClassic.KEY_DEFAULT 定义的 full-key FF 或 0。

因此,当编写 Mifare 卡时,您需要先拥有正确的密钥值(起到保护作用),并且用户在区域内读写数据之前必须成功完成验证。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    package="org.reno"  
    android:versionCode="1"  
    android:versionName="1.0">   
    <uses-permission android:name="android.permission.NFC" />   
    <uses-sdk android:minSdkVersion="14" />   
    <uses-feature android:name="android.hardware.nfc" android:required="true" />   
    <application   
        android:icon="@drawable/ic_launcher"  
        android:label="@string/app_name">   
        <activity   
            android:name="org.reno.Beam"  
            android:label="@string/app_name"  
            android:launchMode="singleTop">   
            <intent-filter>   
                <action android:name="android.intent.action.MAIN" />   
   
                <category android:name="android.intent.category.LAUNCHER" />   
            </intent-filter>   
            <intent-filter>   
                <action android:name="android.nfc.action.TECH_DISCOVERED" />   
            </intent-filter>   
            <meta-data   
                android:name="android.nfc.action.TECH_DISCOVERED"  
                android:resource="@xml/nfc_tech_filter" />   
        </activity>  
    </application>   
</manifest>   

res/xml/nfc_tech_filter.xml:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 
    <tech-list> 
       <tech>android.nfc.tech.MifareClassic</tech> 
    </tech-list> 
</resources> 

读取 MifareClassic 卡的示例如下所示:

     private void processIntent(Intent intent) {    

	        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);   

	        for (String tech : tagFromIntent.getTechList()) {   

	            System.out.println(tech);   

	        }   

	        boolean auth = false;   

	        MifareClassic mfc = MifareClassic.get(tagFromIntent);   

	        try {   

	            String metaInfo = "";   

	            //Enable I/O operations to the tag from this TagTechnology object.   

	            mfc.connect();   

	            int type = mfc.getType(); 

	            int sectorCount = mfc.getSectorCount();   

	            String typeS = "";   

	            switch (type) {   

	            case MifareClassic.TYPE_CLASSIC:   

	                typeS = "TYPE_CLASSIC";   

	                break;   

	            case MifareClassic.TYPE_PLUS:   

	                typeS = "TYPE_PLUS";   

	                break;   

	            case MifareClassic.TYPE_PRO:   

	                typeS = "TYPE_PRO";   

	                break;   

	            case MifareClassic.TYPE_UNKNOWN:   

	                typeS = "TYPE_UNKNOWN";   

	                break;   

	            }   

	            metaInfo += "Card type:" + typeS + "n with" + sectorCount + " Sectorsn, "  

	                    + mfc.getBlockCount() + " BlocksnStorage Space: " + mfc.getSize() + "Bn";   

	            for (int j = 0; j < sectorCount; j++) {   

	                //Authenticate a sector with key A.   

	                auth = mfc.authenticateSectorWithKeyA(j,   

	                        MifareClassic.KEY_DEFAULT);   

	                int bCount;   

	                int bIndex;   

	                if (auth) {   

	                    metaInfo += "Sector " + j + ": Verified successfullyn";   

	                    bCount = mfc.getBlockCountInSector(j);   

	                    bIndex = mfc.sectorToBlock(j);   

	                    for (int i = 0; i < bCount; i++) {   

	                        byte[] data = mfc.readBlock(bIndex);   

	                        metaInfo += "Block " + bIndex + " : "  

	                                + bytesToHexString(data) + "n";   

	                        bIndex++;   

	                    }   

	                } else {   

	                    metaInfo += "Sector " + j + ": Verified failuren";   

	                }   

	            }   

	            promt.setText(metaInfo);   

	        } catch (Exception e) {   

	            e.printStackTrace();   

	        }   

	    }   

	

总结

配备了 NFC 的智能手机支持个人随时随地获取所需的内容,而无需被大量的票根或停车证包围。 该技术甚至支持与朋友取得联系以分享信息、玩游戏和传输数据。 NFC 致力于在工作和娱乐两个方面都取得进步,这是取得成功和推动我们未来生活的关键因素。

关于作者

Songyue Wang 和 Liang Zhang 是英特尔软件和服务事业部的应用工程师,专注于移动应用支持领域,主要负责为 x86 设备进行 Android 应用开发和优化以及 Web HTML5 应用开发。

面向 Android 软件开发套件(SDK)的 x86 Android* 系统映像许可协议

$
0
0

英特尔公司面向 Android 软件开发套件(SDK)的 x86 Android* 系统映像的内部评估许可协议

此《内部评估许可协议》(以下简称“协议”) 的订立双方为英特尔与贵方(作为开发人员个人或法律实体 — 下文认定为“接收方”)。 英特尔应根据《内部评估协议条款与条件》中的规定为接收方提供“评估软件”。

定义。

这些条款具有下列含义:

英特尔、"Intel"或 "INTEL"
英特尔公司
包含地址:
2200 Mission College Blvd.
Santa Clara, CA 95052
总顾问办公室
邮件地址: RNB-4-51
收件人: 软件与服务事业部法务部门

“评估软件”
面向 Android 软件开发套件(SDK)的 x86 Android* 模拟器系统映像(以英特尔提供为准)。

内部评估许可条款与条件

1.定义。

1.1 其他术语。 “协议”、“评估软件”、“英特尔(Intel)”、“保密协议”、“接收方”、“生效日期”具备该协议签名页上赋予它们的含义。

1.2 评估软件(源代码和/或目标代码的格式)及与评估软件相关的文档(包括但不限于一切设计文档、规格和其他相关材料)统称“评估材料”。

1.3 “开源软件”是需要 (a) 以源代码格式公布或分发;(b) 或由用户授予第三方用来制作和/或分发衍生产品;或 (c) 免费重新分发才能使用、修改和/或分发的任何软件(此软件可以是由开源软件或其他软件整合而成、由开源软件派生而出或随同开源软件分发的软件)。 开源软件包括但不限于根据下列许可证或分发模式,或者类似于下列许可证或分发模式的许可证或分发模式获得授权或分发的软件: (a)GNU 通用公共许可证(GPL)或宽通用公共许可证/库通用许可证(LGPL);(b)艺术许可证(如 PERL);(c)Mozilla 公共许可证;(d)网景公共许可证;(e)Sun 社区源代码许可证(SCSL);(f)Sun 工业标准源码许可证(SISL);(g)Apache 软件许可;以及(h)通用公共许可证(CPL)。

1.4 “预发布材料”是“内部测试版”或“公开测试版”中指明的预发布特性;这些特性的功能可能不完善,英特尔可能会在生产任何生产版的评估材料时对其做出重要修改以及/或英特尔和/或英特尔的供应商仍在开发该特性。

2. 目的。 英特尔要求接收方仅将英特尔提供的评估材料用作内部评估评估软件和其他英特尔产品;评估在开发基于评估软件的产品上与英特尔合作的需求;和/或在修改评估软件方面为英特尔提供建议。 接收方不得将评估材料透露、散布或用作商业用途,或对评估材料做出任何更改。

评估材料仅可用作评估目的,接收方不得将评估材料散布或融入其产品或软件。 请联系英特尔销售代表了解商业版评估软件的可用性和费用。

3. 所有权。 评估材料的所有权仍归英特尔或其供应商所有。 接收方不得以任何方式抵押、质押评估材料或使其承担法律义务。 该协议终止或到期时,接收方应归还所有评估材料,不得保留任何副本。

4. 许可。 英特尔在其版权下授予接受方免版税、个人、不可转让、非独家的协议,仅支持其将评估软件用于上述第二段中描述的目的。 除非英特尔与接收方达成书面协定,英特尔及其供应商提供了一个以上评估软件产品或版本(每个为一个版本),否则,许可应按照该部分的规定执行且评估期适用于每个版本。 接收方不得修改评估软件。 接收方不得对未以源代码形式向其提供的任何软件进行拆卸、实施反向工程操作或反编译。

除本文中的授权外,英特尔未以明示或暗示,基于禁止反言的原则或其他,向接受方授予任何其他知识产权。

5. 绝对自愿。 接收方无任何义务购买英特尔提供的任何产品,或授予其许可。 英特尔及其供应商无任何义务提供评估软件支持,或开发非评估版评估软件,或授权任何版本的评估软件。

6. 修改。 本协议不强制被接受方向英特尔提供关于评估材料的意见和建议。 但是,如果接收方向英特尔提供与(a)评估材料或(b)包含评估材料的英特尔产品或流程有关的修改、更正、改进或增强意见和建议, 则接收方应向英特尔授予非独占的、不可撤销的、全球性的、免版税的许可,并在接收方的知识产权下授予英特尔向英特尔的被许可方和客户再授权;以其选择的任何方式使用和公开这些意见和建议;以其选择的任何方式在任何介质上展示、执行、复制、制作、被制作、使用、销售、履行销售要约、引进以及在其他方面公开英特尔及其被许可方生产的体现该意见和建议的产品且不指明其来源的权利。

7. 免责声明。 英特尔及其供应商对评估材料不作任何形式的担保,无论是明确或隐含,包括适用于特定目的的适销性或适用性的隐含担保,或不侵权性的隐含担保。 本评估材料按“原样”的方式提供,不提供任何形式的担保。

8. 责任限制: 对于任何财产损失、人身伤害、利润损失、业务中断或任何特殊、继发或偶发损坏,无论何种原因导致,无论是否违反担保、合同、严格责任或其他条款,英特尔及其供应商均不承担任何责任。 英特尔及其供应商概不承担任何责任,包括侵犯与评估材料相关的任何知识产权的责任。

9. 截止日期。 接收方违反该协议后,英特尔可立即终止该协议。

10. 一般条款。

10.1 管辖法律。 由本协议引起或与本协议有关的任何纠纷都应在不援引冲突法原则的前提下,交由特拉华州内部实体法或位于特拉华州的联邦法院裁决。 各方同意由特拉华州法院裁决和管辖由本协议引起或与本协议相关的所有争议和诉讼。 各方同意《联合国国际货物销售合同公约》不适用于本协议, 并同意上述法院拥有属人管辖权。

10.2 补救措施。 接收方承认对评估材料的任何披露、商品化或公开使用都将对英特尔造成不可挽回的损害,且如果出现被胁迫而违反协议的情况,接收方同意由任何主管司法区之法院强制其执行。

10.3 转让。 接收方不可代表、指定或转让本协议、授予的许可权或其于下文中的任何权利或职责,以公开或隐蔽的方式,通过法律运作、合并(无论接收方是否是保留机构)或收购,或 其它任何执行此类操作的企图,若未经英特尔的事先书面同意,均将无效。 英特尔可自行指定本协议以及与之相关的权利和义务。

10.4 完整协议。 本协议构成接收方和英特尔之间的完整协议,并完整取代接收方和英特尔此前关于该标的达成的任何及所有口头或书面协议。 本协议取代任何及所有“点击接收”或用收缩膜包装的许可,无论是硬拷贝或电子形式,嵌入或包含在评估材料中。 本协议仅可通过明确涉及该协议的书面文件进行修订或补充,且须由接收方和英特尔正式授权的代表签署。 在不限上述条款的情况下,如果接收方向英特尔提交的采购订单或类似材料中的条款和条件以及英特尔标准法律声明中包含的条款与上述条款冲突,那么这些条款将不具有强制力或无效。

10.5 可分割性。 在任何适用法律或适用法庭判决认为本协议的任何规定不具强制力或无效的情况下,这种不具强制力或无效性不会使本协议整体失效或不具强制力,在此情况下,应对此类规定作出更改和解释,以更好地达成受适用法律或法庭判决约束的不具强制力或无效的规定的目的。

10.6 出口法规/出口控制。 若事先未从美国商务部或美国政府的其它机构或部门获得批准或未持有必要的许可证,接收方不得直接或间接出口包含评估材料的任何产品、服务或技术信息、系统。 在从美国出口或从国外目的地复出口任何产品的情况下,接收方应确保按照美国出口管理条例和相应国外政府机构的所有法律、法规、指令或其它规定,分销和出口/复出口或进口该产品。 接收方同意未获得授权或许可之前,接收方及其下属机构不得直接或间接地向美国政府或任何机构、或出口国政府要求提供出口许可证或其它政府批准的国家出口/转口任何技术数据、工艺、产品或服务。 接收方还同意采取措施确保外籍员工有权获得美国出口控制法律控制的任何信息。 向外籍人士(无论其身在何处)发布信息后,出口将“被视为”已发生。

10.7 预发布材料特别条款。 如果评估软件的说明书中指出,评估软件可能包含预发布材料。 接收方兹理解、承认并同意: (i)预发布材料可能未进行完全测试且可能包含漏洞或错误;(ii)预发布版材料以其目前的状态不适合用作商业版本;(iii)预发布材料尚未获得管理审批,因此可能无法在某些国家或环境中使用且(iv)英特尔不担保生产或大范围推广生产版的预发布材料。 英特尔对于开发和/或发布或要约出售或授权基于预发布材料的最终产品无任何义务,并可随时单方面选择放弃预发布材料或任何其他此类开发平台,且对接收方或其他任何人无任何义务和责任。

10.8 开源软件。 如果评估软件中包含开源软件,则该开源软件遵循开源软件注释中适用的开源软件许可协议,且在评估软件中使用了适用的源代码文件和/或文件头。 随附的在线文档中提供了其他详细说明(如果适用)。 关于开源软件,本协议中任何内容都不对任何适用的开源软件许可协议条款下的任何权利产生限制,且不授权取代上述条款。

一切预发布材料的合格性均不受限制,就此而言,允许出现故障

点击接收 EULA 并下载 sysimg_x86-17_r01.zip

隆重介绍 PROJECT ANARCHY™ — HAVOK™ 提供的一款免费移动游戏引擎

$
0
0

Project Anarchy 是面向 iOS、Android (包括 X-86) 和 Tizen 的一款免费移动游戏引擎。 它包括 Havok 视觉引擎以及 Havok 物理引擎、Havok Animation Studio 和 Havok AI。 它包括可扩展的 C++ 架构、优化的移动渲染、灵活的资产管理系统和 Lua 脚本与调试。 此外,Project Anarchy 网站上还有包含完整游戏示例的 SDK 和大量课件,支持游戏开发人员快速开始使用引擎提高速度和实现游戏创意。

在 iOS、Android (including X-86) 和 Tizen 上免费随附,包括 Havok 视觉引擎,并能够在上古卷轴®、光晕®、刺客信条®、神秘海域™ 和 Skylanders™ 等尖端游戏中使用业内领先的 Havok 物理、动画和 AI 工具。

  • 基于可扩展的 C++ 插件的架构
  • 全面的游戏示例,包括完整的源艺术和源代码
  • 关注包含支持、问答、反馈和实践培训论坛的社区
  • 在企业规模或收入上没有商业限制
  • 为附加的可用平台和产品、源和支持提供升级
  • 包括 FMOD — 业内领先的音频工具

参阅随附的产品文档(Havok_Anarchy_2013.pdf)

请登陆 下载页面

唤醒锁: 检测 Android* 应用中的 No-Sleep(无法进入睡眠)问题

$
0
0

摘要

如果 Android* 应用使用唤醒锁不当,将会显著增加电池耗电量。 在本文中,我们将介绍一些提示和技巧,帮助您了解如何确认与误用唤醒锁有关的 No Sleep 漏洞。

1. 介绍
2. 唤醒锁
2.1. 唤醒锁简介
2.2. Android 用户唤醒锁
2.3. Android 内核唤醒锁
2.4. No-Sleep 漏洞
3. 找出 No Sleep 漏洞
3.1. 使用 adb
3.2. 使用 BetterBatteryStats 应用
4. 测试案例
5. 结论
6. 参考文献

1. 介绍

限制电池耗电量对智能手机非常有必要。 为了获得最大的自主性,Android 的操作系统设计可在检测到系统上无用户活动时进入睡眠模式。 一些应用需要设备保持开启状态 — 即使长时间无用户操作。 比如,看视频、听音乐、使用 GPS 以及玩游戏。 Android 可为操作系统或应用提供了这样的机制,以确保设备保持唤醒状态。 该机制称为唤醒锁。 如欲了解其他信息,请阅读 Christopher Bird 的文章: “适用于 Android 的唤醒锁”。

这种机制的出现让管理组件活动的责任落到应用开发人员的身上。 如果使用错误,应用可能会大量消耗电池电量 — 即使应用并未在前台运行。

2. 唤醒锁

2.1.唤醒锁简介

唤醒锁是一种控制主机设备电源状态的软件机制。 操作系统可导出明确的电源管理句柄和 API,以指定某个组件何时需要保持开启或唤醒状态,直至其从任务中被明确释放。

唤醒锁机制可在两个层面上实施: 用户和内核。 下图展示了 Android 唤醒锁实施的内部设计。 用户唤醒锁可被高层面的操作系统服务或应用采用,并通过电源管理服务提供。 它支持应用控制设备的电源状态。 内核唤醒锁由操作系统内核或驱动程序控制。 用户唤醒锁被映射至内核唤醒锁。 任何活动的内核层面唤醒锁都可阻止系统在 ACPI S3 状态挂起(在 RAM 挂起)— 它是移动设备最节能的状态。

2.2. Android 用户唤醒锁

Android 架构通过 PowerManager 导出唤醒锁机制。唤醒锁可划分为并识别四种用户唤醒锁:

标记值CPU屏幕键盘

PARTIAL_WAKE_LOCK

开启

关闭

关闭

SCREEN_DIM_WAKE_LOCK

开启

变暗

关闭

SCREEN_BRIGHT_WAKE_LOCK

开启

变亮

关闭

FULL_WAKE_LOCK

开启

变亮

变亮

请注意,自 API 等级 17 开始,FULL_WAKE_LOCK 将被弃用。 应用应使用 FLAG_KEEP_SCREEN_ON。

可以使用唤醒锁强迫一些组件(CPU、屏幕和键盘)保持唤醒状态。

请了解有关 PARTIAL_WAKE_LOCK 的特别提醒:无论任何显示器超时或屏幕处于任何状态,CPU 都将继续运行 — 即使用户按下电源按钮。 这可能会导致出现静默耗电,即手机看上去处于待机模式(屏幕关闭),但是实际上处于完全唤醒状态。

在其他唤醒锁中,用户仍可使用电源按钮让设备进入睡眠状态。 按下电源按钮后,除局部唤醒锁外所有唤醒锁均将完全释放。

上述即为应用控制唤醒锁的方法。 基本而言,它是一个获取/释放机制。 当应用需要让一些组件保持开启状态时,它便会获取唤醒锁。 当不再需要这些组件处于开启状态时,则需要将唤醒锁释放。

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
..screen will stay on during this section..
wl.release();

2.3. Android 内核唤醒锁

内核唤醒锁是由内核控制的低级唤醒锁。 它们可从内核内部获取/释放。 就此而言,应用开发人员对它们的直接控制更少,但是应用的运行状况可以间接触发这些唤醒锁并在无意中增加电池的耗电量。

下面是内核唤醒锁的示例。

Wlan_rx:当通过 Wi-Fi* 发送或接收数据时由内核控制。

PowerManagerService: 是适用于所有局部唤醒锁的容器。

Sync: 在同步流程运行时启用。

Alarm_rtc: 控制告警(当应用或流程执行定期检查时使用)。

Main: 保持内核处于唤醒状态。 系统进入挂起模式时,这是最后一个被释放的唤醒锁。

2.4. No-Sleep 漏洞

应用必须在某一时刻释放它需要的每个唤醒锁,以便允许系统返回深睡眠模式。 如果该唤醒锁一直未被释放,则该获取/释放机制可能会导致出现漏洞。 即使启用了唤醒锁的应用停止在前台运行,唤醒锁仍在使用中。 当使用释放调用明确释放唤醒锁或应用被终止(强制关闭)时,唤醒锁才可被释放。 让一些唤醒锁处于启用状态将阻止系统进入深睡眠模式 — 即使没有活动大量增加耗电量和静默减少电池的自主性。 这就是 No-Sleep 漏洞。 由于 Android 的事件驱动特性,开发人员可能无法想到其应用获取并需要关闭的唤醒锁的所有代码路径。 这种漏洞类型称为 No-Sleep 漏洞代码路径。

发生这种类型的漏洞的另一种情况是,唤醒锁未有效获取而被释放。 在不同的线程中获取和释放唤醒锁的多线程代码中可能会出现这种情况。 这就是 No-Sleep 漏洞竞态条件。

最后一个问题是 No-sleep 扩张,其中获取唤醒锁的时间比实际所需的时间长。

为何重点指出这些问题? 根据 P. Vekris 的研究: “328 个使用唤醒锁的应用中,55% 的应用未遵循我们针对 no-sleep 漏洞提供的策略”[2012]。 一些主要的应用在出现 No-Sleep 漏洞时被释放。 因此,开发人员需要意识到这一点,以便以最优的方式运行其应用。

3. 找出 No-Sleep 漏洞

您可以通过两种方式解决 no sleep 漏洞: 静态的代码路径扫描分析和动态的运行时分析。 在本文中,我们主要介绍运行时分析。

这种方法无法保证您找到应用中所有的唤醒锁漏洞。 但是,它可以帮助您找到在运行时期间出现的唤醒锁问题。 如要找出唤醒锁问题,您需要按照未释放唤醒锁的代码路径执行。 测试一个应用是否解决了 no sleep 漏洞包括在应用的不同位置操作应用,尝试以不同的方式从应用中退出,以确认唤醒锁是否仍然存在。

在某些情况下,有必要阻止系统进入深睡眠状态 — 即使应用停止在前台运行。 应用可能需要在后台执行一项任务。 此时即为这种情况,例如,如果应用需要长时间下载: 视频或游戏数据集。 在进行下载时,用户可能让应用在后台运行,但是在下载完成前,手机应保持唤醒状态。 在这种情况下,在下载完成前,应用应一直启用唤醒锁。 当然,您需要确保在某个点释放唤醒锁。 例如,当手机在下载期间断开网络,如果无法再执行操作,手机则无需保持唤醒状态。

总之,找出 No Sleep 漏洞与所在的环境关系密切。 没有预定义的标准可让您轻松找出该问题。 只能依靠常识找到上述的漏洞。

3.1. 使用 adb

shell 命令是查看唤醒锁最简单的工具。

如要完整了解内核唤醒锁,请输入:

adb shell cat /proc/wakelocks

namecountexpire_countwake_countactive_sincetotal_time
"PowerManagerService"1502000337817677431
"main"15000984265842688
"alarm"151207920217778251643
"radio-interface"1600016676538930
"alarm_rtc"8044001204136324759
"gps-lock"100010753659786
namesleep_timemax_timelast_change
"PowerManagerService"957294091221409216636679723417252748
"main"02124247323559498127170228
"alarm"2176173620473579769419723371461242
"radio-interface"016593284969486387144974
"alarm_rtc"1200253446201660829365019483176054624
"gps-lock"01075365978637632803440

对于使用内核 3.4 或更高版本的映像,请使用“adb shell cat /sys/kernel/debug/wakeup_sources”。 虽然该格式可提供全部信息,但是不太适合用户使用。 我们在下面介绍的工具更方便。

使用“adb shell dumpsys power”可以轻松查看特定的应用。 以下是该命令典型的输出方式。 您可以看到,在命令发布后,用户唤醒锁将以红色呈现。 该命令可以查看系统中呈现的用户唤醒锁。

Power Manager State:
mIsPowered=true mPowerState=3 mScreenOffTime=1618305 ms
mPartialCount=3
mWakeLockState=SCREEN_ON_BIT
mUserState=SCREEN_BRIGHT_BIT SCREEN_ON_BIT
mPowerState=SCREEN_BRIGHT_BIT SCREEN_ON_BIT
mLocks.gather=SCREEN_ON_BIT
mNextTimeout=2382037 now=2378097 3s from now
mDimScreen=true mStayOnConditions=3 mPreparingForScreenOn=false mSkippedScreenOn=false
mScreenOffReason=0 mUserState=3
mBroadcastQueue={-1,-1,-1}
mBroadcastWhy={0,0,0}
mPokey=0 mPokeAwakeonSet=false
mKeyboardVisible=false mUserActivityAllowed=true
mKeylightDelay=6000 mDimDelay=587000 mScreenOffDelay=7000
mPreventScreenOn=false mScreenBrightnessOverride=-1 mButtonBrightnessOverride=-1
mScreenOffTimeoutSetting=600000 mMaximumScreenOffTimeout=2147483647
mLastScreenOnTime=27380
mBroadcastWakeLock=UnsynchronizedWakeLock(mFlags=0x1 mCount=0 mHeld=false)
mStayOnWhilePluggedInScreenDimLock=UnsynchronizedWakeLock(mFlags=0x6 mCount=0 mHeld=true)
mStayOnWhilePluggedInPartialLock=UnsynchronizedWakeLock(mFlags=0x1 mCount=0 mHeld=true)
mPreventScreenOnPartialLock=UnsynchronizedWakeLock(mFlags=0x1 mCount=0 mHeld=false)
mProximityPartialLock=UnsynchronizedWakeLock(mFlags=0x1 mCount=0 mHeld=false)
mProximityWakeLockCount=0
mProximitySensorEnabled=false
mProximitySensorActive=false
mProximityPendingValue=-1
mLastProximityEventTime=0
mLightSensorEnabled=true mLightSensorAdjustSetting=0.0
mLightSensorValue=11.0 mLightSensorPendingValue=10.0
mHighestLightSensorValue=47 mWaitingForFirstLightSensor=false
mLightSensorPendingDecrease=false mLightSensorPendingIncrease=false
mLightSensorScreenBrightness=42 mLightSensorButtonBrightness=0 mLightSensorKeyboardBrightness=0
mUseSoftwareAutoBrightness=true
mAutoBrightessEnabled=true
creenBrightnessAnimator:
animating: start:42, end:42, duration:480, current:42
startSensorValue:47 endSensorValue:11
startTimeMillis:2361638 now:2378092
currentMask:SCREEN_BRIGHT_BIT
mLocks.size=4:
SCREEN_DIM_WAKE_LOCK          'StayOnWhilePluggedIn_Screen_Dim' activated (minState=1, uid=1000, pid=388)
PARTIAL_WAKE_LOCK             'StayOnWhilePluggedIn_Partial' activated (minState=0, uid=1000, pid=388)
PARTIAL_WAKE_LOCK             'HDA_PARTIAL_WAKE_LOCK' activated (minState=0, uid=10046, pid=4690)
PARTIAL_WAKE_LOCK             'AudioOut_2' activated (minState=0, uid=1013, pid=157)
mPokeLocks.size=0:

如要确认应用进入后台后是否还有唤醒锁启用,您可以按照下列流程操作:

1. 将设备连接至 USB。
2. 启用应用并在该应用上操作。
3. 按电源按钮进入睡眠模式或以某种方式退出应用。
4. 等待 20 秒钟。
5. 以命令行的方式输入下列指令:
> adb shell dumpsys power
6. 查看是否有 PARTIAL_WAKE_LOCKs 与此相同,例如:
PARTIAL_WAKE_LOCK       ‘AudioOut_2’ activated(minState=0, uid=1013, pid=157)
7.每隔 15 秒钟重复一次第 5 步,共重复 3 至 5 次。 如果结果相同,可能出现了问题。

3.2. 使用 BetterBatteryStats 应用

BetterBatteryStats* (https://play.google.com/store/apps/details?id=com.asksven.betterbatterystats&hl=en) 是 Sven Knispel 开发的一款 Android 应用,可在 Google Play 上购买。 它可以收集信息,帮助您发现耗电问题,尤其是唤醒锁问题。

首先,通过选择 “Other”条目,您可以查看深睡眠和唤醒模式与总时间。 理想状态下,大多数情况,如果手机未使用则应处于深睡眠状态。

此外,您还可对比唤醒时间与屏幕开启时间,以了解何时为实际活动状态。 正常情况下,屏幕开启时间和唤醒时间应处于关闭状态。

您可以查看各时间的电池充电评估和唤醒、屏幕开启和 Wi-Fi* 状态。

然后,您可以查看内核唤醒锁。 您可以查看每种内核唤醒锁花费的时间及数量。 时间长或数量多可能代表出现了问题。 在该报告中,您无法找出是哪一应用或流程导致热点出现,但是可以发现特定应用触发的运行状况。

在内核唤醒锁报告中,“PowerManagerService”可汇总用户唤醒锁中花费的时间。 如果该命令行显示了热点,您可以通过查看局部唤醒锁报告找出。

大多数情况下,局部唤醒锁可指出控制它的应用。 找到导致问题出现的元凶会有很大的帮助。 但是,有时,一些活动可能通过其他应用启动。 例如,游戏可能会通过分配给 Android 媒体库的 AudioOut 声道播放声音。 如果未正确编码,您可能会认为未关闭声道是由于游戏出现问题, 而不会认为是 Android Gallery 出现问题。

AlarmManager 可能会提示告警导致唤醒出现,或某个应用做了大量的告警修改。 您可能希望查看“告警”部分,但是只有在拥有根权限的映像上才能进行查看。

此外,网络接入也仅支持有根权限的映像。 如果您察觉到网络上出现较高的流量可能会有帮助。 multipdp/svnet-dormancy 内核唤醒锁可能指示您还有一些较高的网络使用率。

4. 测试案例

让我们看一个使用游戏的真实案例。 启动游戏,玩 5 分钟左右,然后以非常规的方式从游戏中退出。 在我们的案例中,我们通过按主页键强制退出。 音乐停止,主页界面出现。 用户看来,一切都正常。 停止活动几分钟后,屏幕正常变黑。 让手机保持该状态约半个小时的时间,然后使用 BestBatteryStats 来检查它。 在“Other”界面上,您可以看到,虽然屏幕未开启,但是手机仍然处于唤醒状态。 此外,您还可以看到电池耗电率为 8.5%/小时。 因此在这种状态下,充满电的手机持续使用时间也不会超过 12 个小时。

现在,我们来看一下内核唤醒锁。 我们可以看到,虽然没有活动,但是两个内核唤醒锁仍然保持唤醒状态。 其中一个是 PowerManagerService,这意味着有用户局部唤醒锁开启;另一个是 AudioOutLock 等待锁。 我们来看一下局部唤醒锁界面。

在局部唤醒锁界面上,我们可以看到媒体库应用中的音频通道仍然打开。 这很奇怪,因为用户未明确使用媒体库应用。 实际上,游戏启动了媒体库,以便播放游戏的音乐。 开发人员忘记了在主页按钮中断应用时关闭音频通道。 开发人员应将这种情况考虑在内,并相应地对应用进行修改。

5. 结论

唤醒锁是非常有用且强大的工具。 但是如果使用不当,它们可能会对设备的电池寿命产生非常不好的影响,从而极大地影响用户体验。 对于开发人员来讲,应确保在 QA 过程中其代码未导致任何 No Sleep 漏洞出现。 他们应考虑使用可用的工具对实际使用中其应用对电池的影响进行分析,并尽量降低其对用户设备的影响。

6. 参考文献


英特尔® 硬件加速执行管理器安装指南 — Mac OS X*

$
0
0

更新日期:2013 年 4 月 25 日

介绍

本文将指导您安装英特尔® 硬件加速执行管理器(英特尔® HAXM),这是一款可以使用英特尔® 虚拟化技术(VT)加快 Android* 开发速度的硬件辅助虚拟化引擎(管理程序)。

前提条件

英特尔 HAXM 要求首先安装 Android* SDK (版本为 17 或更高)。 更多信息,请访问 Android* 开发人员网站 (http://developer.android.com/sdk/)。

系统要求

硬件要求:

  • 支持英特尔® VT-x、英特尔® EM64T(英特尔® 64) 和病毒防护 (XD) 功能的英特尔® 处理器
  • 至少 1 GB 的可用 RAM

支持的操作系统:

  • Mac OS X* 10.6 Snow Leopard 和 10.7 Lion (32/64 位)

重要提示: 英特尔 HAXM 无法在未采用英特尔处理器或采用了不符合上述“硬件要求”中描述的硬件特性的系统上使用。如需了解您的英特尔处理器能力,请访问 http://ark.intel.com/
此外,英特尔 HAXM 仅可在英特尔提供的 Android* x86 模拟器映像上使用。
英特尔 HAXM 不能和 ARM* Android* 模拟器映像或非英特尔 x86 Android* 模拟器映像一起使用

下载英特尔® HAXM

综述

安装英特尔 HAXM 时可以选择通过 Android* SDK 管理器的方式 (推荐),或者通过手动的方式(即手动从英特尔的网站下载安装程序)。

注:英特尔 HAXM 现在还不能自动检查更新。 如欲获取最新版本,请使用 Android* SDK 管理器 (推荐) 或者从 英特尔® 开发人员专区 Android* 开发人员网站下载英特尔 HAXM 软件包。

手动下载

  1. 请转至 http://software.intel.com/en-us/android
  2. 为您的平台选择英特尔 HAXM 安装程序包。
  3. 解压安装程序并使用适合您平台的安装说明。

通过 Android* SDK 管理器下载

  1. 启动 Android* SDK 管理器。
  2. 在 Extras 下,选中紧挨着 "Intel x86 Emulator Accelerator (HAXM)"的复选框。
  3. 点击 "Install package…"按钮。
  4. 查看英特尔公司许可协议。 如您接受所述条款,选择“Accept”并点击“Install”。
  5. SDK 管理器会将安装程序下载到 SDK 主目录下的 "tools"目录中。
  6. 解压 "tools"目录中的安装程序,并使用适合您平台的安装说明。

在 Mac OS X* 上安装英特尔® HAXM

警告: 如果您的系统不符合系统要求(包括对诸如英特尔® 虚拟化技术 (英特尔® VT) 等英特尔处理器特性的支持),英特尔® 硬件加速执行管理器(英特尔® HAXM)将无法安装。

  1. http://software.intel.com/en-us/android处或者使用 SDK 管理器下载安装程序包。
  2. 打开 DMG 文件,然后运行其中的安装程序。
  3. 如果已经安装了较老版本的英特尔 HAXM,您将会看到一个对话框通知:

    点击 “OK” 消除对话框。 然后,您可以退出安装程序以保持当前的英特尔 HAXM 版本,或继续安装并升级英特尔 HAXM。

  4. 您将会看到一个欢迎界面:

  5. 点击“继续”
  6. 系统将会提示您调整分配至英特尔 HAXM 的内存量。

    注: 此外,对于英特尔 HAXM,该安装程序还相当于配置工具。 如要更改内存设置,请再次运行该安装程序。

  7. 下一个界面将会确认您的英特尔 HAXM 内存配置设置:

  8. 选择将用于安装英特尔 HAXM 的硬盘,然后点击“Continue”。
  9. 英特尔 HAXM 安装完成后,点击“Close”退出安装程序。

英特尔 HAXM 现已安装并可使用。

如要确认英特尔 HAXM 是否正在运行,请打开终端窗口并运行下列命令:

 
1kextstat | grep intel

如果英特尔 HAXM 操作正确,命令将会显示一条状态消息,提示名为“com.intel.kext.intelhaxm”的内核扩展已加载。

如要停止或开始英特尔 HAXM,请按照下列命令操作:

停止:

 
1sudo kextunload –b com.intel.kext.intelhaxm

开始:

 
1sudo kextload –b com.intel.kext.intelhaxm

调整英特尔® HAXM 内存分配

如要更改分配至英特尔 HAXM 的内存量,请再次运行安装程序。

卸载英特尔® HAXM

警告: 卸载英特尔 HAXM 前,请关闭所有 Android* x86 模拟器实例。 英特尔 HAXM 无法在使用中卸载。

如要卸载英特尔 HAXM,请打开终端窗口并运行下列命令:

 
1sudo /System/Library/Extensions/intelhaxm.kext/Contents/Resources/uninstall.sh

系统将提示您输入当前的用户密码。 按照卸载程序的提示卸载英特尔 HAXM。

重要提示: 卸载英特尔 HAXM 将禁用所有英特尔® x86 Android* 模拟器的加速。 现有的 Android* 虚拟设备将继续运行,但停止加速。

再次安装英特尔 HAXM 将重新启用 Android* 模拟器加速。

使用英特尔® HAXM

英特尔 HAXM 要求使用英特尔提供的 Android* x86 系统映像。 这些映像可通过 Android* SDK 管理器下载或通过英特尔开发人员专区网站手动下载。

英特尔 x86 Android* 模拟器映像将会使用 Android* SDK 随附的 “emulator-x86”二进制自动运行。 如果英特尔 HAXM 安装成功并可运行,将可加速模拟(使用英特尔虚拟化技术)。

故障排除

英特尔 HAXM 要求使用英特尔提供的 Android* x86 系统映像。 这些映像可通过 Android* SDK 管理器下载或通过英特尔® 开发人员专区网站手动下载。

英特尔病毒防护(XD)功能错误
安装英特尔 HAXM 时,您可能会遇到有关英特尔 XD 支持的错误。
下列情况可能会导致该错误消息出现:

  • 电脑的处理器不支持英特尔 XD
  • 未启用英特尔 XD

不支持英特尔 XD
英特尔 HAXM 要求使用采用病毒防护(XD)功能的英特尔处理器,且不能用于不具备该硬件特性的系统。 如要确认您英特尔处理器的功能,请访问 http://ark.intel.com/

未启用英特尔 XD
注: 如果处理器支持,Apple* 电脑将永久启用英特尔 XD。
如果您收到错误消息,提示未启用英特尔 XD,则您的电脑不满足使用英特尔 HAXM 的最低系统要求。 如要确认您英特尔处理器的功能,请访问 http://ark.intel.com/

英特尔® 虚拟化技术(英特尔® VT-x)功能

当安装英特尔 HAXM 时,您可能会遇到英特尔 VT-x 支持相关的错误。

下列情况可能会导致该错误消息出现:

电脑的处理器不支持英特尔 VT-x

  • 未启用英特尔 VT-x

不支持英特尔 VT-x
英特尔 HAXM 要求使用采用英特尔 VT-x 功能的英特尔处理器,且不能用于不具备该硬件特性的系统。 如要确认您英特尔® 处理器的功能,请访问 http://ark.intel.com/

未启用英特尔 VT-x
注: 如果处理器支持,Apple* 电脑将永久启用英特尔 VT-x。
如果您收到错误消息,提示未启用英特尔 VT,则您的电脑不满足使用英特尔 HAXM 的最低系统要求。 如要确认您英特尔处理器的功能,请访问 http://ark.intel.com/

提示与技巧

以下是一些建议,可帮助您使用英特尔 HAXM 驱动程序获得最佳 Android* 模拟器体验。

  • 在 AVD 管理器中针对您的映像启用 GPU 加速。 英特尔 HAXM 驱动程序可通过处理器中的英特尔虚拟化技术在本地执行大部分的 CPU 指令,且 GPU 加速可将 OpenGL* 调用迁移至主机 GPU。
  • 在终端中使用下列命令启动模拟器:

    ./emulator-x86 –avd <avd name> -partition-size 1024 –gpu on
     
    • 尺寸为 1024 的分区允许安装大小为 1GB 的应用。 它不同于 AVD 管理器中 SDCard 的大小选择,可指定在模拟器内分配多大的内存来存储介质文件。 将 GPU 设置为开将提供更佳的图形性能。
    • 确保您为 GL 库设置的环境变量正确。 使用下列命令在终端中设置 LD_LIBRARY_PATH。 修改命令以选择您 SDK 的安装位置。

      export LD_LIBRARY_PATH=<sdk install location>/tools/lib

      如要在新终端启动时自动运行该命令,您可以将该命令添加至您的 ~/.bash_profile 脚本。
  • 当安装英特尔 HAXM 时,将驱动程序设置为使用系统中一半的可用内存。 例如,如果您的系统拥有 6 gig 的内存,那么请将 3 gig 用于英特尔 HAXM 驱动程序。 相对于系统内存而言,这可让英特尔 HAXM 驱动程序的内存更平衡。
  • 创建映像时,请勿将“Device ram size”设置为大于分配至英特尔 HAXM 驱动程序的内存。 在上述示例中,设备内存大小不应大于 3 gig,因为分配至英特尔 HAXM 的内存只有 3 gig。
  • 有时,在首次启动映像时,将会在启动界面挂起。 启动流程完成,但是未出现主界面。 点击模拟器上的主页按钮,打开主界面。
  • 更多启动模拟器的命令行选择,请参阅 Android* 开发人员网站

Changelog

  • 在模拟器中将 Linux 内核更新至 3.4
  • 添加了对模拟器 64 - x86 的支持,以便能够在 32 位和 64 位 Mac OSX 上运行
  • 修复了在 Ivy Bridge 平台上运行 Mountain Lion 10.8 时出现的内核崩溃故障
  • 提高了稳定性

面向 Android* 操作系统的英特尔® 图形性能分析器

$
0
0

介绍

英特尔® 图形性能分析器(英特尔® GPA)套件是一套强大的图形和游戏分析工具,能够按照游戏开发人员的工作方式执行,通过快速提供可操作的数据帮助开发人员从系统层面下至每个绘制调用找到开发性能的机会,以节约宝贵的优化时间。

目前,英特尔® GPA 支持基于英特尔® 凌动? 处理器且运行 Google* Android* OS 的手机和平板电脑。 该版工具套件支持您使用您选择的开发系统(Windows*、OS X* 或 Ubuntu* OS)优化 OpenGL* ES 工作负载。 借助该功能,Android* 开发人员可以:

  • 获取包括 CPU、GPU 和 OpenGL* ES API 在内的二十多种关键系统标准的实时视图
  • 进行若干图形管线实验以隔离图形瓶颈
  • 当使用基于英特尔凌动处理器的平板电脑时,运行英特尔 GPA 帧分析器来执行具体的帧分析和优化
  • 当使用基于采用 PowerVR* 显卡的英特尔凌动处理器的 Android* 设备时,运行英特尔 GPA 平台分析器来执行具体的平台分析

如要下载免费版的英特尔 GPA,请访问 英特尔 GPA 主页,并点击 Download按钮,下载相应的产品版本。 关于为 Android* 操作系统平台开发游戏或应用,请根据您的开发系统选择英特尔 GPA 版本。

后续步骤

关于在 Android* OS 上启动英特尔 GPA 的具体信息,请参阅产品的在线帮助此外,英特尔 GPA 主页还包括产品信息(包括在 Windows* 操作平台上分析 DirectX* 游戏的有关信息)链接。

如果您希望系统通知您英特尔 GPA 产品更新,请点击该链接

我们一如既往地欢迎您提出建议,因此请在英特尔 GPA 支持论坛上发表您的评论,告诉我们能够做什么来改进您使用上述工具的体验。

*其他的名称和品牌可能是其他所有者的资产。

面向 Android* Jelly Bean 4.3 的英特尔® 凌动™ x86 映像安装指南 - 推荐

$
0
0

介绍

本指南在安装面向 Android* Jelly Bean 的英特尔® 凌动™ x86 映像方面提供了相关指导,该映像可用于英特尔 x86 架构上的开发。

前提条件

Android x86 模拟器映像要求安装 Android SDK。 有关安装和配置 Android SDK 的说明,请访问 Android 开发人员网站(http://developer.android.com/sdk/)。

可选: 英特尔硬件加速执行管理器 (HAXM)有助于加快面向 Android 的 X86 模拟器映像的速度。 更多信息,请见本指南中的“优化”部分。

已知问题:

  • Caffeinemark 可能出现问题并在 logcat 中的 ashmem/libdvm 处提示出现崩溃。  
  • 在浏览器中播放视频剪辑时仅有音频,没有视频。 仅当使用浏览器时会出现这种情况,当使用全屏回放时不会出现。
  • ddms、uiautomatorviewer 或 monkeylmage 无法使用屏幕捕获
  • 无法使用快照功能
  • 无法重置为出厂数据
  • 如果未设置任何前后摄像头,摄像头应用将会在启动时崩溃
  • 手机通话期间 3G 连接断开

安装

通过 Android SDK 管理器进行下载

  1. 启动 Android SDK 管理器。
  2. 在“Android 4.3 (API 18)”下,选择“Intel x86 Atom System Image”:
  3. 选中后,点击“Install Package”按钮。
  4. 查看英特尔公司许可协议。 如您接受所述条款,选择“Accept”并点击“Install”。
  5. SDK 管理器将下载系统映像,并将其解压至 Android SDK 目录中的相应位置。

使用系统映像

  1. 打开 Android AVD 管理器并创建新的 ACD,将“Target”设置为“Android 4.3 – API Level 18”,并将“CPU/ABI”设置为“Intel Atom (x86)”。
    面向 Android Jelly Bean 的英特尔凌动 x86 映像可利用硬件 GPU 特性增强游戏、图形密集型项目和用户界面元素的性能。 如要获得最佳性能,请确保在创建映像时勾选“Use Host GPU”方框。
    注: GPU 加速的功能和性能很大程度上取决于您电脑上的显卡和显卡驱动程序。 必须在每个 AVD 上启用 GPU 加速。

    注:如果 "Intel Atom (x86)" CPU/ABI 选项不可用,请确保系统映像安装正确。
  2. 点击 “Create AVD”按钮。
  3. AVD 已安装成功,现可使用:

优化

CPU 加速

借助采用英特尔 VT-x 技术的基于硬件的虚拟化,面向 Android Jelly Bean 的英特尔凌动 x86 映像的性能可得到很大改进。

如果您的电脑搭载了支持 VT-x 的英特尔处理器,建议您配合该系统映像使用英特尔硬件加速执行管理器(HAXM)。 欲了解更多有关英特尔 HAXM 的信息,请访问 http://www.intel.com/software/android

注:英特尔 HAXM 仅适用于 Windows 与 OS X 操作系统。 对于 Linux 主机,可使用基于内核的虚拟机(KVM)来加速模拟性能。 如欲了解在 Ubuntu 上安装和配置 KVM 的信息,请参考该指南: https://help.ubuntu.com/community/KVM/Installation

在 Android* 平台上设置原生 OpenGL ES*

$
0
0

Setting up Native OpenGL ES* on Android* Platforms final.docx
BSD2.0.txt
ParticleSystemNDK.zip
README.txt

摘要

本文具体介绍了在 Android 平台上创建原生 OpenGL ES 2.0 图形应用的基本步骤。 首先将讨论使用 Java* API 设置 OpenGL ES 2.0 应用的流程,随后将介绍在共享库中使用原生渲染来转换应用。

注:为了尽可能向更多的受众提供支持,本文中未使用 IDE。 所有的项目创建、维护和部署均将通过 Google 提供的命令行工具集执行。

项目设置

如要创建默认的 Android 项目,当出现命令提示符时执行下列命令。

android 创建项目--target <TID> \
 --name <ProjName> \
 --path <FolderPath> \
 --activity <ActivityName> \
 --package <Package>

注:具体的目标 ID 将取决于如何配置 Android SDK。 出现命令提示符时通过运行 android list targets检索可用目标列表。

下列设置将用于该项目:

--name DemoProject
--activity DemoProjectActivity
--package demo.project

Android 实用程序生成的项目是默认的“Hello World”项目。 在项目的根目录中时,如果出现命令提示符,通过运行 ant debug来确认项目是否正常初始化。

添加 OpenGL ES 支持

Android 可直接向 Java 曝露 OpenGL ES API 以便应用开发人员使用。 我们将使用设置 OpenGL 的分类和方法来利用 Java API 或执行原生渲染。

因此,我们将会预先讨论使用 Java API 渲染简单场景的详细情况。 接下来,我们将会对示例应用进行修改以使用原生渲染。

卸载标题栏

运行 Hello World 应用时,该应用的标题栏在运行中可见。 一般而言,这种运行状况在编写 OpenGL ES 应用时不需要。

通过在 AndroidManifest.xml 文件中添加适当的活动标记主题属性可禁用该运行状况。

android:theme=�@android:style/Theme.NoTitleBar.Fullscreen�

或者,也可以在活动类的 onCreate 方法内运行下列代码。

requestWindowFeature(Window.FEATURE_NO_TITLE);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                     WindowManager.LayoutParams.FLAG_FULLSCREEN);

更换默认视图

Hello World 项目使用了 setContentView 的超载,向 XML 资源中添加了资源标识符以压缩并设置为当前的活动视图。 必须使用能够渲染 OpenGL ES 文本的视图接口来更换该操作。 Android 可提供 Java 类 GLSurfaceView,它可以压缩渲染接口和 EGL 显示。

您可以将 “res/layout/main.xml”文件从项目中删除,因为该视图可通过编程方式创建。

GLSurfaceView

适用于 GLSurfaceView 的两种导入方法是 setEGLContextClientVersion 和 setRenderer。

setEGLContextClientVersion 方法可设置需要使用的 ES 版本。 对于该项目,我们使用了 OpenGL ES 2.0。

渲染至环境由从 GLSurfaceView.Renderer 继承的类实例来控制。渲染器示例通过调用 setRenderer 方法来设置。

必须将 Activity 类的 onPause 和 onResume 覆盖才能够在 GLSurfaceView 类上分别调用方法来暂停/恢复渲染线程。

下列是完整的包含 GLSurfaceView 的 DemoActivity 类:

public class DemoActivity extends Activity 
{
	private GLSurfaceView view;

	@Override
	public void onCreate(Bundle savedInstanceState) 
{
		super.onCreate(savedInstanceState);

		view = new GLSurfaceView();

		// Tell EGL to use a ES 2.0 Context
		view.setupEGLContextClientVersion(2);

		// Set the renderer
		view.setRenderer(new DemoProjectRenderer());

		setContentView(view);
	}

	@Override
	protected void onPause() 
{
		super.onPause();
		view.onPause();
	}

	@Override
	protected void onResume() 
{
		super.onResume();
		view.onResume();
	}
}

GLSurfaceView.Renderer

从 GLSurfaceView.Renderer 继承的类负责向 OpenGL 环境中绘制。 GLSurfaceView.Renderer 曝露了三种必须在继承的类中执行的摘要方法: onSurfaceCreated、onSurfaceChanged 和 onDrawFrame。

Android 应用暂停或挂起时,OpenGL 环境以及所有与其相关的资源都将被破坏。 因此,针对应用的初始化和资源加载应在 onSurfaceCreated 功能中处理。

注:有一种方法 — setPreserveEGLContextOnPause — 可以让 EGL 跨越暂停/恢复界限来尝试和保存环境。 但是请注意,这种功能依赖于硬件对多 EGL 环境的支持,因此,调用它并不能确保一定将环境保存。

演示项目将使用 Java OpenGL ES API 来清除颜色缓冲区的品红色。

针对演示项目从 GLSurfaceView.Renderer 得出的类如下所示:

class DemoProjectRenderer implements GLSurfaceView.Renderer 
{

	public void onDrawFrame(GL10 gl) 
{
		gl.glClear(gl.GL_COLOR_BUFFER_BIT);
	}

	public void onSurfaceChanged(GL10 gl, int width, int height) 
{		
		gl.glViewport(0, 0, width, height);
	}

	public void onSurfaceCreated(GL10 gl, EGLConfig config) 
{
gl.glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
	}
}

AndroidManifest.xml

清单文件应通过在清单元素下添加下列 XML 元素来指定对 OpenGL ES 2 的需求。

<uses-feature android:glEsVersion=``0x00020000'' android:required=``true'' />

迁移至原生渲染

无需重新实现现有的代码部分来使用 Java 接口,可以通过从 Java 类调用原生代码来利用现有的 C/C++ 代码库。 原生代码已编译至共享库,并使用 APK 文件部署。

所有的原生代码都位于项目根目录中的 jni 文件夹下。

JNI 基础

原生代码通过 JNI 框架曝露至 Java 各类。 如欲了解 JNI 框架的具体解释,请参阅 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html

必须在载入程序中遵守 JNI 命名规则,以便能够正确找到原生方法。 所有的原生方法:

  • 必须以前缀 Java_开始
  • 然后使用完全限定的 mangled 类名
  • 然后使用完全限定的 mangled 方法名

例如,以下是一个简单的原生 C 函数:

void nativeLibraryFunction(int width, int height);

如要在不修改现有函数的情况下将该方法暴露至 Java 代码,请加入 JNI 头文件并创建可调用现有原生方法的封装方法。

#include <jni.h>
JNIEXPORT void JNICALL Java_demo_project_LibraryClass_LibraryFunctionWrapper(JNIEnv* env, jobject obj, jint width, jint height)
{
    nativeLibraryFunction(width, height);
}

上述函数假定面向项目的软件包是 demo.project,并将使用名为 LibraryClass 的 Java 类来暴露原生函数。

在所有导出的 JNI 函数中第一个参数属于“JNIEnv*.”类型。该参数有多种功能,其中最重要的是支持原生代码回调至 Java 代码。 本文中暂不讨论这种运行状况。

对于静态函数, jobject 参数是调用 Java 类的参数。

其他的参数类型从 JNI 框架暴露。 对于内置 C 类型,JNI 框架可自动控制转换。 对于阵列和复杂的类型,请参考文档。

在 Java 端上必须导入共享库。 这可通过调用至 System.loadLibrary 来实现。这一般在面向该类的静态初始化器中完成。

此外,类必须声明适用于导出方法的接口。 这些方法为静态,并声明为本地。

class LibraryClass
{
    static
{
        System.loadLibrary("demo");
    }
    public static native void LibraryFunctionWrapper(int width, int height);
}

重要的一点是,LibraryClass 名称与导出的原生方法暴露的名称一致。 此外,需要将导出的功能的定义标记为本地。

此处,库应遵守目标平台上的共享库规则。 对于基于 Unix 的目标(如 Android),库名称应以 “lib”为前缀并附加 “.so”。 对于基于 Windows* 的目标,应附加扩展名“dll”。

注:对于复杂的函数声明,Java 可提供实用程序 javah,为原生函数生成头文件定义(考虑到 Java 类文件)。

现在,您可从代码中的任何位置将该方法调用为静态 Java 方法。 对于具体的示例,DemoProject 现可迁移至原生渲染。

迁移初始化代码

在项目 jni 文件夹中创建 C 文件。 此处,该文件为“nativelibrary.c.”。

文件将会使用所有的原生 OpenGL ES 调用。

void InitializeOpenGL() 
{
	glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
}
void resizeViewport(int newWidth, int newHeight) 
{
	glViewport(0, 0, newWidth, newHeight);
}
void renderFrame() 
{
	glClear(GL_COLOR_BUFFER_BIT);
}

假定这些方法已存在于项目或静态库中。 如要使用这些方法 JNI,需要为这三种方法中的每一种方法创建 JNI 封装方法。 这些方法可采用另一种 C 文件 jniExports.c。

JNIEXPORT void JNICALL Java_demo_project_SomeClass_init(JNIEnv*) 
{
	InitializeOpenGL();
}
JNIEXPORT void JNICALL Java_demo_project_SomeClass_resize(JNIEnv*, jint width, jint height) 
{
	resizeViewport(width, height);
}
JNIEXPORT void JNICALL Java_demo_project_SomeClass_render(JNIEnv*) 
{
	renderFrame();
}

在 Java 端上,导出的方法在库类中被声明。

class LibraryClass 
{
	static 
{
		System.loadLibrary("demo");
	}

	public static native void init();
	public static native void resize(int width, int height);
	public static native void render();
}

现在,GLSurfaceView.Renderer 派生类已进行了修改以调用原生方法:

class DemoProjectRenderer extends GLSurfaceView.Renderer 
{
	public void onDrawFrame(GL10 gl) 
{
		LibraryClass.render();
	}

	public void onSurfaceChanged(GL10 gl, int width, int height) 
{
		LibraryClass.resize(width, height);
	}

	public void onSurfaceCreated(GL10 gl, EGLConfig config) 
{
		LibraryClass.init();
	}
}

配置原生 Build

Android.mk

在 “jni”文件夹中,创建了 “Android.mk”文件以指导 NDK 编译原生模块。 在粒子示例项目中使用的示例 Android.mk 如下所示:

# Tell Android where to locate source files
# "my-dir" is a macro function which will return the path of the current 
directory(where Android.mk resides)
LOCAL_PATH := $(call my-dir)

# Clear contents of the LOCAL_* variables
include $(CLEAR_VARS)

# All the source files to include in this module
LOCAL_SRC_FILES := nativeLibrary.c \
                   jniExports.c 

# The name of the module
LOCAL_MODULE := libdemo

# Compilation flags
LOCAL_CFLAGS := -Werror

# Static libraries to link with
LOCAL_LDLIBS := -llog –landroid -lGLESv2

# Build the module
include $(BUILD_SHARED_LIBRARY)

从命令提示符运行 ndk-build命令以构建共享库。 这一步应在使用 ant 构建 Android 应用之前完成。

读取 APK 中的资产

访问资产是迁移至本地渲染需要特别关注的一个领域。 资产管理器从 Java 传送至原生代码。 例如,在活动 onCreate 方法中,添加了下列代码行:

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    assetManager = getAssets();
    LibraryClass.initializeAssetManager(assetManager);

    view = new GLSurfaceView();

    // Tell EGL to use a ES 2.0 Context
    view.setupEGLContextClientVersion(2);

    // Set the renderer
    view.setRenderer(new DemoProjectRenderer());

    setContentView(view);
}

JNIEXPORT void JNICALL Java_demo_project_LibraryClass_initializeAssetManager(JNIEnv* env, jobject obj, jobject assetManager)
{
    AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
}

AAssetManager_fromJava 函数由 NDK 提供,可获取原生指针至资产管理器实例。 APK 中存储的资产可通过 AAssetManager API 访问。 关于使用 AAssetManager API 读取文件的示例,请参阅粒子示例源代码中的 util/file.c。

粒子示例代码

上述文本详细介绍了在 Android 平台上启用原生 OpenGL ES 工作负载的一套基础步骤。 如欲了解更完整的示例,适用于原生 OpenGL ES 2.0 粒子系统源代码可通过 http://software.intel.com/en-us/articles/Android-code-samples获得。 与文档相关的源代码部分将在下文中进行介绍。

ParticlesActivity.java

本类储存了主要的应用活动。 它负责创建 GLSurfaceView 派生类,以及通过调用 createAssetManager 将应用的资产管理器传送至原生 C 代码。

ParticlesView.java

在粒子示例中,从 GLSurfaceView 中继承了一个明确的类来设置 OpenGL ES 客户端版本。 此外,接口渲染作为内部类来实现。

ParticlesLib.java

本类可导入共享库并声明示例使用的三种原生方法: init、step 和 createAssetManager。

Shared Library Code

示例中使用的共享库的代码位于 jni 目录下。

导出的 C 函数钩子位于 jni/gl_code.cpp 中。它们可暴露初始化、帧步骤和资产创建函数。 这些方法的实现位于 jni/App.c 中。

示例中使用的粒子系统位于 jni/Particles.c and jni/Particles.h 中。

位于示例中的其他文件是适用于数学函数、简单几何创建和纹理加载的实用程序方法。 该代码位于 jni/util 目录下。

值得特别关注的一个文件是读取资产数据的简单实用程序函数,它可在 util/file.c 中找到。

关于作者

Chris Kirkpatrick 是就职于英特尔软件与服务事业部的软件应用工程师,在个人设备外形(Personal Form Factors)部提供英特尔显卡解决方案支持。 他拥有俄勒冈州立大学计算机科学学士学位。

声明

本文件中包含关于英特尔产品的信息。 本文件不构成对任何知识产权的授权,包括明示的、暗示的,也无论是基于禁止反言的原则或其他。 英特尔不承担任何其他责任。英特尔在此作出免责声明:本文件不构成英特尔关于其产品的使用和/或销售的任何明示或暗示的保证,包括不就其产品的(i)对某一特定用途的适用性、(ii)适销性以及(iii)对任何专利、版权或其他知识产权的侵害的承担任何责任或作出任何担保。

除非经过英特尔的书面同意认可,英特尔的产品无意被设计用于或被用于以下应用:即在这样的应用中可因英特尔产品的故障而导致人身伤亡。

英特尔有权随时更改产品的规格和描述而毋需发出通知。 设计者不应信赖任何英特产品所不具有的特性,设计者亦不应信赖任何标有“保留权利”或“未定义”的说明或特性描述。 对此,英特尔保留将来对其进行定义的权利,同时,英特尔不应为因其日后更改该等说明或特性描述而产生的冲突和不相容承担任何责任。 此处的信息可能随时更改,恕不另行通知。 请勿使用本文信息完成一项产品设计。

本文件所描述的产品可能包含使其与宣称的规格不符的设计缺陷或失误。 这些缺陷或失误已收录于勘误表中,可索取获得。

在发出订单之前,请联系当地的英特尔营业部或分销商以获取最新的产品规格。

索取本文件中或英特尔的其他材料中提的、包含订单号的文件的复印件,可拨打1-800-548-4725,或登陆 http://www.intel.com/design/literature.htm

在性能检测过程中涉及的软件及其性能只有在英特尔微处理器的架构下方能得到优化。 诸如SYSmark和MobileMark等测试均系基于特定计算机系统、硬件、软件、操作系统及功能。 上述任何要素的变动都有可能导致测试结果的变化。 请参考其他信息及性能测试(包括结合其他产品使用时的运行性能)以对目标产品进行全面评估。

对本文件中包含的软件源代码的提供均依据相关软件许可而做出,任何对该等源代码的使用和复制均应按照相关软件许可的条款执行。

英特尔和 Intel 标识是英特尔在美国和/或其他国家的商标。

OpenGL 是注册商标,OpenGL ES 标识是 Silicon Graphics Inc. 的注册商标,需获 Khronos 的许可方能使用。

英特尔公司© 2013 年版权所有。 保留所有权利。

*其他的名称和品牌可能是其他所有者的资产。

如何测试并调试基于 NDK 的 Android 应用

$
0
0

本文概述了如何为 x86 平台测试和调试基于 NDK 的应用。 本文将从头至尾完整展示如何创建示例应用,并演示如何测试和调试。

1. 开发环境

请确保已安装了 Android 应用开发环境。 如果尚未安装,请查看 Android 开发人员网站上的说明[1]。 在下文中,我们仅列出了所需的主要组件。

  • Android SDK: Android 软件开发套件可提供必要的工具和库,帮助开发在基于 Android 的设备上运行的应用。
  • Android NDK: Android NDK 是一款支持您在 Android 应用中嵌入使用原生代码的组件的工具套件。

在该示例中,我们仅需要上述两个组件,但是如果您想要使用 IDE,则需要下载并安装下列组件:

Eclipse*:多个项目中的常用 IDE,包括通过安装 ADT 插件获得的 Android 项目。

ADT: Android 开发工具套件,面向 Eclipse 的插件。

CDT: C/C++ 开发工具套件 — 如果您希望在 Eclipse 中构建 C/C++ 代码。

Cygwin*: Cygwin 是可为 Windows* 提供 Linux* 界面(look-and-feel)环境的工具集。 在 Windows OS 中,我们需要用它运行“ndk-build”来构建原生代码。

2. 测试环境

对于 x86 平台目标,需要使用基于 x86 的设备或 x86 模拟器进行测试。 随着今年四月 IA 手机的上市,如 Lava Xolo X900 和 Lenovo K800,采用 Android 的 x86 平板电脑和手机将越来越普遍。 对于没有 x86 设备需要测试的用户,使用 x86 模拟器即可。 Android SDK 管理器可用于安装 x86 模拟器,且面向英特尔凌动平台的 Android 4.0.3 和 Android 2.3.3 映像已在官方软件版本中提供。 请见图 1 和 2。


图 1. 面向 Android* 4.0.3 的英特尔® 凌动? x86 系统映像


图 2. 面向 Android* 2.3.3 的英特尔® 凌动? x86 系统映像

对于无法在官方版本中找到的 Android 版本,请尝试从 Android 源代码构建并将其放入相应的文件夹下(例如对于 Android 2.3.3,放在 $ANDROID_NDK_ROOT/platforms/android-10/images/ 下)。

英特尔® 硬件加速执行管理器(英特尔® HAXM)也可帮助开发人员获得更快的 Android 模拟速度。 HAXM 是一个硬件辅助虚拟化引擎(管理程序),该引擎可以使用英特尔® 虚拟化技术 (Intel®VT) 加快主机上的 Android 应用模拟速度。 配合使用英特尔提供的 Android x86 模拟器映像和正式版的 Android SDK 管理器,HAXM 可以帮助您在英特尔 VT 支持的系统上更快地进行模拟。


图 3.英特尔® 硬件加速执行管理器

3. 编写示例代码

现在,我们将创建一个名为 CPUIdApp [3] 的简单应用,它可以返回主机 CPU 的主要特性。 原生代码有两种主要功能:一种是获取 CPU 信息;另一种是分析字符串。 您可以将其写入 cpuid.c 文件,在 Linux 操作系统中使用 gcc 构建,或在 Windows 操作系统中使用 Cygwin 构建。 运行示例应用后,解析的 CPU ID 信息将会出现在屏幕上。 我们的目的是在示例活动中展示解析的 CPU ID 信息。 关于如何创建该项目的更多详细信息,请参阅 [1, 4]。

第一步是创建一个 Android 项目。 请从附件的 cupid.c 中查看源代码。

$mkdir jni-cpuid && cd jni-cpuid

该命令将创建一个简单的“Hello World”Android 项目。

$android create project –package “com.test.cpuid� –activity “CPUIdApp� –path . –target “android-9�

为了实现我们的目标,我们需要将 src/com/test/cupid/CPUIdApp.java 更改为下列内容:

……
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
		TextView tv = new TextView(this);   //create a TextView as a container for the result
		tv.setText(cpuid_get());  //get parsed CPU ID information from native function and set to tv
		setContentView(tv);
    }
 
	private static native String cpuid_get();  //declare a native function but do not implement
	static { System.loadLibrary("cpuid"); }   //load the native library contains the native function we need
}

下一步是在原生代码中实现 cupid_get 功能。

$ant debug
$javah –d jni –classpath bin/classes com.test.cpuid.CPUIdApp

然后系统将自动创建包含 com_test_cpuid_CPUIdApp.h 的 jni 目录,并在头文件中声明需要实现的功能。

JNIEXPORT  jstring  JNICALL  Java_com_test_cpuid_CPUIdApp_cpuid_1get
  (JNIEnv *, jclass);

然后,将 cupid.c 移至 jni 并创建一个 com_test_cpuid_CPUIdApp.c 文件来实现 Java_com_test_cpuid_CPUIdApp_cpuid_1get 功能。

#include "com_test_cpuid_CPUIdApp.h"
extern void cpuid_parse(char *buf);
 
JNIEXPORT jstring JNICALL Java_com_example_cpuid_CPUIdApp_cpuid_1get(JNIEnv *env, jclass jc)
{
        char buf[1024];
        cpuid_parse(buf);
        return (*env)->NewStringUTF(env, buf);
}
The last step is to create Android.mk file for building the native code in the next session.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := cpuid
LOCAL_SRC_FILES := cpuid.c com_test_cpuid_CPUIdApp.c
include $(BUILD_SHARED_LIBRARY)

4. 在 x86 模拟器上构建、部署和测试

现在开始运行 “ndk-build”来构建原生代码吧。 如要为 x86 架构构建,需要将 “APP_ABI=x86”添加为参数或 Android.mk 文件上。

$ndk-build APP_ABI=x86

Compile x86    : cpuid <= cpuid.c
Compile x86    : cpuid <= com_test_cpuid_CPUIdApp.c
SharedLibrary  : libcpuid.so
Install        : libcpuid.so => libs/x86/libcpuid.so
 

然后使用 “ant” 构建整个项目。 请在构建项目前先清理项目。

$ant clean && ant debug

CPUIdApp-debug.apk 将在“bin”目录中创建并可通过“adb install”命令进行安装。

$adb install bin/CPUIdApp-debug.apk

最后,在模拟器中运行 CPUIdApp 来查看输出。

5. 调试以检查错误

有两种方式可以调试 Android NDK 应用: adb logcat and ndk-gdb. 我们将在本部分讨论这两种方法。

5.1 使用 adb logcat 获取日志输出

对于基于 Java* 的应用,如果使用了 Log.d(),可以通过运行“adb logcat”来获取日志信息。 运行 “adb logcat”命令时,也会显示其它应用和系统的日志。

运行我们之前在模拟器上创建的 CPUIdApp 后,将会出现一个错误对话框,应用将崩溃。 使用“adb logcat”检查出现了什么问题。

$adb logcat

…
D/dalvikvm( 1616): No JNI_OnLoad found in /data/data/com.test.cpuid/lib/libcpuid.so 0xb49300f8, skipping init
W/dalvikvm( 1616): No implementation found for native Lcom/test/cpuid/CPUIdApp;.cpuid_get ()Ljava/lang/String;
…

日志表示 Lcom/test/cupid/CPUIdApp.cpuid_get 功能未实现。 在 jni/com_test_cpuid_CPUIdApp.c 中检查代码后,我们发现 Java_com_example_cpuid_CPUIdApp_cpuid_1get 应命名为 Java_com_test_cpuid_CPUIdApp_cpuid_1get。 请注意, Typos 是开发中经常会出现的一个问题。 因此,需要在 jni/com_test_cpuid_CPUIdApp.c 中将 Java_com_example_cpuid_CPUIdApp_cpuid_1get 重命名为 Java_com_test_cpuid_CPUIdApp_cpuid_1get 并重新构建该项目。

$ndk-build APP_ABI=x86
$ant clean && ant debug
$adb install –r bin/CPUIdApp-debug.apk

然后,在模拟器中重新运行 CPUIdApp。 正常输出如下图所示。 如果您希望了解这些 CPUID 操作码的具体信息,请参阅 [4, 10]。


图 4. CPUIdApp 结果

如欲了解其他信息,可使用 android.util.Log 提供的一系列 Log.*() 功能来打印所需信息。 这在 Java 文件中非常简单:

…
import android.util.Log;
…
Log.d(“CPUIdApp”, “try to get cupid_get…”);  //print useful information as needed
…

重新构建并运行 CPUIdApp 后,同样使用“adb logcat”获取日志输出:

D/CPUIdApp( 2327): try to get cpuid_get...

事实上,它不仅能够在 Java 代码中使用,也能够在 C/C++ 代码中使用。 按照下列方式修改 com_test_cpuid_CPUIdApp.c:

…
#include <android> 
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, “CPUIdApp”, __VA_ARGS__)) 
… 
JNIEXPORT jstring JNICALL Java_com_test_cpuid_CPUIdApp_cpuid_1get(JNIEnv *env, jclass jc) 
{ 
        char buf[1024]; 
        cpuid_parse(buf); 
        LOGI("cpuid_1get buf value: "); //the same way in native side to print useful information 
        LOGI(buf); 
        return (*env)->NewStringUTF(env, buf); 
} 
To build this, we need to modify Android.mk, by adding: 
LOCAL_LDLIBS := -llog 
LOCAL_C_INCLUDES += system/core/include/cutils 
LOCAL_SHARED_LIBRARIES := libcutils 
</android>

然后:

$ndk-build APP_ABI=x86 && ant clean && ant debug && adb install –r bin/CPUIdApp-debug.apk

运行后您将会获得下列日志信息:

I/CPUIdApp( 2475): cpuid_1get buf value:
I/CPUIdApp( 2475): CPUID Features(EAX=1): ECX = 0x00000201 EDX = 0x0781abfd
I/CPUIdApp( 2475): HT - NO
I/CPUIdApp( 2475): VT - NO
I/CPUIdApp( 2475): SSE - YES
I/CPUIdApp( 2475): SSE2 - YES
I/CPUIdApp( 2475): SSE3 - YES
I/CPUIdApp( 2475): SSSE3 - YES
I/CPUIdApp( 2475): SSE41 - NO
I/CPUIdApp( 2475): SSE42 - NO
I/CPUIdApp( 2475): AES - NO
I/CPUIdApp( 2475): AVX - NO

5.2 使用 ndk-gdb 调试 C/C++ 代码

Android NDK r4 采用了一个名为 “ndk-gdb”的辅助 shell 脚本,以便能够在 NDK 生成的机器代码中轻松启动原生调试会话。 脚本位于 NDK 的顶级目录,可通过应用项目目录或其他子目录中的命令行来调用。

我们试一下:

在项目目录的根目录中,运行“ndk-gdb --start”,以下的输出将会出现在终端上:

发现的可调试标记: false
错误: 软件包 com.test.cpuid 不可调试! 您可以通过以下两种方式进行修复:
— 调用“ndk-build”时,使用 NDK_DEBUG=1 重新构建。
— 修改您的清单以设置 android:将可调试属性设置为“true”,然后按照正常步骤重新构建。

使用上述两种方式: 1)修改清单,并在应用标签中添加 android:debuggable=”true” ;并 2) 通过运行 “ndk-build APP_ABI=x86 NDK_DEBUG=1” 进行重新构建。

$ ndk-build APP_ABI=x86 NDK_DEBUG=1
$ ant clean && ant debug && adb install –r bin/CPUIdApp-debug.apk
$ndk-gdb –start com.test.cpuid.CPUIdApp –force –verbose

应用被启动,并将显示:

…
…
and track explicitly loaded dynamic code.
0xb7eb2ff9 in __futex_syscall4 ()
   from /home/user/labs/cpuid/obj/local/x86/libc.so
(gdb)

所有“gdb”命令均可用于调试原生代码。 有时,在我们看到 “gdb”提示前,原生部分已完成。 此时,在 src/com/test/cpuid/CPUIdApp.java 处添加 “android.os.Debug.waitForDebugger()”:

…
import android.os.Debug;
…
        Log.d("CPUIdApp", "waiting for debug ...");
        android.os.Debug.waitForDebugger();  //make app pause
        Log.d("CPUIdApp", "try to get cpuid_get...");
        tv.setText(cpuid_get());
…

通过这种方式,我们可以对 cupid_get() 功能进行调试并获得更多详细信息。

6. 结论

在本文中,我们借助简单的示例应用介绍了基于 Android NDK 的应用的创建、安装、测试和调试。您可以在真正的 x86 设备或 x86 模拟器上,并通过“adb logcat”和 Android SDK/NDK 工具中提供的“ndk-gdb”命令来测试应用。 这些设备可在真正的 x86 设备或 x86 模拟器上测试,并可通过 “adb logcat”(由 Android SDK/NDK 工具提供)进行调试。

使用“adb logcat”获取简单信息或与系统相关的信息。

如欲了解详细信息,需要使用“ndk-gdb”。

我们仅介绍了如何通过命令行执行这些步骤,对于想要使用 Eclipse 的开发人员,请参阅 [7 和 8]。

参考:

[1] Android 开发人员网站。 http://developer.android.com/index.html

[2] 示例 NDK 应用。 http://developer.android.com/sdk/ndk/overview.html#samples=

[3] 英特尔硬件加速执行管理器安装指南。 http= ://redfort-software.intel.com/en-us/articles/installation-instructions-fo= r-intel-hardware-accelerated-execution-manager-windows/

[4] Wiki 上有关 CPUID opcode 的信息。 http://en.wikipedia.org/wiki/CPUID

[5] 面向英特尔架构的基于 NDK 的 Android 应用。 http://redfort-software.intel.com/en= -us/articles/creating-and-porting-ndk-based-android-apps-for-ia/

[6] 借助 ndk-debug 使用 cgdb。 http://mhandroid.wordpress.com/2011/01/23/using-cgdb-with-= ndk-debug-and-cgdb-tutorial/

[7] 使用用于 Android C/C++ 调试的 Eclipse。 http://mhandroid.wordpress.com/2011/01/23/using-eclipse-fo= r-android-cc-debugging/

[8] 使用用于 Android C/C++ 开发的 Eclipse。 http://mhandroid.wordpress.com/2011/01/23/using-eclipse-fo= r-android-cc-development/

[9] 面向英特尔架构的 Android NDK。 htt= p://redfort-software.intel.com/en-us/articles/ndk-for-ia/

[10] 英特尔® 64 和 IA-32 架构开发人员手册: Vol.2A. http://ww= w.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-archit= ectures-software-developer-vol-2a-manual.html

[11] NDK-GDB 介绍。 http://source-android.frandroid.com/ndk/docs/NDK-GDB.html

声明

本文件中包含关于英特尔产品的信息。 本文件不构成对任何知识产权的授权,包括明示的、暗示的,也无论是基于禁止反言的原则或其他。 英特尔不承担任何其他责任。英特尔在此作出免责声明:本文件不构成英特尔关于其产品的使用和/或销售的任何明示或暗示的保证,包括不就其产品的(i)对某一特定用途的适用性、(ii)适销性以及(iii)对任何专利、版权或其他知识产权的侵害的承担任何责任或作出任何担保。

除非经过英特尔的书面同意认可,英特尔的产品无意被设计用于或被用于以下应用:即在这样的应用中可因英特尔产品的故障而导致人身伤亡。

英特尔有权随时更改产品的规格和描述而毋需发出通知。 设计者不应信赖任何英特产品所不具有的特性,设计者亦不应信赖任何标有“保留权利”或“未定义”的说明或特性描述。 对此,英特尔保留将来对其进行定义的权利,同时,英特尔不应为因其日后更改该等说明或特性描述而产生的冲突和不相容承担任何责任。 此处的信息可能随时更改,恕不另行通知。 请勿使用本文信息完成一项产品设计。

本文件所描述的产品可能包含使其与宣称的规格不符的设计缺陷或失误。 这些缺陷或失误已收录于勘误表中,可索取获得。

在发出订单之前,请联系当地的英特尔营业部或分销商以获取最新的产品规格。

索取本文件中或英特尔的其他材料中提的、包含订单号的文件的复印件,可拨打1-800-548-4725,或登陆 http://www.intel.com/design/literature.htm

在性能检测过程中涉及的软件及其性能只有在英特尔微处理器的架构下方能得到优化。 诸如 SYSmark 和 MobileMark 等测试均系基于特定计算机系统、硬件、软件、操作系统及功能。 上述任何要素的变动都有可能导致测试结果的变化。 请参考其他信息及性能测试(包括结合其他产品使用时的运行性能)以对目标产品进行全面评估。

对本文件中包含的软件源代码的提供均依据相关软件许可而做出,任何对该等源代码的使用和复制均应按照相关软件许可的条款执行。

英特尔、Atom、凌动和 Intel 标识是英特尔在美国和/或其他国家的商标。

英特尔公司 © 2013 年版权所有。 保留所有权利。
*其他的名称和品牌可能是其他所有者的资产。

英特尔® 硬件加速执行管理器

$
0
0

最新更新:2013 年 11 月 5 日

英特尔® 硬件加速执行管理器是一个硬件辅助的虚拟化引擎(hypervisor,虚拟机监视器),它使用英特尔® 虚拟化技术加速安卓应用在主机上的模拟。英特尔® 硬件加速执行管理器与英特尔提供的安卓 x86 模拟器映像及官方Android SDK Manager(安卓软件开发套件)相结合,可在启用英特尔虚拟机的系统上更快地模拟安卓系统。

英特尔硬件加速执行管理器支持以下平台:

Microsoft Windows*
Windows 8(32/64 位)、Windows 7(32/64 位)、Windows Vista*(32/64 位)、Windows XP(仅限 32 位)

安装指南和系统要求 - Windows

haxm-windows_r04.zip (1.0.8)
描述:
系统驱动程序
(2014 年 4 月 15 日)
大小: 1.93MB
校验和:
(MD5)
dbec9d4145a2a7acdf19cb10eb7a9539
(SHA-1)
cc72b38962fc53823f969d4fb9155f9efa3558b8

Mac OS* X
搭载 Mac OS X 10.6 及更高版本的基于英特尔的 Macs(32/64 位)

安装指南和系统要求 - Mac OS X

haxm-macosx_r04.zip (1.0.8)
描述:
系统驱动程序
(2014 年 4 月 15 日)
Size: 245KB
校验和:
(MD5)
a34986b66a55a4bebbc939927339b54a
(SHA-1)
e3d68c7d59f0f8b289cdc38e203d0952917bf2cb

Linux
Ubuntu(64 位)

安装指南和系统要求 - Linux

面向 Android* 开发人员的英特尔学习系列计划 #11:基于英特尔® 凌动™ 处理器的 Android* 的 OpenGL ES* 支持、性能和特性

$
0
0

1. 简介

适用于基于 Android 的 3D 图形的标准 API 是 OpenGL ES,它是当前所有移动设备上使用最广泛的 3D 图形 API。 Android 使用 OpenGL ES 来加速 2D 和 3D 图形。在早期的 Android 版本中,OpenGL ES 加速在某种程度上并不是必要选项,但是,随着 Android 不断演进以及屏幕尺寸不断增大,加速的 OpenGL ES 成为 Android 图形系统的基本组成部分。

OpenGL ES 的三个版本分别为 1.0 、1.1 和 2.0,其中前两者支持 Android 的所有版本;而 2.0 从 Android 2.2 开始提供支持。今天,Android 开发人员可以选择任意一个版本。表 1 总结了迄今为止所有的主要 Android 版本,以及哪些版本中内置了针对英特尔® 凌动™ 处理器的系统映像。

版本名称API支持英特尔® 凌动™ 支持
Android 1.5Cupcake3OpenGL ES 1.0 
Android 1.5Cupcake3OpenGL ES 1.0 
Android 1.6Donut4OpenGL ES 1.0, 1.1 
Android 2.0Eclair5OpenGL ES 1.0, 1.1 
Android 2.1Eclair7OpenGL ES 1.0, 1.1 
Android 2.2Froyo8OpenGL ES 1.0、1.1、2.0 
Android 2.3.3Gingerbread10OpenGL ES 1.0、1.1、2.0
Android 3.0Honeycomb11OpenGL ES 1.0、1.1、2.0 
Android 3.1Honeycomb12OpenGL ES 1.0、1.1、2.0 
Android 3.2Honeycomb13OpenGL ES 1.0、1.1、2.0 
Android 4.0Ice Cream Sandwich14OpenGL ES 1.0、1.1、2.0 
Android 4.0.3Ice Cream Sandwich15OpenGL ES 1.0、1.1、2.0
Android 4.1Jelly Bean16OpenGL ES 1.0、1.1、2.0

表 1: 采用集成 OpenGL ES* 以及英特尔® 凌动™ 处理器系统映像的 Android* 版本概述

自 Android 2.3.3 起,Android 可在英特尔凌动平台上使用,包括 OpenGL ES 1.0、1.1 和 2.0。基于英特尔凌动处理器的 OpenGL ES 支持全面的功能,并且优于其他大部分的 Android 解决方案,因为它具备独特的特性组合:

  • PowerVR SGX540 与 SGX544MP2 GPU (频率为 400 MHz 或更高)
  • 更快的浮点
  • 面向 Android 虚拟设备模拟的 x86 系统映像
  • 英特尔® 硬件加速执行管理器(英特尔 HAXM)
  • 英特尔® 图形性能分析器(英特尔 GPA)

英特尔与谷歌联手将继续为 Android 平台提供出色的支持,包括持续不断地为将来的 Android 版本提供 x86 系统映像、英特尔 HAXM 和英特尔 GPA 支持。

2. 面向 Android 虚拟设备模拟的 x86 系统映像

每个嵌入式开发人员都知道虚拟设备模拟器如何加速新应用软件的开发。但是,使用面向 ARM 系统映像的 Android 虚拟设备(AVD)将会非常缓慢,因为 AVD 必须模拟 Windows* 或 Linux* 开发系统上的每一个 ARM 指令。仅在典型的 ARM AVD 上启动 Android 便有可能需要花费 5 分钟或更长的时间。英特尔借助英特尔硬件加速执行管理器(英特尔 HAXM)解决了这一问题。将该工具安装到英特尔 x86 凌动系统映像 AVD 上并配合其使用时,应用开发速度将会得到极大的提升,您甚至不需要英特尔凌动硬件来启动。

请注意,谷歌的 AVD 模拟目前仅支持 OpenGL ES 1.0 和 1.1 开发,而不支持 2.0。这是谷歌模拟软件的局限所在 — 无论 CPU 或 GPU 的架构如何。

3. 英特尔® 图形性能分析器

对于开发基于英特尔凌动处理器的 Android 上的 OpenGL ES 应用的开发人员而言,另一个可使用的重要工具是英特尔图形性能分析器(英特尔 GPA)。该工具套件支持用户实时查看数十个关键系统指标,包括 CPU、GPU 和 OpenGL ES。英特尔 GPA 可在 Windows 或 Ubuntu Linux 开发系统上运行,并可通过 Android 调试接口(adb)与目标 Android 设备上的驱动程序组件进行通信 通过做一些实验,开发人员能够快速从视觉上看到图形管线中的瓶颈,并找到优化代码的最佳机遇。

更多信息以及下载面向 Android 开发的最新版英特尔 GPA(2012 R4),请参见: http://software.intel.com/en-us/vcsource/tools/intel-gpa?cid=sem121p7972

4. 从何处获取 OpenGL ES 驱动程序

获取面向 Android 的英特尔凌动处理器的 OpenGL ES 驱动程序非常简单。当你下载支持英特尔凌动处理器的 Android SDK 时,它们已经集成至 x86 系统映像。英特尔与谷歌开发人员合作,让在 x86 设备上开发 Android 应用与在 ARM 设备上一样轻松 — 即使您的应用大量使用了 OpenGL ES。

Android 2.3.3 (Gingerbread)、4.0.3 (Ice Cream Sandwich)和 4.1 版(Jelly Bean) 可为英特尔凌动处理器的内建提供全面的支持,包括 OpenGL ES 1.1 和 2.0 驱动程序。仅需从 Android SDK 管理器中选择上述版本中的一个。确保您选择的版本在已包括在“英特尔 x86 凌动系统映像”列表中。此外,还需确保下载并安装英特尔硬件加速执行管理器(英特尔 HAXM),它位于 “Extras” 下的 SDK 管理器中。如果您尚未安装 Android SDK 管理器,可从下列网站进行下载: http://developer.android.com/sdk/index.html

或者,您也可以直接从英特尔网站上下载英特尔 x86 系统映像: https://software.intel.com/zh-cn/articles/android-404-ice-cream-sandwich-x86-emulator-system-image

5. PowerVR* GPU

英特尔凌动处理器采用 PowerVR 图形加速器,它是当前移动设备上使用最普遍的 OpenGL ES 加速器。PowerVR 构建在通用可扩展渲染引擎(USSE)架构上,是一种业经验证的成熟设计。然而,并非所有 PowerVR 内核的构建方式都一样。SGX540 系列的 USSE 数量是 SGX530 内核的两倍,SGX544MP2 内核是其四倍,因此性能也分别将是两倍或四倍(如果时钟速率相同)。但是,英特尔凌动处理器比其他实施采用的时钟速率更高,因此能够为 OpenGL ES 提供更高的性能,最终可提供更为流畅的用户体验。表 2 总结了基于英特尔凌动处理器的 PowerVR 核心家族。

英特尔® 凌动™ 系列GPU 核心GPU 时钟
英特尔® 凌动™ Z24XXPowerVR SGX 540400 MHz
英特尔® 凌动™ Z2580PowerVR SGX 544MP2TBA

表 2: 面向 Android* 的英特尔® 凌动™ 处理器中的 OpenGL ES* 加速器

实际上,PowerVR 中的 USSE 架构能够满足 OpenGL 2.1 和 DirectX* 10.1 的统一着色器模型要求,但是只有 OpenGL ES 1.1 和 OpenGL ES 2.0 及其扩展曝露的特性 Android 开发人员才可使用。

6. OpenGL ES 扩展

根据定义 OpenGL ES 1.1 和 2.0 的 Khronos 标准文档,在不同的平台上所使用的 OpenGL ES 功能集应相同。这就是创建标准化 API 的目的。但是,GPU 开发人员可通过扩展的形式将其 GPU 的特殊特性传输至 OpenGL ES。Khronos 维护 OpenGL ES 扩展的官方在线注册表,所有扩展信息均记录在: http://www.khronos.org/registry/gles

最重要的 OpenGL ES 扩展可在大部分的 Android 平台上使用,如压缩纹理和直接纹理传输支持,但是 OpenGL ES 目前在使用的压缩纹理有许多不同的格式。英特尔凌动处理器中的 PowerVR 核心可为各种压缩纹理格式提供支持。

压缩纹理是一项面向 3D 应用的重要技术,有助于降低内存要求和提高性能,但是正在使用的各种平台仅通过扩展定义,因此在每个平台上都各有差别。使用最广泛的是 Ericsson Texture Compression (ETC1_RGB8),但是它仅支持每像素 8 位的精度,而且不支持每像素 alpha。 除了 ETC1_RGB8 之外,PowerVR GPU 还支持 PVRTC 格式,相比 ETC1_RGB8,PVRTC 有一些重要的优势。PVRTC 格式支持每像素 2 位或 4 位精度的压缩纹理,并带有可选的每像素 alpha 信息。这些功能可通过 ETC1_RGB8 格式显著降低纹理尺寸,并可更灵活地创建 alpha 值混合效果。

此外,PowerVR 核心和 PVRTC 也用于各代的 Apple iPhone*、iPod* Touch 和 iPad* 设备,因此,它还在基本 OpenGL ES 标准之外,提供了英特尔凌动处理器 Android 的兼容性,这在开发跨 Android 和 iOS 平台的应用时非常重要。更多信息,请参见“纹理压缩支持”:

http://developer.android.com/guide/topics/graphics/opengl.html

其他的重要 OpenGL ES 扩展可支持在 OpenGL ES 和其他 Android 系统的组件之间快速传输纹理映像,如从 OpenMAX* 传输的视频帧。面向 OpenGL ES 的英特尔凌动处理器驱动程序也支持这些重要的扩展。

Android 应用不应假定任何特定 OpenGL ES 适用于任何特定设备。运行良好的应用应向 OpenGL ES 查询运行时可用扩展的列表。扩展列表可使用下列调用从 OpenGL ES 和 EGL 驱动程序获取:

	glGetString(GL_EXTENSIONS);
	eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
Google play 网站上有一款适用的应用,可运行该查询并显示任何一台运行该应用的 Android 设备的返回列表:https://play.google.com/store/apps/details?id=com.realtechvr.glview

可在 Android 上使用的 OpenGL ES 扩展有很大的差别,原因在于 GPU 内核,而非 CPU 架构的差别。英特尔凌动处理器提供的 OpenGL ES 与其他采用 PowerVR GPU 的 Android 平台基本相同,虽然英特尔凌动处理器采用 x86 CPU 架构。事实上,相比其他大部分的 GPU,英特尔凌动处理器上的 PowerVR 核心可提供更多专用的 OpenGL ES 扩展,而且其中一些扩展非常有帮助。当然,使用这些专用的扩展将会限制您的应用向采用 PowerVR 核心的 Android 设备移植。名称以“IMG”结尾的扩展可能是 PowerVR 专用的,但这也不是绝对的。您最好使用诸如 GLView 的工具对一些 Android 设备亲自进行测试,以了解您所需的扩展是否存在。

以下是 PowerVR 专用的 OpenGL ES 扩展的示例

		glFramebufferTexture2DMultisampleIMG()
		glRenderbufferStorageMultisampleIMG()
		glMultiDrawArraysEXT()
		glMultiDrawElementsEXT()
7. 浮点性能

CPU 和 GPU 核心为 OpenGL ES 应用能否提供快速浮点性能对于是否能够运行良好至关重要。着色器程序大量使用浮点,这是在 GPU 上执行;一般而言,OpenGL ES 应用代码也需要大量的浮点计算,而这必须在 CPU 上执行并能够调用至 OpenGL ES。这是英特尔凌动处理器明显优于基于 ARM 的解决方案的另一方面,因为英特尔凌动处理器在 CPU 和 GPU 核心上都能够快速执行浮点计算。

不具备浮点硬件的系统将为 OpenGL ES 1.1 使用定点计算,而非不同的驱动程序,这种系统称 “Common-Lite”。但是,英特尔为 Android 提供的系统映像仅包括适用于 OpenGL ES 1.1 的 “Common”(浮点)驱动程序,因为所有的英特尔凌动处理器的 CPU 和 GPU 核心中都内建了硬件浮点,因此,便无需使用任何定点。适用于 OpenGL ES 2.0 的 Khronos 标准仅可管理浮点。

8. Android 框架 SDK

Android SDK 采用 GLSurfaceView 类,可为您提供最轻松的方式在 Android 应用中使用 OpenGL ES。该类可以处理大部分的 EGL 初始化、线程,并能够分配供 OpenGL ES 渲染以及 Android 显示的接口。此外,OpenGL ES 还可渲染至具备其他功能(如转换和 alpha 值混合)的 TextureView 对象,但是需要设置和使用更多代码。Android SDK 还可通过以下谷歌和 Khronos 提供的软件包中的 Java* 绑定为 OpenGL ES 提供支持:

  • jvax.microedition.khronos.egl: The Khronos standard implementation
  • javax.microedition.khronos.opengles: The Khronos standard implementation
  • android.opengl: Updated to provide better performance

以下三个版本的 OpenGL ES API 可在今天的 Android 上使用:1.0、1.1 和 2.0。OpenGL ES 1.0 已替换为 1.1。 OpenGL ES 2.0 通过着色器编程可提供更大的灵活性,但是无法与面向 OpenGL ES 1.1 编写的传统代码兼容。表 3 总结了可用于应用开发的 OpenGL ES API 版本以及面向 Android 为其进行定义的类。

OpenGL ES API 版本
OpenGL ES 1.0android.opengl.GLES10
OpenGL ES 1.0android.opengl.GLES10Ext
OpenGL ES 1.1android.opengl.GLES11
OpenGL ES 1.0android.opengl.GLES11Ext
OpenGL ES 2.0android.opengl.GLES20

表 3: Android 中的 OpenGL ES 支持类

面向 Android 的英特尔凌动处理器平台为通过 SDK 或 NDK 使用任何版本的 OpenGL ES 的应用提供全面的支持。

9. Android SDK

原生开发套件(NDK)由谷歌开发,旨在通过绕过 Dalvik VM 并在本地运行 C/C++ 代码来帮助开发人员在其 Android 应用中达到更高的性能。谷歌决定将 NDK 向所有 Android 开发人员开放,因为它能够简化在 C/C++ 中编写的应用的移植流程,并支持在性能需求最高处(如 3D 游戏)提供最佳的性能。

Android NDK 可支持 OpenGL ES 1.1 和 2.0,并可为其提供一些示例应用。大部分使用 OpenGL ES 的应用使用 C/C++ 进行编写,NDK 可提供一种能够将 C/C++ 代码与 Android 框架结合起来的机制,该机制基于 Java 。这称为 Java 原生接口(JNI),它现在正成为在 Android 上实施需要快速图形的应用的主要方法。自 r6b 版本起,NDK 开始支持面向英特尔凌动处理器的 JNI,您可通过以下网站下载: http://developer.android.com/sdk/ndk/index.html

10. Renderscript

Renderscript 首次推出是在 Android 3.0 中。这是谷歌开发的又一项技术,旨在通过绕过 Dalvik VM 帮助加速计算密集型算法,包括图形。但是,与 NDK 不同,Renderscript 代码是在 Android 设备上运行时编译的。Renderscript 旨在开发多个处理器,但是目前它仅支持在 CPU 上使用的处理内核,而不支持 GPU 上的。谷歌准备在未来版本中对 Renderscript 进行改进以利用 GPU 内核,当实现时,现有的 Renderscript 需要能够开发该新能力;希望不会出现修改。

Renderscript 可提取运行它的硬件,这样,应用开发人员则无需考虑 CPU 架构或实际可用的处理器数量。但是,Renderscript 无法使用现有的并行计算标准来完成它,如 GLSL 或 OpenCL*。它是通过一种新语言来完成的,该语言基于 C99 并包括内置 OpenGL ES 支持。Renderscript 的提取功能可确保它可在任意 Android 设备上使用,包括英特尔凌动处理器。关于 Renderscript 的更多信息,请参见: http://android-developers.blogspot.com/2011/02/introducing-renderscript.html

11. 结论

英特尔凌动处理器的 x86 架构在开发面向 Android 的 OpenGL ES 应用时并无任何困难,因为该处理器可提供基于 ARM 的解决方案能够提供的所有功能,甚至更多。在确保 OpenGL ES 在不同 Android 平台上的兼容性时,GPU 架构更重要;英特尔凌动处理器的 PowerVR 内核是当下使用最广泛的 GPU。英特尔凌动处理器结合了采用快速浮点的一流 PowerVR 核心以及可提供快速 AVD 模拟和图形管线性能分析的卓越支持软件,可为面向 Android 的 OpenGL ES 应用提供最佳的整体解决方案。

12. 关于作者

Clay D. Montgomery 是嵌入式系统 OpenGL 驱动程序和应用领域首屈一指的开发人员。他曾在 STB Systems、VLSI Technology、Philips Semiconductors、Nokia、Texas Instruments、AMX 等公司担任过图形加速器硬件、图形驱动程序、API 和跨多平台 OpenGL 应用的设计师,也曾担任过独立咨询师。他曾参与开发第一代面向 Freescale i.MX 和 TI OMAP 平台的 OpenGL ES、OpenVG 和 SVG 驱动程序和应用,以及 Vivante、AMD 和 PowerVR 核心。他曾在嵌入式 Linux 上开发过 OpenGL * ES 并开办过关于该内容的研讨会,并曾代理过 Khronos Group 的多家公司。

OpenGL ES、OpenMAX 和 OpenVG 是 Khronos Group 的商标。

OpenCL 和 OpenCL 标识是苹果公司的商标,需获得 Khronos 的许可方能使用。

DirectX 是微软公司的商标。

版权所有, 2012 年 12 月 25 日,英特尔公司。


调试 Android* x86 应用程序的方法以及要使用的工具

$
0
0

1.简介

众所周知,Android* 开发人员头顶许多称呼:设计员、程序猿等,并且通常会不可避免地被称为故障检修工。代码中的错误无法避免,因此无论您是否一开始就造成错误,了解调试工具以及如何迅速而有效地跟踪并解决错误都很重要。鉴于此,如今的 Android 开发人员必须掌握有效的调试技巧。本文提供了 Android 应用程序调试工具的简单教学,用于帮助 Android SDK以及相关工具的新手迅速入门,并在 Android x86 平台上更有效地解决故障。

2.SDK 应用程序调试工具

Android SDK 提供了试应用程序所需的大多数工具。如果希望进行诸如单步调试代码、查看变量值以及暂停执行应用程序的操作,则需要兼容 JDWP 的调试程序。如果使用 Eclipse,则已附带兼容 JDWP 的调试程序,无需设置。如果使用其它 IDE,则可使用其附带的调试程序并将调试程序与特殊端口连接,使其可以和您设备上的应用程序虚拟机通信。

如果使用 ADT(Android 开发工具)插件在 Eclipse 中进行开发,则可使用内置的 Java* 调试程序并结合 DDMS(Dalvik 调试监测程序服务器)来调试应用程序。为了便于访问调试程序和 DDMS,Eclipse 以视图形式显示调试程序和 DDMS 功能,这些都是自定义的 Eclipse 视图,根据您所在的视图显示特定选项卡和窗口。Eclipse 还可负责为您启动ADB (Android Debug Bridge) 主机守护程序,从而无需手动运行该工具。如果使用其他 IDE 进行调试,则可使用 Android SDK 提供的所有调试工具,例如 ADB、DDMS、Java 调试程序等。

图 1. Dalvik 调试监测程序服务器

借助 DDMS,开发人员可查看进程的堆区使用情况、跟踪对象的内存分配、使用模拟器或设备的文件系统、检查线程信息、获取方法配置、使用网络流量工具(在 Android 4.0 中提供)、使用 LogCat 跟踪代码信息以及模拟手机操作和位置。如欲了解更多信息,请参阅 http://developer.android.com/guide/developing/debugging/ddms.html。Android SDK 还提供 Hierarchy Viewer(层级观察器)和 layoutopt(布局优化分析工具)帮助开发人员调试布局问题。

Hierarchy Viewer应用程序可让您调试并优化您的用户界面 (UI)。它以可视方式呈现布局的视图层级(View Hierarchy 口),提供放大的显示视图(Pixel Perfect 窗口)。

图 2. Hierarchy Viewer(层级查看器)

View Hierarchy窗口显示形成您设备上或模拟器上运行的活动的 UI 的视图对象。您可以用它在整个视图树的上下文中查看各个视图对象。对于每个视图对象,View Hierarchy 窗口还显示渲染性能数据。在选择节点时,视图的额外信息出现在节点上方的小窗口中。 在单击其中一个节点时,可看到有关图像、视图计数和渲染时间的信息。

图 3. 查看对象信息窗口

Pixel Perfect是一个工具,用于检查像素属性并通过设计图排布用户界面。Pixel Perfect 窗口显示模拟器或设备上可见的屏幕的放大图像。在该窗口中,可检查屏幕图像中各个像素的属性。也可使用 Pixel Perfect 窗口根据位图设计帮助排布应用程序的用户界面。

图 4. Pixel Perfect 窗口

layoutopt工具可让您分析 XML 文件,该文件定义应用程序的用户界面以查找视图层级中的不当之处。要运行工具,可打开终端并从 SDK 工具/目录启动 layoutopt <xmlfiles>。<xmlfiles> 变量是以空格分隔的要分析的资源的列表,可以是未编译的资源 xml 文件或这些文件的目录。工具会加载指定的 XML 文件并根据一组预定义的规则分析它们的定义和层级。 下面是来自工具的输出示例:

$ layoutopt samples/ samples/compound.xml 7:23 The root-level <FrameLayout/> can be replaced with <merge/> 11:21 This LinearLayout layout or its FrameLayout parent is useless samples/simple.xml 7:7 The root-level <FrameLayout/> can be replaced with <merge/> samples/too_deep.xml -1:-1 This layout has too many nested layouts: 13 levels, it should have <= 10! 20:81 This LinearLayout layout or its LinearLayout parent is useless 24:79 This LinearLayout layout or its LinearLayout parent is useless 28:77 This LinearLayout layout or its LinearLayout parent is useless 32:75 This LinearLayout layout or its LinearLayout parent is useless 36:73 This LinearLayout layout or its LinearLayout parent is useless 40:71 This LinearLayout layout or its LinearLayout parent is useless 44:69 This LinearLayout layout or its LinearLayout parent is useless 48:67 This LinearLayout layout or its LinearLayout parent is useless 52:65 This LinearLayout layout or its LinearLayout parent is useless 56:63 This LinearLayout layout or its LinearLayout parent is useless samples/too_many.xml 7:413 The root-level <FrameLayout/> can be replaced with <merge/> -1:-1 This layout has too many views: 81 views, it should have <= 80! samples/useless.xml 7:19 The root-level <FrameLayout/> can be replaced with <merge/> 11:17 This LinearLayout layout or its FrameLayout parent is useless

 

Traceview是执行日志的图形化查看器,这些日志在您使用调试类记录代码中的跟踪信息时创建。Traceview 可帮助您调试应用程序并概述其性能。Traceview 可加载日志文件并在窗口中显示其数据,该窗口如图 5 和图 6 所示以两个面板将您的应用程序可视化:

 

图 5. 时间轴面板描述每个线程和方法何时开始和停止

图 6. Profile(概要)面板提供方法中花费的所有时间的摘要。

dmtracedump是一种工具,为您提供一种备选方式,用于从跟踪日志文件生成图形调用栈图。该工具使用 Graphviz Dot 实用程序创建图形化输出,因此您需要在运行 dmtracedump 之前安装 Graphviz。dmtracedump 工具以树图形式生成调用堆栈数据,每个调用表示为一个节点。它使用箭头显示调用流程(从父节点至子节点)。图 7 显示了 dmtracedump 输出的一个示例。

图 7. dmtracedump

3.NDK 应用程序调试工具

由于 Android NDK 基于 GCC 工具链,Android NDK 包含 GDB、GNU 调试程序,因而可让您启动、暂停、检查和修改程序。在 Android 设备上,GDB 配置为客户端/服务器模式,在嵌入式设备上这种配置更为常见。程序在设备上作为服务器和远程客户端运行。开发人员的工作站与其连接,并发送与本地应用程序相似的调试命令。GDB 本身是一个命令行实用程序,如果手动使用会显得较为繁琐。幸好 GDB 可由大多数 IDE 尤其是 CDT 处理。从而可直接使用 Eclipse 来添加断点并检查程序,但前提是先正确配置它!

通过单击文本编辑器的左端,Eclipse 确实可方便地用 Java 和 C/C++ 源文件插入断点。Java 断点借助 ADT 插件可以立即使用,该插件管理通过 Android Debug Bridge 进行的调试。但对 CDT 并非如此,CDT 并不能感知 Android。因此,插入断点将不会有作用,除非我们配置 CDT 以使用 NDK 的 GDB,GDB 本身需要绑定至原生应用程序以对其进行调试。 在 NDK 版本中改善了对调试程序的支持(例如,之前不能调试纯原生线程)。尽管 NDK 越来越适用,但 NDK R5(甚至包括 R7)还很不完善。但是,它仍然有用处! 现在让我们了解下如何调试原生应用程序。

首先通过以下步骤在我们的应用程序中启用调试模式:
1)有一步操作很重要,但也很容易被忽略,那就是在 Android 项目中激活调试标记。该操作在应用程序清单 AndroidManifest.xml 中完成。请勿忘记对原生代码使用适用的 SDK 版本:

<?xml version="1.0" encoding="utf-8"?> <manifest ...> <uses-sdk android:minSdkVersion="10"/> <application ... android:debuggable="true"> ...

 

2)在清单中启用调试标记会自动以原生代码激活调试模式。但是,APP_OPTIM 标记也控制着调试模式。如果已在 Android.mk 中手动设置它,则检查是否已设置其值以进行调试(并不发布)或直接删除它:

APP_OPTIM := debug

 

 

3)现在让我们配置将连接至设备的 GDB 客户端。重新编译项目并插入设备或启动模拟器。运行然后离开应用程序。确保加载应用程序并且其 PID 可用。可通过使用以下命令(在 Windows 中使用 Cygwin)监听进程来检查它:

$ adb shell ps |grep gl2jni

 

 

应该会返回一行:

app_75 13178 1378 201108 68672 ffffffff 80118883 S com.android.gl2jni

 

 

4)打开终端窗口并转到项目目录。运行 ndk-gdb 命令(位于 Android NDK 文件夹,例如 android-ndk-r8\):

$ ndk-gdb

 

 

该命令不会返回消息,但是会在 obj\local\x86 目录创建三个文件(对于 arm 设备目录为 obj\local\armeabi):

 

  • gdb.setup:这是为 GDB 客户端生成的配置文件。
  • app_process:该文件直接从您的设备检索。其为系统可执行文件,在系统启动时启动,并可形成分支,启动新的应用程序。GBD 需要该参考文件来查找其标记。在某些方面,其为您的应用程序的二进制输入点。
  • libc.so:该文件也可直接从您的设备检索。其为 GDB 使用的 Android 标准 C 库(通常称为 bionic),用于保持跟踪运行时期间创建的所有原生线程。

5)在您的项目目录中,复制 obj\local\x86\gdb.setup 并将其命名为 gdb2.setup。打开它并删除请求 GDB 客户端连接至运行于设备上的 GDB 服务器的以下行(将由 Eclipse 自身执行):
target remote :5039

6在 Eclipse 主菜单中,转至“Run(运行)| Debug Configurations(调试配置)...”,并在名为 GL2JNIActivityDefault 的 C/C++ 应用程序项目中创建新的调试配置。该配置将在您的计算机上启动 GDB 客户端并连接至设备上运行的 GDB 服务器。

7在 Main(主菜单)选项卡中,使用浏览按钮,将项目设置为自己的项目目录,将 C/C++ 应用程序设置为指向 obj\local\ x86\app_process(可以使用绝对或相对路径)。

图 8. 为 C/C++ 应用程序调试配置

8使用窗口底部的链接“Select other(选择其他)...”,将启动程序类型切换为“Standard Create Process Launcher(标准创建进程启动程序)”:

图 9. 选择首选启动程序

9转至调试程序文件并设置调试程序类型为 gdbserver,将 GDB 调试程序设置为 android-ndk-r8\toolchains\x86-4.4.3\prebuilt\windows\bin\i686-android-linux-gdb.exe 或针对 arm 平台设置为 android-ndk-r8\toolchains\arm-linux-androideabi-4.4.3\prebuilt\linux-x86\bin\arm-linux-androideabi-gdb,针对 arm 平台将 GDB 命令文件需求设置为指向位于 \obj\local\x86 或 obj\local\armeabi\ 中的 gdb2.setup 文件(使用绝对或相对路径均可)。

图 10. 调试程序设置面板

10转至 Connection(连接)选项卡并将类型设置为 TCP。主机名、IP 地址和端口号 (localhost d 5039) 都保留默认值。

图 11. 调试程序设置面板上的链接设置

11现在让我们配置 Eclipse 以在设备上运行 GDB 服务器。复制 android-ndk-r8\ndk-gdb 并用文本编辑器打开它。查找以下行:
$GDBCLIENT -x `native_path $GDBSETUP`

由于 GDB 客户端将由 Eclipse 本身运行,因此对其进行注释:

#$GDBCLIENT -x `native_path $GDBSETUP`

12在 Eclipse 主菜单中,转到“Run(运行)| External Tools(外部工具)| External Tools Configurations(外部工具
配置)...”,并创建新配置 GL2JNIActivity_GDB。
该配置将在设备上启动 GDB 服务器。

13在 Main(主菜单)选项卡上,将位置设置为指向 android-ndk-r8 中我们修改过的 ndk-gdb。 将工作目录设置为您的应用程序目录位置
也可设置 Arguments(变量)文本框:

  • Verbose:详细查看 Eclipse 控制台中发生了什么。
  • Force:自动终止之前所有会话。
  • start:让 GDB 服务器启动应用程序,而不是在应用程序启动之后连接至应用程序。该选项在您仅调试原生代码而非 Java 代码时有用。

图 12. 外部工具配置

14现在,和往常一样启动应用程序。

15一旦应用程序启动,就可直接通过控制台启动 ndk-gdb 或启动外部工具配置 GL2JNIActivity_GDB,该配置将启动设备上的 GDB 服务器。GDB 服务器接收远程 GDB 客户端发送的调试命令,并在本地调试您的应用程序。

16打开 jni\gl_code.cpp 并通过双击文本编辑器的左端在 setupGraphics 中设置断点(或右键单击并选择 Toggle breakpoint(切换断点))。

图 13. 断点设置

17最后启动 GL2JNIActivity 默认 C/C++ 应用程序配置启动 GDB 客户端。它会通过套接字连接将调试命令从 Eclipse CDT 中继至 GDB 服务器。从开发人员的观点来看,这与调试本地应用程序很相似。

也有一些专用工具用于调试图形性能,例如 Intel® GPA System Analyzer为英特尔® 图形性能分析器(英特尔® GPA)之一,新增加了对于英特尔架构 Android 设备的支持,并且专供应用程序和驱动程序工程师优化其 OpenGL* ES 工作量。

该部分提供的信息涉及如何配置英特尔 GPA 并通过 USB 连接将其用于您的 Android 设备。在连接至 Android 设备时,英特尔 GPA System Analyzer 提供 OpenGL ES API、CPU 和 GPU 性能标准,并通过提供多个图形管线状态重写以帮助分析 OpenGL ES 应用程序性能。

要在基于 Android x86 的设备上使用英特尔 GPA System Analyzer,需要从文档检查目标机器和固件/版本。

要开始收集标准,需要在客户端系统上安装英特尔 GPA System Analyzer 并将其连接至目标设备:

1在 Windows*/Linux* 客户端机器上安装英特尔 GPA 2012 R3。

2启动英特尔 GPA System Analyzer。

3确保 Android 设备通过 USB 电缆连接至客户端系统。

4在客户端系统检测目标设备时,最多等待 10 秒。发现的设备会出现在对话框窗口中。目标设备的列表会每隔 5 到 6 秒刷新一次。

5查找要连接的设备并单击“Connect(连接)”。英特尔 GPA System Analyzer 会将所需的组件复制到目标设备并生成已安装应用程序的列表。可通过单击“Stop(停止)”中断连接进程。

图 14. 选择互联设备

6从可用应用程序列表中选择所需的应用程序。“Application List(应用程序列表)”屏幕显示所有用户以及 Android 设备上安装的所有系统应用程序。

图 15. 应用列表

7将会启动应用程序并且您将在英特尔 GPA System Analyzer 窗口中看到其数据。

8要切换至不同应用程序,单击“Back(返回)”。请注意,将强制关闭正在运行的应用程序。

9要切换至不同目标,单击“Back(返回)”。
PowerVR 显卡架构由以下核心模块构成,这些模块可将提交的 3D 应用程序数据转换为渲染的图形:Tile Accelerator (TA)、Image Synthesis Processor (ISP) 以及 Texture & Shading Processor (TSP)。“GPU” 组中的英特尔 GPA 标准对应这些核心模块之一,“Metrics List(标准列表)”中标准的顺序取决于图形管线中核心模块的顺序。

图 16. Intel GPA System Analyzer 窗口

Perf是自 Linux 版本 2.6.30 起 Linux 中很有用的一个工具,可同时用于与硬件和软件相关的性能分析。尽管 Android 基于 Linux 构建,但和不包含其他 Linux 组件和库一样,它也不包含 perf。您必须将静态构建的 perf 推送至其中。如果您已有该工具,只需将其置于 /system/bin/ 下,就可有效发挥其作用。有关 perf 的简短说明、基本用法和教程,可访问 https://perf.wiki.kernel.org/index.php/Main_Page
借助 traceview,开发人员可获取 Java 代码的性能信息;借助 perf,开发人员可获取有关原生和系统级代码的性能信息,如图 17 中所示。

图 17. 性能统计数据

图 18. 函数调用栈

UxTune是一个工程工具,用于 Android 用户交互分析和优化。它是一种增强的 pyTimeChart 工具。
UxTune 设计特性包括:

  • 垂直相关:将跨层的系统事件映射至用户级别活动,例如事件、手势、帧等。
  • 水平相关:将不同系统实体间的运行时活动(例如一个线程触发垃圾回收)关联。
  • 基于 pyTimeChart 的可视化。

要使用 UxTune 分析响应能力,开发人员需要熟悉 Android 系统的某些重要进程(在 pyTimeChart 中显示为行),即:

  1. InputReader 行:该行以触摸坐标显示所有触摸事件。事件将发送至 InputDispatcher。
  2. InputDispatcher 行:InputDispatcher 将把连续的触摸事件打包,并将该包发送至应用程序的 uiThread。
  3. uiThread 行:该行显示从 InputDispatcher 收到的包的主要触摸事件。uiThread 将根据特定操作绘制(渲染)其表面。 “D” 表示绘制进程。
  4. Surface 行:uiThread 在绘制开始时锁定其表面,并在绘制完成后解锁表面。“S” 和 “E” 表示应用程序渲染的开始和结束。
  5. SurfaceFlinger 行:在完成应用程序渲染后,应用程序将通知 SurfaceFlinger 合成并更新屏幕。“S” 表示 SurfaceFlinger 开始处理应用程序请求,而 “E” 表示合成完成(帧缓冲区交换完成)。

图 19. UxTune 分析窗口

Meter-FPS是一个工具,用于测量系统的 FPS 值,它会截取显卡处理路径以获得每帧的记录,还包含其他标准,例如最大帧时间、帧时间变化、#长时帧和掉帧率。fps 监控器有两种模式。Real Time Pattern(实时模式)可实时显示所有正在运行的应用程序的 fps。Measure Pattern(测量模式)可在用户定义的启动和停止时间测量 fps 和其他参数。要使用该工具,必须取得设备最高权限。
设置环境:
setprop debug.graphic_log 1
stop zygote
start zygote

图 20 显示了配置界面,开发人员可在其中为调试目标配置工具。

20. Meter-FPS 配置

在 Real Time(实时)模式中单击监控器按钮。fps 工具将监控所有正在运行的应用程序,并在屏幕上的浮动窗口中更新 fps。

图 21. Meter-FPS 实时模式

在 Measure(测量)模式中单击监控器按钮。将显示一个浮动窗口,其中显示“Click to start(单击以开始)...”;单击浮动窗口开始监控。

图 22. Meter-FPS 实时模式 1

现在测量模式正在运行:

图 23. Meter-FPS 实时模式 1

单击浮动窗口停止监控;其将显示结果:

图 24. Meter-FPS 分析结果列表

单击上面列表中的每个项目以获取详细记录:

图 25. Meter-FPS 分析详细记录

参考:

http://developer.android.com/guide/developing/debugging/index.html
http://www.eclipse.org/sequoyah/documentation/native_debug.php
http://mhandroid.wordpress.com/2011/01/23/using-eclipse-for-android-cc-development/
http://mhandroid.wordpress.com/2011/01/23/using-eclipse-for-android-cc-debugging/
http://packages.python.org/pytimechart/userguide.html
https://perf.wiki.kernel.org/index.php/Main_Page

相关文章与资源:

关于作者

Xiaodong Wang 是英特尔软件及服务事业部的应用工程师。 他专注于采用 Android 操作系统的基于英特尔的平台的 ISV。 Xiaodong 提供技术支持的 PRC Plus 项目(Android 平板电脑 ISV 启用)成功启用了前 50 个 NDK 应用程序作为技术接口。最近 Xiaodong 参与了英特尔的数个创新项目,并在开发过程中扮演重要角色。尤其是其中一个项目被选为英特尔信息技术峰会的演示项目,而 Xiaodong 成功地提供了技术支持。 在加入英特尔之前,Xiaodong 在 MediaTek 进行有关框架和应用程序开发的工作。Xiaodong 是北京大学硕士,并在作为访问学者在新加坡南洋大学进行研究期间,在《IEEE 计算机汇刊》上发表了一篇技术论文。他感兴趣的领域为移动互联网技术(例如 LBS、NFC AR 等)以及创新设计。

 

声明

 

本文件中包含关于英特尔产品的信息。本文件不构成对任何知识产权的授权,包括明示的、暗示的,也无论是基于禁止反言的原则或其他。英特尔不承担任何其他责任。英特尔在此作出免责声明:本文件不构成英特尔关于其产品的使用和/或销售的任何明示或暗示的保证,包括不就其产品的(i)对某一特定用途的适用性、(ii)适销性以及(iii)对任何专利、版权或其他知识产权的侵害的承担任何责任或作出任何担保。

除非经过英特尔的书面同意认可,英特尔的产品无意被设计用于或被用于以下应用:即在这样的应用中可因英特尔产品的故障而导致人身伤亡。

英特尔有权随时更改产品的规格和描述,恕不另行通知。设计者不应信赖任何英特产品所不具有的特性,设计者亦不应信赖任何标有保留权利摂或未定义摂说明或特性描述。对此,英特尔保留将来对其进行定义的权利,同时,英特尔不应为因其日后更改该等说明或特性描述而产生的冲突和不相容承担任何责任。此处提供的信息可随时更改,恕不另行通知。请勿根据本文件提供的信息完成一项产品设计。

本文件所描述的产品可能包含使其与宣称的规格不符的设计缺陷或失误。这些缺陷或失误已收录于勘误表中,可索取获得。

在发出订单之前,请联系当地的英特尔营业部或分销商以获取最新的产品规格。

如欲获得本文涉及的带编号文档的副本或其他英特尔文献,可致电 1-800-548-4725,或访问: http://www.intel.com/design/literature.htm
性能测试中使用的软件和工作负载可能仅在英特尔® 微处理器上针对性能进行了优化。诸如SYSmark和MobileMark等测试均系基于特定计算机系统、硬件、软件、操作系统及功能。上述任何要素的变动都有可能导致测试结果的变化。请参考其他信息及性能测试(包括结合其他产品使用时的运行性能)以对目标产品进行全面评估。
对本文件中包含的软件源代码的提供均依据相关软件许可而做出,任何对该等源代码的使用和复制均应按照相关软件许可的条款执行。英特尔和 Intel 标识是英特尔在美国和/或其他国家的商标。
英特尔公司 © 2012 年版权所有。所有权保留。
* 其他的名称和品牌可能是其他所有者的资产。

基于 Android 的 3D 视频样本代码

$
0
0

下载样本代码

简介

Android中,创建一个能够播放视频剪辑的应用非常简单;创建一个采用 3D 图形平面的游戏应用也非常简单。但是,创建一个能够在 3D 图形对象上播放视频的应用却不容易。本文介绍了我为应对该挑战创建的应用。该应用可在 3D 平面上渲染视频,并支持用户以交互的方式在视频平面上播放。

该应用需要解决三大实施问题:

  1. 如何构建代码以支持用户在播放视频时变更 3D 平面?
  2. 虽然 Android 中默认的 MediaPlayer配备了全面的播放操作,但是难以获得视频图像数据并以定制的方式对其进行渲染。
  3. 如何设计图形组件以执行视频数据渲染?

此外,该应用还面临设备功能的挑战,因为它需要视频和图形对象同时运行。本文将对该款应用的特性和使用进行介绍,然后对其设计进行简要的介绍。

特性

该应用具备以下特性:

  1. 它支持用户从其本地媒体库中选择视频剪辑。
  2. 该应用支持横向和纵向两种方向;当方向转换时,视频能够持续播放。
  3. 它可提供三种播放模式:
    1. 默认模式:这是常规播放模式;视频剪辑如同在常规媒体播放器中一样播放。
    2. 随机旋转:视频的平面可随横向和纵向随机旋转;其颜色也可在红色色调和正常颜色之间切换。
    3. 触摸旋转:用户可以使用触摸功能向左、右滑动并旋转平面,具体取决于速度。
    4. 当将应用移动至后台或关闭时,可将当前的视频剪辑保存并在应用重新激活时进行播放。

:应用中没有视频会话控制;因此用户无法停止、快进或回放视频。如果将应用移动至后台或关闭,视频只能从头开始播放。

使用模式

开始播放视频剪辑

该应用未包含任何视频,因此用户可以选择 Android 平台支持的任意视频剪辑进行播放。但是,建议使用采用 H.264AVC 编解码器以 MPEG-4 标准处理的视频编辑,因为我们在开发时是采用这种格式。应用首次启动时,将会显示文件选择器界面(请见上一页的截图)。

用户选择首选的文件选择器后,系统将会提供屏幕指示。选择视频剪辑后,将开始播放。
:有时,视频开始前需要等待一段时间 — 约 5 ~ 10 秒。

选择不同的模式

应用开始播放时是使用常规模式。如要更改模式,用户可点击 UI 上的选项按钮,启动选项菜单。

选项菜单有四个选项:前三个是播放模式选项;最后一个选项可支持用户选择不同的视频剪辑。

 

随机旋转

该选择可支持渲染视频的平面随着横、纵轴呈 3D 效果随机旋转。此外,它还可定期在屏幕上呈现红色色调。

 

触摸旋转

在触摸旋转模式中,用户可以向左、右滑动,从而让平面沿着纵轴左、右旋转。当滑动更快时,旋转将会加快;当用户停止滑动时,旋转将会随之减速。

 

设计

该应用中的三个主要组件包括:为用户提供交互式应用演示的 UI 组件;进行视频播放的视频组件;渲染视频帧缓冲区并在特殊模式下创建 3D 效果的 OpenGL* 平面。

该视频播放组件有两个线程。视频引擎线程使用 MediaCodec类。该类在 Android JellyBean 版本(API 16)中推出。它可以提供低级别的 Android 媒体框架 API,因此您可以在帧层面控制播放。在每个视频帧上,图形组件可以控制图像数据,并更改渲染图像的方式。

此外,播放组件还可执行播放视频剪辑音轨的音频引擎线程。为使视频和音频线程同步,从而让人物的口型与其说出的声音相匹配,我们实施了 AV 同步算法。视频播放可使其时间戳与音频时间戳时刻保持一致。它可以对播放速度进行微调,以便将视频帧控制在 30 毫秒的时间范围内。

图形组件可添加一个 GLSurfaceView,从而在该类中嵌入一个定制的渲染类。渲染类可实施渲染器接口来执行 OpenGL 渲染算法。该算法可在纹理平面上实施 3D 旋转效果,还可根据用户的输入将模式更改为其他算法。

在渲染器中,对视频帧旋转和着色是通过一个简单的顶点和像素着色器来控制的。视频平面的旋转通过应用一系列的欧拉角旋转来实现。帧的着色通过将视频帧内容与固定颜色(在本案例中为红色)在像素着色器中进行线性混合来实现。

此外,图形组件还可用作视频引擎的视频帧监听器,并可在实施过程中传送至 MediaCodec 对象,这样每当有可用帧时便可调用渲染功能。图形组件可在 UI 组件中提供一个选项,这样用户便能够更改播放模式。

MediaCodec 编解码流程与视频帧保持同步,图形组件中的渲染器功能与图形帧保持同步。因此,当访问帧缓冲区时,两个组件中的功能必须保持同步。

相关链接与资源:

如要了解更多为 Android 开发人员提供的英特尔工具,请访问:面向 Android 的英特尔® 开发人员专区

作者简介

Mark Liu 是英特尔超便携设备事业部 (Intel Ultra-Mobile Group) 的软件工程师,负责开发基于 Android 设备的验证框架。此外,他还参与英特尔超便携设备事业部的多个其他 Android 项目,包括智能手机和平板电脑设备。他所做的大部分工作都与媒体播放、视频会议和软件栈性能调优相关。

加入英特尔软件和设备事业部基于英特尔® 凌动™ 处理器的设备软件支持团队后,他负责多项不同的任务,包括 Android 样本媒体应用的开发、Windows* 8 媒体框架的系统优化以及用于编写媒体应用的文档。

Chris Kirkpatrick 是英特尔软件与服务事业部的软件工程师,负责为视觉与交互式计算工程设计团队提供英特尔图形解决方案开发支持。他拥有俄勒冈州立大学计算机科学理学士学位。

借助 UiAutomator 实现自动 Android* 测试

$
0
0

我将为大家介绍一款出色的工具,它能够自动测试 Android* 应用的 UI。 这款工具称为 UiAutomator。 您可以从下链接获得最新的文档: http://developer.android.com/tools/help/uiautomator/index.htmlhttp://developer.android.com/tools/testing/testing_ui.html

UiAutomator 具备一些优势和缺点 。

优势:

  • 可用于使用不同分辨率的设备显示器上
  • 事件能够链接至 Android UI 控制。 例如,点击带有文本 “Ok” 的按钮,而无需点击坐标位置(x=450,y=550)。
  • 能够复制复杂的用户操作序列
  • 总是执行相同的动作序列,从而能够帮助我们在不同的设备上收集性能标准。
  • 能够不改变任何 Java* 代码而多次运行并在不同的设备上运行
  • 能够使用设备上的硬件按钮

缺点:

  • 无法配合 OpenGL* 和 HTML5 应用使用,因为这些应用没有 Android UI 组件。
  • 编写 JavaScript* 非常耗时

脚本部署

为了对如何使用 UiAutomator 进行介绍,我将展示一个简单的程序。 该程序是标准的 Android 信息应用,能够向任何一个手机号码发送短信。

以下简要介绍了我们实施的操作:

  1. 查找并运行应用程序
  2. 创建和发送短信

如您所见,这非常简单。

测试准备

为了分析 UI 界面,我们将使用 uiautomatorviewer。

uiautomatorviewer 展示了 Node Detail 中所有 UI 组件的截屏,因此您能够看到不同的属性。 从属性中,您可以找到目标元素。

定制开发环境

如果您使用的是 Eclipse*:

  1. 在 Eclipse 中创建一个新的 Java 项目。 我们将该项目称为: SendMessage
  2. Project Explorer中右击您的项目并点击Properties
  3. Properties中选择 Java Build Path,并添加所需的库:
  • 点击 Add Library > JUnit并在 JUnit3中选择添加 JUnit支持
  • 点击 Add External JARs ...
  • <android-sdk>/platforms/directory中选择最新版的 SDK。 同样在该目录下,选择下列文件: uiautomator.jarandroid.jar

如果您使用的是其他开发环境,请确保将 android.jaruiautomator.jar文件添加至项目设置中。

创建脚本

使用 Java 类在以前创建的文件中创建一个项目, 称其为:SendMessage。 该类继承了 UiAutomatorTestCase 类,使用 Ctrl + Shift + o 键(适用于 Eclipse),添加所需的库。

创建三个函数来测试该应用:

  1. 搜索并运行该应用
  2. 发送短信
  3. 退出应用的主功能表

创建一个可帮助我们运行上述所有特性的函数 — 一种主要函数:

public void test() {
	// Here will be called for all other functions
	}

查找并运行应用的函数

该函数非常简单。 按主页按钮,显示主窗口后,打开功能表并查找该应用的图标。 点击该图标启动应用。

private void findAndRunApp() throws UiObjectNotFoundException {
		// Go to main screen
		getUiDevice().pressHome();
		// Find menu button
		UiObject allAppsButton = new UiObject(new UiSelector()
		.description("Apps"));
		// Click on menu button and wait new window
		allAppsButton.clickAndWaitForNewWindow();
		// Find App tab
		UiObject appsTab = new UiObject(new UiSelector()
		.text("Apps"));
		// Click on app tab
		appsTab.click();
		// Find scroll object (menu scroll)
		UiScrollable appViews = new UiScrollable(new UiSelector()
		.scrollable(true));
		// Set the swiping mode to horizontal (the default is vertical)
		appViews.setAsHorizontalList();
		// Find Messaging application
		UiObject settingsApp = appViews.getChildByText(new UiSelector()
		.className("android.widget.TextView"), "Messaging");
		// Open Messaging application
		settingsApp.clickAndWaitForNewWindow();

		// Validate that the package name is the expected one
	    UiObject settingsValidation = new UiObject(new UiSelector()
	    .packageName("com.android.mms"));
	    assertTrue("Unable to detect Messaging",
	    		settingsValidation.exists());
	}
所有的类名、按钮上的文本等均来自 uiautomatorviewer。

发送短信

该函数可查找并按下编写新应用的按钮,输入接收文本信息的电话号码并按发送按钮。 电话号码和文本可通过函数参数发送:

private void sendMessage(String toNumber, String text) throws UiObjectNotFoundException {
		// Find and click New message button
		UiObject newMessageButton = new UiObject(new UiSelector()
		.className("android.widget.TextView").description("New message"));
		newMessageButton.clickAndWaitForNewWindow();

		// Find to box and enter the number into it
		UiObject toBox = new UiObject(new UiSelector()
		.className("android.widget.MultiAutoCompleteTextView").instance(0));
		toBox.setText(toNumber);
		// Find text box and enter the message into it
		UiObject textBox = new UiObject(new UiSelector()
		.className("android.widget.EditText").instance(0));
		textBox.setText(text);

		// Find send button and send message
		UiObject sendButton = new UiObject(new UiSelector()
		.className("android.widget.ImageButton").description("Send"));
		sendButton.click();
	}
显示电话号码和文本信息的字段没有任何特殊功能,因为这些字段的任何文本和描述都不可用。 因此,通过按照元素在界面层级中的排列位置在该实例中来使用元素,便可找到它们。

为了添加将参数传递至脚本的功能,我们可以指定想要发送该信息的位置的数量以及文本信息。 该函数测试()可初始化默认设置,如果系统通过命令行向任何参数发送信息,则可使用以下默认设置进行替换:

// Default parameters
		String toNumber = "123456";
		String text = "Test message";

		String toParam = getParams().getString("to");
		String textParam = getParams().getString("text");
if (toParam != null) {
// Remove spaces
			toNumber = toParam.trim();
		}
		if (textParam != null) {
			text = textParam.trim();
		}
因此,我们可以使用小密钥 -e、参数的第一个名称和第二个值通过脚本中的命令行来传递参数。 例如,我的应用可以发送数字来发送 " 777777 »:-e 至 777777

您可能会遇到一些问题。 例如,该应用不理解一些字符而失败。 包含某些字符的文本无法传达,因为无法理解而失败。 比如:空格键、&、<、>、(、) 、"、'以及一些 Unicode 字符。 当使用这些字符编写字符串(如空间线:blogspaceblog)时,我将更换这些字符。 因此,当脚本启动 UiAutomator 时,我们将使用能够处理我们的输入参数的脚本。 我们添加了函数测试(),通过该测试,我们可以检查是否有选项、解析参数,如果有,可将其更换为实际字符。 以下是一个示例代码,演示了我们之前插入的内容:

if (toParam != null) {
			toParam = toParam.replace("blogspaceblog", "");
			toParam = toParam.replace("blogamperblog", "&");
			toParam = toParam.replace("bloglessblog", "<");
			toParam = toParam.replace("blogmoreblog", ">");
			toParam = toParam.replace("blogopenbktblog", "(");
			toParam = toParam.replace("blogclosebktblog", ")");
			toParam = toParam.replace("blogonequoteblog", "'");
			toParam = toParam.replace("blogtwicequoteblog", "\"");
			toNumber = toParam.trim();
		}
		if (textParam != null) {
			textParam = textParam.replace("blogspaceblog", "");
			textParam = textParam.replace("blogamperblog", "&");
			textParam = textParam.replace("bloglessblog", "<");
			textParam = textParam.replace("blogmoreblog", ">");
			textParam = textParam.replace("blogopenbktblog", "(");
			textParam = textParam.replace("blogclosebktblog", ")");
			textParam = textParam.replace("blogonequoteblog", "'");
			textParam = textParam.replace("blogtwicequoteblog", "\"");
			text = textParam.trim();
		}

退出应用的主功能表

该函数是我们所实施的函数中最简单的一个。 仅需按下回环中的一个按钮,直至其显示该按钮,即可创建一条新信息。

private void exitToMainWindow() {
		// Find New message button
		UiObject newMessageButton = new UiObject(new UiSelector()
		.className("android.widget.TextView").description("New message"));

		// Press back button while new message button doesn't exist
		while(!newMessageButton.exists()) {
			getUiDevice().pressBack();
		}
	}

以下是我们的源代码:源代码

package blog.send.message;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;

public class SendMessage extends UiAutomatorTestCase {
	public void test() throws UiObjectNotFoundException {
		// Default parameters
		String toNumber = "123456";
		String text = "Test message";

		String toParam = getParams().getString("to");
		String textParam = getParams().getString("text");
		if (toParam != null) {
			toParam = toParam.replace("blogspaceblog", "");
			toParam = toParam.replace("blogamperblog", "&");
			toParam = toParam.replace("bloglessblog", "<");
			toParam = toParam.replace("blogmoreblog", ">");
			toParam = toParam.replace("blogopenbktblog", "(");
			toParam = toParam.replace("blogclosebktblog", ")");
			toParam = toParam.replace("blogonequoteblog", "'");
			toParam = toParam.replace("blogtwicequoteblog", "\"");
			toNumber = toParam.trim();
		}
		if (textParam != null) {
			textParam = textParam.replace("blogspaceblog", "");
			textParam = textParam.replace("blogamperblog", "&");
			textParam = textParam.replace("bloglessblog", "<");
			textParam = textParam.replace("blogmoreblog", ">");
			textParam = textParam.replace("blogopenbktblog", "(");
			textParam = textParam.replace("blogclosebktblog", ")");
			textParam = textParam.replace("blogonequoteblog", "'");
			textParam = textParam.replace("blogtwicequoteblog", "\"");
			text = textParam.trim();
		}
		findAndRunApp();
	    	sendMessage(toNumber, text);
	    	exitToMainWindow();
	}
	// Here will be called for all other functions
	private void findAndRunApp() throws UiObjectNotFoundException {
		// Go to main screen
		getUiDevice().pressHome();
		// Find menu button
		UiObject allAppsButton = new UiObject(new UiSelector()
		.description("Apps"));
		// Click on menu button and wait new window
		allAppsButton.clickAndWaitForNewWindow();
		// Find App tab
		UiObject appsTab = new UiObject(new UiSelector()
		.text("Apps"));
		// Click on app tab
		appsTab.click();
		// Find scroll object (menu scroll)
		UiScrollable appViews = new UiScrollable(new UiSelector()
		.scrollable(true));
		// Set the swiping mode to horizontal (the default is vertical)
		appViews.setAsHorizontalList();
		// Find Messaging application
		UiObject settingsApp = appViews.getChildByText(new UiSelector()
		.className("android.widget.TextView"), "Messaging");
		// Open Messaging application
		settingsApp.clickAndWaitForNewWindow();

		// Validate that the package name is the expected one
	    UiObject settingsValidation = new UiObject(new UiSelector()
	    .packageName("com.android.mms"));
	    assertTrue("Unable to detect Messaging",
	    		settingsValidation.exists());
	}

	private void sendMessage(String toNumber, String text) throws UiObjectNotFoundException {
		// Find and click New message button
		UiObject newMessageButton = new UiObject(new UiSelector()
		.className("android.widget.TextView").description("New message"));
		newMessageButton.clickAndWaitForNewWindow();

		// Find to box and enter the number into it
		UiObject toBox = new UiObject(new UiSelector()
		.className("android.widget.MultiAutoCompleteTextView").instance(0));
		toBox.setText(toNumber);
		// Find text box and enter the message into it
		UiObject textBox = new UiObject(new UiSelector()
		.className("android.widget.EditText").instance(0));
		textBox.setText(text);

		// Find send button and send message
		UiObject sendButton = new UiObject(new UiSelector()
		.className("android.widget.ImageButton").description("Send"));
		sendButton.click();
	}

	private void exitToMainWindow() {
		// Find New message button
		UiObject newMessageButton = new UiObject(new UiSelector()
		.className("android.widget.TextView").description("New message"));

		// Press back button while new message button doesn't exist
		while(!newMessageButton.exists()) {
			getUiDevice().pressBack();
			sleep(500);
		}
	}
}

如要生成测试组件的配置文件,请从命令行运行以下命令:编译并运行测试 UiAutomator

  1. <android-sdk>/tools/android create uitest-project -n <name> -t  <target-id> -p <path>
    ,其中 <name> 是为测试 UiAutomator 而创建的项目的名称(在我们的案例中: SendMessage);<target-id> 是所选的设备和 Android API Level(您可以获得已安装设备列表、组(<android-sdk>/工具/ android 列表目标);<path> 是包含该项目的目录的路径。
  2. 您必须导出环境变量 ANDROID_HOME:
    • Windows*:
      set ANDROID_HOME=<path_to_your_sdk>
    • UNIX*:
      export ANDROID_HOME=<path_to_your_sdk>
  3. 进入包含项目文件的目录 build.xml(在第 1 步中生成),并运行命令:
    ant build
  4. 使用 adb push 将 JAR 文件复制至该设备:
    adb push <path_to_output_jar> /data/local/tmp/
    在我们的案例中,该命令为:
    adb push <project_dir>/bin/SendMessage.jar /data/local/tmp/
  5. 运行该脚本:
    adb shell uiautomator runtest /data/local/tmp/SendMessage.jar –c blog.send.message.SendMessage

关于作者

Egor Churaev (egor.churaev@intel.com)— 软件实习生

相关文章与资源:

英特尔® 集成式本机开发人员体验(英特尔® INDE)– 常见问题解答

$
0
0

目录

  1. 什么是英特尔® INDE?
  2. 英特尔® INDE 的关键特性是什么?
  3. 如何获得一套工具?
  4. 安装和运行英特尔® INDE 的系统硬件和软件要求是什么?
  5. 如何接收英特尔® INDE 提供的工具的许可?
  6. 如何接收英特尔® INDE 及其提供的工具的更新?
  7. 英特尔® INDE 可提供哪些工具?
  8. 英特尔 INDE 内的工具支持开发哪些目标设备?
  9. 我希望英特尔® INDE 支持的一款工具。 如何与英特尔分享我的反馈?
  10. 使用英特尔® INDE 是否需要互联网连接?

什么是英特尔® INDE?
英特尔® INDE是面向当今开发人员的一款测试版跨平台办公套件,可为开发人员提供工具、支持、集成和更新,以便为在 ARM* 上运行且在基于英特尔® 架构的设备上运行时可获得最佳性能的 Android* 创建高性能的 C++/Java* 应用。 首版英特尔® INDE 主要提供工具以便为 Android* 目标开发链的每个步骤提供支持,并为 Microsoft Windows* 目标提供支持。 其他的支持将在今年陆续添加。

英特尔® INDE 的关键特性是什么?
英特尔® INDE 可为环境设置、代码创建、编辑、调试和分析提供工具、样本和数据库,从而帮助开发人员更快地开发。 开发人员借助集成至常见 IDE 中的工具可快速编码,而且通过自动更新至最新的工具和技术来满足未来的需求。 英特尔® INDE 可支持运行 Microsoft Windows* 7-8.1 的 64 位主机系统、运行 Android 4.3 & up.= 的基于 ARM* 和英特尔® 架构的目标设备以及基于英特尔® 架构的 Microsoft Windows* 7-8.1 设备。 英特尔® INDE 是早期开放的测试版,可以从以下链接免费获取:intel.com/software/INDE

本版本中支持的主要特性包括:

  • 快速开发: 集成工具的常见 IDE 集成包括:Eclipse* & vs-android*
  • 易于使用: 构建、编译、分析和调试 Android* 应用的 C++/Java 工具 & 样本。
  • 适应未来需求:自动更新至最新的工具 & 技术。

如何获得一套工具?
英特尔® INDE 可作为测试版从 www.intel.com/software/INDE免费下载。

安装和运行英特尔® INDE 的系统硬件和软件要求是什么?
英特尔® INDE 可在 64 位 Microsoft Windows 7-8.1 主机系统上运行。 您的系统必须在 BIOS 中启用 英特尔® 虚拟化技术¹才能够运行英特尔® 硬件加速执行管理器(英特尔® HAXM)。 英特尔® HAXM 是英特尔® INDE 环境设置组件中的可选安装。

系统要求

  • Microsoft Windows* 7 64 位或更新版本
  • 4GB RAM
  • 6GB 可用磁盘空间

如何接收英特尔® INDE 提供的工具的许可?
英特尔® INDE 将提示您查看并接收您在工具安装期间通过英特尔® INDE 下载的所有工具的许可。

如何接收英特尔® INDE 及其提供的工具的更新?
英特尔® INDE 将定期检查软件更新。 软件更新可用时,您将会通过英特尔® INDE 接收到一条通知,且它将提示您在系统上安装该更新。

英特尔® INDE 可提供哪些工具?
英特尔® INDE 可提供主流英特尔和第三方工具可选安装包括:

英特尔工具:

  • 面向 Android* 的英特尔® INDE Media 软件包
  • 英特尔® 线程构建模块
  • Compute Code Builder
  • 面向 Android 的英特尔® C++ 编译器
  • 系统分析器 — 英特尔® 图形性能分析器(英特尔® GPA)组件
  • 平台分析器 — 英特尔® GPA 组件
  • 帧分析器 — 英特尔® GPA 组件
  • 英特尔® 帧调试器测试版
  • Environment Setup — 包括英特尔® 硬件加速执行管理器(英特尔® HAXM)的可选安装

第三方工具:

  • Google Android* SDK — Environment Setup 的可选组件
  • Android* NDK — Environment Setup 的可选组件
  • Android* Design — Environment Setup 的可选组件
  • Apache Ant* — Environment Setup 的可选组件
  • 面向 Microsoft* Visual Studio* 的 vs-android 插件 — Environment Setup 的可选安装

英特尔 INDE 内的工具支持开发哪些目标设备?
所有的工具均可用于开发 Android 4.3 及更高版本的 Android* 目标,除分析器和帧调试器之外,这两者可用于 Android 4.4 设备及更高版本。 此外,分析器、compute code builder 和线程工具还支持基于英特尔架构的设备上运行的 Microsoft Windows* 7-8.1 客户端目标。

我希望英特尔® INDE 支持的一款工具。 如何与英特尔分享我的反馈?
您的反馈对我们非常重要。 请将您的反馈提交至 英特尔® INDE 论坛

使用英特尔® INDE 是否需要互联网连接?
安装英特尔® INDE 及其中的可用工具需要稳定的互联网连接。 从英特尔® INDE 下载工具后,使用它们不需要互联网连接。 但是,维护和检查更新和通知需要使用它。

相关文章与资源:


1英特尔® 虚拟化技术要求计算机系统搭载兼容的英特尔® 处理器、基本输入输出系统(BIOS)及虚拟机监控器(VMM)。 其运行、性能及其他表现取决于硬件及软件的配置。 相关应用软件可能无法与所有的操作系统兼容。 详情请咨询您的电脑制造商。 更多信息敬请登陆 http://www.intel.com/content/www/cn/zh/virtualization/virtualization-technology/hardware-assist-virtualization-technology.html

样本代码:随机数应用

$
0
0

下载 PDF 文档

下载样本代码

Christopher Bird,软件应用工程师

应用来源:
英特尔 SSG

简介

随机数生成器(RNG)是一种可为值无法预测的间隔生成一串数字的实用程序或设备。 RNG 是信息安全应用不可或缺的组件。 事实上,加密协议具备强大的功能,但是由于底层的密钥生成方式薄弱而受到广泛的攻击。 硬件辅助的 RNG 可修复该弱点,从而显著提高加密的功能。

本文概括介绍了随机数 API,并展示了如何使用不同的 API 在 Android* 操作系统上生成随机数。

我们建议您对这些特性进行尝试,并按照本文的内容编译代码。

代码及介绍

在 Android 中生成随机数有四种方式。

  • java.util.random
  • java.security.SecureRandom
  • /dev/urandom
  • OpenSSL* API

但是,如果您使用 RNG 生成加密密钥来保护数据,典型的随机类更容易遭到攻击,因此不应使用这种方式。 其他三种方式可提供强大的密钥。

java.util.random

使用 Java* 随机数 API 非常简单。 调用 Random.nextInt() 将返回一个 4 位的随机值(包括 2^32 个值)。 该 API 适用于不依赖真正的随机数的实例。

for (int i = 0; i < lastVal; i += 2) {
	dataRandomPoints[i] = (rand.nextInt() % widget_width);
	dataRandomPoints[i+1] = (rand.nextInt() % widget_height);

}

java.security.SecureRandom

SecureRandom 与 java.util.Random 类似,借助它,您可以生成一个 SecureRandom.nextInt() 调用来获取一个 4 位随机值。 虽然 SecureRandom 的加密功能很强大,但是开发人员应注意到最新的建议,即在生成随机数之前使用 /dev/urandom 的字节来生成 SecureRandom。 以下示例不是从 /dev/urandom 生成。

SecureRandom srand = new SecureRandom();
shouldDraw = (srand.nextInt() % randomMod );

/dev/urandom

Linux* 操作系统(包括 Android)包含一个内核创建的特殊文件,该特殊文件可为应用生成随机数。 它是四种方式中最慢的一种,可将部分操作系统(如设备驱动程序)的噪音整合至 RNG,从而生成密码安全的高熵值。 通过从 /dev/urandom 文件进行读取,我们可以直接从内核层面获取随机数。   /dev/urandom 将访问硬件辅助 RNG(如果可用)。

unsigned int cKeyBuffer[keysize];
memset(cKeyBuffer, 0, sizeof(unsigned int) * keysize);

FILE *fin;
strcpy(filein, "/dev/urandom");
fin = fopen(filein, "rb");

if (fin != NULL) {
	fread(cKeyBuffer, sizeof(int), keysize, fin);
	fclose (fin);
}

OpenSSL API

此外,我们还可使用 OpenSSL API 获取原生(C)代码中的随机数。 你可以看到,OpenSSL 可以使用 /dev/urandom 的字节生成,然后用于生成密码安全的随机数。 OpenSSL API 将访问硬件辅助的 RNG(如果可用)。

int seedbytes = 1024;
unsigned int cKeyBuffer[keysize];
memset(cKeyBuffer, 0, sizeof(unsigned int) * keysize);

if (!opensslIsSeeded) {

	if (!RAND_load_file("/dev/urandom", seedbytes)) {
		__android_log_print(ANDROID_LOG_ERROR, TAG, "Failed to seed OpenSSL RNG");
		return jKeyBuffer;
	}

	opensslIsSeeded = 1;
}

if (!RAND_bytes((unsigned char *)cKeyBuffer, keysize * sizeof(int))) {
	__android_log_print(ANDROID_LOG_ERROR, TAG, "Faled to create OpenSSSL random integers: %ul", ERR_get_error);
}

结论

通过按照本文中介绍的样本实施代码,您可以快速了解如何使用四种不同的方式来生成随机数。

作者介绍

Christopher Bird 是英特尔软件和解决方案事业部(SSG)、开发人员关系部门、英特尔® 凌动™ 处理器高接触性软件支持团队的一员。

相关文章与资源:

声明

本文件中包含关于英特尔产品的信息。 本文件不构成对任何知识产权的授权,包括明示的、暗示的,也无论是基于禁止反言的原则或其他。 英特尔不承担任何其他责任。英特尔在此作出免责声明:本文件不构成英特尔关于其产品的使用和/或销售的任何明示或暗示的保证,包括不就其产品的(i)对某一特定用途的适用性、(ii)适销性以及(iii)对任何专利、版权或其他知识产权的侵害的承担任何责任或作出任何担保。

除非经过英特尔的书面同意认可,英特尔的产品无意被设计用于或被用于以下应用:即在这样的应用中可因英特尔产品的故障而导致人身伤亡。


英特尔有权随时更改产品的规格和描述,恕不另行通知。 设计者不应信赖任何英特产品所不具有的特性,设计者亦不应信赖任何标有保留权利摂或未定义摂说明或特性描述。 对此,英特尔保留将来对其进行定义的权利,同时,英特尔不应为因其日后更改该等说明或特性描述而产生的冲突和不相容承担任何责任。 此处提供的信息可随时更改,恕不另行通知。 请勿根据本文件提供的信息完成一项产品设计。

本文件所描述的产品可能包含使其与宣称的规格不符的设计缺陷或失误。 这些缺陷或失误已收录于勘误表中,可索取获得。

在发出订单之前,请联系当地的英特尔营业部或分销商以获取最新的产品规格。

如欲获得本文涉及的带编号文档的副本或其他英特尔文献,可致电 1-800-548-4725,或访问: http://www.intel.com/design/literature.htm

在性能检测过程中涉及的软件及其性能只有在英特尔微处理器的架构下方能得到优化。 SYSmark* 和 MobileMark* 等性能测试均使用特定的计算机系统、组件、软件、操作和功能进行测量。 上述任何要素的变动都有可能导致测试结果的变化。 请参考其他信息及性能测试(包括结合其他产品使用时的运行性能)以对目标产品进行全面评估。

对本文件中包含的软件源代码的提供均依据相关软件许可而做出,任何对该等源代码的使用和复制均应按照相关软件许可的条款执行。

英特尔、Intel 标识、Atom 和凌动是英特尔公司在美国和其他国家(地区)的商标。

英特尔公司 © 2014 年版权所有。 所有权保留。

* 其他的名称和品牌可能是其他所有者的资产。

Viewing all 172 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>