Merge "Import translations. DO NOT MERGE" into nyc-dev
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index f9a7d19..ac968c8 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -42,7 +42,7 @@
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For more information about communicating with USB hardware, read the
- * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB developer guide</a>.</p>
* </div>
*/
public class UsbManager {
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index fb482b4..b0f15b5 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -102,8 +102,8 @@
* </tr>
* <tr>
* <td>ACTION_DRAG_ENDED</td>
- * <td style="text-align: center;">X</td>
- * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
* <td style="text-align: center;"> </td>
* <td style="text-align: center;"> </td>
* <td style="text-align: center;"> </td>
@@ -359,7 +359,7 @@
* The drag handler or listener for a View can use the metadata in this object to decide if the
* View can accept the dragged View object's data.
* <p>
- * This method returns valid data for all event actions.
+ * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}.
* @return The ClipDescription that was part of the ClipData sent to the system by startDrag().
*/
public ClipDescription getClipDescription() {
@@ -377,7 +377,7 @@
* The object is intended to provide local information about the drag and drop operation. For
* example, it can indicate whether the drag and drop operation is a copy or a move.
* <p>
- * This method returns valid data for all event actions.
+ * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}.
* </p>
* @return The local state object sent to the system by startDrag().
*/
diff --git a/docs/html-intl/intl/ja/training/basics/data-storage/files.jd b/docs/html-intl/intl/ja/training/basics/data-storage/files.jd
index dddfe37..b920c1a 100644
--- a/docs/html-intl/intl/ja/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/ja/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,7 +250,7 @@
-
+
<p>たとえば、自分のアプリでダウンロードした追加のリソースや一時的なメディア ファイルです。</p>
</dd>
</dl>
@@ -265,7 +265,7 @@
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -366,7 +366,7 @@
<div class="note">
<p><strong>注:</strong> ユーザーがアプリをアンインストールすると、Android システムは次を削除します。
-</p>
+</p>
<ul>
<li>内部ストレージに保存したすべてのファイル</li>
<li>{@link
diff --git a/docs/html-intl/intl/ko/training/basics/data-storage/files.jd b/docs/html-intl/intl/ko/training/basics/data-storage/files.jd
index 71652b5..0b717a8 100644
--- a/docs/html-intl/intl/ko/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/ko/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,7 +250,7 @@
앱을 제거하면 같이 삭제됩니다. 이러한 파일은
엄밀히 말해 외부 저장소에 저장된 파일이기 때문에 사용자 및 다른 앱의 액세스가 가능하긴 하지만, 앱 외부에서
사용자에게 값을 실제로 제공하지는 않습니다. 사용자가 앱을 제거하면 앱의 외부 개인 디렉터리 내 모든 파일을 시스템에서
-삭제합니다.
+삭제합니다.
<p>예를 들어 앱에서 다운로드한 추가 리소스 또는 임시 미디어 파일이 이에 해당합니다.</p>
</dd>
</dl>
@@ -265,7 +265,7 @@
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -357,7 +357,7 @@
myFile.delete();
</pre>
-<p>파일이 내부 저장소에 저장되어 있는 경우, {@link android.content.Context}에 위치를 요청하고 {@link android.content.Context#deleteFile deleteFile()}을 호출하여 파일을
+<p>파일이 내부 저장소에 저장되어 있는 경우, {@link android.content.Context}에 위치를 요청하고 {@link android.content.Context#deleteFile deleteFile()}을 호출하여 파일을
삭제할 수도 있습니다.</p>
<pre>
@@ -366,7 +366,7 @@
<div class="note">
<p><strong>참고:</strong> 사용자가 앱을 제거하면 Android 시스템이
-다음 항목을 삭제합니다.</p>
+다음 항목을 삭제합니다.</p>
<ul>
<li>내부 저장소에 저장한 모든 파일</li>
<li>{@link
diff --git a/docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd b/docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd
index d071d39..0e00645 100644
--- a/docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,12 +250,12 @@
. Embora esses arquivos estejam teoricamente à disposição do usuário e de outros aplicativo por estarem
no armazenamento externo, na verdade são arquivos que não têm valor para o usuário
fora do aplicativo. Ao desinstalar o aplicativo, o sistema exclui
-todos os arquivos no diretório privado externo do aplicativo.
+todos os arquivos no diretório privado externo do aplicativo.
<p>Por exemplo, recursos adicionais baixados através do aplicativo ou arquivos de mídia temporários.</p>
</dd>
</dl>
-<p>Para salvar arquivos públicos no armazenamento externo, use o método
+<p>Para salvar arquivos públicos no armazenamento externo, use o método
{@link android.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()} para obter um {@link java.io.File} que representa
o diretório correto no armazenamento externo. O método exige um argumento que especifica
@@ -265,7 +265,7 @@
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -366,7 +366,7 @@
<div class="note">
<p><strong>Observação:</strong> quando o usuário desinstala o aplicativo, o sistema Android também
-exclui:</p>
+exclui:</p>
<ul>
<li>Todos os arquivos salvos no armazenamento interno</li>
<li>Todos os arquivos salvos no armazenamento externo usando {@link
diff --git a/docs/html-intl/intl/ru/training/basics/data-storage/files.jd b/docs/html-intl/intl/ru/training/basics/data-storage/files.jd
index 2afecea..2b8f880 100644
--- a/docs/html-intl/intl/ru/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/ru/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,7 +250,7 @@
вашего приложения пользователем. Хотя технически эти файлы доступны для пользователя и других приложений, поскольку находятся
во внешнем хранилище, они не имеют никакой ценности для пользователей
вне вашего приложения. Когда пользователь удаляет ваше приложение, система удаляет
-все файлы из каталога закрытых файлов вашего приложения во внешнем хранилище.
+все файлы из каталога закрытых файлов вашего приложения во внешнем хранилище.
<p>Например, к этой категории относятся дополнительные ресурсы, загруженные приложением, и временные мультимедийные файлы.</p>
</dd>
</dl>
@@ -265,7 +265,7 @@
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -332,7 +332,7 @@
общее пространство в хранилище. Эта информация также позволять
избежать переполнения объема хранилища сверх определенного уровня.</p>
-<p>Однако система не гарантирует возможность записи такого же количества байт, как указано
+<p>Однако система не гарантирует возможность записи такого же количества байт, как указано
в {@link java.io.File#getFreeSpace}. Если выводимое число на
несколько мегабайт превышает размер данных, которые вы хотите сохранить, или если файловая система заполнена
менее, чем на 90%, дальше можно действовать спокойно.
@@ -366,13 +366,13 @@
<div class="note">
<p><strong>Примечание.</strong> При удалении пользователем вашего приложения система Android удаляет
-следующие элементы:</p>
+следующие элементы:</p>
<ul>
<li>Все файлы, сохраненные во внутреннем хранилище</li>
<li>Все файлы, сохраненные во внешнем хранилище с использованием {@link
android.content.Context#getExternalFilesDir getExternalFilesDir()}.</li>
</ul>
-<p>Однако вам следует регулярно вручную очищать кэш-память, чтобы удалить файлы, созданные с помощью
+<p>Однако вам следует регулярно вручную очищать кэш-память, чтобы удалить файлы, созданные с помощью
{@link android.content.Context#getCacheDir()}, а также удалять любые
другие ненужные файлы.</p>
</div>
diff --git a/docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd b/docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd
index 1442275..4ec1d68 100644
--- a/docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,7 +250,7 @@
-
+
<p>例如,您的应用下载的其他资源或临时介质文件。</p>
</dd>
</dl>
@@ -265,7 +265,7 @@
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -311,7 +311,7 @@
<p>无论您对于共享的文件使用 {@link
android.os.Environment#getExternalStoragePublicDirectory
-getExternalStoragePublicDirectory()} 还是对您的应用专用文件使用
+getExternalStoragePublicDirectory()} 还是对您的应用专用文件使用
{@link android.content.Context#getExternalFilesDir
getExternalFilesDir()} ,您使用诸如
{@link android.os.Environment#DIRECTORY_PICTURES} 的 API 常数提供的目录名称非常重要。
@@ -332,7 +332,7 @@
此信息也可用来避免填充存储卷以致超出特定阈值。
</p>
-<p>但是,系统并不保证您可以写入与 {@link java.io.File#getFreeSpace}
+<p>但是,系统并不保证您可以写入与 {@link java.io.File#getFreeSpace}
指示的一样多的字节。如果返回的数字比您要保存的数据大小大出几 MB,或如果文件系统所占空间不到 90%,则可安全继续操作。否则,您可能不应写入存储。
@@ -366,7 +366,7 @@
<div class="note">
<p><strong>注意:</strong>当用户卸载您的应用时,Android 系统会删除以下各项:
-</p>
+</p>
<ul>
<li>您保存在内部存储中的所有文件</li>
<li>您使用 {@link
diff --git a/docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd b/docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd
index 8b8d0a7..cda5864 100644
--- a/docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd
@@ -40,7 +40,7 @@
該物件的用途很廣,例如非常適用於影像檔案或透過網路交換的項目。
</p>
-<p>本課程將顯示如何在您的應用程式中執行與檔案相關的基本任務。本課程假設您已熟悉 Linux 檔案系統的基本概念,以及
+<p>本課程將顯示如何在您的應用程式中執行與檔案相關的基本任務。本課程假設您已熟悉 Linux 檔案系統的基本概念,以及
{@link java.io} 中的標準檔案輸入/輸出 API。
</p>
@@ -183,7 +183,7 @@
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,12 +250,12 @@
-
+
<p>例如,您的應用程式下載的附加資源,或暫存媒體檔案都是私用檔案。</p>
</dd>
</dl>
-<p>若您希望將公用檔案儲存在外部儲存空間,請使用
+<p>若您希望將公用檔案儲存在外部儲存空間,請使用
{@link android.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()} 方法取得代表外部儲存空間內相應目錄的 {@link java.io.File}。
該方法採用對要儲存的檔案類型進行指定 (以便能合理區分這些檔案與其他公用檔案) 的引數,諸如 {@link android.os.Environment#DIRECTORY_MUSIC} 或 {@link
@@ -265,7 +265,7 @@
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -366,7 +366,7 @@
<div class="note">
<p><strong>注意:</strong>使用者解除安裝您的應用程式時,Android 系統會刪除以下檔案:
-</p>
+</p>
<ul>
<li>您在內部儲存空間儲存的所有檔案</li>
<li>您使用 {@link
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 911e256..a9f1985 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -59,7 +59,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on June 6, 2016.
+<p style="clear:both"><em>Data collected during a 7-day period ending on July 11, 2016.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -81,7 +81,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on June 6, 2016.
+<p style="clear:both"><em>Data collected during a 7-day period ending on July 11, 2016.
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -101,7 +101,7 @@
<img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0%7CGL%203.1&chf=bg%2Cs%2C00000000&chd=t%3A48.6%2C41.8%2C9.6&chco=c4df9b%2C6fad0c&cht=p&chs=400x250">
+src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0%7CGL%203.1&chf=bg%2Cs%2C00000000&chd=t%3A47.5%2C41.9%2C10.6&chco=c4df9b%2C6fad0c&cht=p&chs=400x250">
<p>To declare which version of OpenGL ES your application requires, you should use the {@code
android:glEsVersion} attribute of the <a
@@ -119,21 +119,21 @@
</tr>
<tr>
<td>2.0</td>
-<td>48.6%</td>
+<td>47.5%</td>
</tr>
<tr>
<td>3.0</td>
-<td>41.8%</td>
+<td>41.9%</td>
</tr>
<tr>
<td>3.1</td>
-<td>9.6%</td>
+<td>10.6%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on June 6, 2016</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on July 11, 2016</em></p>
@@ -147,28 +147,28 @@
"Large": {
"hdpi": "0.5",
"ldpi": "0.2",
- "mdpi": "4.5",
- "tvdpi": "2.2",
+ "mdpi": "4.4",
+ "tvdpi": "2.1",
"xhdpi": "0.5"
},
"Normal": {
- "hdpi": "41.1",
- "mdpi": "4.2",
+ "hdpi": "40.9",
+ "mdpi": "4.1",
"tvdpi": "0.1",
- "xhdpi": "25.6",
- "xxhdpi": "15.0"
+ "xhdpi": "26.3",
+ "xxhdpi": "15.1"
},
"Small": {
- "ldpi": "2.0"
+ "ldpi": "1.9"
},
"Xlarge": {
"hdpi": "0.3",
- "mdpi": "3.1",
+ "mdpi": "2.9",
"xhdpi": "0.7"
}
},
- "densitychart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A2.2%2C11.8%2C2.3%2C41.9%2C26.8%2C15.0&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
- "layoutchart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A4.1%2C7.9%2C86.0%2C2.0&chl=Xlarge%7CLarge%7CNormal%7CSmall"
+ "densitychart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&chd=t%3A2.1%2C11.4%2C2.2%2C41.7%2C27.5%2C15.1&chf=bg%2Cs%2C00000000&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chs=400x250&cht=p",
+ "layoutchart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&chd=t%3A3.9%2C7.7%2C86.5%2C1.9&chf=bg%2Cs%2C00000000&chl=Xlarge%7CLarge%7CNormal%7CSmall&chs=400x250&cht=p"
}
];
@@ -176,7 +176,7 @@
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chs=500x250&cht=p&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A0.1%2C2.0%2C1.9%2C18.9%2C31.6%2C35.4%2C10.1&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop%7CMarshmallow",
+ "chart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&chd=t%3A0.1%2C1.9%2C1.7%2C17.8%2C30.2%2C35.1%2C13.3&chf=bg%2Cs%2C00000000&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop%7CMarshmallow&chs=500x250&cht=p",
"data": [
{
"api": 8,
@@ -186,47 +186,47 @@
{
"api": 10,
"name": "Gingerbread",
- "perc": "2.0"
+ "perc": "1.9"
},
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "1.9"
+ "perc": "1.7"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "6.8"
+ "perc": "6.4"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "9.4"
+ "perc": "8.8"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "2.7"
+ "perc": "2.6"
},
{
"api": 19,
"name": "KitKat",
- "perc": "31.6"
+ "perc": "30.1"
},
{
"api": 21,
"name": "Lollipop",
- "perc": "15.4"
+ "perc": "14.3"
},
{
"api": 22,
"name": "Lollipop",
- "perc": "20.0"
+ "perc": "20.8"
},
{
"api": 23,
"name": "Marshmallow",
- "perc": "10.1"
+ "perc": "13.3"
}
]
}
diff --git a/docs/html/auto/images/logos/auto/lincoln.png b/docs/html/auto/images/logos/auto/lincoln.png
new file mode 100644
index 0000000..0ade9fe
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/lincoln.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/mbenz.png b/docs/html/auto/images/logos/auto/mbenz.png
new file mode 100644
index 0000000..84deacd
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/mbenz.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/opel.png b/docs/html/auto/images/logos/auto/opel.png
index 7e25ed5..fcb7040 100644
--- a/docs/html/auto/images/logos/auto/opel.png
+++ b/docs/html/auto/images/logos/auto/opel.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/renault.png b/docs/html/auto/images/logos/auto/renault.png
index d252aa3..2970430 100644
--- a/docs/html/auto/images/logos/auto/renault.png
+++ b/docs/html/auto/images/logos/auto/renault.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/rsm.png b/docs/html/auto/images/logos/auto/rsm.png
new file mode 100644
index 0000000..fa0e56a
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/rsm.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/tata.png b/docs/html/auto/images/logos/auto/tata.png
new file mode 100644
index 0000000..dfc4a5f
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/tata.png
Binary files differ
diff --git a/docs/html/auto/index.jd b/docs/html/auto/index.jd
index 843aabf..5b67641 100644
--- a/docs/html/auto/index.jd
+++ b/docs/html/auto/index.jd
@@ -507,7 +507,12 @@
width="120" height="120" class="img-logo" />
</a>
</div>
-
+ <div class="col-5">
+ <a href=" http://www.lincoln.com/">
+ <img src="{@docRoot}auto/images/logos/auto/lincoln.png"
+ width="120" height="120" class="img-logo" />
+ </a>
+ </div>
<div class="col-5">
<a href="http://www.mahindra.com/">
<img src="{@docRoot}auto/images/logos/auto/mahindra.png"
@@ -520,16 +525,22 @@
width="120" height="120" class="img-logo" />
</a>
</div>
+ </div>
+ <div class="cols cols-leftp">
<div class="col-5">
<a href="http://www.mazda.com/">
<img src="{@docRoot}auto/images/logos/auto/mazda.png"
width="120" height="120" class="img-logo" />
</a>
</div>
- </div>
- <div class="cols cols-leftp">
- <div class="col-5">
+ <div class="col-5">
+ <a href="http://www.mercedes-benz.com/">
+ <img src="{@docRoot}auto/images/logos/auto/mbenz.png"
+ width="120" height="120" class="img-logo" />
+ </a>
+ </div>
+ <div class="col-5">
<a href="http://www.mitsubishi-motors.com/">
<img src="{@docRoot}auto/images/logos/auto/mitsubishi.png"
width="120" height="120" class="img-logo" />
@@ -542,20 +553,22 @@
width="120" height="120" class="img-logo" />
</a>
</div>
+ </div>
+ <div class="cols cols-leftp">
<div class="col-5">
<a href="http://www.opel.com/">
<img src="{@docRoot}auto/images/logos/auto/opel.png"
width="120" height="120" class="img-logo" />
</a>
</div>
+
<div class="col-5">
<a href="http://www.peugeot.com/">
<img src="{@docRoot}auto/images/logos/auto/peugeot.png"
width="120" height="120" class="img-logo" />
</a>
</div>
- </div>
- <div class="cols cols-leftp">
+
<div class="col-5">
<a href="http://www.ramtrucks.com/">
<img src="{@docRoot}auto/images/logos/auto/ram.png"
@@ -569,27 +582,37 @@
width="120" height="120" class="img-logo" />
</a>
</div>
+ </div>
+ <div class="cols cols-leftp">
+ <div class="col-5">
+ <a href="http://www.renaultsamsungm.com/ ">
+ <img src="{@docRoot}auto/images/logos/auto/rsm.png"
+ width="120" height="120" class="img-logo" />
+ </a>
+ </div>
+
<div class="col-5">
<a href="http://www.seat.com/">
<img src="{@docRoot}auto/images/logos/auto/seat.png"
width="120" height="120" class="img-logo" />
</a>
</div>
+
<div class="col-5">
<a href="http://www.skoda-auto.com/">
<img src="{@docRoot}auto/images/logos/auto/skoda.png"
width="120" height="120" class="img-logo" />
</a>
</div>
- </div>
- <div class="cols cols-leftp">
+
<div class="col-5">
<a href="http://www.smotor.com/">
<img src="{@docRoot}auto/images/logos/auto/ssangyong.png"
width="120" height="120" class="img-logo" />
</a>
</div>
-
+ </div>
+ <div class="cols cols-leftp">
<div class="col-5">
<a href="http://www.subaru-global.com/">
<img src="{@docRoot}auto/images/logos/auto/subaru.png"
@@ -597,13 +620,20 @@
</a>
</div>
-
<div class="col-5">
<a href="http://www.globalsuzuki.com/automobile/">
<img src="{@docRoot}auto/images/logos/auto/suzuki.png"
width="120" height="120" class="img-logo" />
</a>
</div>
+
+ <div class="col-5">
+ <a href="http://www.tatamotors.com/">
+ <img src="{@docRoot}auto/images/logos/auto/tata.png"
+ width="120" height="120" class="img-logo" />
+ </a>
+ </div>
+
<div class="col-5">
<a href="http://www.vauxhall.co.uk/">
<img src="{@docRoot}auto/images/logos/auto/vauxhall.png"
@@ -618,7 +648,8 @@
width="120" height="120" class="img-logo" />
</a>
</div>
-
+
+
<div class="col-5">
<a href="http://www.volvocars.com/intl">
<img src="{@docRoot}auto/images/logos/auto/volvo.png"
diff --git a/docs/html/guide/topics/resources/layout-resource.jd b/docs/html/guide/topics/resources/layout-resource.jd
index 8c5708a..ab381c3 100644
--- a/docs/html/guide/topics/resources/layout-resource.jd
+++ b/docs/html/guide/topics/resources/layout-resource.jd
@@ -33,16 +33,17 @@
<dt>syntax:</dt>
<dd>
<pre class="stx">
-<?xml version="1.0" encoding="utf-8"?>
-<<a href="#viewgroup-element"><em>ViewGroup</em></a> xmlns:android="http://schemas.android.com/apk/res/android"
+<?xml version="1.0" encoding="utf-8"?>
+<<a href="#viewgroup-element"><em>ViewGroup</em></a>
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
- android:layout_height=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
- android:layout_width=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
+ android:layout_height=["<em>dimension</em>" | "match_parent" | "wrap_content"]
+ android:layout_width=["<em>dimension</em>" | "match_parent" | "wrap_content"]
[<em>ViewGroup-specific attributes</em>] >
<<a href="#view-element"><em>View</em></a>
android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
- android:layout_height=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
- android:layout_width=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
+ android:layout_height=["<em>dimension</em>" | "match_parent" | "wrap_content"]
+ android:layout_width=["<em>dimension</em>" | "match_parent" | "wrap_content"]
[<em>View-specific attributes</em>] >
<<a href="#requestfocus-element">requestFocus</a>/>
</<em>View</em>>
@@ -82,15 +83,17 @@
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The height for the group, as a
-dimension value (or <a
-href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
-or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
+dimension value (or
+<a href="more-resources.html#Dimension">dimension resource</a>) or a keyword
+({@code "match_parent"} or {@code "wrap_content"}). See the <a href=
+"#layoutvalues">valid values</a> below.
</dd>
<dt><code>android:layout_width</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The width for the group, as a
-dimension value (or <a
-href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
-or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
+dimension value (or
+<a href="more-resources.html#Dimension">dimension resource</a>) or a keyword
+({@code "match_parent"} or {@code "wrap_content"}). See the <a href=
+"#layoutvalues">valid values</a> below.
</dd>
</dl>
<p>More attributes are supported by the {@link android.view.ViewGroup}
@@ -114,15 +117,17 @@
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The height for the element, as
-a dimension value (or <a
-href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
-or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
+a dimension value (or
+<a href="more-resources.html#Dimension">dimension resource</a>) or a keyword
+({@code "match_parent"} or {@code "wrap_content"}). See the <a href=
+"#layoutvalues">valid values</a> below.
</dd>
<dt><code>android:layout_width</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The width for the element, as
-a dimension value (or <a
-href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
-or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
+a dimension value (or
+<a href="more-resources.html#Dimension">dimension resource</a>) or a keyword
+({@code "match_parent"} or {@code "wrap_content"}). See the <a href=
+"#layoutvalues">valid values</a> below.
</dd>
</dl>
<p>More attributes are supported by the {@link android.view.View}
@@ -221,9 +226,6 @@
deprecate <code>fill_parent</code>.</td>
</tr>
<tr>
- <td><code>fill_parent</code></td>
- <td>Sets the dimension to match that of the parent element.</td>
- </tr><tr>
<td><code>wrap_content</code></td>
<td>Sets the dimension only to the size required to fit the content of this element.</td>
</tr>
@@ -245,8 +247,8 @@
<pre>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
@@ -279,4 +281,4 @@
</ul>
</dd>
-</dl>
+</dl>
\ No newline at end of file
diff --git a/docs/html/images/training/tv/tif/app-link-2x.png b/docs/html/images/training/tv/tif/app-link-2x.png
new file mode 100644
index 0000000..d9d0582
--- /dev/null
+++ b/docs/html/images/training/tv/tif/app-link-2x.png
Binary files differ
diff --git a/docs/html/images/training/tv/tif/app-link-diagram.png b/docs/html/images/training/tv/tif/app-link-diagram.png
new file mode 100644
index 0000000..92328ad
--- /dev/null
+++ b/docs/html/images/training/tv/tif/app-link-diagram.png
Binary files differ
diff --git a/docs/html/images/training/tv/tif/app-link.png b/docs/html/images/training/tv/tif/app-link.png
new file mode 100644
index 0000000..7573a18
--- /dev/null
+++ b/docs/html/images/training/tv/tif/app-link.png
Binary files differ
diff --git a/docs/html/topic/libraries/support-library/features.jd b/docs/html/topic/libraries/support-library/features.jd
index 584bef8..d648384 100755
--- a/docs/html/topic/libraries/support-library/features.jd
+++ b/docs/html/topic/libraries/support-library/features.jd
@@ -142,7 +142,7 @@
</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v4/} directory. The library does not contain user
+<code><sdk>/extras/android/support/v4/</code> directory. The library does not contain user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -169,7 +169,7 @@
<p>
After you download the Android Support Libraries, this library is located in the
- {@code <sdk>/extras/android/support/multidex/} directory. The library does not contain
+ <code><sdk>/extras/android/support/multidex/</code> directory. The library does not contain
user interface resources. To include it in your application project, follow the instructions
for
<a href= "{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
@@ -229,7 +229,7 @@
</ul>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v7/appcompat/} directory. The library contains user
+<code><sdk>/extras/android/support/v7/appcompat/</code> directory. The library contains user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries with
resources</a>.</p>
@@ -250,7 +250,7 @@
implementations, and are used extensively in layouts for TV apps.</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v7/cardview/} directory. The library contains user interface
+<code><sdk>/extras/android/support/v7/cardview/</code> directory. The library contains user interface
resources. To include it in your application project, follow the instructions
for <a href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding
libraries with resources</a>.</p>
@@ -271,7 +271,7 @@
For detailed information about the v7 gridlayout library APIs, see the
{@link android.support.v7.widget android.support.v7.widget} package in the API reference.</p>
-<p>This library is located in the {@code <sdk>/extras/android/support/v7/gridlayout/}
+<p>This library is located in the <code><sdk>/extras/android/support/v7/gridlayout/</code>
directory . The library contains user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries with
@@ -332,7 +332,7 @@
title card.</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v7/palette/} directory. The library does not contain
+<code><sdk>/extras/android/support/v7/palette/</code> directory. The library does not contain
user interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -354,7 +354,7 @@
limited window of data items.</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v7/recyclerview/} directory. The library contains
+<code><sdk>/extras/android/support/v7/recyclerview/</code> directory. The library contains
user interface resources. To include it in your application project, follow the instructions
for <a href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding
libraries with resources</a>.</p>
@@ -383,7 +383,7 @@
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v7/preference} directory. For more information
+<code><sdk>/extras/android/support/v7/preference</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -447,7 +447,7 @@
</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v13/} directory. The library does not contain user
+<code><sdk>/extras/android/support/v13/</code> directory. The library does not contain user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -479,7 +479,7 @@
</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v14/} directory. The library does not contain user
+<code><sdk>/extras/android/support/v14/</code> directory. The library does not contain user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -508,7 +508,7 @@
</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v17/} directory. The library does not contain user
+<code><sdk>/extras/android/support/v17/</code> directory. The library does not contain user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -550,7 +550,7 @@
</ul>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/v17/leanback} directory. For more information
+<code><sdk>/extras/android/support/v17/leanback</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -571,7 +571,7 @@
<p></p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/annotations} directory. For more information
+<code><sdk>/extras/android/support/annotations</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -596,7 +596,7 @@
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/design} directory. For more information
+<code><sdk>/extras/android/support/design</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -624,7 +624,7 @@
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/customtabs} directory. For more information
+<code><sdk>/extras/android/support/customtabs</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -655,7 +655,7 @@
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/percent} directory. For more information
+<code><sdk>/extras/android/support/percent</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -685,7 +685,7 @@
<p>After you download the Android Support Libraries, this library is located in the
-{@code <sdk>/extras/android/support/recommendation} directory. For more information
+<code><sdk>/extras/android/support/recommendation</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
diff --git a/docs/html/training/articles/perf-tips.jd b/docs/html/training/articles/perf-tips.jd
index 4a3184c..82de69a 100644
--- a/docs/html/training/articles/perf-tips.jd
+++ b/docs/html/training/articles/perf-tips.jd
@@ -43,7 +43,7 @@
that you can simply say "device X is a factor F faster/slower than device Y",
and scale your results from one device to others. In particular, measurement
on the emulator tells you very little about performance on any device. There
-are also huge differences between devices with and without a
+are also huge differences between devices with and without a
<acronym title="Just In Time compiler">JIT</acronym>: the best
code for a device with a JIT is not always the best code for a device
without.</p>
@@ -88,7 +88,7 @@
but this also generalizes to the fact that two parallel arrays of ints
are also a <strong>lot</strong> more efficient than an array of {@code (int,int)}
objects. The same goes for any combination of primitive types.</li>
-
+
<li>If you need to implement a container that stores tuples of {@code (Foo,Bar)}
objects, try to remember that two parallel {@code Foo[]} and {@code Bar[]} arrays are
generally much better than a single array of custom {@code (Foo,Bar)} objects.
@@ -401,19 +401,6 @@
need to solve. Make sure you can accurately measure your existing performance,
or you won't be able to measure the benefit of the alternatives you try.</p>
-<p>Every claim made in this document is backed up by a benchmark. The source
-to these benchmarks can be found in the <a
-href="http://code.google.com/p/dalvik/source/browse/#svn/trunk/benchmarks">code.google.com
-"dalvik" project</a>.</p>
-
-<p>The benchmarks are built with the
-<a href="http://code.google.com/p/caliper/">Caliper</a> microbenchmarking
-framework for Java. Microbenchmarks are hard to get right, so Caliper goes out
-of its way to do the hard work for you, and even detect some cases where you're
-not measuring what you think you're measuring (because, say, the VM has
-managed to optimize all your code away). We highly recommend you use Caliper
-to run your own microbenchmarks.</p>
-
<p>You may also find
<a href="{@docRoot}tools/debugging/debugging-tracing.html">Traceview</a> useful
for profiling, but it's important to realize that it currently disables the JIT,
diff --git a/docs/html/training/basics/data-storage/files.jd b/docs/html/training/basics/data-storage/files.jd
index 58a1d5f..349af78 100644
--- a/docs/html/training/basics/data-storage/files.jd
+++ b/docs/html/training/basics/data-storage/files.jd
@@ -192,7 +192,7 @@
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -259,7 +259,7 @@
your app. Although these files are technically accessible by the user and other apps because they
are on the external storage, they are files that realistically don't provide value to the user
outside your app. When the user uninstalls your app, the system deletes
- all files in your app's external private directory.
+ all files in your app's external private directory.
<p>For example, additional resources downloaded by your app or temporary media files.</p>
</dd>
</dl>
@@ -274,7 +274,7 @@
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -296,7 +296,7 @@
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -375,7 +375,7 @@
<div class="note">
<p><strong>Note:</strong> When the user uninstalls your app, the Android system deletes
-the following:</p>
+the following:</p>
<ul>
<li>All files you saved on internal storage</li>
<li>All files you saved on external storage using {@link
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index e66237a..4c2155b 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -93,13 +93,19 @@
Activities</a> for more information.</p>
</div>
</div>
- <li>Under <strong>Add an activity to <<em>template</em>></strong>, select <strong>Blank
- Activity</strong> and click <strong>Next</strong>.</li>
+ <li>Under <strong>Add an activity to <<em>template</em>></strong>,
+ select <strong>Basic Activity</strong> and click <strong>Next</strong>.
+ </li>
+
<li>Under <strong>Customize the Activity</strong>, change the
- <strong>Activity Name</strong> to <em>MyActivity</em>. The <strong>Layout Name</strong> changes
- to <em>activity_my</em>, and the <strong>Title</strong> to <em>MyActivity</em>. The
- <strong>Menu Resource Name</strong> is <em>menu_my</em>.
- <li>Click the <strong>Finish</strong> button to create the project.</li>
+ <strong>Activity Name</strong> to <em>MyActivity</em>. The <strong>Layout
+ Name</strong> changes to <em>activity_my</em>, and the <strong>Title</strong>
+ to <em>MyActivity</em>. The <strong>Menu Resource Name</strong> is
+ <em>menu_my</em>.
+ </li>
+
+ <li>Click the <strong>Finish</strong> button to create the project.
+ </li>
</ol>
<p>Your Android project is now a basic "Hello World" app that contains some default files. Take a
@@ -180,4 +186,6 @@
string and color definitions.</dd>
</dl>
-<p>To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
+<p>
+ To run the app, continue to the <a href="running-app.html">next lesson</a>.
+</p>
\ No newline at end of file
diff --git a/docs/html/training/displaying-bitmaps/load-bitmap.jd b/docs/html/training/displaying-bitmaps/load-bitmap.jd
index f963baa..81eb1ab 100644
--- a/docs/html/training/displaying-bitmaps/load-bitmap.jd
+++ b/docs/html/training/displaying-bitmaps/load-bitmap.jd
@@ -115,8 +115,8 @@
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
- while ((halfHeight / inSampleSize) > reqHeight
- && (halfWidth / inSampleSize) > reqWidth) {
+ while ((halfHeight / inSampleSize) >= reqHeight
+ && (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
diff --git a/docs/html/training/testing/ui-testing/uiautomator-testing.jd b/docs/html/training/testing/ui-testing/uiautomator-testing.jd
index 05ddc34..5d42107 100644
--- a/docs/html/training/testing/ui-testing/uiautomator-testing.jd
+++ b/docs/html/training/testing/ui-testing/uiautomator-testing.jd
@@ -26,7 +26,7 @@
<h2>You should also read</h2>
<ul>
- <li><a href="{@docRoot}reference/android/support/test/package-summary.html">
+ <li><a href="{@docRoot}reference/android/support/test/uiautomator/package-summary.html">
UI Automator API Reference</a></li>
</ul>
diff --git a/docs/html/training/tv/tif/channel.jd b/docs/html/training/tv/tif/channel.jd
index 999f1ca..59e357a 100644
--- a/docs/html/training/tv/tif/channel.jd
+++ b/docs/html/training/tv/tif/channel.jd
@@ -13,6 +13,7 @@
<li><a href="#permission">Get Permission</a></li>
<li><a href="#register">Register Channels in the Database</a></li>
<li><a href="#update">Update Channel Data</a></li>
+ <li><a href="#applink">Add App Link Information</a></li>
</ol>
<h2>Try It Out</h2>
<ul>
@@ -22,10 +23,13 @@
</div>
</div>
-<p>Your TV input must provide Electronic Program Guide (EPG) data for at least one channel in its
-setup activity. You should also periodically update that data, with consideration for the size of
-the update and the processing thread that handles it. This lesson discusses creating and updating
-channel and program data on the system database with these considerations in mind.</p>
+<p>Your TV input must provide Electronic Program Guide (EPG) data for at least
+one channel in its setup activity. You should also periodically update that
+data, with consideration for the size of the update and the processing thread
+that handles it. Additionally, you can provide app links for channels
+that guide the user to related content and activities.
+This lesson discusses creating and updating channel and program data on the
+system database with these considerations in mind.</p>
<p> </p>
@@ -70,6 +74,10 @@
ID</li>
</ul>
+<p>If you want to provide app link details for your channels, you need to
+update some additional fields. For more information on app link fields, see
+<a href="#applink">Add App Link Information</a>.
+
<p>For internet streaming based TV inputs, assign your own values to the above accordingly so that
each channel can be identified uniquely.</p>
@@ -236,4 +244,112 @@
<p>Other techniques to separate the data update tasks from the UI thread include using the
{@link android.os.HandlerThread} class, or you may implement your own using {@link android.os.Looper}
and {@link android.os.Handler} classes. See <a href="{@docRoot}guide/components/processes-and-threads.html">
-Processes and Threads</a> for more information.</p>
\ No newline at end of file
+Processes and Threads</a> for more information.</p>
+
+<h2 id="applink">Add App Link Information</h2>
+
+<p>Channels can use <em>app links</em> to let users easily launch a related
+activity while they are watching channel content. Channel apps use
+app links to extend user engagement by launching activities that show
+related information or additional content. For example, you can use app links
+to do the following:</p>
+
+<ul>
+<li>Guide the user to discover and purchase related content.</li>
+<li>Provide additional information about currently playing content.</li>
+<li>While viewing episodic content, start viewing the next episode in a
+series.</li>
+<li>Let the user interact with content—for example, rate or review
+content—without interrupting content playback.</li>
+</ul>
+
+<p>App links are displayed when the user presses <b>Select</b> to show the
+TV menu while watching channel content.</p>
+
+<img alt="" src="{@docRoot}images/training/tv/tif/app-link.png"
+srcset="{@docRoot}images/training/tv/tif/app-link.png 1x,
+{@docRoot}images/training/tv/tif/app-link-2x.png 2x" id="figure1"/>
+<p class="img-caption"><strong>Figure 1.</strong> An example app link
+displayed on the <b>Channels</b> row while channel content is shown.</p>
+
+<p>When the user selects the app link, the system starts an activity using
+an intent URI specified by the channel app. Channel content continues to play
+while the app link activity is active. The user can return to the channel
+content by pressing <b>Back</b>.</p>
+
+<h3 id="card">Provide App Link Channel Data</h4>
+
+<p>Android TV automatically creates an app link for each channel,
+using information from the channel data. To provide app link information,
+specify the following details in your
+{@link android.media.tv.TvContract.Channels} fields:
+</p>
+
+<ul>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_COLOR} - The
+accent color of the app link for this channel. For an example accent color,
+see figure 2, callout 3.
+</li>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_ICON_URI} -
+The URI for the app badge icon of the app link for this channel. For an
+example app badge icon, see figure 2, callout 2.
+</li>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_INTENT_URI} -
+The intent URI of the app link for this channel. You can create the URI
+using {@link android.content.Intent#toUri(int) toUri(int)} with
+{@link android.content.Intent#URI_INTENT_SCHEME URI_INTENT_SCHEME} and
+convert the URI back to the original intent with
+{@link android.content.Intent#parseUri parseUri()}.
+</li>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_POSTER_ART_URI}
+- The URI for the poster art used as the background of the app link
+for this channel. For an example poster image, see figure 2, callout 1.</li>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_TEXT} -
+The descriptive link text of the app link for this channel. For an example
+app link description, see the text in figure 2, callout 3.</li>
+</ul>
+
+<img alt="" src="{@docRoot}images/training/tv/tif/app-link-diagram.png"/>
+<p class="img-caption"><strong>Figure 2.</strong> App link details.</p>
+
+<p>If the channel data doesn't specify app link information, the system
+creates a default app link. The system chooses default details as follows:</p>
+
+<ul>
+<li>For the intent URI
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_INTENT_URI}),
+the system uses the {@link android.content.Intent#ACTION_MAIN ACTION_MAIN}
+activity for the {@link android.content.Intent#CATEGORY_LEANBACK_LAUNCHER
+CATEGORY_LEANBACK_LAUNCHER} category, typically defined in the app manifest.
+If this activity is not defined, a non-functioning app link appears—if
+the user clicks it, nothing happens.</li>
+<li>For the descriptive text
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_TEXT}), the system
+uses "Open <var>app-name</var>". If no viable app link intent URI is defined,
+the system uses "No link available".</li>
+<li>For the accent color
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_COLOR}),
+the system uses the default app color.</li>
+<li>For the poster image
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_POSTER_ART_URI}),
+the system uses the app's home screen banner. If the app doesn't provide a
+banner, the system uses a default TV app image.</li>
+<li>For the badge icon
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_ICON_URI}), the
+system uses a badge that shows the app name. If the system is also using the
+app banner or default app image for the poster image, no app badge is shown.
+</li>
+</ul>
+
+<p>You specify app link details for your channels in your app's
+setup activity. You can update these app link details at any point, so
+if an app link needs to match channel changes, update app
+link details and call
+{@link android.content.ContentResolver#update(android.net.Uri,
+android.content.ContentValues, java.lang.String, java.lang.String[])
+ContentResolver.update()} as needed. For more details on updating
+channel data, see <a href="#update">Update Channel Data</a>.
+</p>
+
+
+
diff --git a/docs/html/wear/preview/_book.yaml b/docs/html/wear/preview/_book.yaml
index a4acad0..3bea2fd 100644
--- a/docs/html/wear/preview/_book.yaml
+++ b/docs/html/wear/preview/_book.yaml
@@ -18,6 +18,8 @@
path: /wear/preview/features/ui-nav-actions.html
- title: Bridging for Notifications
path: /wear/preview/features/bridger.html
+ - title: Wrist Gestures
+ path: /wear/preview/features/gestures.html
- title: Get Started
path: /wear/preview/start.html
diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd
index 11331a7..4233624 100644
--- a/docs/html/wear/preview/api-overview.jd
+++ b/docs/html/wear/preview/api-overview.jd
@@ -25,6 +25,7 @@
<li><a href="#remote-input">Remote Input</a></li>
<li><a href="#bridging">Bridging Mode</a></li>
<li><a href="#imf">Input Method Framework</a></li>
+ <li><a href="#wrist-gestures">Wrist Gestures</a></li>
</ol>
</li>
@@ -79,12 +80,11 @@
watch face using the API.
</p>
-<p>For examples of how to use this feature,
+<p>For information about this API,
see <a href="{@docRoot}wear/preview/features/complications.html">
Watch Face Complications</a>.
</p>
-
<h3 id="drawers">Navigation and Action drawers</h3>
<p>Wear 2.0 introduces two new widgets, navigation drawer and action drawer. These
@@ -233,6 +233,24 @@
Input Method Framework</a>.
</p>
+<h3 id="wrist-gestures">Wrist Gestures</h3>
+
+<p>
+ Wrist gestures can enable quick, one-handed interactions with your app
+ when use of a touch screen is inconvenient. The following
+ <a href="https://support.google.com/androidwear/answer/6312406">wrist gestures</a>
+ are available for use by apps:
+</p>
+
+<ul>
+ <li>Flick wrist out</li>
+ <li>Flick wrist in</li>
+</ul>
+
+<p>For more information, see
+<a href="{@docRoot}wear/preview/features/gestures.html">
+ Wrist Gestures</a>.
+</p>
<h2 id="stand-alone">Standalone Devices</h2>
diff --git a/docs/html/wear/preview/downloads.jd b/docs/html/wear/preview/downloads.jd
index 8689504..4bc401b 100644
--- a/docs/html/wear/preview/downloads.jd
+++ b/docs/html/wear/preview/downloads.jd
@@ -223,8 +223,8 @@
</p>
<p class="warning">
- <strong>Warning:</strong> Installing a system image on a watch removes all data from the
- watch, so you should back up your data first.
+ <strong>Warning:</strong> Installing a system image on a watch removes all
+ data from the watch, so you should back up your data first.
</p>
<h3 id="preview_system_images">
@@ -233,8 +233,13 @@
<p>
The preview includes system images for testing your app. Based on your
- device, you can download a preview system image from the following tables
- and flash it to the corresponding device.
+ device, you can download a preview system image from one of the
+ following tables and flash it to the corresponding device.
+ </p>
+
+ <p>
+ To restore your device to its original state during the preview,
+ you can flash the appropriate retail system image, below, to the device.
</p>
<h4 id="preview_image_for_lge_watch_urbane_2nd_edition">
@@ -261,9 +266,9 @@
<td>
Preview image for testing
</td>
- <td><a href="#top" onclick="onDownload(this)">nemo-nvd36i-factory-9cdd2ac0.tgz</a><br>
- MD5: b33ba8e59780fbe5c83d8936b108640f<br>
- SHA-1: 9cdd2ac01f2976cafe5a21958298dac159b7a325
+ <td><a href="#top" onclick="onDownload(this)">nemo-nvd83h-factory-48ac950c.tgz</a><br>
+ MD5: dd351884cce9fb5bf1bdec0a8e5f56e3<br>
+ SHA-1: 48ac950c48faef96a7770e3c1acb56d23a28d859
</td>
</tr>
@@ -302,9 +307,9 @@
<td>
Preview image for testing
</td>
- <td><a href="#top" onclick="onDownload(this)">sturgeon-nvd36i-factory-2cbe5080.tgz</a><br>
- MD5: ccc972cdc33cba778a2f624066ef5713<br>
- SHA-1: 2cbe5080ded060ce43ba65ff27e2290b28981634
+ <td><a href="#top" onclick="onDownload(this)">sturgeon-nvd83h-factory-cb5a11ab.tgz</a><br>
+ MD5: 38c1047992b1d28f6833d9f6c8470cdc<br>
+ SHA-1: cb5a11ab0260ea3ca7da5894e73e41f70357da6b
</td>
</tr>
<tr id="sturgeon-non-preview">
diff --git a/docs/html/wear/preview/features/gestures.jd b/docs/html/wear/preview/features/gestures.jd
new file mode 100644
index 0000000..7806c4e
--- /dev/null
+++ b/docs/html/wear/preview/features/gestures.jd
@@ -0,0 +1,323 @@
+page.title=Wrist Gestures
+meta.keywords="wear-preview"
+page.tags="wear-preview"
+page.image=images/cards/card-n-sdk_2x.png
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+ <ul>
+ <li><a href="#using_wlv">Using a WearableListView</a></li>
+ <li><a href="#using_key_events">Using Key Events Directly</a></li>
+ <li><a href="#best_practices">Best Practices</a></li>
+ </ul>
+
+</div>
+</div>
+
+ <p>
+ Wrist gestures can enable quick, one-handed interactions with your app
+ when use of a touch screen is inconvenient. For example, a user can scroll
+ through notifications with one hand while holding a cup of water with the
+ other. Other examples of using wrist gestures when a touch screen would
+ be inconvenient include:
+ </p>
+
+ <ul>
+ <li>In an app for jogging, navigating through vertical screens that show
+ the steps taken, time elapsed, and current pace
+ </li>
+
+ <li>At the airport with luggage, scrolling through flight and gate
+ information
+ </li>
+
+ <li>Scrolling through news articles
+ </li>
+ </ul>
+
+ <p>
+ To review the wrist gestures on your watch, first confirm gestures are
+ turned on by selecting <strong>Settings > Gestures > Wrist Gestures
+ On</strong>. (Wrist gestures are on by default.) Then complete the
+ Gestures tutorial on the watch (<strong>Settings > Gestures >
+ Launch Tutorial</strong>).
+ </p>
+
+ <p>
+ The following gestures from the <a href=
+ "https://support.google.com/androidwear/answer/6312406">Android Wear
+ Help</a> are unavailable to apps:
+ </p>
+
+ <ul>
+ <li>Push wrist down
+ </li>
+
+ <li>Raise wrist up
+ </li>
+
+ <li>Shaking the wrist
+ </li>
+ </ul>
+
+ <p>
+ Wrist gestures can be used in these ways:
+ </p>
+
+ <ul>
+ <li>
+ <a href="#using_wlv">Using a WearableListView</a>, which
+ has predefined gesture actions
+ </li>
+
+ <li>
+ <a href="#using_key_events">Using key events directly</a> to
+ define new user actions
+ </li>
+ </ul>
+
+ <p>
+ Each wrist gesture is mapped to an <code>int</code> constant from the
+ <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.html">KeyEvent</a></code>
+ class, as shown in the following table:
+ </p>
+
+ <table>
+ <tr>
+ <th>
+ Gesture
+ </th>
+ <th>
+ KeyEvent
+ </th>
+ <th>
+ Description
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ Flick wrist out
+ </td>
+ <td>
+ <a href=
+ "{@docRoot}reference/android/view/KeyEvent.html#KEYCODE_NAVIGATE_NEXT">
+ KEYCODE_NAVIGATE_NEXT</a>
+ </td>
+ <td>
+ This key code goes to the next item.
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ Flick wrist in
+ </td>
+ <td>
+ <a href=
+ "{@docRoot}reference/android/view/KeyEvent.html#KEYCODE_NAVIGATE_PREVIOUS">
+ KEYCODE_NAVIGATE_PREVIOUS</a>
+ </td>
+ <td>
+ This key code goes to the previous item.
+ </td>
+ </tr>
+ </table>
+
+ <h2 id="using_wlv">
+ Using a WearableListView
+ </h2>
+
+ <p>
+ A <code><a href=
+ "{@docRoot}reference/android/support/wearable/view/WearableListView.html">
+ WearableListView</a></code> has predefined actions for occurrences of
+ wrist gestures when the View has the focus. For more information, see
+ <a href="#best_practices">Best Practices</a>. For information about using
+ <code>WearableListView</code>, see <a href=
+ "{@docRoot}training/wearables/ui/lists.html">Creating
+ Lists</a>.
+ </p>
+
+ <p>
+ Even if you use a <code>WearableListView</code>, you may want to use
+ constants from the <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.html">KeyEvent</a></code>
+ class. The predefined actions can be overridden by subclassing the
+ <code>WearableListView</code> and re-implementing the
+ <code>onKeyDown()</code> callback. The behavior can be disabled entirely
+ by using <code>setEnableGestureNavigation(false)</code>. Also see
+ <a href="{@docRoot}training/keyboard-input/commands.html">
+ Handling Keyboard Actions</a>.
+ </p>
+
+ <h2 id="using_key_events">
+ Using Key Events Directly
+ </h2>
+
+ <p>
+ You can use key events outside of a <code><a href=
+ "{@docRoot}reference/android/support/wearable/view/WearableListView.html">
+ WearableListView</a></code> to trigger new actions in response to gesture
+ events. Importantly, these gesture events:
+ </p>
+
+ <ul>
+ <li>Are recognized when a device is in Active mode
+ </li>
+
+ <li>Are delivered in the same way as all key events
+ </li>
+ </ul>
+
+ <p>
+ Specifically, these events are delivered to the top Activity, to the View
+ with keyboard focus. Just as any other key event, a class that relates to
+ user interaction (such as a View or an Activity) that implements
+ <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.Callback.html">
+ KeyEvent.Callback</a></code> can listen to key events that relate to
+ wrist gestures. The Android framework calls the View or Activity that has
+ the focus with the key events; for gestures, the <code>onKeyDown()</code>
+ method callback is called when gestures occur.
+ </p>
+
+ <p>
+ As an example, an app may override predefined actions in a View or
+ Activity (both implementing <code>KeyEvent.Callback</code>) as follows:
+ </p>
+
+ <pre>
+public final class GesturesActivity extends Activity {
+
+ @Override /* KeyEvent.Callback */
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_NAVIGATE_NEXT:
+ // Do something that advances a user View to the next item in an ordered list.
+ return moveToNextItem();
+ case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS:
+ // Do something that advances a user View to the previous item in an ordered list.
+ return moveToPreviousItem();
+ }
+ // If you did not handle it, let it be handled by the next possible element as deemed by the Activity.
+ return super.onKeyDown(keyCode, event);
+ }
+
+ /** Shows the next item in the custom list. */
+ private boolean moveToNextItem() {
+ boolean handled = false;
+ …
+ // Return true if handled successfully, otherwise return false.
+ return handled;
+ }
+
+ /** Shows the previous item in the custom list. */
+ private boolean moveToPreviousItem() {
+ boolean handled = false;
+ …
+ // Return true if handled successfully, otherwise return false.
+ return handled;
+ }
+}
+</pre>
+
+ <h2 id="best_practices">
+ Best Practices
+ </h2>
+
+ <ul>
+ <li>Review the <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.html">KeyEvent</a></code>
+ and <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.Callback.html">
+ KeyEvent.Callback</a></code> pages for the delivery of key events to
+ your View and Activity.
+ </li>
+
+ <li>Keep a consistent directional affordance:
+ <ul>
+ <li>Use "Flick wrist out" for next, "Flick wrist in" for previous
+ </li>
+ </ul>
+ </li>
+
+ <li>Have a touch parallel for a gesture.
+ </li>
+
+ <li>Provide visual feedback.
+ </li>
+
+ <li>Don't use a keycode to implement functionality that would be
+ counter-intuitive to the rest of the system. For example, do not use
+ <code>KEYCODE_NAVIGATE_NEXT</code> to cancel an action or to navigate the
+ left-right axis with flicks.
+ </li>
+
+ <li>Don't intercept the key events on elements that are not part of the
+ user interface, for example the Views that are offscreen or partially
+ covered. This is the same as any other key event.
+ </li>
+
+ <li>Don't reinterpret repeated flick gestures into your own, new gesture.
+ It may conflict with the system's "Shaking the wrist" gesture.
+ </li>
+
+ <li>For a View to receive gesture key events, it must have <a href=
+ "{@docRoot}reference/android/view/View.html#attr_android:focusable">
+ focus</a>; see <a href=
+ "{@docRoot}reference/android/view/View.html#setFocusable(boolean)">
+ View::setFocusable()</a>. Because gestures are treated as key events,
+ they trigger a transition out of "Touch mode" that may do unexpected
+ things. Therefore, since users may alternate between using touch and
+ gestures, the <a href=
+ "{@docRoot}reference/android/view/View.html#setFocusableInTouchMode(boolean)">
+ View::setFocusableInTouchmode()</a> method may be necessary. In some
+ cases, it also may be necessary to use
+ <code>setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS)</code> so
+ that when focus changes after a change to or from "Touch mode," your
+ intended View gets the focus.
+ </li>
+
+ <li>Use <code>requestFocus()</code> and <code>clearFocus()</code>
+ carefully:
+ <ul>
+ <li>When calling <code><a href=
+ "{@docRoot}reference/android/view/View.html#requestFocus()">
+ requestFocus()</a></code>, be sure that the View really should have
+ focus. If the View is offscreen, or is covered by another View,
+ surprises can occur when gestures trigger callbacks.
+ </li>
+
+ <li>The <code><a href=
+ "{@docRoot}reference/android/view/View.html#clearFocus()">
+ clearFocus()</a></code> initiates a focus search to find another
+ suitable View. Depending on the View hierarchy, this search might
+ require non-trivial computation. It can also end up assigning focus
+ to a View you don’t expect to receive focus.
+ </li>
+ </ul>
+ </li>
+
+ <li>Key events are delivered first to the View with focus in the View
+ hierarchy. If the focused View does not handle the event (i.e., returns
+ <code>false</code>), the event is not delivered to the parent View, even
+ if it can receive focus and has a <a href=
+ "{@docRoot}reference/android/text/method/KeyListener.html">
+ KeyListener</a>. Rather, the event is delivered to the current Activity
+ holding the View hierarchy with focus. Thus, it may be necessary to
+ catch all events at the higher level and then pass relevant codes down.
+ Alternatively, you might subclass the Activity and override the
+ <code><a href=
+ "{@docRoot}reference/android/app/Activity.html#dispatchKeyEvent(android.view.KeyEvent)">
+ dispatchKeyEvent(KeyEvent event)</a></code> method to ensure that keys
+ are intercepted when necessary, or are handled when not handled at
+ lower layers.
+ </li>
+ </ul>
diff --git a/docs/html/wear/preview/features/ui-nav-actions.jd b/docs/html/wear/preview/features/ui-nav-actions.jd
index 1ba275f..fb14264 100644
--- a/docs/html/wear/preview/features/ui-nav-actions.jd
+++ b/docs/html/wear/preview/features/ui-nav-actions.jd
@@ -12,7 +12,7 @@
<ol>
<li><a href="#create a drawer">Create a Drawer Layout</a></li>
<li><a href="#initialize">Initialize the Drawer List</a></li>
- <li><a href="#creating">Create a Custom View Drawer</a></li>
+ <li><a href="#creating">Create a Custom Drawer View</a></li>
<li><a href="#listen to events">Listen for Drawer Events</a></li>
<li><a href=#peeking">Peeking Drawers</a></li>
</ol>
@@ -37,8 +37,8 @@
</div>
</div>
<p>As part of the <a href="http://www.google.com/design/spec-wear">Material Design</a>
- for Android Wear, Wear 2.0 adds interactive navigation and action drawers.
- The navigation drawer appears at the top of the screen and lets users jump to
+ for Android Wear, Wear 2.0 adds interactive navigation and action drawers.
+ The navigation drawer appears at the top of the screen and lets users jump to
different views within
the app, similar to the navigation drawer on a phone. The action drawer appears
at the bottom of the screen and provides context-specific actions for the user,
@@ -59,7 +59,8 @@
<div class="cols">
<p>This lesson describes how to implement action and navigation drawers in your
-app using the {@code WearableDrawerLayout} APIs.
+app using the {@code WearableDrawerLayout} APIs. For more information, see the
+downloadable <a href="{@docRoot}preview/setup-sdk.html#docs-dl">API reference</a>.
</p>
<h2 id="create a drawer">Create a Drawer Layout</h2>
@@ -99,41 +100,44 @@
</android.support.wearable.view.drawer.WearableDrawerLayout>
</pre>
+
<h2 id="initialize">Initialize the Drawer List</h2>
<p>One of the first things you need to do in your activity is to initialize the
drawers list of items. You should implement {@code WearableNavigationDrawerAdapter}
to populate the navigation drawer contents. To populate the action drawer with
-a list of actions, inflate an XML file into the Menu (via MenuInflater).</p>
+a list of actions, inflate an XML file into the Menu (via {@code MenuInflater}).
+</p>
<p>The following code snippet shows how to initialize the contents of your drawers:
</p>
+
<pre>
public class MainActivity extends WearableActivity implements
WearableActionDrawer.OnMenuItemClickListener{
private WearableDrawerLayout mwearableDrawerLayout;
private WearableNavigationDrawer mWearableNavigationDrawer;
private WearableActionDrawer mWearableActionDrawer;
-
+
...
-
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
-
+
......
-
-
+
+
// Main Wearable Drawer Layout that wraps all content
mWearableDrawerLayout = (WearableDrawerLayout) findViewById(R.id.drawer_layout);
-
+
// Top Navigation Drawer
mWearableNavigationDrawer = (WearableNavigationDrawer) findViewById(R.id.top_navigation_drawer);
mWearableNavigationDrawer.setAdapter(new YourImplementationNavigationAdapter(this));
// Peeks Navigation drawer on the top.
mWearableDrawerLayout.peekDrawer(Gravity.TOP);
-
+
// Bottom Action Drawer
mWearableActionDrawer = (WearableActionDrawer) findViewById(R.id.bottom_action_drawer);
@@ -149,44 +153,58 @@
}
</pre>
-<h2 id="creating">Create a Custom View Drawer</h2>
-<p>To use custom views in drawers, add <code>WearableDrawerView</code> to the
-<code>WearableDrawerLayout</code>. To set the contents of the drawer, call <code>
-<a href="https://x20web.corp.google.com/~psoulos/docs/reference/android/support/wearable/view/drawer/WearableDrawerView.html#setDrawerContent(android.view.View)">setDrawerContent(View)</a></code>
- instead of manually adding the view to the hierarchy. You must also specify the
- drawer position with the <code>android:layout_gravity</code> attribute. </p>
-<p> The following example specifies a top drawer:</p>
+<h2 id="creating">Create a Custom Drawer View</h2>
+
+<p>To use custom views in drawers, add <code>WearableDrawerView</code> to the
+<code>WearableDrawerLayout</code>. To set the peek view and drawer contents, add
+ them as children of the {@code WearableDrawerView} and specify their IDs in the
+ {@code peek_view} and {@code drawer_content} attributes respectively. You must
+ also specify the drawer position with the {@code android:layout_gravity}
+ attribute. </p>
+
+<p> The following example specifies a top drawer with peek view and drawer
+contents:</p>
+
<pre>
-<android.support.wearable.view.drawer.WearableDrawerLayout>
- <FrameLayout
- android:id=”@+id/content” />
-
- <WearableDrawerView
- android:layout_width=”match_parent”
- andndroid:layout_height=”match_parent”
- android:layout_gravity=”top”>
- <FrameLayout
- android:id=”@+id/top_drawer_content” />
- </WearableDrawerView>
-</android.support.wearable.view.drawer.WearableDrawerView>
+ <android.support.wearable.view.drawer.WearableDrawerView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="top"
+ android:background="@color/red"
+ app:drawer_content="@+id/drawer_content"
+ app:peek_view="@+id/peek_view">
+ <FrameLayout
+ android:id="@id/drawer_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <!-- Drawer content goes here. -->
+ </FrameLayout>
+ <LinearLayout
+ android:id="@id/peek_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:orientation="horizontal">
+ <!-- Peek view content goes here. -->
+ <LinearLayout>
+ </android.support.wearable.view.drawer.WearableDrawerView>
</pre>
<h2 id="listen to events">Listen for Drawer Events</h2>
-<p>To listen for drawer events, call {@code setDrawerStateCallback()}on your
+<p>To listen for drawer events, call {@code setDrawerStateCallback()} on your
{@code WearableDrawerLayout} and pass it an implementation of
{@code WearableDrawerLayout.DrawerStateCallback}. This interface provides callbacks
for drawer events such as <code>onDrawerOpened()</code>,
<code>onDrawerClosed(),</code> and <code>onDrawerStatechanged()</code>.</p>
<h2 id="peeking">Peeking Drawers</h2>
-<p>To set the drawers to temporarily appear, call <code>peekDrawer()</code> on
+<p>To set the drawers to temporarily appear, call <code>peekDrawer()</code> on
your {@code WearableDrawerLayout} and pass it the {@code Gravity} of the drawer.
This feature is especially useful because it allows immediate access to the
- alternate drawer views or actions associated with it. </p>
+ alternate drawer views or actions associated with it: </p>
-<pre>{@code mWearableDrawerLayout.peekDrawer</code>(<code>Gravity.BOTTOM);}</pre>
+<pre>{@code mWearableDrawerLayout.peekDrawer(Gravity.BOTTOM);}</pre>
-<p>You can also call {@code setPeekContent()} on your drawer to display a custom
- view when the drawer is peeking.</p>
+
diff --git a/docs/html/wear/preview/program.jd b/docs/html/wear/preview/program.jd
index a130663..e2bf92f 100644
--- a/docs/html/wear/preview/program.jd
+++ b/docs/html/wear/preview/program.jd
@@ -79,6 +79,11 @@
</div>
<div class="col-4of12">
+ <h5>
+ </h5>
+
+ <p>
+ </p>
</div>
</div>
</div>
@@ -90,7 +95,7 @@
<p>
The Android Wear 2.0 Developer Preview runs from 18 May 2016 until the
- final Android Wear public release to OEMs, planned for Q4 2016.
+ final Android Wear public release to OEMs.
</p>
<p>
@@ -136,7 +141,7 @@
</p>
<p>
- At milestones 4 and 5 you'll have access to the final Android Wear 2.0
+ At milestone 4, you'll have access to the final Android Wear 2.0
APIs and SDK to develop with, as well as near-final system images to test
system behaviors and features. Android Wear 2.0 will use the Android N
API level at this time. You can begin final compatibility testing of your
@@ -196,9 +201,9 @@
</h3>
<p>
- You can download these hardware system images at <a href=
+ You can download these hardware system images from the <a href=
"{@docRoot}wear/preview/downloads.html">Download and Test with a
- Device</a>:
+ Device</a> page:
</p>
<ul>
@@ -210,7 +215,15 @@
</ul>
<p>
- Please keep in mind that the Developer Preview system images
+ To restore your device to its
+ original state during the preview, you can flash the
+ appropriate retail system image from
+ the <a href="{@docRoot}wear/preview/downloads.html">Download and
+ Test with a Device</a> page.
+ </p>
+
+ <p>
+ Please keep in mind that the preview system images
are for app developers only, and for compatibility testing and
early development only, and are not ready for day-to-day use.
</p>
diff --git a/docs/html/wear/preview/start.jd b/docs/html/wear/preview/start.jd
index 65d4b56..8fccdc8 100644
--- a/docs/html/wear/preview/start.jd
+++ b/docs/html/wear/preview/start.jd
@@ -107,10 +107,10 @@
<tr>
<td>
- <a href="http://storage.googleapis.com/androiddevelopers/shareables/wear-preview/wearable-support-preview-1-docs.zip">wearable-support-preview-1-docs.zip</a>
+ <a href="http://storage.googleapis.com/androiddevelopers/shareables/wear-preview/wearable-support-preview-2-docs.zip">wearable-support-preview-2-docs.zip</a>
</td>
- <td>MD5: 02f9dc7714c00076b323c9081655c3b2<br>
- SHA-1: 075f3821ee9b66a919a0e8086f79c12bc9576fb2
+ <td>MD5: afb770c9c5c0431bbcbdde186f1eae06<br>
+ SHA-1: 81d681e61cee01f222ea82e83297d23c4e55b8f3
</td>
</tr>
</table>
@@ -146,16 +146,26 @@
plugin.
</li>
- <li>In the <code>build.gradle</code> file for the Wear module, in the
- <code>dependencies</code> section, update the existing reference to the
+ <li>In the <code>build.gradle</code> file for the Wear module:
+ <ul>
+ <li>In the <code>android</code> section, update the
+ <code>compileSdkVersion</code> to 24.
+ </li>
+
+ <li>In the <code>android</code> section, update the
+ <code>targetSdkVersion</code> to 24.
+ </li>
+
+ <li>In the <code>dependencies</code> section, update
+ the existing reference to the
Wearable Support Library (for example, <code>compile
'com.google.android.support:wearable:1.4.0'</code>) by changing it to the
following, which requires that your the Google Repository <a href=
"#install_android_studio_and_the_latest_packages">is the latest
version</a>:
- <pre>
-compile 'com.google.android.support:wearable:2.0.0-alpha1'
- </pre>
+ <code>compile 'com.google.android.support:wearable:2.0.0-alpha2'</code>
+ </li>
+ </ul>
</li>
<li>See the following page for setting up a watch or emulator with a
@@ -190,13 +200,24 @@
wizard.
</li>
- <li>In the <code>build.gradle</code> file for the Wear module, in the
- <code>dependencies</code> section, update the existing reference to the
- Wearable Support Library (perhaps <code>compile
- 'com.google.android.support:wearable:1.4.0'</code>) to:
- <pre>
-compile 'com.google.android.support:wearable:2.0.0-alpha1'
- </pre>
+ <li>In the <code>build.gradle</code> file for the Wear module:
+ <ul>
+ <li>In the <code>android</code> section, update the
+ <code>compileSdkVersion</code> to 24.
+ </li>
+ <li>In the <code>android</code> section, update the
+ <code>targetSdkVersion</code> to 24.
+ </li>
+ <li>In the <code>dependencies</code> section, update
+ the existing reference to the
+ Wearable Support Library (for example, <code>compile
+ 'com.google.android.support:wearable:1.4.0'</code>) by changing it to the
+ following, which requires that your the Google Repository <a href=
+ "#install_android_studio_and_the_latest_packages">is the latest
+ version</a>:
+ <code>compile 'com.google.android.support:wearable:2.0.0-alpha2'</code>
+ </li>
+ </ul>
</li>
<li>See the following page for setting up a watch or emulator with a
diff --git a/docs/html/wear/preview/support.jd b/docs/html/wear/preview/support.jd
index d03edf3..78b4e4b 100644
--- a/docs/html/wear/preview/support.jd
+++ b/docs/html/wear/preview/support.jd
@@ -16,7 +16,262 @@
Wear Developer Google+ community</a>.
</p>
-<h2 id="dp">Developer Preview 1</h2>
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+<ul>
+ <li><a href="#general">General Advisories</a></li>
+ <li><a href="#deprecations">Deprecations</a></li>
+ <li><a href="#dp2">Developer Preview 2</a></li>
+ <li><a href="#dp1">Developer Preview 1</a></li>
+</ul>
+
+</div>
+</div>
+
+<h2 id="general">General Advisories</h2>
+
+<p>
+ The developer preview is for <strong>app developers and other early
+ adopters</strong> and is available for daily use, development, or
+ compatibility testing. Please be aware of these general notes about the
+ release:
+</p>
+
+<ul>
+ <li>The developer preview may have various <strong>stability issues</strong> on
+ supported devices. Users may encounter system instability, such as kernel
+ panics and crashes.
+ </li>
+ <li>Some apps <strong>may not function as expected</strong> on the new
+ platform version. This includes Google’s apps and other apps.
+ </li>
+</ul>
+
+<h2 id="deprecations">Deprecations</h2>
+
+<p>The following fields are deprecated in the preview:</p>
+
+<ul>
+ <li>The <code>Notification.WearableExtender#setCustomSizePreset(int)</code>
+ method no longer accepts <code>SIZE_FULL_SCREEN</code> and this value is now
+ undefined.
+ </li>
+ <li>The <code>Notification.WearableExtender#setContentIcon(int)</code> method
+ is deprecated.
+ </li>
+</ul>
+
+<h2 id="dp2">Developer Preview 2</h2>
+
+<div class="wrap">
+ <div class="cols">
+ <div class="col-6of12">
+ <p><em>Date: July 2016<br />
+ Builds: Wearable Support 2.0.0-alpha2, NVD83H<br/>
+ Emulator support: x86 & ARM (32-bit)<br/>
+ </em></p>
+ </div>
+ </div>
+</div>
+
+<h3 id="new-in-fdp2">
+ <strong>New in Preview 2</strong>
+</h3>
+
+<h4 id="platform-version-24">
+ Platform API Version
+</h4>
+
+<p>
+ The Android Platform API version is incremented to 24 to match Android Nougat.
+ You can update the following in your Android Wear 2.0 Preview project
+ to <strong>24</strong>:
+</p>
+
+<ul>
+ <li><code>compileSdkVersion</code></li>
+ <li><code>targetSdkVersion</code></li>
+</ul>
+
+<h4 id="wearable-drawers">
+ Wearable drawers
+</h4>
+
+<p>
+ The following are feature additions for <a href=
+ "{@docRoot}wear/preview/features/ui-nav-actions.html">
+ wearable drawers</a>:
+</p>
+
+<ul>
+ <li>Drawer peeking is now supported in the <code>onCreate()</code> method
+ of your app's activity.
+ </li>
+
+ <li>The automatic drawer peeking behavior is
+ inverted. Now the bottom drawer peeks when the user scrolls down the view
+ and top drawer peeks when the user scrolls to the top of the view
+ (previously scrolling down did not show peek view).
+ </li>
+
+ <li>Two new attributes, <code>peek_view</code> and
+ <code>drawer_content</code>, are added to
+ <code>WearableDrawerView</code> to specify contents of custom drawers and
+ peek view in your XML layout (previously, custom drawer contents were
+ specified only through Java code).
+ </li>
+
+ <li>The Navigation drawer now displays page indicator dots.
+ </li>
+
+ <li>Peek views now close automatically after one second.
+ </li>
+
+ <li>The <code>WearableNavigationDrawer</code> now automatically closes
+ after five seconds or when an item is tapped.
+ </li>
+
+ <li>There is improved drawer handling (size and margins) for devices with chins:
+ <ul>
+ <li>Size: The bottom drawer is slightly smaller when there is a
+ chin.
+ </li>
+ <li>Margins: <code>WearableDrawerLayout</code> sets its bottom margin
+ size equal to the size of the chin, so that the bottom drawer is
+ fully visible.
+ </li>
+ </ul>
+ <li>The navigation drawer contents are now updated when
+ <code><a href="{@docRoot}reference/android/widget/ArrayAdapter.html#notifyDataSetChanged()">
+ notifyDataSetChanged</a></code> is called on the adapter.
+ </li>
+
+ <li>In your <code>WearableActionDrawer</code>, when there is only one
+ action, its icon is shown in the peek view and the action is executed
+ when the peek view is tapped.
+ </li>
+
+ <li>When the peek view of your <code>WearableActionDrawer</code> has
+ more than one action, both the first action and the overflow icons are
+ shown.
+ </li>
+</ul>
+
+<h4 id="gestures">
+ Wrist gestures
+</h4>
+
+<p>
+ Wrist gestures can enable quick, one-handed interactions with your app.
+ For example, a user can
+ scroll through notifications with one hand while holding a cup of water
+ with the other. For more information, see <a href=
+ "{@docRoot}wear/preview/features/gestures.html">
+ Wrist Gestures</a>.
+</p>
+
+<h3 id="known-issues-2">
+ <strong>Known Issues</strong>
+</h3>
+
+<h4 id="notifications-2">
+ Notifications
+</h4>
+
+<ul>
+ <li>This preview release does not include support for notification
+ groups.
+ </li>
+
+ <li>The user interface for the action drawer can sometimes have a
+ transparent background.
+ </li>
+
+ <li>The system does not generate Smart Reply responses even if
+ <code>setAllowGeneratedReplies(true)</code> is set.
+ </li>
+</ul>
+
+<h4 id="complications-2">
+ Complications
+</h4>
+
+<ul>
+ <li>When tapping on the music complication on a watch face, Play Music
+ crashes if the Apps launcher provider is used.
+ </li>
+</ul>
+
+<h4 id="system-user-interface-2">
+ System User Interface
+</h4>
+
+<ul>
+ <li>Pressing the hardware button in ambient mode triggers active mode
+ with the app launcher instead of active mode only.
+ </li>
+
+ <li>Double pressing the power hardware button while on the launcher
+ causes the watch screen to turn black.
+ </li>
+
+ <li>Dismissing multiple notifications can cause app to forcibly close.
+ </li>
+
+ <li>Turning screen lock to off (Enable and disable) functionality is not
+ reliable.
+ </li>
+
+ <li>The "Ok Google" detection and voice transcription may not work
+ reliably. Additionally, Search does not retrieve results.
+ </li>
+
+ <li>Tapping Google keyboard English (United States) displays a "Settings
+ under construction" message.
+ </li>
+
+ <li>First calendar event notification must be dismissed in order to show
+ the rest of the event card.
+ </li>
+
+ <li>Unable to turn off the Wi-Fi on a wearable.
+ </li>
+</ul>
+
+<h4 id="companion-app-2">
+ Companion App
+</h4>
+
+<ul>
+ <li>An actions card is shown in the Android Wear companion app, even
+ though there are no actions.
+ </li>
+</ul>
+
+<h4 id="devices-2">
+ Devices
+</h4>
+
+<ul>
+ <li>On the Huawei Watch, selecting the language, followed by multiple
+ acknowledgement dialogues results in a black screen.
+ </li>
+
+ <li>On the LG Watch Urbane 2nd Edition, when answering a call from the watch, the
+ watch does not provide audio from the caller.
+ </li>
+
+ <li>On the LG Watch Urbane 2nd Edition,
+ please do the following to prevent battery drain:
+ Turn on Airplane mode (to disable the cellular radio) and then
+ turn on Bluetooth.
+ </li>
+</ul>
+
+<h2 id="dp1">Developer Preview 1</h2>
<div class="wrap">
<div class="cols">
@@ -29,36 +284,10 @@
</div>
</div>
-
-<h3 id="general_advisories">General advisories</h3>
-
-<p>
- This Developer Preview release is for app developers only and is designed for
- use in compatibility testing and early development only.
-</p>
-
-<h4 id="deprecations">Deprecations</h4>
-
-
-<p>The following fields are deprecated in the Preview:</p>
-
-<ul>
- <li>The <code>Notification.WearableExtender#setCustomSizePreset(int)</code>
- method no longer accepts <code>SIZE_FULL_SCREEN</code> and this value is now
- undefined.
- </li>
-
- <li>The <code>Notification.WearableExtender#setContentIcon(int)</code> method
- is deprecated.
- </li>
-</ul>
-
<h3 id="known_issues">Known Issues</h3>
-
<h4 id="notifications">Notifications</h4>
-
<ul>
<li>This preview release does not include support for notification groups,
but will be supported in a future release.
@@ -74,18 +303,17 @@
</li>
</ul>
-
<h4 id="complications">Complications</h4>
<ul>
- <li>Battery information is not synchronized between watch face and drop down
- quick menu.
+ <li>Battery information is not synchronized between the
+ watch face and the drop-down Quick menu.
</li>
- <li>Play music crashes when tapping on music complication in watch face.
+ <li>When tapping on the music complication on a watch face, Play Music
+ crashes if the Apps launcher provider is used.
</li>
</ul>
-
<h4 id="system_user_interface">System User Interface</h4>
<ul>
@@ -114,26 +342,24 @@
</li>
</ul>
-
<h4 id="companion_app">Companion App</h4>
<ul>
- <li>'More actions' via Companion app shows a blank screen on phone running
- nyc-release and watch running feldspar-release.
- </li>
- <li>Select watch face on companion wear app will not change watch face on
- wearable.
- </li>
+ <li>Selecting a watch face on the companion app will not change the watch face on
+ wearable.</li>
+ <li>An actions card is shown in the Android Wear companion app, even
+ though there are no actions.
+ </li>
</ul>
-
<h4 id="devices">Devices</h4>
<ul>
<li>On the Huawei Watch, selecting the language, followed by multiple
acknowledgement dialogues results in a black screen.
</li>
- <li>On the LG Watch Urbane LTE, when answering call from the watch, the watch
+ <li>On the LG Watch Urbane 2nd Edition, when
+ answering a call from the watch, the watch
does not provide audio from the caller.
</li>
</ul>
diff --git a/docs/html/work/managed-configurations.jd b/docs/html/work/managed-configurations.jd
index dc3ef0d..91c0637 100644
--- a/docs/html/work/managed-configurations.jd
+++ b/docs/html/work/managed-configurations.jd
@@ -149,9 +149,9 @@
<restriction
android:key="downloadOnCellular"
- android:title="App is allowed to download data via cellular"
+ android:title="@string/download_on_cell_title"
android:restrictionType="bool"
- android:description="If 'false', app can only download data via Wi-Fi"
+ android:description="@string/download_on_cell_description"
android:defaultValue="true" />
</restrictions>
diff --git a/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip b/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip
new file mode 100644
index 0000000..8b6779d
--- /dev/null
+++ b/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip
Binary files differ
diff --git a/packages/SystemUI/res/values-my-rMM/strings_tv.xml b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
index 2c5b94b..f91c5bc 100644
--- a/packages/SystemUI/res/values-my-rMM/strings_tv.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
@@ -27,7 +27,7 @@
<string name="pip_onboarding_title" msgid="7850436557670253991">"ပုံထဲမှပုံ"</string>
<string name="pip_onboarding_description" msgid="4028124563309465267">"နောက်တစ်ခုမဖွင့်မချင်း သင့်ဗီဒီယိုကို ပြသထားပါမည်။ ၎င်းကိုထိန်းချုပ်ရန် "<b>"ပင်မ"</b>" ခလုတ်ကို နှိပ်ပြီးဖိထားပါ။"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ရပါပြီ"</string>
- <string name="recents_tv_dismiss" msgid="3555093879593377731">"ပယ်ပါ"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"ပယ်ရန်"</string>
<string-array name="recents_tv_blacklist_array">
</string-array>
</resources>
diff --git a/tests/AppLaunch/Android.mk b/tests/AppLaunch/Android.mk
index c0560fd..e6f6c39 100644
--- a/tests/AppLaunch/Android.mk
+++ b/tests/AppLaunch/Android.mk
@@ -11,7 +11,9 @@
LOCAL_CERTIFICATE := platform
LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
include $(BUILD_PACKAGE)
# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/AppLaunch/AndroidManifest.xml b/tests/AppLaunch/AndroidManifest.xml
index ac6760b..7dfd7ba 100644
--- a/tests/AppLaunch/AndroidManifest.xml
+++ b/tests/AppLaunch/AndroidManifest.xml
@@ -3,6 +3,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.tests.applaunch"
android:sharedUserId="android.uid.system" >
+
+ <uses-permission android:name="android.permission.REAL_GET_TASKS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk
+ android:minSdkVersion="22"
+ android:targetSdkVersion="24" />
+
<instrumentation android:label="Measure app start up time"
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.android.tests.applaunch" />
@@ -10,4 +18,4 @@
<application android:label="App Launch Test">
<uses-library android:name="android.test.runner" />
</application>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 085b7aa..2346f85 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -15,14 +15,13 @@
*/
package com.android.tests.applaunch;
+import java.io.OutputStreamWriter;
+
import android.accounts.Account;
import android.accounts.AccountManager;
+import android.app.ActivityManagerNative;
import android.app.ActivityManager;
import android.app.ActivityManager.ProcessErrorStateInfo;
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.app.IActivityManager.WaitResult;
-import android.app.UiAutomation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -31,16 +30,29 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.app.UiAutomation;
+import android.app.IActivityManager;
+import android.app.IActivityManager.WaitResult;
+import android.support.test.rule.logging.AtraceLogger;
import android.test.InstrumentationTestCase;
import android.test.InstrumentationTestRunner;
import android.util.Log;
-
+import java.io.File;
+import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
+import android.os.ParcelFileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStreamReader;
/**
* This test is intended to measure the time it takes for the apps to start.
@@ -55,27 +67,66 @@
private static final int JOIN_TIMEOUT = 10000;
private static final String TAG = AppLaunch.class.getSimpleName();
- private static final String KEY_APPS = "apps";
- private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
// optional parameter: comma separated list of required account types before proceeding
// with the app launch
private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
- private static final String KEY_SKIP_INITIAL_LAUNCH = "skip_initial_launch";
+ private static final String KEY_APPS = "apps";
+ private static final String KEY_TRIAL_LAUNCH = "trial_launch";
+ private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
+ private static final String KEY_LAUNCH_ORDER = "launch_order";
+ private static final String KEY_DROP_CACHE = "drop_cache";
+ private static final String KEY_SIMPLEPPERF_CMD = "simpleperf_cmd";
+ private static final String KEY_TRACE_ITERATIONS = "trace_iterations";
+ private static final String KEY_LAUNCH_DIRECTORY = "launch_directory";
+ private static final String KEY_TRACE_DIRECTORY = "trace_directory";
+ private static final String KEY_TRACE_CATEGORY = "trace_categories";
+ private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize";
+ private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval";
private static final String WEARABLE_ACTION_GOOGLE =
"com.google.android.wearable.action.GOOGLE";
private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 60000; //60s to allow app to idle
private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches
- private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps
+ private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 5000; //5s between launching apps
+ private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
+ private static final String LAUNCH_FILE = "applaunch.txt";
+ private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
+ private static final String DEFAULT_TRACE_CATEGORIES = "sched,freq,gfx,view,dalvik,webview,"
+ + "input,wm,disk,am,wm";
+ private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
+ private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
+ private static final String TRIAL_LAUNCH = "TRAIL_LAUNCH";
+ private static final String DELIMITER = ",";
+ private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
+ private static final String APP_LAUNCH_CMD = "am start -W -n";
+ private static final String SUCCESS_MESSAGE = "Status: ok";
+ private static final String THIS_TIME = "ThisTime:";
+ private static final String LAUNCH_ITERATION = "LAUNCH_ITERATION - %d";
+ private static final String TRACE_ITERATION = "TRACE_ITERATION - %d";
+ private static final String LAUNCH_ITERATION_PREFIX = "LAUNCH_ITERATION";
+ private static final String TRACE_ITERATION_PREFIX = "TRACE_ITERATION";
+ private static final String LAUNCH_ORDER_CYCLIC = "cyclic";
+ private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential";
+
private Map<String, Intent> mNameToIntent;
private Map<String, String> mNameToProcess;
+ private List<LaunchOrder> mLaunchOrderList = new ArrayList<LaunchOrder>();
private Map<String, String> mNameToResultKey;
- private Map<String, Long> mNameToLaunchTime;
+ private Map<String, List<Long>> mNameToLaunchTime;
private IActivityManager mAm;
+ private String mSimplePerfCmd = null;
+ private String mLaunchOrder = null;
+ private boolean mDropCache = false;
private int mLaunchIterations = 10;
+ private int mTraceLaunchCount = 0;
+ private String mTraceDirectoryStr = null;
private Bundle mResult = new Bundle();
private Set<String> mRequiredAccounts;
- private boolean mSkipInitialLaunch = false;
+ private boolean mTrailLaunch = true;
+ private File mFile = null;
+ private FileOutputStream mOutputStream = null;
+ private BufferedWriter mBufferedWriter = null;
+
@Override
protected void setUp() throws Exception {
@@ -89,69 +140,231 @@
super.tearDown();
}
- public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException {
+ public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException,
+ IOException, InterruptedException {
InstrumentationTestRunner instrumentation =
(InstrumentationTestRunner)getInstrumentation();
Bundle args = instrumentation.getArguments();
mAm = ActivityManagerNative.getDefault();
-
+ String launchDirectory = args.getString(KEY_LAUNCH_DIRECTORY);
+ mTraceDirectoryStr = args.getString(KEY_TRACE_DIRECTORY);
+ mDropCache = Boolean.parseBoolean(args.getString(KEY_DROP_CACHE));
+ mSimplePerfCmd = args.getString(KEY_SIMPLEPPERF_CMD);
+ mLaunchOrder = args.getString(KEY_LAUNCH_ORDER, LAUNCH_ORDER_CYCLIC);
createMappings();
parseArgs(args);
checkAccountSignIn();
- if (!mSkipInitialLaunch) {
- // do initial app launch, without force stopping
- for (String app : mNameToResultKey.keySet()) {
- long launchTime = startApp(app, false);
- if (launchTime <= 0) {
- mNameToLaunchTime.put(app, -1L);
- // simply pass the app if launch isn't successful
- // error should have already been logged by startApp
- continue;
- } else {
- mNameToLaunchTime.put(app, launchTime);
- }
- sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
- closeApp(app, false);
- sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ // Root directory for applaunch file to log the app launch output
+ // Will be useful in case of simpleperf command is used
+ File launchRootDir = null;
+ if (null != launchDirectory && !launchDirectory.isEmpty()) {
+ launchRootDir = new File(launchDirectory);
+ if (!launchRootDir.exists() && !launchRootDir.mkdirs()) {
+ throw new IOException("Unable to create the destination directory");
}
}
- // do the real app launch now
- for (int i = 0; i < mLaunchIterations; i++) {
- for (String app : mNameToResultKey.keySet()) {
- long prevLaunchTime = mNameToLaunchTime.get(app);
- long launchTime = 0;
- if (prevLaunchTime < 0) {
- // skip if the app has previous failures
- continue;
+
+ try {
+ File launchSubDir = new File(launchRootDir, LAUNCH_SUB_DIRECTORY);
+ if (!launchSubDir.exists() && !launchSubDir.mkdirs()) {
+ throw new IOException("Unable to create the lauch file sub directory");
+ }
+ mFile = new File(launchSubDir, LAUNCH_FILE);
+ mOutputStream = new FileOutputStream(mFile);
+ mBufferedWriter = new BufferedWriter(new OutputStreamWriter(
+ mOutputStream));
+
+ // Root directory for trace file during the launches
+ File rootTrace = null;
+ File rootTraceSubDir = null;
+ int traceBufferSize = 0;
+ int traceDumpInterval = 0;
+ Set<String> traceCategoriesSet = null;
+ if (null != mTraceDirectoryStr && !mTraceDirectoryStr.isEmpty()) {
+ rootTrace = new File(mTraceDirectoryStr);
+ if (!rootTrace.exists() && !rootTrace.mkdirs()) {
+ throw new IOException("Unable to create the trace directory");
}
- launchTime = startApp(app, true);
- if (launchTime <= 0) {
- // if it fails once, skip the rest of the launches
- mNameToLaunchTime.put(app, -1L);
- continue;
+ rootTraceSubDir = new File(rootTrace, TRACE_SUB_DIRECTORY);
+ if (!rootTraceSubDir.exists() && !rootTraceSubDir.mkdirs()) {
+ throw new IOException("Unable to create the trace sub directory");
}
- // keep the min launch time
- if (launchTime < prevLaunchTime) {
- mNameToLaunchTime.put(app, launchTime);
+ assertNotNull("Trace iteration parameter is mandatory",
+ args.getString(KEY_TRACE_ITERATIONS));
+ mTraceLaunchCount = Integer.parseInt(args.getString(KEY_TRACE_ITERATIONS));
+ String traceCategoriesStr = args
+ .getString(KEY_TRACE_CATEGORY, DEFAULT_TRACE_CATEGORIES);
+ traceBufferSize = Integer.parseInt(args.getString(KEY_TRACE_BUFFERSIZE,
+ DEFAULT_TRACE_BUFFER_SIZE));
+ traceDumpInterval = Integer.parseInt(args.getString(KEY_TRACE_DUMPINTERVAL,
+ DEFAULT_TRACE_DUMP_INTERVAL));
+ traceCategoriesSet = new HashSet<String>();
+ if (!traceCategoriesStr.isEmpty()) {
+ String[] traceCategoriesSplit = traceCategoriesStr.split(DELIMITER);
+ for (int i = 0; i < traceCategoriesSplit.length; i++) {
+ traceCategoriesSet.add(traceCategoriesSplit[i]);
+ }
}
- sleep(POST_LAUNCH_IDLE_TIMEOUT);
- closeApp(app, true);
- sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ }
+
+ // Get the app launch order based on launch order, trial launch,
+ // launch iterations and trace iterations
+ setLaunchOrder();
+
+ for (LaunchOrder launch : mLaunchOrderList) {
+
+ // App launch times for trial launch will not be used for final
+ // launch time calculations.
+ if (launch.getLaunchReason().equals(TRIAL_LAUNCH)) {
+ // In the "applaunch.txt" file, trail launches is referenced using
+ // "TRIAL_LAUNCH"
+ long launchTime = startApp(launch.getApp(), true, launch.getLaunchReason());
+ if (launchTime < 0) {
+ List<Long> appLaunchList = new ArrayList<Long>();
+ appLaunchList.add(-1L);
+ mNameToLaunchTime.put(launch.getApp(), appLaunchList);
+ // simply pass the app if launch isn't successful
+ // error should have already been logged by startApp
+ continue;
+ }
+ sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
+ closeApp(launch.getApp(), true);
+ dropCache();
+ sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ }
+
+ // App launch times used for final calculation
+ if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
+ long launchTime = -1;
+ if (null != mNameToLaunchTime.get(launch.getApp())) {
+ long firstLaunchTime = mNameToLaunchTime.get(launch.getApp()).get(0);
+ if (firstLaunchTime < 0) {
+ // skip if the app has failures while launched first
+ continue;
+ }
+ }
+ // In the "applaunch.txt" file app launches are referenced using
+ // "LAUNCH_ITERATION - ITERATION NUM"
+ launchTime = startApp(launch.getApp(), true, launch.getLaunchReason());
+ if (launchTime < 0) {
+ // if it fails once, skip the rest of the launches
+ List<Long> appLaunchList = new ArrayList<Long>();
+ appLaunchList.add(-1L);
+ mNameToLaunchTime.put(launch.getApp(), appLaunchList);
+ continue;
+ } else {
+ if (null != mNameToLaunchTime.get(launch.getApp())) {
+ mNameToLaunchTime.get(launch.getApp()).add(launchTime);
+ } else {
+ List<Long> appLaunchList = new ArrayList<Long>();
+ appLaunchList.add(launchTime);
+ mNameToLaunchTime.put(launch.getApp(), appLaunchList);
+ }
+ }
+ sleep(POST_LAUNCH_IDLE_TIMEOUT);
+ closeApp(launch.getApp(), true);
+ dropCache();
+ sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ }
+
+ // App launch times for trace launch will not be used for final
+ // launch time calculations.
+ if (launch.getLaunchReason().contains(TRACE_ITERATION_PREFIX)) {
+ AtraceLogger atraceLogger = AtraceLogger
+ .getAtraceLoggerInstance(getInstrumentation());
+ // Start the trace
+ try {
+ atraceLogger.atraceStart(traceCategoriesSet, traceBufferSize,
+ traceDumpInterval, rootTraceSubDir,
+ String.format("%s-%s", launch.getApp(), launch.getLaunchReason()));
+ startApp(launch.getApp(), true, launch.getLaunchReason());
+ sleep(POST_LAUNCH_IDLE_TIMEOUT);
+ } finally {
+ // Stop the trace
+ atraceLogger.atraceStop();
+ closeApp(launch.getApp(), true);
+ dropCache();
+ sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ }
+ }
+ }
+ } finally {
+ if (null != mBufferedWriter) {
+ mBufferedWriter.close();
}
}
+
for (String app : mNameToResultKey.keySet()) {
- long launchTime = mNameToLaunchTime.get(app);
- if (launchTime != -1) {
- mResult.putLong(mNameToResultKey.get(app), launchTime);
+ StringBuilder launchTimes = new StringBuilder();
+ for (Long launch : mNameToLaunchTime.get(app)) {
+ launchTimes.append(launch);
+ launchTimes.append(",");
}
+ mResult.putString(mNameToResultKey.get(app), launchTimes.toString());
}
instrumentation.sendStatus(0, mResult);
}
+ /**
+ * If launch order is "cyclic" then apps will be launched one after the
+ * other for each iteration count.
+ * If launch order is "sequential" then each app will be launched for given number
+ * iterations at once before launching the other apps.
+ */
+ private void setLaunchOrder() {
+ if (LAUNCH_ORDER_CYCLIC.equalsIgnoreCase(mLaunchOrder)) {
+ if (mTrailLaunch) {
+ for (String app : mNameToResultKey.keySet()) {
+ mLaunchOrderList.add(new LaunchOrder(app, TRIAL_LAUNCH));
+ }
+ }
+ for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
+ for (String app : mNameToResultKey.keySet()) {
+ mLaunchOrderList.add(new LaunchOrder(app,
+ String.format(LAUNCH_ITERATION, launchCount)));
+ }
+ }
+ if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
+ for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+ for (String app : mNameToResultKey.keySet()) {
+ mLaunchOrderList.add(new LaunchOrder(app,
+ String.format(TRACE_ITERATION, traceCount)));
+ }
+ }
+ }
+ } else if (LAUNCH_ORDER_SEQUENTIAL.equalsIgnoreCase(mLaunchOrder)) {
+ for (String app : mNameToResultKey.keySet()) {
+ if (mTrailLaunch) {
+ mLaunchOrderList.add(new LaunchOrder(app, TRIAL_LAUNCH));
+ }
+ for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
+ mLaunchOrderList.add(new LaunchOrder(app,
+ String.format(LAUNCH_ITERATION, launchCount)));
+ }
+ if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
+ for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+ mLaunchOrderList.add(new LaunchOrder(app,
+ String.format(TRACE_ITERATION, traceCount)));
+ }
+ }
+ }
+ } else {
+ assertTrue("Launch order is not valid parameter", false);
+ }
+ }
+
+ private void dropCache() {
+ if (true == mDropCache) {
+ assertNotNull("Issue in dropping the cache",
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand(DROP_CACHE_SCRIPT));
+ }
+ }
+
private void parseArgs(Bundle args) {
mNameToResultKey = new LinkedHashMap<String, String>();
- mNameToLaunchTime = new HashMap<String, Long>();
+ mNameToLaunchTime = new HashMap<String, List<Long>>();
String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS);
if (launchIterations != null) {
mLaunchIterations = Integer.parseInt(launchIterations);
@@ -169,7 +382,7 @@
}
mNameToResultKey.put(parts[0], parts[1]);
- mNameToLaunchTime.put(parts[0], 0L);
+ mNameToLaunchTime.put(parts[0], null);
}
String requiredAccounts = args.getString(KEY_REQUIRED_ACCOUNTS);
if (requiredAccounts != null) {
@@ -178,7 +391,7 @@
mRequiredAccounts.add(accountType);
}
}
- mSkipInitialLaunch = "true".equals(args.getString(KEY_SKIP_INITIAL_LAUNCH));
+ mTrailLaunch = "true".equals(args.getString(KEY_TRIAL_LAUNCH));
}
private boolean hasLeanback(Context context) {
@@ -222,7 +435,7 @@
}
}
- private long startApp(String appName, boolean forceStopBeforeLaunch)
+ private long startApp(String appName, boolean forceStopBeforeLaunch, String launchReason)
throws NameNotFoundException, RemoteException {
Log.i(TAG, "Starting " + appName);
@@ -230,9 +443,10 @@
if (startIntent == null) {
Log.w(TAG, "App does not exist: " + appName);
mResult.putString(mNameToResultKey.get(appName), "App does not exist");
- return -1;
+ return -1L;
}
- AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch);
+ AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch ,
+ launchReason);
Thread t = new Thread(runnable);
t.start();
try {
@@ -240,21 +454,7 @@
} catch (InterruptedException e) {
// ignore
}
- WaitResult result = runnable.getResult();
- // report error if any of the following is true:
- // * launch thread is alive
- // * result is not null, but:
- // * result is not START_SUCCESS
- // * or in case of no force stop, result is not TASK_TO_FRONT either
- if (t.isAlive() || (result != null
- && ((result.result != ActivityManager.START_SUCCESS)
- && (!forceStopBeforeLaunch
- && result.result != ActivityManager.START_TASK_TO_FRONT)))) {
- Log.w(TAG, "Assuming app " + appName + " crashed.");
- reportError(appName, mNameToProcess.get(appName));
- return -1;
- }
- return result.thisTime;
+ return runnable.getResult();
}
private void checkAccountSignIn() {
@@ -337,39 +537,117 @@
+ " not found in process list, most likely it is crashed");
}
- private class AppLaunchRunnable implements Runnable {
- private Intent mLaunchIntent;
- private IActivityManager.WaitResult mResult;
- private boolean mForceStopBeforeLaunch;
+ private class LaunchOrder {
+ private String mApp;
+ private String mLaunchReason;
- public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch) {
- mLaunchIntent = intent;
- mForceStopBeforeLaunch = forceStopBeforeLaunch;
+ LaunchOrder(String app,String launchReason){
+ mApp = app;
+ mLaunchReason = launchReason;
}
- public IActivityManager.WaitResult getResult() {
+ public String getApp() {
+ return mApp;
+ }
+
+ public void setApp(String app) {
+ mApp = app;
+ }
+
+ public String getLaunchReason() {
+ return mLaunchReason;
+ }
+
+ public void setLaunchReason(String launchReason) {
+ mLaunchReason = launchReason;
+ }
+ }
+
+ private class AppLaunchRunnable implements Runnable {
+ private Intent mLaunchIntent;
+ private Long mResult;
+ private boolean mForceStopBeforeLaunch;
+ private String mLaunchReason;
+
+ public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch,
+ String launchReason) {
+ mLaunchIntent = intent;
+ mForceStopBeforeLaunch = forceStopBeforeLaunch;
+ mLaunchReason = launchReason;
+ }
+
+ public Long getResult() {
return mResult;
}
public void run() {
try {
String packageName = mLaunchIntent.getComponent().getPackageName();
+ String componentName = mLaunchIntent.getComponent().flattenToShortString();
if (mForceStopBeforeLaunch) {
mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
}
- String mimeType = mLaunchIntent.getType();
- if (mimeType == null && mLaunchIntent.getData() != null
- && "content".equals(mLaunchIntent.getData().getScheme())) {
- mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
- UserHandle.USER_CURRENT);
+ String launchCmd = String.format("%s %s", APP_LAUNCH_CMD, componentName);
+ if (null != mSimplePerfCmd) {
+ launchCmd = String.format("%s %s", mSimplePerfCmd, launchCmd);
}
-
- mResult = mAm.startActivityAndWait(null, null, mLaunchIntent, mimeType,
- null, null, 0, mLaunchIntent.getFlags(), null, null,
- UserHandle.USER_CURRENT);
+ Log.v(TAG, "Final launch cmd:" + launchCmd);
+ ParcelFileDescriptor parcelDesc = getInstrumentation().getUiAutomation()
+ .executeShellCommand(launchCmd);
+ mResult = Long.parseLong(parseLaunchTimeAndWrite(parcelDesc, String.format
+ ("App Launch :%s %s",
+ componentName, mLaunchReason)), 10);
} catch (RemoteException e) {
Log.w(TAG, "Error launching app", e);
}
}
+
+ /**
+ * Method to parse the launch time info and write the result to file
+ *
+ * @param parcelDesc
+ * @return
+ */
+ private String parseLaunchTimeAndWrite(ParcelFileDescriptor parcelDesc, String headerInfo) {
+ String launchTime = "-1";
+ boolean launchSuccess = false;
+ try {
+ InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor());
+ StringBuilder appLaunchOuput = new StringBuilder();
+ /* SAMPLE OUTPUT :
+ Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator }
+ Status: ok
+ Activity: com.google.android.calculator/com.android.calculator2.Calculator
+ ThisTime: 357
+ TotalTime: 357
+ WaitTime: 377
+ Complete*/
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ inputStream));
+ String line = null;
+ int lineCount = 1;
+ mBufferedWriter.newLine();
+ mBufferedWriter.write(headerInfo);
+ mBufferedWriter.newLine();
+ while ((line = bufferedReader.readLine()) != null) {
+ if (lineCount == 2 && line.contains(SUCCESS_MESSAGE)) {
+ launchSuccess = true;
+ }
+ if (launchSuccess && lineCount == 4) {
+ String launchSplit[] = line.split(":");
+ launchTime = launchSplit[1].trim();
+ }
+ mBufferedWriter.write(line);
+ mBufferedWriter.newLine();
+ lineCount++;
+ }
+ mBufferedWriter.flush();
+ inputStream.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Error writing the launch file", e);
+ }
+ return launchTime;
+ }
+
}
}