From ad30a85cfce580bcde7287221db3b1aa56230897 Mon Sep 17 00:00:00 2001 From: Xavier Ducrohet <> Date: Fri, 27 Mar 2009 14:31:26 -0700 Subject: [PATCH 01/45] AI 143143: Update ADT changes.txt with JUnit features, and properly restrict ADT package access. BUG=1743054 Automated import of CL 143143 --- tools/eclipse/changes.txt | 1 + .../com.android.ide.eclipse.adt/META-INF/MANIFEST.MF | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/eclipse/changes.txt b/tools/eclipse/changes.txt index 8cd843e20..02d907585 100644 --- a/tools/eclipse/changes.txt +++ b/tools/eclipse/changes.txt @@ -5,6 +5,7 @@ * Project properties (right click project in Package Explorer, then "Properties"), lets you edit project target. * New Launch configuration option to choose debug deployment target. - Ability to export multiple apk from one project, using resource filters. See the 'android' property for Android projects. +- Support for running JUnit tests on a device/emulator from a new "Android JUnit tests" launch configuration. 0.8.1: diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF index c0dfcefd5..0ec97aa38 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF @@ -45,16 +45,16 @@ Require-Bundle: com.android.ide.eclipse.ddms, org.eclipse.ltk.core.refactoring, org.eclipse.ltk.ui.refactoring Eclipse-LazyStart: true -Export-Package: com.android.ide.eclipse.adt, +Export-Package: com.android.ide.eclipse.adt;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.launch;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.project;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.project.internal;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.sdk;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.wizards.newproject;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.eclipse.common, - com.android.ide.eclipse.common.project, - com.android.ide.eclipse.common.resources, + com.android.ide.eclipse.common;x-friends:="com.android.ide.eclipse.tests", + com.android.ide.eclipse.common.project;x-friends:="com.android.ide.eclipse.tests", + com.android.ide.eclipse.common.resources;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.editors;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.editors.descriptors;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.editors.layout;x-friends:="com.android.ide.eclipse.tests", From fe8bec70caf01fa91ae3dd05bc441ba7d7b66929 Mon Sep 17 00:00:00 2001 From: Xavier Ducrohet <> Date: Fri, 27 Mar 2009 15:05:58 -0700 Subject: [PATCH 02/45] AI 143149: Make ADT look for javadoc in docs/reference for the optional libraries (to match the base docs). BUG=1743022 Automated import of CL 143149 --- .../com/android/ide/eclipse/common/AndroidConstants.java | 5 +++-- .../libs/sdklib/src/com/android/sdklib/AddOnTarget.java | 3 ++- .../libs/sdklib/src/com/android/sdklib/SdkConstants.java | 2 ++ .../sdkuilib/src/com/android/sdkuilib/AvdSelector.java | 8 ++++---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java index 226357f7a..d0d8ae3af 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java @@ -90,7 +90,7 @@ public class AndroidConstants { /** Name of the android sources directory */ public static final String FD_ANDROID_SOURCES = "sources"; //$NON-NLS-1$ - + /** Resource java class filename, i.e. "R.java" */ public final static String FN_RESOURCE_CLASS = "R.java"; //$NON-NLS-1$ /** Resource class file filename, i.e. "R.class" */ @@ -128,7 +128,8 @@ public class AndroidConstants { public final static String WS_ASSETS = WS_SEP + SdkConstants.FD_ASSETS; /** Leaf of the javaDoc folder. Does not start with a separator. */ - public final static String WS_JAVADOC_FOLDER_LEAF = SdkConstants.FD_DOCS + "/reference"; //$NON-NLS-1$ + public final static String WS_JAVADOC_FOLDER_LEAF = SdkConstants.FD_DOCS + "/" + + SdkConstants.FD_DOCS_REFERENCE; //$NON-NLS-1$ /** Path of the samples directory relative to the sdk folder. * This is an OS path, ending with a separator. diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java index 0a5910734..d1ae343d5 100644 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java @@ -153,7 +153,8 @@ final class AddOnTarget implements IAndroidTarget { case SKINS: return mLocation + SdkConstants.OS_SKINS_FOLDER; case DOCS: - return mLocation + SdkConstants.FD_DOCS + File.separator; + return mLocation + SdkConstants.FD_DOCS + File.separator + + SdkConstants.FD_DOCS_REFERENCE; default : return mBasePlatform.getPath(pathId); } diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java index 00594d12f..9eb6ade6b 100644 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java @@ -143,6 +143,8 @@ public final class SdkConstants { public final static String FD_LIB = "lib"; /** Name of the SDK docs folder. */ public final static String FD_DOCS = "docs"; + /** Name of the doc folder containing API reference doc (javadoc) */ + public static final String FD_DOCS_REFERENCE = "reference"; /** Name of the SDK images folder. */ public final static String FD_IMAGES = "images"; /** Name of the SDK skins folder. */ diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/AvdSelector.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/AvdSelector.java index 67c70a676..d62c231c1 100644 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/AvdSelector.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/AvdSelector.java @@ -89,9 +89,9 @@ public final class AvdSelector { final TableColumn column1 = new TableColumn(mTable, SWT.NONE); column1.setText("Target Name"); final TableColumn column2 = new TableColumn(mTable, SWT.NONE); - column2.setText("API Level"); + column2.setText("SDK"); final TableColumn column3 = new TableColumn(mTable, SWT.NONE); - column3.setText("SDK"); + column3.setText("API Level"); adjustColumnsWidth(mTable, column0, column1, column2, column3); setupSelectionListener(mTable); @@ -235,8 +235,8 @@ public final class AvdSelector { Rectangle r = table.getClientArea(); column0.setWidth(r.width * 30 / 100); // 30% column1.setWidth(r.width * 45 / 100); // 45% - column2.setWidth(r.width * 15 / 100); // 15% - column3.setWidth(r.width * 10 / 100); // 10% + column2.setWidth(r.width * 10 / 100); // 10% + column3.setWidth(r.width * 15 / 100); // 15% } }); } From 729ff799f77fff783ba1fa46d9adb57e500e4150 Mon Sep 17 00:00:00 2001 From: Jack Palevich <> Date: Fri, 27 Mar 2009 15:49:45 -0700 Subject: [PATCH 03/45] AI 143256: Make the Term emulator work with the most recent keyboard IME. + Makes the "Enter" key work again. + Makes the "Delete" key delete just one character each time you press it instead of two. BUG=1615131 Automated import of CL 143256 --- apps/Term/src/com/android/term/Term.java | 36 +++++++++--------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/apps/Term/src/com/android/term/Term.java b/apps/Term/src/com/android/term/Term.java index d74159b90..1f43843a3 100644 --- a/apps/Term/src/com/android/term/Term.java +++ b/apps/Term/src/com/android/term/Term.java @@ -548,16 +548,6 @@ public class Term extends Activity { + controlKey + " 6 ==> Control-^"). show(); } - - private void print(String msg) { - char[] chars = msg.toCharArray(); - int len = chars.length; - byte[] bytes = new byte[len]; - for (int i = 0; i < len; i++) { - bytes[i] = (byte) chars[i]; - } - mEmulatorView.append(bytes, 0, len); - } } @@ -2707,8 +2697,13 @@ class EmulatorView extends View implements GestureDetector.OnGestureListener { return null; } - public boolean hideStatusIcon() { - return true; + public boolean performEditorAction(int actionCode) { + if(actionCode == EditorInfo.IME_ACTION_UNSPECIFIED) { + // The "return" key has been pressed on the IME. + sendText("\n"); + return true; + } + return false; } public boolean performContextMenuAction(int id) { @@ -2720,13 +2715,12 @@ class EmulatorView extends View implements GestureDetector.OnGestureListener { } public boolean sendKeyEvent(KeyEvent event) { - switch(event.getKeyCode()) { - case KeyEvent.KEYCODE_ENTER: - sendChar('\r'); - break; - case KeyEvent.KEYCODE_DEL: - sendChar(127); - break; + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch(event.getKeyCode()) { + case KeyEvent.KEYCODE_DEL: + sendChar(127); + break; + } } return true; } @@ -2739,10 +2733,6 @@ class EmulatorView extends View implements GestureDetector.OnGestureListener { return true; } - public boolean showStatusIcon(String packageName, int resId) { - return true; - } - private void sendChar(int c) { try { mTermOut.write(c); From f739e79bf4387a6accbd066291f7ee082f9c2259 Mon Sep 17 00:00:00 2001 From: Raphael Moll <> Date: Fri, 27 Mar 2009 16:06:03 -0700 Subject: [PATCH 04/45] AI 143259: ADT #1743364: Refactor all wizard classes & their actions together. BUG=1743364 Automated import of CL 143259 --- .../ide/eclipse/adt/wizards/actions/NewXmlFileAction.java | 2 +- .../{project => wizards/actions}/NewXmlFileWizardAction.java | 4 ++-- .../wizards/newxmlfile}/NewXmlFileCreationPage.java | 3 ++- .../wizards => adt/wizards/newxmlfile}/NewXmlFileWizard.java | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) rename tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/{project => wizards/actions}/NewXmlFileWizardAction.java (94%) rename tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/{editors/wizards => adt/wizards/newxmlfile}/NewXmlFileCreationPage.java (99%) rename tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/{editors/wizards => adt/wizards/newxmlfile}/NewXmlFileWizard.java (98%) diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/actions/NewXmlFileAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/actions/NewXmlFileAction.java index 8c4a115b4..d1530d4ea 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/actions/NewXmlFileAction.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/actions/NewXmlFileAction.java @@ -16,7 +16,7 @@ package com.android.ide.eclipse.adt.wizards.actions; -import com.android.ide.eclipse.editors.wizards.NewXmlFileWizard; +import com.android.ide.eclipse.adt.wizards.newxmlfile.NewXmlFileWizard; import org.eclipse.jface.action.IAction; import org.eclipse.ui.IWorkbenchWizard; diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/actions/NewXmlFileWizardAction.java similarity index 94% rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/actions/NewXmlFileWizardAction.java index c117b4e57..20cfc8275 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/NewXmlFileWizardAction.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/actions/NewXmlFileWizardAction.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.ide.eclipse.adt.project; +package com.android.ide.eclipse.adt.wizards.actions; -import com.android.ide.eclipse.editors.wizards.NewXmlFileWizard; +import com.android.ide.eclipse.adt.wizards.newxmlfile.NewXmlFileWizard; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newxmlfile/NewXmlFileCreationPage.java similarity index 99% rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newxmlfile/NewXmlFileCreationPage.java index 83ab59be1..f3cbfa221 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileCreationPage.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newxmlfile/NewXmlFileCreationPage.java @@ -15,7 +15,7 @@ */ -package com.android.ide.eclipse.editors.wizards; +package com.android.ide.eclipse.adt.wizards.newxmlfile; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.sdk.AndroidTargetData; @@ -31,6 +31,7 @@ import com.android.ide.eclipse.editors.resources.configurations.FolderConfigurat import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier; import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors; import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; +import com.android.ide.eclipse.editors.wizards.ConfigurationSelector; import com.android.ide.eclipse.editors.wizards.ConfigurationSelector.ConfigurationState; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.SdkConstants; diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newxmlfile/NewXmlFileWizard.java similarity index 98% rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newxmlfile/NewXmlFileWizard.java index 125102b96..d7e43cfd7 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/wizards/NewXmlFileWizard.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newxmlfile/NewXmlFileWizard.java @@ -16,11 +16,11 @@ -package com.android.ide.eclipse.editors.wizards; +package com.android.ide.eclipse.adt.wizards.newxmlfile; import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.wizards.newxmlfile.NewXmlFileCreationPage.TypeInfo; import com.android.ide.eclipse.editors.IconFactory; -import com.android.ide.eclipse.editors.wizards.NewXmlFileCreationPage.TypeInfo; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; From 3141ffd322e03b0d7d71f4e3a3052aec2418a54e Mon Sep 17 00:00:00 2001 From: Xavier Ducrohet <> Date: Fri, 27 Mar 2009 18:28:38 -0700 Subject: [PATCH 05/45] AI 143407: Prevent reinstalling APKs during launch if they have not been recompiled since the previous launch. BUG=1743026 Automated import of CL 143407 --- .../ide/eclipse/adt/build/ApkBuilder.java | 4 + .../adt/launch/AndroidLaunchController.java | 46 +++- .../adt/project/ApkInstallManager.java | 207 ++++++++++++++++++ 3 files changed, 250 insertions(+), 7 deletions(-) create mode 100644 tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ApkInstallManager.java diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java index 1edcf79fd..47ea3e731 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java @@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.build; import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.project.ApkInstallManager; import com.android.ide.eclipse.adt.project.ProjectHelper; import com.android.ide.eclipse.adt.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.sdk.Sdk; @@ -551,6 +552,9 @@ public class ApkBuilder extends BaseBuilder { // and store it saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); + // reset the installation manager to force new installs of this project + ApkInstallManager.getInstance().resetInstallationFor(project); + AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), "Build Success!"); } diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java index fafc4020b..b6c7640c7 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java @@ -32,6 +32,7 @@ import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.launch.AndroidLaunchConfiguration.TargetMode; import com.android.ide.eclipse.adt.launch.DelayedLaunchInfo.InstallRetryMode; import com.android.ide.eclipse.adt.launch.DeviceChooserDialog.DeviceChooserResponse; +import com.android.ide.eclipse.adt.project.ApkInstallManager; import com.android.ide.eclipse.adt.project.ProjectHelper; import com.android.ide.eclipse.adt.sdk.Sdk; import com.android.ide.eclipse.common.project.AndroidManifestParser; @@ -762,13 +763,46 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener /** - * Syncs the application on the device/emulator. + * If needed, syncs the application and all its dependencies on the device/emulator. * * @param launchInfo The Launch information object. * @param device the device on which to sync the application * @return true if the install succeeded. */ private boolean syncApp(DelayedLaunchInfo launchInfo, IDevice device) { + boolean alreadyInstalled = ApkInstallManager.getInstance().isApplicationInstalled( + launchInfo.getProject(), device); + + if (alreadyInstalled) { + AdtPlugin.printToConsole(launchInfo.getProject(), + "Application already deployed. No need to reinstall."); + } else { + if (doSyncApp(launchInfo, device) == false) { + return false; + } + } + + // The app is now installed, now try the dependent projects + for (DelayedLaunchInfo dependentLaunchInfo : getDependenciesLaunchInfo(launchInfo)) { + String msg = String.format("Project dependency found, installing: %s", + dependentLaunchInfo.getProject().getName()); + AdtPlugin.printToConsole(launchInfo.getProject(), msg); + if (syncApp(dependentLaunchInfo, device) == false) { + return false; + } + } + + return true; + } + + /** + * Syncs the application on the device/emulator. + * + * @param launchInfo The Launch information object. + * @param device the device on which to sync the application + * @return true if the install succeeded. + */ + private boolean doSyncApp(DelayedLaunchInfo launchInfo, IDevice device) { SyncService sync = device.getSyncService(); if (sync != null) { IPath path = launchInfo.getPackageFile().getLocation(); @@ -812,12 +846,10 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener return false; } - // The app is now installed, now try the dependent projects - for (DelayedLaunchInfo dependentLaunchInfo : getDependenciesLaunchInfo(launchInfo)) { - String msg = String.format("Project dependency found, syncing: %s", - dependentLaunchInfo.getProject().getName()); - AdtPlugin.printToConsole(launchInfo.getProject(), msg); - syncApp(dependentLaunchInfo, device); + // if the installation succeeded, we register it. + if (installResult) { + ApkInstallManager.getInstance().registerInstallation( + launchInfo.getProject(), device); } return installResult; diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ApkInstallManager.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ApkInstallManager.java new file mode 100644 index 000000000..172c555f4 --- /dev/null +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ApkInstallManager.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.eclipse.org/org/documents/epl-v10.php + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ide.eclipse.adt.project; + +import com.android.ddmlib.AndroidDebugBridge; +import com.android.ddmlib.Device; +import com.android.ddmlib.IDevice; +import com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener; +import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; +import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor; +import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener; + +import org.eclipse.core.resources.IProject; + +import java.util.ArrayList; + +/** + * Registers which apk was installed on which device. + *
+ * The goal of this class is to remember the installation of APKs on devices, and provide + * information about whether a new APK should be installed on a device prior to running the + * application from a launch configuration. + * + * The manager uses {@link IProject} and {@link IDevice} to identify the target device and the + * (project generating the) APK. This ensures that disconnected and reconnected devices will + * always receive new APKs (since the APK could be uninstalled manually). + * + * Manually uninstalling an APK from a connected device will still be a problem, but this should + * be a limited use case. + * + * This is a singleton. To get the instance, use {@link #getInstance()} + */ +public class ApkInstallManager implements IDeviceChangeListener, IDebugBridgeChangeListener, + IProjectListener { + + private final static ApkInstallManager sThis = new ApkInstallManager(); + + /** + * Internal struct to associate a project and a device. + */ + private static class ApkInstall { + public ApkInstall(IProject project, IDevice device) { + this.project = project; + this.device = device; + } + IProject project; + IDevice device; + } + + private final ArrayListnull for this specified project, for any device.
+ * @param project the project for which to reset all installations.
+ */
+ public void resetInstallationFor(IProject project) {
+ synchronized (mInstallList) {
+ for (int i = 0 ; i < mInstallList.size() ;) {
+ ApkInstall install = mInstallList.get(i);
+ if (install.project == project) {
+ mInstallList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ }
+ }
+
+ private ApkInstallManager() {
+ AndroidDebugBridge.addDeviceChangeListener(this);
+ AndroidDebugBridge.addDebugBridgeChangeListener(this);
+ ResourceMonitor.getMonitor().addProjectListener(this);
+ }
+
+ /*
+ * Responds to a bridge change by clearing the full installation list.
+ * (non-Javadoc)
+ * @see com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener#bridgeChanged(com.android.ddmlib.AndroidDebugBridge)
+ */
+ public void bridgeChanged(AndroidDebugBridge bridge) {
+ // the bridge changed, there is no way to know which IDevice will be which.
+ // We reset everything
+ synchronized (mInstallList) {
+ mInstallList.clear();
+ }
+ }
+
+ /*
+ * Responds to a device being disconnected by removing all installations related to this device.
+ * (non-Javadoc)
+ * @see com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener#deviceDisconnected(com.android.ddmlib.Device)
+ */
+ public void deviceDisconnected(Device device) {
+ synchronized (mInstallList) {
+ for (int i = 0 ; i < mInstallList.size() ;) {
+ ApkInstall install = mInstallList.get(i);
+ if (install.device == device) {
+ mInstallList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ }
+ }
+
+ /*
+ * Responds to a close project by resetting all its installation.
+ * (non-Javadoc)
+ * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener#projectClosed(org.eclipse.core.resources.IProject)
+ */
+ public void projectClosed(IProject project) {
+ resetInstallationFor(project);
+ }
+
+ /*
+ * Responds to a close project by resetting all its installation.
+ * (non-Javadoc)
+ * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener#projectDeleted(org.eclipse.core.resources.IProject)
+ */
+ public void projectDeleted(IProject project) {
+ resetInstallationFor(project);
+ }
+
+ /*
+ * Does nothing
+ * (non-Javadoc)
+ * @see com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener#deviceChanged(com.android.ddmlib.Device, int)
+ */
+ public void deviceChanged(Device device, int changeMask) {
+ // nothing to do.
+ }
+
+ /*
+ * Does nothing
+ * (non-Javadoc)
+ * @see com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener#deviceConnected(com.android.ddmlib.Device)
+ */
+ public void deviceConnected(Device device) {
+ // nothing to do.
+ }
+
+ /*
+ * Does nothing
+ * (non-Javadoc)
+ * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener#projectOpened(org.eclipse.core.resources.IProject)
+ */
+ public void projectOpened(IProject project) {
+ // nothing to do.
+ }
+
+ /*
+ * Does nothing
+ * (non-Javadoc)
+ * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener#projectOpenedWithWorkspace(org.eclipse.core.resources.IProject)
+ */
+ public void projectOpenedWithWorkspace(IProject project) {
+ // nothing to do.
+ }
+}
From 2f1d5e3425bf4a530fc74d0c0c1448fd97547b8f Mon Sep 17 00:00:00 2001
From: Amith Yamasani <>
Date: Mon, 30 Mar 2009 07:28:42 -0700
Subject: [PATCH 06/45] AI 143472: Reduce dictionary size. Changed the tree
structure to have variable length nodes to save an average of 21% on the
dictionary size. Created a shortened English dictionary for Dream - 50K
words. Added a shortened Spanish dictionary for Dream - 32K words.
BUG=1743626
Automated import of CL 143472
---
.../tools/dict/MakeBinaryDictionary.java | 100 ++++++++++++------
1 file changed, 67 insertions(+), 33 deletions(-)
diff --git a/tools/makedict/src/com/android/tools/dict/MakeBinaryDictionary.java b/tools/makedict/src/com/android/tools/dict/MakeBinaryDictionary.java
index cbe702872..8a8a677da 100755
--- a/tools/makedict/src/com/android/tools/dict/MakeBinaryDictionary.java
+++ b/tools/makedict/src/com/android/tools/dict/MakeBinaryDictionary.java
@@ -45,6 +45,10 @@ public class MakeBinaryDictionary {
public static final String TAG_WORD = "w";
public static final String ATTR_FREQ = "f";
+ private static final int FLAG_ADDRESS_MASK = 0x400000;
+ private static final int FLAG_TERMINAL_MASK = 0x800000;
+ private static final int ADDRESS_MASK = 0x3FFFFF;
+
public static final CharNode EMPTY_NODE = new CharNode();
Listnull if not
+ * specified.
+ *
+ * @param configuration the {@link ILaunchConfiguration} to retrieve the test package info from
+ * @return the test package or null.
+ */
+ private String getTestPackage(ILaunchConfiguration configuration) {
+ // try to retrieve a package name from the JUnit container attribute
+ String containerHandle = getStringLaunchAttribute(
+ JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, configuration);
+ if (containerHandle != null && containerHandle.length() > 0) {
+ IJavaElement element = JavaCore.create(containerHandle);
+ // containerHandle could be a IProject, check if its a java package
+ if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
+ return element.getElementName();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the test class stored in the launch configuration.
+ *
+ * @param configuration the {@link ILaunchConfiguration} to retrieve the test class info from
+ * @return the test class. null if not specified.
+ */
+ private String getTestClass(ILaunchConfiguration configuration) {
+ return getStringLaunchAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME,
+ configuration);
+ }
+
+ /**
+ * Returns the test method stored in the launch configuration.
+ *
+ * @param configuration the {@link ILaunchConfiguration} to retrieve the test method info from
+ * @return the test method. null if not specified.
+ */
+ private String getTestMethod(ILaunchConfiguration configuration) {
+ return getStringLaunchAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME,
+ configuration);
+ }
+
/**
* Gets a instrumentation runner for the launch.
*
@@ -114,11 +167,29 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
}
private String getRunnerFromConfig(ILaunchConfiguration configuration) throws CoreException {
- String runner = configuration.getAttribute(ATTR_INSTR_NAME, EMPTY_STRING);
- if (runner.length() < 1) {
- return null;
+ return getStringLaunchAttribute(ATTR_INSTR_NAME, configuration);
+ }
+
+ /**
+ * Helper method to retrieve a string attribute from the launch configuration
+ *
+ * @param attributeName name of the launch attribute
+ * @param configuration the {@link ILaunchConfiguration} to retrieve the attribute from
+ * @return the attribute's value. null if not found.
+ */
+ private String getStringLaunchAttribute(String attributeName,
+ ILaunchConfiguration configuration) {
+ try {
+ String attrValue = configuration.getAttribute(attributeName, EMPTY_STRING);
+ if (attrValue.length() < 1) {
+ return null;
+ }
+ return attrValue;
+ } catch (CoreException e) {
+ AdtPlugin.log(e, String.format("Error when retrieving launch info %1$s", //$NON-NLS-1$
+ attributeName));
}
- return runner;
+ return null;
}
/**
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
index eb5748269..584d45eb1 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.launch.junit;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.launch.MainLaunchConfigTab;
import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.ProjectChooserHelper;
import org.eclipse.core.resources.IProject;
@@ -241,7 +242,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
private void createTestContainerSelectionGroup(Composite comp) {
mTestContainerRadioButton = new Button(comp, SWT.RADIO);
mTestContainerRadioButton.setText(
- JUnitMessages.JUnitLaunchConfigurationTab_label_containerTest);
+ "Run all tests in the selected project, or package");
GridData gd = new GridData();
gd.horizontalSpan = 3;
mTestContainerRadioButton.setLayoutData(gd);
@@ -249,12 +250,12 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
public void widgetSelected(SelectionEvent e) {
if (mTestContainerRadioButton.getSelection()) {
testModeChanged();
- }
+ }
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
-
+
mContainerText = new Text(comp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalIndent = 25;
@@ -265,7 +266,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
updateLaunchConfigurationDialog();
}
});
-
+
mContainerSearchButton = new Button(comp, SWT.PUSH);
mContainerSearchButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_search);
mContainerSearchButton.addSelectionListener(new SelectionAdapter() {
@@ -821,7 +822,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
@SuppressWarnings("unchecked")
private IJavaElement chooseContainer(IJavaElement initElement) {
- Class[] acceptedClasses = new Class[] { IPackageFragmentRoot.class, IJavaProject.class,
+ Class[] acceptedClasses = new Class[] { IJavaProject.class,
IPackageFragment.class };
TypedElementSelectionValidator validator = new TypedElementSelectionValidator(
acceptedClasses, false) {
@@ -839,7 +840,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
if (element instanceof IPackageFragmentRoot &&
((IPackageFragmentRoot) element).isArchive()) {
return false;
- }
+ }
try {
if (element instanceof IPackageFragment &&
!((IPackageFragment) element).hasChildren()) {
@@ -852,7 +853,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
}
};
- StandardJavaElementContentProvider provider = new StandardJavaElementContentProvider();
+ AndroidJavaElementContentProvider provider = new AndroidJavaElementContentProvider();
ILabelProvider labelProvider = new JavaElementLabelProvider(
JavaElementLabelProvider.SHOW_DEFAULT);
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(),
@@ -974,4 +975,23 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
mInstrumentations = null;
mInstrumentationCombo.removeAll();
}
+
+ /**
+ * Overrides the {@link StandardJavaElementContentProvider} to only display Android projects
+ */
+ private static class AndroidJavaElementContentProvider
+ extends StandardJavaElementContentProvider {
+
+ /**
+ * Override parent to return only Android projects if at the root. Otherwise, use parent
+ * functionality.
+ */
+ @Override
+ public Object[] getChildren(Object element) {
+ if (element instanceof IJavaModel) {
+ return BaseProjectHelper.getAndroidProjects((IJavaModel) element);
+ }
+ return super.getChildren(element);
+ }
+ }
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitPropertyTester.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitPropertyTester.java
new file mode 100644
index 000000000..eadafee77
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitPropertyTester.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ide.eclipse.adt.launch.junit;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.junit.util.TestSearchEngine;
+
+/**
+ * A {@link PropertyTester} that checks if selected elements can be run as Android
+ * JUnit tests.
+ *
+ * Based on org.eclipse.jdt.internal.junit.JUnitPropertyTester. The only substantial difference in
+ * this implementation is source folders cannot be run as Android JUnit.
+ */
+@SuppressWarnings("restriction")
+public class AndroidJUnitPropertyTester extends PropertyTester {
+ private static final String PROPERTY_IS_TEST = "isTest"; //$NON-NLS-1$
+
+ private static final String PROPERTY_CAN_LAUNCH_AS_JUNIT_TEST = "canLaunchAsJUnit"; //$NON-NLS-1$
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.corext.refactoring.participants.properties.IPropertyEvaluator#test(java.lang.Object, java.lang.String, java.lang.String)
+ */
+ public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+ if (!(receiver instanceof IAdaptable)) {
+ final String elementName = (receiver == null ? "null" : //$NON-NLS-1$
+ receiver.getClass().getName());
+ throw new IllegalArgumentException(
+ String.format("Element must be of type IAdaptable, is %s", //$NON-NLS-1$
+ elementName));
+ }
+
+ IJavaElement element;
+ if (receiver instanceof IJavaElement) {
+ element = (IJavaElement) receiver;
+ } else if (receiver instanceof IResource) {
+ element = JavaCore.create((IResource) receiver);
+ if (element == null) {
+ return false;
+ }
+ } else { // is IAdaptable
+ element= (IJavaElement) ((IAdaptable) receiver).getAdapter(IJavaElement.class);
+ if (element == null) {
+ IResource resource = (IResource) ((IAdaptable) receiver).getAdapter(
+ IResource.class);
+ element = JavaCore.create(resource);
+ if (element == null) {
+ return false;
+ }
+ }
+ }
+ if (PROPERTY_IS_TEST.equals(property)) {
+ return isJUnitTest(element);
+ } else if (PROPERTY_CAN_LAUNCH_AS_JUNIT_TEST.equals(property)) {
+ return canLaunchAsJUnitTest(element);
+ }
+ throw new IllegalArgumentException(
+ String.format("Unknown test property '%s'", property)); //$NON-NLS-1$
+ }
+
+ private boolean canLaunchAsJUnitTest(IJavaElement element) {
+ try {
+ switch (element.getElementType()) {
+ case IJavaElement.JAVA_PROJECT:
+ return true; // can run, let JDT detect if there are tests
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+ return false; // not supported by Android test runner
+ case IJavaElement.PACKAGE_FRAGMENT:
+ return ((IPackageFragment) element).hasChildren();
+ case IJavaElement.COMPILATION_UNIT:
+ case IJavaElement.CLASS_FILE:
+ case IJavaElement.TYPE:
+ case IJavaElement.METHOD:
+ return isJUnitTest(element);
+ default:
+ return false;
+ }
+ } catch (JavaModelException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Return whether the target resource is a JUnit test.
+ */
+ private boolean isJUnitTest(IJavaElement element) {
+ try {
+ IType testType = null;
+ if (element instanceof ICompilationUnit) {
+ testType = (((ICompilationUnit) element)).findPrimaryType();
+ } else if (element instanceof IClassFile) {
+ testType = (((IClassFile) element)).getType();
+ } else if (element instanceof IType) {
+ testType = (IType) element;
+ } else if (element instanceof IMember) {
+ testType = ((IMember) element).getDeclaringType();
+ }
+ if (testType != null && testType.exists()) {
+ return TestSearchEngine.isTestOrTestSuite(testType);
+ }
+ } catch (CoreException e) {
+ // ignore, return false
+ }
+ return false;
+ }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/runtime/AndroidJUnitLaunchInfo.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/runtime/AndroidJUnitLaunchInfo.java
index 89cad97ae..8ac80cab5 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/runtime/AndroidJUnitLaunchInfo.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/runtime/AndroidJUnitLaunchInfo.java
@@ -15,35 +15,38 @@
*/
package com.android.ide.eclipse.adt.launch.junit.runtime;
-import org.eclipse.core.resources.IProject;
-
import com.android.ddmlib.IDevice;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.debug.core.ILaunch;
+
/**
* Contains info about Android JUnit launch
*/
public class AndroidJUnitLaunchInfo {
private final IProject mProject;
- private final String mTestPackage;
+ private final String mAppPackage;
private final String mRunner;
- private final boolean mDebugMode;
- private final IDevice mDevice;
-
- public AndroidJUnitLaunchInfo(IProject project, String testPackage, String runner,
- boolean debugMode, IDevice device) {
+
+ private boolean mDebugMode = false;
+ private IDevice mDevice = null;
+ private String mTestPackage = null;
+ private String mTestClass = null;
+ private String mTestMethod = null;
+ private ILaunch mLaunch = null;
+
+ public AndroidJUnitLaunchInfo(IProject project, String appPackage, String runner) {
mProject = project;
- mTestPackage = testPackage;
+ mAppPackage = appPackage;
mRunner = runner;
- mDebugMode = debugMode;
- mDevice = device;
}
-
+
public IProject getProject() {
return mProject;
}
- public String getTestPackage() {
- return mTestPackage;
+ public String getAppPackage() {
+ return mAppPackage;
}
public String getRunner() {
@@ -53,8 +56,80 @@ public class AndroidJUnitLaunchInfo {
public boolean isDebugMode() {
return mDebugMode;
}
+
+ public void setDebugMode(boolean debugMode) {
+ mDebugMode = debugMode;
+ }
public IDevice getDevice() {
return mDevice;
}
+
+ public void setDevice(IDevice device) {
+ mDevice = device;
+ }
+
+ /**
+ * Specify to run all tests within given package.
+ *
+ * @param testPackage fully qualified java package
+ */
+ public void setTestPackage(String testPackage) {
+ mTestPackage = testPackage;
+ }
+
+ /**
+ * Return the package of tests to run.
+ *
+ * @return fully qualified java package. null if not specified.
+ */
+ public String getTestPackage() {
+ return mTestPackage;
+ }
+
+ /**
+ * Sets the test class to run.
+ *
+ * @param testClass fully qualfied test class to run
+ * Expected format: x.y.x.testclass
+ */
+ public void setTestClass(String testClass) {
+ mTestClass = testClass;
+ }
+
+ /**
+ * Returns the test class to run.
+ *
+ * @return fully qualfied test class to run.
+ * null if not specified.
+ */
+ public String getTestClass() {
+ return mTestClass;
+ }
+
+ /**
+ * Sets the test method to run. testClass must also be set.
+ *
+ * @param testMethod test method to run
+ */
+ public void setTestMethod(String testMethod) {
+ mTestMethod = testMethod;
+ }
+
+ /**
+ * Returns the test method to run.
+ *
+ * @return test method to run. null if not specified.
+ */
+ public String getTestMethod() {
+ return mTestMethod;
+ }
+
+ public ILaunch getLaunch() {
+ return mLaunch;
+ }
+
+ public void setLaunch(ILaunch launch) {
+ mLaunch = launch;
+ }
}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/runtime/RemoteAdtTestRunner.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/runtime/RemoteAdtTestRunner.java
index 0a6a3daee..962d76133 100755
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/runtime/RemoteAdtTestRunner.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/runtime/RemoteAdtTestRunner.java
@@ -69,8 +69,9 @@ public class RemoteAdtTestRunner extends RemoteTestRunner {
* executing the tests, and send it back to JDT JUnit. The second is the actual test execution,
* whose results will be communicated back in real-time to JDT JUnit.
*
- * @param testClassNames array of fully qualified test class names to execute. Cannot be empty.
- * @param testName test to execute. If null, will be ignored.
+ * @param testClassNames ignored - the AndroidJUnitLaunchInfo will be used to determine which
+ * tests to run.
+ * @param testName ignored
* @param execution used to report test progress
*/
@Override
@@ -78,16 +79,21 @@ public class RemoteAdtTestRunner extends RemoteTestRunner {
// hold onto this execution reference so it can be used to report test progress
mExecution = execution;
- RemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(mLaunchInfo.getTestPackage(),
+ RemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(mLaunchInfo.getAppPackage(),
mLaunchInfo.getRunner(), mLaunchInfo.getDevice());
- if (testClassNames != null && testClassNames.length > 0) {
- if (testName != null) {
- runner.setMethodName(testClassNames[0], testName);
- } else {
- runner.setClassNames(testClassNames);
- }
+ if (mLaunchInfo.getTestClass() != null) {
+ if (mLaunchInfo.getTestMethod() != null) {
+ runner.setMethodName(mLaunchInfo.getTestClass(), mLaunchInfo.getTestMethod());
+ } else {
+ runner.setClassName(mLaunchInfo.getTestClass());
+ }
}
+
+ if (mLaunchInfo.getTestPackage() != null) {
+ runner.setTestPackageName(mLaunchInfo.getTestPackage());
+ }
+
// set log only to first collect test case info, so Eclipse has correct test case count/
// tree info
runner.setLogOnly(true);
From 8a2dece67d273e16565bee8d8d952bde0ea5b982 Mon Sep 17 00:00:00 2001
From: Raphael Moll <>
Date: Wed, 1 Apr 2009 12:29:32 -0700
Subject: [PATCH 18/45] AI 144048: ADT #1743364: Uncomment the system resource
chooser code. Rationale: we want to keep that code around, so we need to
compile it to make sure it doesn't use obsoleted APIs. That does it.
BUG=1743364
Automated import of CL 144048
---
.../ide/eclipse/adt/ui/ResourceChooser.java | 63 ++++++++++---------
1 file changed, 34 insertions(+), 29 deletions(-)
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/ui/ResourceChooser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/ui/ResourceChooser.java
index 4290f6b79..26396116c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/ui/ResourceChooser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/ui/ResourceChooser.java
@@ -20,6 +20,10 @@ import com.android.ide.eclipse.common.resources.IResourceRepository;
import com.android.ide.eclipse.common.resources.ResourceItem;
import com.android.ide.eclipse.common.resources.ResourceType;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
@@ -39,11 +43,11 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
private IResourceRepository mProjectResources;
- // TODO: enable when we can display the system resources.
- // private Pattern mSystemResourcePattern;
- // private IResourceRepository mSystemResources;
- // private Button mProjectButton;
- // private Button mSystemButton;
+ private final static boolean SHOW_SYSTEM_RESOURCE = false; // TODO re-enable at some point
+ private Pattern mSystemResourcePattern;
+ private IResourceRepository mSystemResources;
+ private Button mProjectButton;
+ private Button mSystemButton;
private String mCurrentResource;
@@ -60,14 +64,15 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
mResourceType = type;
mProjectResources = project;
- // TODO: enable when we can display the system resources.
- // mSystemResources = system;
mProjectResourcePattern = Pattern.compile(
"@" + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$ //$NON-NLS-2$
- // TODO: enable when we can display the system resources.
- // mSystemResourcePattern = Pattern.compile(
- // "@android:" + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ if (SHOW_SYSTEM_RESOURCE) {
+ mSystemResources = system;
+ mSystemResourcePattern = Pattern.compile(
+ "@android:" + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
setTitle("Resource Chooser");
setMessage(String.format("Choose a %1$s resource",
@@ -89,8 +94,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
ResourceItem item = (ResourceItem)elements[0];
mCurrentResource = mResourceType.getXmlString(item,
- // TODO: enable when we can display the system resources.
- false /*mSystemButton.getSelection()*/);
+ SHOW_SYSTEM_RESOURCE && mSystemButton.getSelection());
}
}
@@ -100,9 +104,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
createMessageArea(top);
- // TODO: enable when we can display the system resources.
- // createButtons(top);
-
+ createButtons(top);
createFilterText(top);
createFilteredList(top);
@@ -115,8 +117,10 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
* Creates the radio button to switch between project and system resources.
* @param top the parent composite
*/
- /* TODO: enable when we can display the system resources.
private void createButtons(Composite top) {
+ if (!SHOW_SYSTEM_RESOURCE) {
+ return;
+ }
mProjectButton = new Button(top, SWT.RADIO);
mProjectButton.setText("Project Resources");
mProjectButton.addSelectionListener(new SelectionAdapter() {
@@ -136,7 +140,6 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
}
});
}
- */
/**
* Setups the current list based on the current resource.
@@ -147,20 +150,22 @@ public class ResourceChooser extends AbstractElementListSelectionDialog {
ResourceItem[] items = mProjectResources.getResources(mResourceType);
setListElements(items);
}
- /*
- * TODO: enable when we can display the system resources.
- if (setupInitialSelection(mProjectResourcePattern, mProjectResources) == false) {
- if (setupInitialSelection(mSystemResourcePattern, mSystemResources) == false) {
- // if we couldn't understand the current value, we default to the project resources
- IResourceItem[] items = mProjectResources.getResources(mResourceType);
- setListElements(items);
- mProjectButton.setSelection(true);
+
+ if (SHOW_SYSTEM_RESOURCE) {
+ if (setupInitialSelection(mProjectResourcePattern, mProjectResources) == false) {
+ if (setupInitialSelection(mSystemResourcePattern, mSystemResources) == false) {
+ // if we couldn't understand the current value,
+ // we default to the project resources
+ ResourceItem[] items = mProjectResources.getResources(mResourceType);
+ setListElements(items);
+ mProjectButton.setSelection(true);
+ } else {
+ mSystemButton.setSelection(true);
+ }
} else {
- mSystemButton.setSelection(true);
+ mProjectButton.setSelection(true);
}
- } else {
- mProjectButton.setSelection(true);
- }*/
+ }
}
/**
From dfa5494492fbab008a932a116cc74553e27ab941 Mon Sep 17 00:00:00 2001
From: Mike Ritter <>
Date: Wed, 1 Apr 2009 17:30:12 -0700
Subject: [PATCH 19/45] AI 144164: Adding droiddocs/javadocs usage to Pdk-docs
to get correct style. BUG=1646802
Automated import of CL 144164
---
pdk/Pdk.mk | 72 +++-
pdk/README | 106 +++--
pdk/docs/audio_sub_system.html | 261 ------------
pdk/docs/audio_sub_system.jd | 56 +++
pdk/docs/bluetooth.html | 276 -------------
pdk/docs/bluetooth.jd | 82 ++++
pdk/docs/{bring_up.html => bring_up.jd} | 207 +---------
pdk/docs/build_new_device.html | 333 ---------------
pdk/docs/build_new_device.jd | 130 ++++++
.../{build_system.html => build_system.jd} | 210 +---------
pdk/docs/camera.html | 280 -------------
pdk/docs/camera.jd | 87 ++++
...isplay_drivers.html => display_drivers.jd} | 210 +---------
pdk/docs/getting_source_code.html | 335 ----------------
pdk/docs/getting_source_code.jd | 126 ++++++
pdk/docs/gps.html | 259 ------------
pdk/docs/gps.jd | 49 +++
.../{group__memory.html => group__memory.jd} | 25 +-
...__networking.html => group__networking.jd} | 26 +-
pdk/docs/index.html | 248 ------------
pdk/docs/index.jd | 39 ++
...work.html => instrumentation_framework.jd} | 181 +--------
...esting.html => instrumentation_testing.jd} | 211 +---------
pdk/docs/intro_source_code.html | 378 ------------------
pdk/docs/intro_source_code.jd | 169 ++++++++
...d_input.html => keymaps_keyboard_input.jd} | 210 +---------
pdk/docs/power_management.html | 311 --------------
pdk/docs/power_management.jd | 108 +++++
pdk/docs/source_setup_guide.html | 323 ---------------
pdk/docs/source_setup_guide.jd | 116 ++++++
pdk/docs/system_requirements.html | 262 ------------
pdk/docs/system_requirements.jd | 63 +++
pdk/docs/{telephony.html => telephony.jd} | 211 +---------
pdk/docs/wifi.html | 250 ------------
pdk/docs/wifi.jd | 49 +++
pdk/hosting/app.yaml | 4 +-
pdk/hosting/pdk.py | 18 +-
37 files changed, 1238 insertions(+), 5043 deletions(-)
delete mode 100755 pdk/docs/audio_sub_system.html
create mode 100755 pdk/docs/audio_sub_system.jd
delete mode 100755 pdk/docs/bluetooth.html
create mode 100755 pdk/docs/bluetooth.jd
rename pdk/docs/{bring_up.html => bring_up.jd} (66%)
delete mode 100755 pdk/docs/build_new_device.html
create mode 100755 pdk/docs/build_new_device.jd
rename pdk/docs/{build_system.html => build_system.jd} (62%)
delete mode 100755 pdk/docs/camera.html
create mode 100755 pdk/docs/camera.jd
rename pdk/docs/{display_drivers.html => display_drivers.jd} (61%)
delete mode 100755 pdk/docs/getting_source_code.html
create mode 100755 pdk/docs/getting_source_code.jd
delete mode 100755 pdk/docs/gps.html
create mode 100755 pdk/docs/gps.jd
rename pdk/docs/{group__memory.html => group__memory.jd} (54%)
rename pdk/docs/{group__networking.html => group__networking.jd} (57%)
delete mode 100755 pdk/docs/index.html
create mode 100644 pdk/docs/index.jd
rename pdk/docs/{instrumentation_framework.html => instrumentation_framework.jd} (50%)
rename pdk/docs/{instrumentation_testing.html => instrumentation_testing.jd} (77%)
delete mode 100755 pdk/docs/intro_source_code.html
create mode 100755 pdk/docs/intro_source_code.jd
rename pdk/docs/{keymaps_keyboard_input.html => keymaps_keyboard_input.jd} (71%)
delete mode 100755 pdk/docs/power_management.html
create mode 100755 pdk/docs/power_management.jd
delete mode 100755 pdk/docs/source_setup_guide.html
create mode 100755 pdk/docs/source_setup_guide.jd
delete mode 100755 pdk/docs/system_requirements.html
create mode 100755 pdk/docs/system_requirements.jd
rename pdk/docs/{telephony.html => telephony.jd} (61%)
delete mode 100755 pdk/docs/wifi.html
create mode 100755 pdk/docs/wifi.jd
diff --git a/pdk/Pdk.mk b/pdk/Pdk.mk
index abe9491d2..fbe8b5c90 100644
--- a/pdk/Pdk.mk
+++ b/pdk/Pdk.mk
@@ -16,7 +16,7 @@
# Assemble the Platform Development Kit (PDK)
# (TODO) Figure out why $(ACP) builds with target ndk but not pdk_docs
-# (TODO) Build doxygen (depend on latest version)
+# (TODO) Build doxygen (depend on latest version) -> line 25 error
pdk:
@echo "Package: $@ has targets ndk, pdk_docs and pdk_all"
@@ -38,6 +38,8 @@ include $(LOCAL_PATH)/ndk/Ndk.mk
# Doxygenize the header files to create html docs in the generatedDocs dir.
# Copy the appengine files, the template files and the generated html
# to the docs dir and zip everything up to the distribution directory.
+# Run javadocs/droiddocs/clearsilver on the generatedDocs dir to get the right
+# styles added to the html.
# Workspace directory
@@ -149,13 +151,27 @@ $(pdk_docs_intermediates)/pdk.py: $(pdk_hosting_dir)/pdk.py
@echo "PDK: $@"
$(copy-file-to-target-with-cp)
+# Copy appengine server files for new system
+$(OUT_DOCS)/app.yaml: $(pdk_hosting_dir)/app.yaml
+ @echo "PDK: $@"
+ $(copy-file-to-target-with-cp)
+
+$(OUT_DOCS)/pdk.py: $(pdk_hosting_dir)/pdk.py
+ @echo "PDK: $@"
+ $(copy-file-to-target-with-cp)
+
+# All the files that we depend upon
+all_pdk_docs_files := $(pdk_doxygen_config_override_file) \
+ $(pdk_doxygen_config_file) $(pdk_docs_intermediates)/header.html \
+ $(pdk_docs_intermediates)/footer.html $(pdk_doxy_docsfiles_dir)/groups.dox \
+ $(pdk_doxy_docsfiles_dir)/main.dox all_copied_pdk_templates
# Run doxygen and copy all output and templates to the final destination
# We replace index.html with a template file so don't use the generated one
pdk_doxygen: all_copied_pdk_headers $(pdk_doxygen_config_override_file) \
$(pdk_doxygen_config_file) $(pdk_docs_intermediates)/header.html \
$(pdk_docs_intermediates)/footer.html $(pdk_doxy_docsfiles_dir)/groups.dox \
- $(pdk_doxy_docsfiles_dir)/main.dox
+ $(pdk_doxy_docsfiles_dir)/main.dox
@echo "Files for Doxygination: $^"
@mkdir -p $(pdk_generated_source_dir)
@rm -f $(pdk_generated_source_dir)/*
@@ -164,7 +180,40 @@ pdk_doxygen: all_copied_pdk_headers $(pdk_doxygen_config_override_file) \
@cd $(pdk_generated_source_dir) && chmod ug+rx *
@rm -f $(pdk_generated_source_dir)/index.html
@cp -fp $(pdk_generated_source_dir)/* $(pdk_docs_dest_dir)
-
+
+
+# ==== docs for the web (on the google app engine server) =======================
+# Run javadoc/droiddoc/clearsilver to get the formatting right
+
+# make droiddocs run after we make our doxygen docs
+$(pdk_docs_intermediates)/pdk-timestamp: pdk_doxygen
+ @touch $(pdk_docs_intermediates)/pdk-timestamp
+
+$(LOCAL_PATH)/pdk-timestamp: $(pdk_docs_intermediates)/pdk-timestamp
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := pdk-timestamp samples/samplejni/src/com/example/jniexample/JNIExample.java
+LOCAL_MODULE_CLASS := development/pdk/ndk/samples/samplejni/src/com/example/jniexample
+LOCAL_DROIDDOC_SOURCE_PATH := $(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
+LOCAL_DROIDDOC_HTML_DIR := ../../../$(pdk_docs_dest_dir)
+
+LOCAL_MODULE := online-pdk
+
+LOCAL_DROIDDOC_OPTIONS := \
+ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
+ $(web_docs_sample_code_flags) \
+ -toroot /online-pdk/ \
+ -hdf android.whichdoc online-pdk
+
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := build/tools/droiddoc/templates-pdk
+LOCAL_DROIDDOC_CUSTOM_ASSET_DIR := assets-pdk
+
+include $(BUILD_DROIDDOC)
+
+# The docs output dir is: out/target/common/docs/online-pdk
+DOCS_OUT_DIR := $(OUT_DOCS)/$(LOCAL_MODULE)
+
# Name the tar files
name := android_pdk_docs-$(REQUESTED_PRODUCT)
ifeq ($(TARGET_BUILD_TYPE),debug)
@@ -173,21 +222,25 @@ endif
name := $(name)-$(BUILD_NUMBER)
pdk_docs_tarfile := $(pdk_docs_intermediates)/$(name).tar
pdk_docs_tarfile_zipped := $(pdk_docs_tarfile).gz
+new_pdk_docs_tarfile := $(pdk_docs_intermediates)/new-$(name).tar
+new_pdk_docs_tarfile_zipped := $(new_pdk_docs_tarfile).gz
-.PHONY: pdk pdk_docs pdk_doxygen all_copied_pdk_headers all_copied_pdk_templates
+.PHONY: pdk pdk_docs pdk_doxygen all_copied_pdk_headers all_copied_pdk_templates pdk-timestamp
-pdk_docs: $(pdk_docs_tarfile_zipped)
+pdk_docs: $(pdk_docs_tarfile_zipped) $(new_pdk_docs_tarfile)
@echo "PDK: Docs tarred and zipped"
# Put the pdk_docs zip files in the distribution directory
$(call dist-for-goals,pdk_docs,$(pdk_docs_tarfile_zipped))
+$(call dist-for-goals,pdk_docs,$(new_pdk_docs_tarfile_zipped))
# zip up tar files
%.tar.gz: %.tar
- @echo "PDK: zipped $<"
+ @echo "PDK docs: zipped $<"
$(hide) gzip -cf $< > $@
# tar up all the files to make the pdk docs.
+# old version
$(pdk_docs_tarfile): pdk_doxygen all_copied_pdk_templates \
$(pdk_docs_intermediates)/pdk.py $(pdk_docs_intermediates)/app.yaml
@echo "PDK: $@"
@@ -195,6 +248,13 @@ $(pdk_docs_tarfile): pdk_doxygen all_copied_pdk_templates \
@rm -f $@
$(hide) tar rf $@ -C $(pdk_docs_intermediates) docs pdk.py app.yaml
+# new version
+$(new_pdk_docs_tarfile): $(DOCS_OUT_DIR)-timestamp
+ @echo "PDK docs: $@"
+ @mkdir -p $(dir $@)
+ @rm -f $@
+ $(hide) tar rf $@ -C $(OUT_DOCS) $(LOCAL_MODULE)
+
# Debugging reporting can go here, add it as a target to get output.
pdk_debug:
@echo "You are here: $@"
diff --git a/pdk/README b/pdk/README
index 86621552e..18ff5d120 100644
--- a/pdk/README
+++ b/pdk/README
@@ -4,78 +4,72 @@ Building the pdk (platform development kit)
(We currently support version 1.4.6)
sudo apt-get install doxygen
+
+Make sure that you are using the right version of java
+
+ sudo update-java-alternatives -s java-1.5.0-sun
+
+If that doesn't work, go through the instructions on
+
+ http://source.android.com/download again.
+
2) from the root
. build/envsetup.sh
-3) run choosecombo
- Build for the simulator or the device?
- 1. Device
- 2. Simulator
-
- Which would you like? [1] 1
-
-
- Build type choices are:
- 1. release
- 2. debug
-
- Which would you like? [1] 1
-
-
- Product choices are:
- 0. emulator
- 1. generic
- 2. sim
- 3. surf
- You can also type the name of a product if you know it.
- Which would you like? [generic] 1
-
-
- Variant choices are:
- 1. user
- 2. userdebug
- 3. eng
- Which would you like? [eng] 3
-
- ============================================
- TARGET_PRODUCT=generic
- TARGET_BUILD_VARIANT=eng
- TARGET_SIMULATOR=false
- TARGET_BUILD_TYPE=release
- TARGET_ARCH=arm
- HOST_ARCH=x86
- HOST_OS=linux
- HOST_BUILD_TYPE=release
- BUILD_ID=
- ============================================
4) mkdir dist
mkdir logs
- mkpdkcupcake.sh
+
+then build everything:
-(which contains:
+ time make -j4 pdk pdk_all dist DIST_DIR=dist 2>&1 | tee logs/`date +%y%m%d-%H%M%S`
-DT=`date +%y%m%d-%H%M%S`
-time make -j4 pdk pdk_all dist DIST_DIR=dist 2>&1 | tee logs/$DT
+so you can have a record of the build commands in the logs directory.
-so you can see the results of the build in the logs directory.)
5) the pdk tar file is put in the dist directory.
+6) the pdk-docs are in
+
+ out/target
+
The build target 'pdk' brings in the pdk/ndk make files into the build system.
- Then there are three targets:
- pdk_docs - which builds the pdk documentation
- ndk - which builds the native development kit (native compiler, linker, etc.)
- pdk_all - which builds the above two targets
+ Then there are three targets:
+ pdk_docs - which builds just the pdk documentation
+ ndk - which builds the native development kit (native compiler, linker, etc.)
+ pdk_all - which builds the above two targets
-for doxygen version changing you can pass in the variable:
-doxygen_version='AudioHardwareInterface serves as the glue between proprietary audio drivers and the Android AudioFlinger service, the core audio service that handles all audio-related requests from applications.
-
To implement an audio driver, create a shared library that implements the interface defined in AudioHardwareInterface.h. You must name your shared library libaudio.so so that it will get loaded from /system/lib at runtime. Place libaudio sources and Android.mk in partner/acme/chipset_or_board/libaudio/.
The following stub Android.mk file ensures that libaudio compiles and links to the appropriate libraries:
-LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE := libaudio - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libmedia \ - libhardware - -LOCAL_SRC_FILES += MyAudioHardware.cpp - -LOCAL_CFLAGS += - -LOCAL_C_INCLUDES += - -LOCAL_STATIC_LIBRARIES += libaudiointerface - -include $(BUILD_SHARED_LIBRARY) -- - -
Note: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, click here.
- - - - - -AudioHardwareInterface serves as the glue between proprietary audio drivers and the Android AudioFlinger service, the core audio service that handles all audio-related requests from applications.
+
To implement an audio driver, create a shared library that implements the interface defined in AudioHardwareInterface.h. You must name your shared library libaudio.so so that it will get loaded from /system/lib at runtime. Place libaudio sources and Android.mk in partner/acme/chipset_or_board/libaudio/.
The following stub Android.mk file ensures that libaudio compiles and links to the appropriate libraries:
+LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := libaudio + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libmedia \ + libhardware + +LOCAL_SRC_FILES += MyAudioHardware.cpp + +LOCAL_CFLAGS += + +LOCAL_C_INCLUDES += + +LOCAL_STATIC_LIBRARIES += libaudiointerface + +include $(BUILD_SHARED_LIBRARY) ++ + +
Note: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, click here.
+ + + diff --git a/pdk/docs/bluetooth.html b/pdk/docs/bluetooth.html deleted file mode 100755 index edd3c260d..000000000 --- a/pdk/docs/bluetooth.html +++ /dev/null @@ -1,276 +0,0 @@ - - - -Android's Bluetooth stack uses BlueZ version 3.36 for GAP, SDP, and RFCOMM profiles, and is a SIG-qualified Bluetooth 2.0 host stack.
- -Bluez is GPL licensed, so the Android framework interacts with userspace bluez code through D-BUS IPC to avoid proprietary code.
- -Headset and Handsfree (v1.5) profiles are implemented in the Android framework and are both tightly coupled with the Phone App. These profiles are also SIG qualified.
- -The diagram below offers a library-oriented view of the Bluetooth stack. Click Bluetooth Process Diagram for a process-oriented view.
- -
BlueZ is Bluetooth 2.0 compatible and should work with any 2.0 chipset. There are two integration points:
-The BlueZ kernel sub-system attaches to your hardware-specific UART driver using the hciattach daemon.
For example, for MSM7201A, this is drivers/serial/msm_serial.c. You may also need to edit command line options to hciattach via init.rc.
The method for powering on and off your bluetooth chip varies from Android V 1.0 to post 1.0.
- -/sys/modules/board_[PLATFORM]/parameters/bluetooth_power_on.rfkill API. See arch/arm/mach-msm/board-trout-rfkill.c for an example.BlueZ provides a rich set of command line tools for debugging and interacting with the Bluetooth sub-system, including:
-hciconfighcitoolhcidumpsdptooldbus-senddbus-monitorAndroid's Bluetooth stack uses BlueZ version 3.36 for GAP, SDP, and RFCOMM profiles, and is a SIG-qualified Bluetooth 2.0 host stack.
+ +Bluez is GPL licensed, so the Android framework interacts with userspace bluez code through D-BUS IPC to avoid proprietary code.
+ +Headset and Handsfree (v1.5) profiles are implemented in the Android framework and are both tightly coupled with the Phone App. These profiles are also SIG qualified.
+ +The diagram below offers a library-oriented view of the Bluetooth stack. Click Bluetooth Process Diagram for a process-oriented view.
+ +
BlueZ is Bluetooth 2.0 compatible and should work with any 2.0 chipset. There are two integration points:
+The BlueZ kernel sub-system attaches to your hardware-specific UART driver using the hciattach daemon.
For example, for MSM7201A, this is drivers/serial/msm_serial.c. You may also need to edit command line options to hciattach via init.rc.
The method for powering on and off your bluetooth chip varies from Android V 1.0 to post 1.0.
+ +/sys/modules/board_[PLATFORM]/parameters/bluetooth_power_on.rfkill API. See arch/arm/mach-msm/board-trout-rfkill.c for an example.BlueZ provides a rich set of command line tools for debugging and interacting with the Bluetooth sub-system, including:
+hciconfighcitoolhcidumpsdptooldbus-senddbus-monitorOnce your code is built and you have verified that all necessary directories exist, power on and test your device with basic bring up, as described below. Bring up tests are typically designed to stress certain aspects of your system and allow you to characterize the device's behavior.
Before considering Android-specific modifications to the Linux kernel, verify that you can build, deploy, and boot a core Linux kernel on your target hardware.
+
Your kernel configuration file should include the following:
@@ -530,32 +358,3 @@ service akmd /sbin/akmd-
The directions below describe how to configure make files for new mobile devices and products.
-//device/partner.- mkdir device/partner/<company_name>
products directory beneath the company directory you created in step 1.- mkdir device/partner/<company_name>/products/
device/partner/<company_name>/products/<first_product_name>.mk, that includes the following code:- $(call inherit-product, target/product/generic.mk) - # - # Overrides - PRODUCT_NAME := <first_product_name> - PRODUCT_DEVICE := <board_name>
products directory, create an AndroidProducts.mk file that point to (and is responsible for finding) the individual product make files.- # - # This file should set PRODUCT_MAKEFILES to a list of product makefiles - # to expose to the build system. LOCAL_DIR will already be set to - # the directory containing this file. - # - # This file may not rely on the value of any variable other than - # LOCAL_DIR; do not use any conditionals, and do not look up the - # value of any variable that isn't set in this file or in a file that - # it includes. - # - - PRODUCT_MAKEFILES := \ - $(LOCAL_DIR)/first_product_name.mk \
PRODUCT_DEVICE variable <board_name> referenced in the product-specific make file above. This will include a make file that gets accessed by any product using this board.- mkdir device/partner/<company_name>/<board_name>
product_config.mk file in the directory created in the previous step (device/partner/<company_name>/<board_name>). If this directory does not include a product_config.mk file, the build will fail.- # These definitions override the defaults in config/config.make for <board_name> - # - # TARGET_NO_BOOTLOADER := false - # TARGET_HARDWARE_3D := false - # - TARGET_USE_GENERIC_AUDIO := true
system.prop file in your <board_name> directory(device/partner/<company_name>/<board_name>).- # system.prop for- # This overrides settings in the products/generic/system.prop file - # - # rild.libpath=/system/lib/libreference-ril.so - # rild.libargs=-d /dev/ttyS0
<second_product_name>.mk within products/AndroidProducts.mk.- PRODUCT_MAKEFILES := \ - $(LOCAL_DIR)/first_product_name.mk \ - $(LOCAL_DIR)/second_product_name.mk
device/partner/<company_name>/<board_name> must include an Android.mk file with at least the following code:- # make file for new hardwarefrom - # - LOCAL_PATH := $(call my-dir) - # - # this is here to use the pre-built kernel - ifeq ($(TARGET_PREBUILT_KERNEL),) - TARGET_PREBUILT_KERNEL := $(LOCAL_PATH)/kernel - endif - # - file := $(INSTALLED_KERNEL_TARGET) - ALL_PREBUILT += $(file) - $(file): $(TARGET_PREBUILT_KERNEL) | $(ACP) - $(transform-prebuilt-to-target) - # - # no boot loader, so we don't need any of that stuff.. - # - LOCAL_PATH := partner/<company_name>/<board_name> - # - include $(CLEAR_VARS) - # - # include more board specific stuff here? Such as Audio parameters. - #
device/partner/company_name/products/<second_product_name>.mk that includes:- $(call inherit-product, partner/google/products/generic.mk) - # - # Overrides - PRODUCT_NAME := <second_product_name> - PRODUCT_DEVICE := <board_name>
By now, you should have two new products, called <first_product_name> and <second_product_name> associated with <company_name>. To verify that a product is properly configured (<first_product_name>, for example), execute the following:
-
- cd device - . ./envsetup.sh - partner_setup <first_product_name> - make PRODUCT-<first_product_name>-user --
You should find new build binaries located in device/out/target/product/<board_name>.
-
-
-
The file tree below illustrates what your own system should look like after completing the steps above.
--
<company_name><board_name>Android.mkproduct_config.mksystem.propproductsAndroidProducts.mk<first_product_name>.mk<second_product_name>.mkThe directions below describe how to configure make files for new mobile devices and products.
+//device/partner.+ mkdir device/partner/<company_name>
products directory beneath the company directory you created in step 1.+ mkdir device/partner/<company_name>/products/
device/partner/<company_name>/products/<first_product_name>.mk, that includes the following code:+ $(call inherit-product, target/product/generic.mk) + # + # Overrides + PRODUCT_NAME := <first_product_name> + PRODUCT_DEVICE := <board_name>
products directory, create an AndroidProducts.mk file that point to (and is responsible for finding) the individual product make files.+ # + # This file should set PRODUCT_MAKEFILES to a list of product makefiles + # to expose to the build system. LOCAL_DIR will already be set to + # the directory containing this file. + # + # This file may not rely on the value of any variable other than + # LOCAL_DIR; do not use any conditionals, and do not look up the + # value of any variable that isn't set in this file or in a file that + # it includes. + # + + PRODUCT_MAKEFILES := \ + $(LOCAL_DIR)/first_product_name.mk \
PRODUCT_DEVICE variable <board_name> referenced in the product-specific make file above. This will include a make file that gets accessed by any product using this board.+ mkdir device/partner/<company_name>/<board_name>
product_config.mk file in the directory created in the previous step (device/partner/<company_name>/<board_name>). If this directory does not include a product_config.mk file, the build will fail.+ # These definitions override the defaults in config/config.make for <board_name> + # + # TARGET_NO_BOOTLOADER := false + # TARGET_HARDWARE_3D := false + # + TARGET_USE_GENERIC_AUDIO := true
system.prop file in your <board_name> directory(device/partner/<company_name>/<board_name>).+ # system.prop for+ # This overrides settings in the products/generic/system.prop file + # + # rild.libpath=/system/lib/libreference-ril.so + # rild.libargs=-d /dev/ttyS0
<second_product_name>.mk within products/AndroidProducts.mk.+ PRODUCT_MAKEFILES := \ + $(LOCAL_DIR)/first_product_name.mk \ + $(LOCAL_DIR)/second_product_name.mk
device/partner/<company_name>/<board_name> must include an Android.mk file with at least the following code:+ # make file for new hardwarefrom + # + LOCAL_PATH := $(call my-dir) + # + # this is here to use the pre-built kernel + ifeq ($(TARGET_PREBUILT_KERNEL),) + TARGET_PREBUILT_KERNEL := $(LOCAL_PATH)/kernel + endif + # + file := $(INSTALLED_KERNEL_TARGET) + ALL_PREBUILT += $(file) + $(file): $(TARGET_PREBUILT_KERNEL) | $(ACP) + $(transform-prebuilt-to-target) + # + # no boot loader, so we don't need any of that stuff.. + # + LOCAL_PATH := partner/<company_name>/<board_name> + # + include $(CLEAR_VARS) + # + # include more board specific stuff here? Such as Audio parameters. + #
device/partner/company_name/products/<second_product_name>.mk that includes:+ $(call inherit-product, partner/google/products/generic.mk) + # + # Overrides + PRODUCT_NAME := <second_product_name> + PRODUCT_DEVICE := <board_name>
By now, you should have two new products, called <first_product_name> and <second_product_name> associated with <company_name>. To verify that a product is properly configured (<first_product_name>, for example), execute the following:
+
+ cd device + . ./envsetup.sh + partner_setup <first_product_name> + make PRODUCT-<first_product_name>-user ++
You should find new build binaries located in device/out/target/product/<board_name>.
+
+
+
The file tree below illustrates what your own system should look like after completing the steps above.
++
<company_name><board_name>Android.mkproduct_config.mksystem.propproductsAndroidProducts.mk<first_product_name>.mk<second_product_name>.mkAndroid's camera subsystem connects the camera application to the application framework and user space libraries, which in turn communicate with the camera hardware layer that operates the physical camera.
-The diagram below illustrates the structure of the camera subsystem.
-
To implement a camera driver, create a shared library that implements the interface defined in CameraHardwareInterface.h. You must name your shared library libcamera.so so that it will get loaded from /system/lib at runtime. Place libcamera sources and Android.mk in partner/acme/chipset_or_board/libcamera/.
The following stub Android.mk file ensures that libcamera compiles and links to the appropriate libraries:
-LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE := libcamera - -LOCAL_SHARED_LIBRARIES := \ - libutils \ - librpc \ - liblog - -LOCAL_SRC_FILES += MyCameraHardware.cpp - -LOCAL_CFLAGS += - -LOCAL_C_INCLUDES += - -LOCAL_STATIC_LIBRARIES += \ - libcamera-common \ - libclock-rpc \ - libcommondefs-rpc - -include $(BUILD_SHARED_LIBRARY) -- - -
The following diagram illustrates the sequence of function calls and actions necessary for your camera to preview.
-
-
-
-The following diagram illustrates the sequence of function calls and actions necessary for your camera to take a picture.
-
-
-
-Note: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, click here.
- - - - - -Android's camera subsystem connects the camera application to the application framework and user space libraries, which in turn communicate with the camera hardware layer that operates the physical camera.
+The diagram below illustrates the structure of the camera subsystem.
+
To implement a camera driver, create a shared library that implements the interface defined in CameraHardwareInterface.h. You must name your shared library libcamera.so so that it will get loaded from /system/lib at runtime. Place libcamera sources and Android.mk in partner/acme/chipset_or_board/libcamera/.
The following stub Android.mk file ensures that libcamera compiles and links to the appropriate libraries:
+LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := libcamera + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + librpc \ + liblog + +LOCAL_SRC_FILES += MyCameraHardware.cpp + +LOCAL_CFLAGS += + +LOCAL_C_INCLUDES += + +LOCAL_STATIC_LIBRARIES += \ + libcamera-common \ + libclock-rpc \ + libcommondefs-rpc + +include $(BUILD_SHARED_LIBRARY) ++ + +
The following diagram illustrates the sequence of function calls and actions necessary for your camera to preview.
+
+
+
+The following diagram illustrates the sequence of function calls and actions necessary for your camera to take a picture.
+
+
+
+Note: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, click here.
+ + + + + diff --git a/pdk/docs/display_drivers.html b/pdk/docs/display_drivers.jd similarity index 61% rename from pdk/docs/display_drivers.html rename to pdk/docs/display_drivers.jd index c20afe547..d1272079e 100755 --- a/pdk/docs/display_drivers.html +++ b/pdk/docs/display_drivers.jd @@ -1,187 +1,12 @@ - - - - -Android relies on a double buffer to smoothly render page flips (please see Functionality for details). -
Android relies on Git, a version control system, to install the Android platform. You will need to install Git 1.5.2 or greater in order to access the source tree. Please visit http://git.or.cz/ for more information regarding Git.
-Git permits you to control access to working directories, and we recommend that you use it to limit Android repository access to only a few people within your organization (please refer to your Google NDA for potential contractual restraints on sharing Android source access).
-You may clone Google's repository to a local copy for sharing internally (see Git documentation for details).
- - -To install the Git package, execute:
--% sudo apt-get install git-core -- - -
Once Git is cleanly installed, you need to establish a connection with Google's Git server, a connection that requires an RSA key in order to authenticate requests.
- - -Each developer must have a unique RSA key in order to access Android source code. To generate an RSA key:
--
% ssh-keygen -t rsa -C email@domain.com
id_rsa in this example).id_rsa: This file contains the private half of your RSA key. You shouldn't share this file with anyone. id_rsa.pub: This is the public half or your RSA key and you should send it to your Google technical account manager.Send your Google Account Manager your public key file in order to establish Git server access.
- - -Once you have generated an RSA key and shared the public file with Google, you can test your connection with the Git server with the following command:
--% ssh android-git.ext.google.com -- -
You should receive one of the following results:
- -| Result | -Cause | -Action | -
|---|---|---|
-fatal: What do you think I am? A shell?
- |
- Success | -None. You successfully connected to the Git server. (You should not have shell access and it's expected to receive this error.) | -
| ssh hangs and eventually times out. | -Your setup is failing to locate and establish a basic connection. | -Google needs to debug network settings. | -
| Error: Permission denied <public key> | -Either you are not using the matching username or the RSA private key does not match the public key. | -Try executing: -
-% ssh $USER@android-
- git.ext.google.com
- |
-
Android source code is maintained in two repositories: device and kernel. The device repository includes the Android framework (things like the Activity Manager, Window Manager, Telephony Manager, View System, etc.). The kernel repository includes the core code necessary to run the operating system (things like the Display Driver, Camera Driver, Keypad Driver, Power Management, etc.). (Please see What is Android? for details.)
Save device and kernel code at the same directory level, for example:
--
/home/joe/android/device/home/joe/android/kernelDevice Code
-To download device code, you need your username and a unique <path> string supplied by Google to execute the following:
-% git-clone $USER@android-git.ext.google.com:<path>/device.git -- -
Kernel Code
-To download kernel code, you need your username and a unique <path> string supplied by Google to execute the following:
-% git-clone $USER@android-git.ext.google.com:<path>/kernel.git -- - - -
You likely already have Linux running on your platform and only need to integrate Android-specific changes. The following directions describe how to extract an Android patch.
-diff on the two kernel packages to get Android-specific changes.Android relies on Git, a version control system, to install the Android platform. You will need to install Git 1.5.2 or greater in order to access the source tree. Please visit http://git.or.cz/ for more information regarding Git.
+Git permits you to control access to working directories, and we recommend that you use it to limit Android repository access to only a few people within your organization (please refer to your Google NDA for potential contractual restraints on sharing Android source access).
+You may clone Google's repository to a local copy for sharing internally (see Git documentation for details).
+ + +To install the Git package, execute:
++% sudo apt-get install git-core ++ + +
Once Git is cleanly installed, you need to establish a connection with Google's Git server, a connection that requires an RSA key in order to authenticate requests.
+ + +Each developer must have a unique RSA key in order to access Android source code. To generate an RSA key:
++
% ssh-keygen -t rsa -C email@domain.com
id_rsa in this example).id_rsa: This file contains the private half of your RSA key. You shouldn't share this file with anyone. id_rsa.pub: This is the public half or your RSA key and you should send it to your Google technical account manager.Send your Google Account Manager your public key file in order to establish Git server access.
+ + +Once you have generated an RSA key and shared the public file with Google, you can test your connection with the Git server with the following command:
++% ssh android-git.ext.google.com ++ +
You should receive one of the following results:
+ +| Result | +Cause | +Action | +
|---|---|---|
+fatal: What do you think I am? A shell?
+ |
+ Success | +None. You successfully connected to the Git server. (You should not have shell access and it's expected to receive this error.) | +
| ssh hangs and eventually times out. | +Your setup is failing to locate and establish a basic connection. | +Google needs to debug network settings. | +
| Error: Permission denied <public key> | +Either you are not using the matching username or the RSA private key does not match the public key. | +Try executing: +
+% ssh $USER@android-
+ git.ext.google.com
+ |
+
Android source code is maintained in two repositories: device and kernel. The device repository includes the Android framework (things like the Activity Manager, Window Manager, Telephony Manager, View System, etc.). The kernel repository includes the core code necessary to run the operating system (things like the Display Driver, Camera Driver, Keypad Driver, Power Management, etc.). (Please see What is Android? for details.)
Save device and kernel code at the same directory level, for example:
++
/home/joe/android/device/home/joe/android/kernelDevice Code
+To download device code, you need your username and a unique <path> string supplied by Google to execute the following:
+% git-clone $USER@android-git.ext.google.com:<path>/device.git ++ +
Kernel Code
+To download kernel code, you need your username and a unique <path> string supplied by Google to execute the following:
+% git-clone $USER@android-git.ext.google.com:<path>/kernel.git ++ + + +
You likely already have Linux running on your platform and only need to integrate Android-specific changes. The following directions describe how to extract an Android patch.
+diff on the two kernel packages to get Android-specific changes.Android defines a user space C abstraction interface for GPS hardware. The interface header is defined in include/hardware/gps.h. In order to integate GPS with Android, you need to build a shared library that implements this interface.
To implement a GPS driver, create a shared library that implements the interface defined in gps.h. You must name your shared library libgps.so so that it will get loaded from /system/lib at runtime. Place GPS sources and Android.mk in partner/acme/chipset_or_board/gps/ (where "acme" is your product name and "chipset_or_board" is your hardware target).
The following stub Android.mk file ensures that libgps compiles and links to the appropriate libraries:
-LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE := libgps - -LOCAL_STATIC_LIBRARIES:= \ -# include any static library dependencies - -LOCAL_SHARED_LIBRARIES := \ -# include any shared library dependencies - -LOCAL_SRC_FILES += \ -# include your source files. eg. MyGpsLibrary.cpp - -LOCAL_CFLAGS += \ -# include any needed compile flags - -LOCAL_C_INCLUDES:= \ -# include any needed local header files - -include $(BUILD_SHARED_LIBRARY) -- - -
Note: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, click here.
- - - - - -Android defines a user space C abstraction interface for GPS hardware. The interface header is defined in include/hardware/gps.h. In order to integate GPS with Android, you need to build a shared library that implements this interface.
To implement a GPS driver, create a shared library that implements the interface defined in gps.h. You must name your shared library libgps.so so that it will get loaded from /system/lib at runtime. Place GPS sources and Android.mk in partner/acme/chipset_or_board/gps/ (where "acme" is your product name and "chipset_or_board" is your hardware target).
The following stub Android.mk file ensures that libgps compiles and links to the appropriate libraries:
+LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := libgps + +LOCAL_STATIC_LIBRARIES:= \ +# include any static library dependencies + +LOCAL_SHARED_LIBRARIES := \ +# include any shared library dependencies + +LOCAL_SRC_FILES += \ +# include your source files. eg. MyGpsLibrary.cpp + +LOCAL_CFLAGS += \ +# include any needed compile flags + +LOCAL_C_INCLUDES:= \ +# include any needed local header files + +include $(BUILD_SHARED_LIBRARY) ++ + +
Modules | |
| Porividng Heap Memory | |
The Open Handset Distribution (OHD) is a software distribution for mobile devices, often referred to as Android, developed by members of the Open Handset Alliance. Android includes an operating system, middleware, and key applications typically required for a mobile device.
- -This porting guide describes the steps necessary to port Android to a new mobile device. Android is designed as a highly-portable, hardware-independent platform based on Linux, and porting the platform to new devices requires little more than porting the Linux kernel and developing the Linux drivers necessary for your device.
- -The current version of this guide describes bringing Android up to "PDA-level" functionality; functionality sufficient to support non-multimedia apps that run on unconnected mobile devices through the standard user interface devices such as keypad and display. Future versions of this guide will cover complete telephony, multi-media and peripheral integration to create a complete mobile device.
- - -This porting guide is intended for engineers proficient with running (and writing drivers for) Linux on embedded devices. -
The guide also assumes you have a target hardware that matches Device Requirements and that you -can boot and run a recent (2.6.x) version of the Linux kernel -with at least keypad and display drivers properly installed.
- - -To get started with Android, start with the publicly-available documentation at http://code.google.com/android/documentation.html, paying particular attention to What is Android? and Getting Started with Android.
- - -Start with the following sections in order to port Android to your target hardware.
-The Open Handset Distribution (OHD) is a software distribution for mobile devices, often referred to as Android, developed by members of the Open Handset Alliance. Android includes an operating system, middleware, and key applications typically required for a mobile device.
+ +This porting guide describes the steps necessary to port Android to a new mobile device. Android is designed as a highly-portable, hardware-independent platform based on Linux, and porting the platform to new devices requires little more than porting the Linux kernel and developing the Linux drivers necessary for your device.
+ +The current version of this guide describes bringing Android up to "PDA-level" functionality; functionality sufficient to support non-multimedia apps that run on unconnected mobile devices through the standard user interface devices such as keypad and display. Future versions of this guide will cover complete telephony, multi-media and peripheral integration to create a complete mobile device.
+ + +This porting guide is intended for engineers proficient with running (and writing drivers for) Linux on embedded devices. +
The guide also assumes you have a target hardware that matches Device Requirements and that you +can boot and run a recent (2.6.x) version of the Linux kernel +with at least keypad and display drivers properly installed.
+ + +To get started with Android, start with the publicly-available documentation at http://code.google.com/android/documentation.html, paying particular attention to What is Android? and Getting Started with Android.
+ + +Start with the following sections in order to port Android to your target hardware.
+It's possible that the instrumentation apk isn't installed on your device or that the package name is incorrect in the Manifest file.
- -It's possible that the instrumentation apk isn't installed on your device or that the package name is incorrect in the Manifest file.
- -Android source code is maintained in two code bases: the Android Linux kernel (kernel directory) and Android platform and applications (device directory). This document provides a high-level introduction to the source code organization and an overview of the major components of each primary directory.
The Android Linux kernel includes enhancements to the Linux 2.6 kernel that provide additional drivers to support the Android platform, including:
-Look for Android-specific enhancements in the following directories:
-/drivers/android/drivers/misc/include/linuxThe following list outlines the directory structure found within the device branch of Android source code:
You can develop Android applications with the same standard tools you use to develop any Java application. The Android core libraries provide the functionality needed to build rich mobile applications and the Android development tools are designed to simplify running, debugging, and testing your applications.
- -Add project-specific source code to the Android source tree under the partner directory in a directory specific to the application or service you are building. For example, all Google-specific applications would be placed under device/partner/google/. A Google search application would be placed under device/partner/google/apps/Search.
-
See Building Android for a new Mobile Device for detailed instructions.
- - - -Android source code is maintained in two code bases: the Android Linux kernel (kernel directory) and Android platform and applications (device directory). This document provides a high-level introduction to the source code organization and an overview of the major components of each primary directory.
The Android Linux kernel includes enhancements to the Linux 2.6 kernel that provide additional drivers to support the Android platform, including:
+Look for Android-specific enhancements in the following directories:
+/drivers/android/drivers/misc/include/linuxThe following list outlines the directory structure found within the device branch of Android source code:
You can develop Android applications with the same standard tools you use to develop any Java application. The Android core libraries provide the functionality needed to build rich mobile applications and the Android development tools are designed to simplify running, debugging, and testing your applications.
+ +Add project-specific source code to the Android source tree under the partner directory in a directory specific to the application or service you are building. For example, all Google-specific applications would be placed under device/partner/google/. A Google search application would be placed under device/partner/google/apps/Search.
+
See Building Android for a new Mobile Device for detailed instructions.
+ + diff --git a/pdk/docs/keymaps_keyboard_input.html b/pdk/docs/keymaps_keyboard_input.jd similarity index 71% rename from pdk/docs/keymaps_keyboard_input.html rename to pdk/docs/keymaps_keyboard_input.jd index 9a1a66a42..d52a73fe3 100755 --- a/pdk/docs/keymaps_keyboard_input.html +++ b/pdk/docs/keymaps_keyboard_input.jd @@ -1,180 +1,5 @@ - - - - -The snippet above contains artificial line breaks to maintain a print-friendly document.
-Android supports its own Power Management (on top of the standard Linux Power Management) designed with the premise that the CPU shouldn't consume power if no applications or services require power. For more information regarding standard Linux power management, please see Linux Power Management Support at http://kernel.org.
-Android requires that applications and services request CPU resources with "wake locks" through the Android application framework and native Linux libraries. If there are no active wake locks, Android will shut down the CPU.
-The image below illustrates the Android power management architecture.
-
Wake locks are used by applications and services to request CPU resources.
- - -| Wake Lock | -Description | -
|---|---|
| ACQUIRE_CAUSES_WAKEUP |
- Normally wake locks don't actually wake the device, they just cause it to remain on once it's already on. Think of the video player app as the normal behavior. Notifications that pop up and want the device to be on are the exception; use this flag to be like them. | -
| FULL_WAKE_LOCK | -Wake lock that ensures that the screen and keyboard are on at full brightness. | -
| ON_AFTER_RELEASE | -When this wake lock is released, poke the user activity timer so the screen stays on for a little longer. | -
| PARTIAL_WAKE_LOCK | -Wake lock that ensures that the CPU is running. The screen might not be on. | -
| SCREEN_BRIGHT_WAKE_LOCK | -Wake lock that ensures that the screen is on at full brightness; the keyboard backlight will be allowed to go off. | -
| SCREEN_DIM_WAKE_LOCK | -Wake lock that ensures that the screen is on, but the keyboard backlight will be allowed to go off, and the screen backlight will be allowed to go dim. | -
All power management calls follow the same basic format:
-PowerManager service.The snippet below illustrates this process.
--PowerManager pm = (PowerManager)mContext.getSystemService( - Context.POWER_SERVICE); -PowerManager.WakeLock wl = pm.newWakeLock( - PowerManager.SCREEN_DIM_WAKE_LOCK - | PowerManager.ON_AFTER_RELEASE, - TAG); -wl.acquire(); - // ... -wl.release(); -- - -
The Android Framework exposes power management to services and applications through the PowerManager class.
User space native libraries (any hardware function in //device/lib/hardware/ meant to serve as supporting libraries for Android runtime) should never call into Android Power Management directly (see the image above). Bypassing the power management policy in the Android runtime will destabilize the system.
All calls into Power Management should go through the Android runtime PowerManager APIs.
-Please visit -http://code.google.com/android/reference/android/os/PowerManager.html for a description of the API and examples.
- - -You can register Kernel-level drivers with the Android Power Manager driver so that they're notified immediately before power down or after power up. For example, you might set a display driver to completely power down when a request comes in to power down from the user space (see the Android MSM MDDI display driver for a sample implementation).
-To register drivers with the Android PM driver, implement call-back handlers and register them with the Android PM, as illustrated in the snippet below:
--android_register_early_suspend(android_early_suspend_t *handler) -android_register_early_resume(android_early_resume_t *handler) --
It is critical in a drive to return immediately and not wait for anything to happen in the call back.
- - -Android supports its own Power Management (on top of the standard Linux Power Management) designed with the premise that the CPU shouldn't consume power if no applications or services require power. For more information regarding standard Linux power management, please see Linux Power Management Support at http://kernel.org.
+Android requires that applications and services request CPU resources with "wake locks" through the Android application framework and native Linux libraries. If there are no active wake locks, Android will shut down the CPU.
+The image below illustrates the Android power management architecture.
+
Solid elements represent Android blocks and dashed elements represent partner-specific blocks.
+ + + +Wake locks are used by applications and services to request CPU resources.
+ + +| Wake Lock | +Description | +
|---|---|
| ACQUIRE_CAUSES_WAKEUP |
+ Normally wake locks don't actually wake the device, they just cause it to remain on once it's already on. Think of the video player app as the normal behavior. Notifications that pop up and want the device to be on are the exception; use this flag to be like them. | +
| FULL_WAKE_LOCK | +Wake lock that ensures that the screen and keyboard are on at full brightness. | +
| ON_AFTER_RELEASE | +When this wake lock is released, poke the user activity timer so the screen stays on for a little longer. | +
| PARTIAL_WAKE_LOCK | +Wake lock that ensures that the CPU is running. The screen might not be on. | +
| SCREEN_BRIGHT_WAKE_LOCK | +Wake lock that ensures that the screen is on at full brightness; the keyboard backlight will be allowed to go off. | +
| SCREEN_DIM_WAKE_LOCK | +Wake lock that ensures that the screen is on, but the keyboard backlight will be allowed to go off, and the screen backlight will be allowed to go dim. | +
All power management calls follow the same basic format:
+PowerManager service.The snippet below illustrates this process.
++PowerManager pm = (PowerManager)mContext.getSystemService( + Context.POWER_SERVICE); +PowerManager.WakeLock wl = pm.newWakeLock( + PowerManager.SCREEN_DIM_WAKE_LOCK + | PowerManager.ON_AFTER_RELEASE, + TAG); +wl.acquire(); + // ... +wl.release(); ++ + +
The Android Framework exposes power management to services and applications through the PowerManager class.
User space native libraries (any hardware function in //device/lib/hardware/ meant to serve as supporting libraries for Android runtime) should never call into Android Power Management directly (see the image above). Bypassing the power management policy in the Android runtime will destabilize the system.
All calls into Power Management should go through the Android runtime PowerManager APIs.
+Please visit +http://code.google.com/android/reference/android/os/PowerManager.html for a description of the API and examples.
+ + +You can register Kernel-level drivers with the Android Power Manager driver so that they're notified immediately before power down or after power up. For example, you might set a display driver to completely power down when a request comes in to power down from the user space (see the Android MSM MDDI display driver for a sample implementation).
+To register drivers with the Android PM driver, implement call-back handlers and register them with the Android PM, as illustrated in the snippet below:
++android_register_early_suspend(android_early_suspend_t *handler) +android_register_early_resume(android_early_resume_t *handler) ++
It is critical in a drive to return immediately and not wait for anything to happen in the call back.
+ + + diff --git a/pdk/docs/source_setup_guide.html b/pdk/docs/source_setup_guide.html deleted file mode 100755 index 1588b2946..000000000 --- a/pdk/docs/source_setup_guide.html +++ /dev/null @@ -1,323 +0,0 @@ - - - - -This section provides instructions on how to configure your host system to build Android for mobile devices. While Android is designed as host-environment agnostic, it has been tested and is known to work on the following Linux operating system; Ubuntu 6.06 (Dapper), 7.10 (Gutsy), and 8.04. Cygwin is not recommended.
- - -Android requires the following system packages:
-On a clean Dapper system, type the following:
--% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev zlib1g-dev - build-essential --
This snippet includes an artificial line break to maintain a print-friendly document.
- - --## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu -## team, and may not be under a free license. Please satisfy yourself as to -## your rights to use the software. Also, please note that software in -## universe WILL NOT receive any review or updates from the Ubuntu security -## team. -# Line commented out by installer because it failed to verify: -deb http://us.archive.ubuntu.com/ubuntu/ gutsy universe -# Line commented out by installer because it failed to verify: -deb-src http://us.archive.ubuntu.com/ubuntu/ gutsy universe -# Line commented out by installer because it failed to verify: -deb http://us.archive.ubuntu.com/ubuntu/ gutsy-updates universe -# Line commented out by installer because it failed to verify: -deb-src http://us.archive.ubuntu.com/ubuntu/ gutsy-updates universe -
-% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev zlib1g-dev - build-essential --This snippet includes an artificial line break to maintain a print-friendly document. -
Install the X11 development environment with the following commands:
--% sudo apt-get install x-dev -% sudo apt-get install libx11-dev -% sudo apt-get install libncurses5-dev --
On a clean system, type the following:
--% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev -zlib1g-dev build-essential -% sudo apt-get install x-dev -% sudo apt-get install libx11-dev -% sudo apt-get install libncurses5-dev -% sudo apt-get install sun-java5-jdk -- - -
Android source code includes a hard dependency on the Java Developer Kit (JDK) 5.0 Update 12 or greater. The specific file name of the Update 12 package is jdk-1_5_0_12-linux-i586.bin. To download this version of the Java JDK:
Once you have cleanly installed the JDK, modify your PATH environment variable to include <jdk-install-dir>/jdk1.5.0_12/bin at its beginning so that Dapper will use the correct installation.
Ubuntu 7.10
-An alternative method to quickly install Java is to enable multiverse repo in /etc/apt/sources.list and then execute:
-% sudo apt-get install sun-java5-jdk -- - -
This section provides instructions on how to configure your host system to build Android for mobile devices. While Android is designed as host-environment agnostic, it has been tested and is known to work on the following Linux operating system; Ubuntu 6.06 (Dapper), 7.10 (Gutsy), and 8.04. Cygwin is not recommended.
+ + +Android requires the following system packages:
+On a clean Dapper system, type the following:
++% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev zlib1g-dev + build-essential ++
This snippet includes an artificial line break to maintain a print-friendly document.
+ + ++## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu +## team, and may not be under a free license. Please satisfy yourself as to +## your rights to use the software. Also, please note that software in +## universe WILL NOT receive any review or updates from the Ubuntu security +## team. +# Line commented out by installer because it failed to verify: +deb http://us.archive.ubuntu.com/ubuntu/ gutsy universe +# Line commented out by installer because it failed to verify: +deb-src http://us.archive.ubuntu.com/ubuntu/ gutsy universe +# Line commented out by installer because it failed to verify: +deb http://us.archive.ubuntu.com/ubuntu/ gutsy-updates universe +# Line commented out by installer because it failed to verify: +deb-src http://us.archive.ubuntu.com/ubuntu/ gutsy-updates universe +
+% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev zlib1g-dev + build-essential ++This snippet includes an artificial line break to maintain a print-friendly document. +
Install the X11 development environment with the following commands:
++% sudo apt-get install x-dev +% sudo apt-get install libx11-dev +% sudo apt-get install libncurses5-dev ++
On a clean system, type the following:
++% sudo apt-get install flex bison gperf libesd0-dev libwxgtk2.6-dev +zlib1g-dev build-essential +% sudo apt-get install x-dev +% sudo apt-get install libx11-dev +% sudo apt-get install libncurses5-dev +% sudo apt-get install sun-java5-jdk ++ + +
Android source code includes a hard dependency on the Java Developer Kit (JDK) 5.0 Update 12 or greater. The specific file name of the Update 12 package is jdk-1_5_0_12-linux-i586.bin. To download this version of the Java JDK:
Once you have cleanly installed the JDK, modify your PATH environment variable to include <jdk-install-dir>/jdk1.5.0_12/bin at its beginning so that Dapper will use the correct installation.
Ubuntu 7.10
+An alternative method to quickly install Java is to enable multiverse repo in /etc/apt/sources.list and then execute:
+% sudo apt-get install sun-java5-jdk ++ + + diff --git a/pdk/docs/system_requirements.html b/pdk/docs/system_requirements.html deleted file mode 100755 index 2f236cf80..000000000 --- a/pdk/docs/system_requirements.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - -
While Android is designed to support a wide variety of hardware platforms and configurations, this section provides recommended minimum device requirements.
-| Feature | -Minimum Requirement | -Notes | -
|---|---|---|
| Chipset | -ARM-based | -For the first release, Android is primarily targeted towards mobile handsets and portions of the platform, such as Dalvik VM graphics processing, currently assume an ARM architecture. | -
| Memory | -128 MB RAM; 256 MB Flash External | -Android can boot and run in configurations with less memory, but it isn't recommended. | -
| Storage | -Mini or Micro SD | -Not necessary for basic bring up, but recommended. | -
| Primary Display | -HVGA required | -The current Android interface targets a touch-based HVGA resolution display with a touch-interface no smaller than 2.8 inches in size. However, smaller displays will suffice for initial porting. | -
| Navigation Keys | -5-way navigation with 5 application keys, power, camera and volume controls | -- |
| Camera | -2MP CMOS | -Not required for basic bring up. | -
| USB | -Standard mini-B USB interface | -Android uses the USB interface for flashing the device system images and debugging a running device. | -
| Bluetooth | -1.2 or 2.0 | -Not required for initial bring up. | -
If available, your Android device can also benefit from the following optional device characteristics:
-While Android is designed to support a wide variety of hardware platforms and configurations, this section provides recommended minimum device requirements.
+ +| Feature | +Minimum Requirement | +Notes | +
|---|---|---|
| Chipset | +ARM-based | +For the first release, Android is primarily targeted towards mobile handsets and portions of the platform, such as Dalvik VM graphics processing, currently assume an ARM architecture. | +
| Memory | +128 MB RAM; 256 MB Flash External | +Android can boot and run in configurations with less memory, but it isn't recommended. | +
| Storage | +Mini or Micro SD | +Not necessary for basic bring up, but recommended. | +
| Primary Display | +HVGA required | +The current Android interface targets a touch-based HVGA resolution display with a touch-interface no smaller than 2.8 inches in size. However, smaller displays will suffice for initial porting. | +
| Navigation Keys | +5-way navigation with 5 application keys, power, camera and volume controls | ++ |
| Camera | +2MP CMOS | +Not required for basic bring up. | +
| USB | +Standard mini-B USB interface | +Android uses the USB interface for flashing the device system images and debugging a running device. | +
| Bluetooth | +1.2 or 2.0 | +Not required for initial bring up. | +
If available, your Android device can also benefit from the following optional device characteristics:
+Android uses wpa_supplicant as the platform interface to the Wi-Fi device. Your Wi-Fi driver must be compatible with the standard wpa_supplicant in addition to extensions added to the supplicant (specifically, the "DRIVER" commands described in wifi.h/wifi_command()).
To create a Wi-Fi driver for Android:
-include/hardware/wifi.h, which also defines the Wi-Fi supplicant.libs/hardware/wifi/wpa_cli utilities.You can find the default implementation in libs/hardware/wifi/wifi.c. If you need to make changes, create a new source file similar to wifi.c, for example, wifi_mywifi.c.
Update the default Android.mk file (libs/hardware/wifi/Android.mk) as shown below.
-LOCAL_SHARED_LIBRARIES += libnetutils - -ifeq ($(TARGET_DEVICE),acme) -LOCAL_SRC_FILES += wifi/wifi_mywifi.c -else -LOCAL_SRC_FILES += wifi/wifi.c -endif -- - -
Note: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, click here.
- - - - - -Android uses wpa_supplicant as the platform interface to the Wi-Fi device. Your Wi-Fi driver must be compatible with the standard wpa_supplicant in addition to extensions added to the supplicant (specifically, the "DRIVER" commands described in wifi.h/wifi_command()).
To create a Wi-Fi driver for Android:
+include/hardware/wifi.h, which also defines the Wi-Fi supplicant.libs/hardware/wifi/wpa_cli utilities.You can find the default implementation in libs/hardware/wifi/wifi.c. If you need to make changes, create a new source file similar to wifi.c, for example, wifi_mywifi.c.
Update the default Android.mk file (libs/hardware/wifi/Android.mk) as shown below.
+LOCAL_SHARED_LIBRARIES += libnetutils + +ifeq ($(TARGET_DEVICE),acme) +LOCAL_SRC_FILES += wifi/wifi_mywifi.c +else +LOCAL_SRC_FILES += wifi/wifi.c +endif ++ + +
Note: This document relies on some Doxygen-generated content that appears in an iFrame below. To return to the Doxygen default content for this page, click here.
+ + + + + + diff --git a/pdk/hosting/app.yaml b/pdk/hosting/app.yaml index 407cbb08b..6e08141bc 100644 --- a/pdk/hosting/app.yaml +++ b/pdk/hosting/app.yaml @@ -4,8 +4,8 @@ runtime: python api_version: 1 handlers: -- url: /docs - static_dir: docs +- url: /online-pdk + static_dir: online-pdk - url: / script: pdk.py diff --git a/pdk/hosting/pdk.py b/pdk/hosting/pdk.py index e88f826f8..421f19550 100644 --- a/pdk/hosting/pdk.py +++ b/pdk/hosting/pdk.py @@ -26,11 +26,9 @@ from google.appengine.ext.webapp.util import run_wsgi_app class MainPage(webapp.RequestHandler): def get(self): - self.redirect('docs/index.html') + self.redirect('online-pdk/index.html') -application = webapp.WSGIApplication( - [('/', MainPage)], - debug=True) +application = webapp.WSGIApplication([('/', MainPage)], debug=True) def main(): run_wsgi_app(application) @@ -38,6 +36,18 @@ def main(): if __name__ == "__main__": main() +# Testing +# You must install google appengine. See: http://code.google.com/appengine/downloads.html +# +# Here's the command to run the pdk-docs server locally: +# pythonILaunchManager - RUN_MODE or
* DEBUG_MODE.
* @param apk the resource to the apk to launch.
+ * @param packageName the Android package name of the app
+ * @param debugPackageName the Android package name to debug
* @param debuggable the debuggable value of the app, or null if not set.
* @param requiredApiVersionNumber the api version required by the app, or
* {@link AndroidManifestParser#INVALID_MIN_SDK} if none.
@@ -322,7 +324,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param launch the launch object
*/
public void launch(final IProject project, String mode, IFile apk,
- String packageName, Boolean debuggable, int requiredApiVersionNumber,
+ String packageName, String debugPackageName, Boolean debuggable, int requiredApiVersionNumber,
final IAndroidLaunchAction launchAction, final AndroidLaunchConfiguration config,
final AndroidLaunch launch, IProgressMonitor monitor) {
@@ -331,7 +333,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// create the launch info
final DelayedLaunchInfo launchInfo = new DelayedLaunchInfo(project, packageName,
- launchAction, apk, debuggable, requiredApiVersionNumber, launch, monitor);
+ debugPackageName, launchAction, apk, debuggable, requiredApiVersionNumber, launch,
+ monitor);
// set the debug mode
launchInfo.setDebugMode(mode.equals(ILaunchManager.DEBUG_MODE));
@@ -922,6 +925,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
DelayedLaunchInfo delayedLaunchInfo = new DelayedLaunchInfo(
androidProject.getProject(),
manifestParser.getPackage(),
+ manifestParser.getPackage(),
launchInfo.getLaunchAction(),
apk,
manifestParser.getDebuggable(),
@@ -1524,14 +1528,14 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
for (int i = 0; i < mWaitingForDebuggerApplications.size(); ) {
final DelayedLaunchInfo launchInfo = mWaitingForDebuggerApplications.get(i);
if (client.getDevice() == launchInfo.getDevice() &&
- applicationName.equals(launchInfo.getPackageName())) {
+ applicationName.equals(launchInfo.getDebugPackageName())) {
// this is a match. We remove the launch info from the list
mWaitingForDebuggerApplications.remove(i);
// and connect the debugger.
String msg = String.format(
"Attempting to connect debugger to '%1$s' on port %2$d",
- launchInfo.getPackageName(), client.getDebuggerListenPort());
+ launchInfo.getDebugPackageName(), client.getDebuggerListenPort());
AdtPlugin.printToConsole(launchInfo.getProject(), msg);
new Thread("Debugger Connection") { //$NON-NLS-1$
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
index 7dae56d00..f3bd28a07 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
@@ -44,6 +44,9 @@ public final class DelayedLaunchInfo {
/** Package name */
private final String mPackageName;
+
+ /** Debug package name */
+ private final String mDebugPackageName;
/** IFile to the package (.apk) file */
private final IFile mPackageFile;
@@ -79,7 +82,8 @@ public final class DelayedLaunchInfo {
* Basic constructor with activity and package info.
*
* @param project the eclipse project that corresponds to Android app
- * @param packageName package name of Android app
+ * @param packageName package name of Android app
+ * @param debugPackageName the package name of the Andriod app to debug
* @param launchAction action to perform after app install
* @param pack IFile to the package (.apk) file
* @param debuggable debuggable attribute of the app's manifest file.
@@ -88,11 +92,12 @@ public final class DelayedLaunchInfo {
* @param launch the launch object
* @param monitor progress monitor for launch
*/
- public DelayedLaunchInfo(IProject project, String packageName,
+ public DelayedLaunchInfo(IProject project, String packageName, String debugPackageName,
IAndroidLaunchAction launchAction, IFile pack, Boolean debuggable,
int requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) {
mProject = project;
mPackageName = packageName;
+ mDebugPackageName = debugPackageName;
mPackageFile = pack;
mLaunchAction = launchAction;
mLaunch = launch;
@@ -129,6 +134,17 @@ public final class DelayedLaunchInfo {
return mPackageName;
}
+ /**
+ * Returns the Android app process name that the debugger should connect to. Typically this is
+ * the same value as {@link getPackageName}
+ */
+ public String getDebugPackageName() {
+ if (mDebugPackageName == null) {
+ return getPackageName();
+ }
+ return mDebugPackageName;
+ }
+
/**
* @return the application package file
*/
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
index d057ac709..9f12b16e4 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
@@ -306,9 +306,10 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
// everything seems fine, we ask the launch controller to handle
// the rest
- controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
- manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
- launchAction, config, androidLaunch, monitor);
+ controller.launch(project, mode, applicationPackage,manifestParser.getPackage(),
+ manifestParser.getPackage(), manifestParser.getDebuggable(),
+ manifestParser.getApiLevelRequirement(), launchAction, config, androidLaunch,
+ monitor);
}
@Override
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java
index 9bcc63d06..24ebe21c0 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java
@@ -63,7 +63,6 @@ class AndroidJUnitLaunchAction implements IAndroidLaunchAction {
try {
mLaunchInfo.setDebugMode(info.isDebugMode());
mLaunchInfo.setDevice(info.getDevice());
- mLaunchInfo.setLaunch(info.getLaunch());
JUnitLaunchDelegate junitDelegate = new JUnitLaunchDelegate(mLaunchInfo);
final String mode = info.isDebugMode() ? ILaunchManager.DEBUG_MODE :
ILaunchManager.RUN_MODE;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java
index 543daf06f..19067921b 100755
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java
@@ -25,6 +25,7 @@ import com.android.ide.eclipse.adt.launch.LaunchConfigDelegate;
import com.android.ide.eclipse.adt.launch.junit.runtime.AndroidJUnitLaunchInfo;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
+import com.android.ide.eclipse.common.project.AndroidManifestParser.Instrumentation;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import org.eclipse.core.resources.IFile;
@@ -60,7 +61,6 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
AndroidLaunchConfiguration config, AndroidLaunchController controller,
IFile applicationPackage, AndroidManifestParser manifestParser) {
- String appPackage = manifestParser.getPackage();
String runner = getRunner(project, configuration, manifestParser);
if (runner == null) {
AdtPlugin.displayError("Android Launch",
@@ -68,19 +68,46 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
androidLaunch.stopLaunch();
return;
}
- AndroidJUnitLaunchInfo junitLaunchInfo = new AndroidJUnitLaunchInfo(project, appPackage,
- runner);
+ // get the target app's package
+ String targetAppPackage = getTargetPackage(manifestParser, runner);
+ if (targetAppPackage == null) {
+ AdtPlugin.displayError("Android Launch",
+ String.format("A target package for instrumention test runner %1$s could not be found!",
+ runner));
+ androidLaunch.stopLaunch();
+ return;
+ }
+ String testAppPackage = manifestParser.getPackage();
+ AndroidJUnitLaunchInfo junitLaunchInfo = new AndroidJUnitLaunchInfo(project,
+ testAppPackage, runner);
junitLaunchInfo.setTestClass(getTestClass(configuration));
junitLaunchInfo.setTestPackage(getTestPackage(configuration));
junitLaunchInfo.setTestMethod(getTestMethod(configuration));
-
+ junitLaunchInfo.setLaunch(androidLaunch);
IAndroidLaunchAction junitLaunch = new AndroidJUnitLaunchAction(junitLaunchInfo);
-
- controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
+
+ controller.launch(project, mode, applicationPackage, testAppPackage, targetAppPackage,
manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
junitLaunch, config, androidLaunch, monitor);
}
-
+
+ /**
+ * Get the target Android application's package for the given instrumentation runner, or
+ * null if it could not be found.
+ *
+ * @param manifestParser the {@link AndroidManifestParser} for the test project
+ * @param runner the instrumentation runner class name
+ * @return the target package or null
+ */
+ private String getTargetPackage(AndroidManifestParser manifestParser, String runner) {
+ for (Instrumentation instr : manifestParser.getInstrumentations()) {
+ if (instr.getName().equals(runner)) {
+ return instr.getTargetPackage();
+ }
+ }
+ return null;
+ }
+
/**
* Returns the test package stored in the launch configuration, or null if not
* specified.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
index 584d45eb1..34e64e327 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
@@ -955,7 +955,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
try {
mInstrValidator = new InstrumentationRunnerValidator(project);
mInstrumentations = (mInstrValidator == null ? null :
- mInstrValidator.getInstrumentations());
+ mInstrValidator.getInstrumentationNames());
if (mInstrumentations != null) {
mInstrumentationCombo.removeAll();
for (String instrumentation : mInstrumentations) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
index f22fc7cda..7ebbb0997 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.launch.junit;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
+import com.android.ide.eclipse.common.project.AndroidManifestParser.Instrumentation;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import org.eclipse.core.resources.IProject;
@@ -29,7 +30,7 @@ import org.eclipse.jdt.core.IJavaProject;
*/
class InstrumentationRunnerValidator {
private final IJavaProject mJavaProject;
- private String[] mInstrumentations = null;
+ private String[] mInstrumentationNames = null;
private boolean mHasRunnerLibrary = false;
static final String INSTRUMENTATION_OK = null;
@@ -73,7 +74,11 @@ class InstrumentationRunnerValidator {
}
private void init(AndroidManifestParser manifestParser) {
- mInstrumentations = manifestParser.getInstrumentations();
+ Instrumentation[] instrumentations = manifestParser.getInstrumentations();
+ mInstrumentationNames = new String[instrumentations.length];
+ for (int i = 0; i < instrumentations.length; i++) {
+ mInstrumentationNames[i] = instrumentations[i].getName();
+ }
mHasRunnerLibrary = hasTestRunnerLibrary(manifestParser);
}
@@ -94,13 +99,13 @@ class InstrumentationRunnerValidator {
}
/**
- * Return the set of instrumentations for the Android project.
+ * Return the set of instrumentation names for the Android project.
*
* @return nullINSTRUMENTATION_OK if valid, otherwise returns error message
*/
String validateInstrumentationRunner(String instrumentation) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
index 85ba96839..f853adacb 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
@@ -52,6 +52,7 @@ public class AndroidManifestParser {
private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
+ private final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; //$NON-NLS-1$
private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
private final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
private final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
@@ -76,6 +77,33 @@ public class AndroidManifestParser {
public final static int INVALID_MIN_SDK = -1;
+ /**
+ * Instrumentation info obtained from manifest
+ */
+ public static class Instrumentation {
+ private final String mName;
+ private final String mTargetPackage;
+
+ public Instrumentation(String name, String targetPackage) {
+ mName = name;
+ mTargetPackage = targetPackage;
+ }
+
+ /**
+ * Returns the fully qualified instrumentation class name
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Returns the Android app package that is the target of this instrumentation
+ */
+ public String getTargetPackage() {
+ return mTargetPackage;
+ }
+ }
+
/**
* XML error & data handler used when parsing the AndroidManifest.xml file.
*
@@ -100,7 +128,8 @@ public class AndroidManifestParser {
* the attribute was not present. */
private int mApiLevelRequirement = INVALID_MIN_SDK;
/** List of all instrumentations declared by the manifest */
- private final ArrayList*U3mr$-1(GzORfBlg%yLWEH4{Sry8m^ZUoX2Gz=M I_dj^e8`gXdhZ1Lqd-4EMu$? zr-mrCs8>cuYm`bcs(K!P6{x3z0@hl_#~PUKJU49aaO-<_5hc;5g6fSI8^Ad57s09d z;8h8Ka6`<*RGTadY#psJzPZUjy~OOqBy)2ua2X-*qd^G@C}dqvDYaa&YnaU&DwGqU zWFfX-3w@?uP1rgdk ~*?#8f*UaVpzbHs@xt&%HB6*)Jz|n#0)f2ocCltkQf-L zr|iCJH-kepLT?FeO+d&%1u-CI)#w$(z`#Jt*l3MS8|rKrsWCcIp;Aw h;sWTQ3HHn}Vlt-S$3jXs&SJ=mMQi#^$XJsskl@nMZw~+Nd% ciLs>`>F741>L3~d#tOj)`W=Uo5I2S~Nf~1xNiD_{ zE>akVl9UWK7D7;buJ|k?ES%wYZrnn1s4U)v&r-zAH3QHV;h+1?^5CJIvkN_19mmP3 z78A!#bLdA;@$`Q`Mu=*ZH|<2MC3IWlt$Ff(!1V*Z@A1wvIoD(V$&8jABdQL71c(xX zD dO9Gm3nhaTm}k3Wa03?V3Sb0Z`T`YRb! zHj?`Ub%D%z4jr82fd`*vVlD@3_~cF7x#F^6t3KRjMAkG9c;1K{T b+k^|uaK`S0D{jPwpt^tm5{Vb z$Q>>V%*=G?w3aw^=rAXaoFsV1XvOoU9Zf uHyoI z4_n8Y?AW%E-rO9O<^ZDuF^Dt;>OgBP`vD!r;I)vqC@KP2P$dgWWCRpU9AQcoLe@vs zVZ`87iL7PQrUo`LWL*a+wpu2)b>?PsvVN5`HPkj-PTHPjQ_>=?tq^OEp{PyXS|Zvo zL}#S~s-@M!Y)u;?B`EY<3n?e_O5X=GC^n9XD>XFlQ5oApFeS3NGq}ZRj0lL}gA%er zPIIT6K5>rL$`og3mTC7KNt!aeX^czXcsX0QjZsdH;CqIUcd(ThF$VAbMM;HYl#$37 zN)|#;vH)HMBjAIl*&L$MsF6)QN8VnBs6q&!7@&ZJGgvE_NH}$Jk+ahsvY?a_!HUr7 zwmJIT0j6gcc-Q;h!9ajKa~La#i3ws^=?6f%K(>|uwg=eRNCNdlaRD|~V+JdhcHe ^L3wq2E{A%IvER#Jv@RnLMgSB>M1UiIW@Dw;_NJEr L)!;D!xc!Zp;?aU<(?>tc*8YsVrX=jY-xdX zYzGo0cvqx HKATFv1iW~#x^(UoIXf@`ZOW$VUiSUAxaF0AR<_6 z&gc5hg`!NRP?O9-?v>mrkrm>|5Q&0Yp*M4m?(`YbYL%xBFS5LxVXXWYMftEMF7V+H z!u6xI4sY2k)GG<~dYQ|%4Ur_4IPvt(9R=qx7V`N?L zHV>B>G)wf(o+ewGCn?2D_Y xdkMW z7l0oQRbO#6{PF=P%o?jto?bBg@DxM@P*9Y`R+n}s=irG&{^N(Icx2xsJ@1R!UO s_aSg} zIwOP&tO9rKZLpzXz5_gRdOqR)BT8h8&3doQEOe-s4BJMlq={v@lNE`LHJHS5;^ZvP zKKdkQp8W~OpLvEKJ@7D(Kk^)|ym8eE3RjTTTro~9{ot6KZgKed9H%GdSy}FK&tpqG zJCS1|c?@{oSYc{5=aIwR3kzV!Xhaf857n B~G#ohVDW^h`8X_y4o$umQ**H{T z$0bdo*nq-PtH;#Y1-iXHL(K}~o0_Dhn3D$&bM%E1MD-Dp!7-9r6R|=kcbuG9;Ml1- z7M3~~0$$ V{z@W>1&Cgz!6 z>>{d^W8wH>;4dFB+`GSm4@t`yZU-Jezc&M|uD`G`;KwI(dbv`3z|}i#6kWf6sxjSZ8FYLbts_2uf^(BoSVi3*56$ zd3q`ZNwG%12YhC=Ex+~?A~yP8g#W<^*Ji%_sjol2!cgkDd_?H^qNAIKfEb8lOQmFK zb%ajeqw2sJ;@HrvMx^5DwAz%*mPlZs7r6Hs$9JB$bg~L2vRy&Hx;h}y;}^Vs-Wj1X z$i3eAo5u%x{PA^x9YaD^xC+JyQT(DSD80-RfO6SlBSW4Ad|os_auFUr9{AVig_H9M zm>6s1anL(~2Vc$}FV>LMFmR7|`o2p?b8gy|)9HKK{Qx3GIV(jlt0Y2fpj hpqqs literal 0 HcmV?d00001 diff --git a/samples/JetBoy/res/drawable/asteroid02.png b/samples/JetBoy/res/drawable/asteroid02.png new file mode 100755 index 0000000000000000000000000000000000000000..7255da573728e78150421e30d18d80dc6f453833 GIT binary patch literal 6633 zcmV KLZ*U+ IBfRsybQWXdwQbLP>6p Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh f59&ghTmgWD0l;*T zI7 09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&nehQ1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_ LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ 0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 z fg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vF IcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a (?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-k iKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BK T#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000jZNkl *YGmP^9T7}UJBMM;xkti5K zj3&en3P=?FKrn&=^1+xO8i_FhU%?OzU?c*DWPr#RVVGf<9tP;{=~s1CcRjjp-RF7i zz5H-)H%d&1PFK&wsr~8Rdrorp{++eg`meS26; )WSzz%>N06PG70PFzR z0k8w$g*x1iydk^yMm(np+zQ+Y+@h*`Rhd-PHV`4=1Paie2py1BUkyUMZ@dw-_OhM z-N! @1ke5~a%a5G-E9+PXK7Ui3;QwO0)(1WOlEs|2KQO@q zKi0%K%Y~&LXU=WV@8?vd=R1#ohjV8y@xZI^XHR<{!^`IZLzFs<6GBi3O4% }NBFn-| zli8UG7Uo)Ptgi9oqu<7~X2C?LDjF132xV;vm#*|#Uh6Z_jA^z~M*RVceuXz4xk~2B zMOFFZ8!`VIWdRQ4NMe;N5jOjtwvTWUaFHRe0*K&)(o7xG%@{39L_n-TJs?nx0-*|& zqHJsqF(S-Nq%>l|im=%oaUvRUq1WNz3)2reYhR=2=bjH1FsI7?hVvA|5v#t |Bo0R24BiiPRSvN+%3j-&IGoi%(>U}J+zEQn%bgAV}{0*%;E`amxabVh+VjcK O~MRt_GkULI_~M7$J@=)*6EUfksh<%+&y#wcI{$#aal;y+)opACQ22P3KGv8x( zBhbte8nLCF7@V~fMM?MSCK>|e>S>CV(`c2W2y$)W0%8Rh8&se*5wmMHB@#sh!k9w< zi~%2Dz7d#6K$RnaeJ%hPkU#WZADnM=dD*TU=PdJ6DXFVh7Fod>gZE%ujGNhyZB8Mo z2oNg8mjM~Sc?3l2&wKW?nP^5>ltwJH5o8g6%6umyG77>G@RE2`Es0S@eqK3mnmf)3qP?0*v!TnQodj*@_ z5usNy*>)`Mn_$<0y-ZHzpz6k%=e7bczzL9F@_}EaswVbK_Ic||VAd$Tk>$`_lQ=Sr zDy68DqV!D6%y8h&lmS)nJ}^Bu z!?FABqQNGk%bU2_7vcI{{IECP>w*eA^W-V63?pU^9p?Cfz0f(2F%W0A_KqlGYlj(U zj=Wcr4?PVLvU>IzFtwck7F79-%nh=aA1-;-v4~se9NxpIg5!s0$ IjB;sUO>G^#xYA(8T38*AjkGQbk9RL{8Fq~Br^4V8j!KcgsOHdLF?^h z3?z|UTSH^}04VncuLtkmr@Z4QW302}K`Fhmd#=TFJ0qyFfA<7&Vo(vvVMXv2dACHw zU?YPTTZEv9NFDnX(!?^qtBI@$tx3TS*HDFcZjrLHh8A6nb7+8K=t0K|Z#rCTNMiw1 z##XRB0DP{CSeVI#5QL&sLQp0r5*Fqs@Kpc-mly(|p_Z(*!ZRQcd@XCQd3XRZLfmY! zxOXqpmsfBOLT4G%m_*_h#nySmf^~pVY-9*kz$J2BFg4TbL9D%f7GUcA71>&ktJaH1 zoU6l^22eqRVr+daiY-++j)h|=*UX;(B5hF**&OMth2bidH@Ma;el#SRo+boC(Y=g~ z3@#Qb6+#77o)aoh5?$9nvTXpwl4+=&mUXqLQLWczTts9XAr$2Os?O?SgIF*ssIN`l z#D=Qy_(HD>9uTU*fVjU-y5|r@e+K7)*pkK$Ge1xF%+pkP2^tZ%o22uLSQ}Ant$~E= z{sbtt4S=yCJ}A`~vagij1Dl-@c_K{j+s|xTGF-VxRRpXPjHwro)>b37mb%88TK-CH z2_lxYm36Lse}m t6i4s9i{`=}BuWY8hzrjwaqj8{vkTMQdH1bg9HQ3& z47W213=k+h1Yeu`VB}frl=v&B*nIRf_dj@oL$k9KomIqeUF8{5m$<5tC(0ag21VcF zE5%w^SsQTr>;=xPbSYIaBBWM0zqH2kr48 |b1< zmCh2!7L0g>?siJy4hUOAzz9)d=nX3(E9{+)(SC=s-+g9W%y6jM+S?n0OASdgC2nS* zP!0pZ2aFL0!-{juT}lkIvlATNJI#^(Q|w!qAWLIbR@Qmy@u#VZf>4eaR)KaqWB;CM z5*-l+SBaAZjL8jjw$lQxBGAd}(pF@_Im56BR9*?j(sCuf*F)kIlS~lG6+{BTTe3a- z7_F_6cYA~Y#u}2$vA#8;ECWeoNn%G937M<2p#XFS1s5-_a{Jx4vFq4vq nsGCCL)*I<~;k0~tt(dO I5TDsS??`4mg>?L^Qy} z5mgZ|78>noPHi^$_`jS4qn{Ar>)TxwE<|`Fc;Q?}5tOnBRAu1m#)x9z2?`g_t#Ib+ z-=K4Og@*GiOgJcWp7@W)xwN#3GdW0|_ZtT;HZ1OIvu~k6 Fj2Lfoix{bJ cfl{*<+*bXMuoD`_kf|1I1(p#Rf @syG0;MEn);k30^S>kx{;OI_LL3TX1G2U=ltr@D^bG zW_O4GNsy K0wFMyB@8Rb3Czv3m`ewQVHb?O zUI_7}$2e1$JVKr3>Ns8Yr6Nul^oM-v8(aM8!y~pvZERvb4ZIcDc&-mfyaIT)54?r| zN9POPcxTRi`z&4+D+X(0vMgf%o(a;1qZpO71a@^BEFYA08_X-iUWxYsMJc?ew>2UJ z&p$pf;%^@Hcp5 ntud N@XV&_J6{oGF)LVKD~L0LF@nE#2tw*M zk97uXA>@jwt0$-!HVVh5PZ~aZQV?se7^CkZ=- hlsn zeLO}PjLN$BQH3W^p722(xM_hDG#bC+0F1^ZtRe)4WuTO2lg(^*82tY}b`DGL0N4Sr n17HWh4uBm1I{;p=<39%gebb7qM#}?)00000NkvXXu0mjf-3etv literal 0 HcmV?d00001 diff --git a/samples/JetBoy/res/drawable/asteroid03.png b/samples/JetBoy/res/drawable/asteroid03.png new file mode 100755 index 0000000000000000000000000000000000000000..c343741ae3e88f0771031ed6efd317422cad5156 GIT binary patch literal 6771 zcmV-(8jR(MP) KLZ*U+ IBfRsybQWXdwQbLP>6p Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh f59&ghTmgWD0l;*T zI7 09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&nehQ1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_ LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ 0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 z fg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vF IcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a (?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-k iKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BK T#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000l3Nkl $`mc(z`rxA*$>yYJpx zRVN>A&kPm;V%#>d-1X_|t*T$0<$q2cB_h0#m*xe&b^z=E*a5HuU =XoEFa_?TY7yyc%j?778^xe++uLEBL=6`Ay@GPwNIWO -s>jc?54PLsL7aOBfqFt~{TZdW6*&5Q2k<&C>dz`c&bzL%Tsx%^6LR3v zCXI=hjUr~f7-KOF`0nE!Zols=_a9rGSzGV^KH`5(8~v|JslNf9d_DrW$&31!I9Gk+ z6&Y7fYC5TB|3xjLKr{E~Biw&qu;+pCB9?#Z05+_%ox?>;?tW`6DW zTw&j$jQ&fl)jt5~^8vsxsP}qNw}^N3>!#YgxY6gtQp}65*vr`T2x)JV*|`lOtxz`S z@Ldlu-?rTF>KAdtRGVw38~nm`S904!J?=U(zx#osXa1ts&0enq{Rc{^dw$vgVjz3! zODa*YU*IOezsEa!DAWb7nA+sV-8sEn=y^*xwwGk2!TbY9=x3HjEh3CVayEJN{)gE; zJ;7zW46^tj*9;7E`Ss&mfAA8%dSrrceCzm4$DUmLvKRj$qxIiH8B(8104?ByBI-I6 zk10q&0&oK&c8?RcAI~7<>}wXhX18Tu!y_na)rd~F&tnfAV|wC6q@6CE)Kl@E+zQns zCTOR0+FksvQLGcXYbykLl`Bn^-B<19;Pi|5&u kH3=z$cyOwVFQO=GT;2ECzCdpwCc6F_w4^4SNo>JaGU)5HirH5J!eI&B=P3Y~}%z zmtMhI{sgwOj0rVypqZW+U}|avm-fk1j}8ol2>1<#!-x6#$z5Fb<~>XdCw%ft54@+y z3o%Cj_D^aFKNNuT-zP3EJpZY)>a{PK>hq?9IqR9w?F&P#kdaoCv8rQpt&J~o;y~e1 zB%vV=G+HYJAqq9QXo@VOW;^Vgh?&hI#Ct@9k+D%mn<4qq8I;l}Agma?Gvt{iYM A&St^Gxh8ipxf7fS+GvbXs4cal1S<79^=5@gMi~kNBJHu>p_L*G1B!*?h$~9t z(h40YlmS6QoM63TR95-muk4lCr49AvZyvwJ#O71L_qGkd+}cwts-?905MuSsm-d+% z4Cq>@!~w1020bfy>#<%D#{nv{B%z|4m%i;iR3nA;f)&O1a0As@!1@do1k@TK;sca| zJhj-uVnR(A8vwFR2Y4z24T9D*Yn_a>lO1-sK)vNPQ+)NVGht!vO xE`Lq*aT^HVe*Ou6PlejhM?13^O>GAWCDj0)!~g zOpaB#=A{#i3 rFesulXn^GH7hr3jM%V-(FKrj~^C zx&>L`@IX>E)M^oUA?;d}0zqMnLT_1{cmbslFNhbM6^zk1<(QxA;JwEfO{gGA0(2v! z+uvZiIfjY!kT~`{UAg?@ETAT+Uq>uA?Dq^*4QNnG^T?B{Jbb2)j9yICsFx?Wl|G&G zIO_>RO}!d2JXoRGj1ezneTO)~TS2T~Gmp*74B)IsDNtI0QkX!a1I7G8kCk>tYRlp= zcY^gLoJb17_0vRwM}$M$Z2>>yy<9#%V7Y#uA$L$X*zDyjop_Mdo@M=2ui)wf!>H~C zHgjkb01EHryldorhjUV%v|JDt=iYaPAOc|$qI9`Qg+i&)4c6Oz3I}TI^GYeYg{Kgq z9tEVUXR%ogr5n+9cZA-ELtVWK8L2AzsUy!lMl1I3YO!lD=G3thbk;j4rSV?yPEbnF zLFwP+k(TwpEBtvY(Yl18wW89fVB#7@YAO1z1fW$J9{{6DX6M54xs-}P6e>1-K;ax( zvALZ9sv=w$gqEu(%m34%Vx*OjR6_cNr(UlzS+!JrhcF3=k}`68Tl%mzTZ&T3Q}$lY zwLkDq$~`DydBf9*CsD1b^ZgOz{7x}i5e2I3pKPs2LlTxjwq1nf=Y`enbb%S~ 7dG#uJXyK0yOouc(`V*c z+<20!UUMz`1{>J^CZKS+M;oXn0qsskU`mA=Xhl6PUBrrFF^#rDs9M-g0GA>pmyT$L zYM#xkOjF&oV0^sECHn`#3(iTI&z(Y0WiB^mY7 Bn_8x0X>5fQWo6KI?jA{{V3T4#Q70}-%Z==43U3OuwJ%EE?HT5~&ab~|Ihf15x( z`siZFr;b>{U@PtjEG%|eT}xR$+hwH#Z8L@*zl5kYinktdrKyLBK?j;3(u5ULMs-_& zc$9cdeH2{4^zJ4zGs85S6~vd&Ok{{E1{0O3aAK;#;82zPoGXckFy_v=NQnalpZ-az zLG{B%WP;>n0B`l4e~EOD58PmR@l-(W6`N^6k$Z;f70z~Y&aCtpofzZl>#t%W+8|q9 zK+vV2*-BgD1rbk}R0*mLyjBFwVN}}2_g2ZfDM779P#d7wSVeh@GHNSU$oW9p*~qZY zQmfaQkM{9PA3n-jyLX>4`jtTc>9)mxTpIk8)_gT95 Y{cCEWX9opPw~i{r30nVcpV-h-n; z(X*7IP(3AMprD?Fj0{#8**C)%zL&GM) Hy=m_P&pQun@|Gl|5`Ob+x*X_~d zR!9qBWg}x`AYpK7fX+tB+0`XZ&n|OldI-|lvSd=A14Wb=&dhFb^06mqcQZD-DS2Tj z9864(aqW%QG8y#ASC8W@s5k@#E_dXqCyX_=@ObBmDh(c4OZd#~kARYU6nx^@yc+v2 zjeNnmkgq&p$i1Q(89?au3kv7Sols3ejDq#WC3LNhG5Wl4(MFM`1xrht ;7k4a(oE6kmESE=Rwu zm3-N`fG->c9S6+psuCL5>|2ZiB``MJ a1c9Uy^6*N9Pk-|yD1VPaeg3(;9{;*hd<`FR z_bHFHLL&(n8whDNBW5lhW^ky2sI9aoa;^r#InO{NVz3!gF;EFhzs{Y|%ROEcxf2Ek z2MBGKr4uJPef$)2k3PiVJMU(b21&h2r!Rc)pC4y#t}P}ofBb{@63;FG3-U2#0`8wR zJib_v7>EPS%36=br491b;fk`hN5B?kUm#D*9>Bh-29-)szV0s+J6gd=tIGb#8pY}Y ztyYCF4yjZVM(c*K=wiI%6L z7z4f3va;4=wcV$edk`Ut0(MW-8EqvXLJ%4H zeM{Q6G#W9DTEMaSjJMv}V_{7eO~5O+<_Vthe8AHM0B{ZPac4Ognv@&%=e+rffITfu zx95oBh+R`nn)SFWjlEzqx78acOIs5gHa0Rk?F=1ihFTSB)rcZ@*xX~Cr*M{yjU2oq z%^iP!N6t4MOE7_YCvfX_4M_YX001rlKI*)BJw=z1dY_vQh1{?|U?75i?rF9XMn~&3 zYcVd{((eHTTN*+vh!aexa8BrFj;ye(uc!3$0_Pk?2@7q{C+^F*?L `Qx!H`$&H4G-uw-AOQ%_OGTh>7BWsA9@W(R#X_ zoL( ^I}q^lU7A_|g$ENDl3GY$G AF~rN}c! zuMoOUvDk(A4xH&IPOri2hGH$%*g}I2j_JVsy@Fdo*3J!U{XYh90R+g~McglXTg*Vt z)PU!j-G<#Q!^w5U@nvCYQ?Z^ItTiBdt9hyxl;#1gxDDjvl+$Au1`?hh0M7sP6z~Q? z-sGLX7Uze`p0@_2QZ%bdaZ*H%lKV%9^bw;u3Y_|(6B*Ah08bHHmw~!mkiF$V1$O~w zT`p%^P1C=6f5NvO>(NX7kDNn%P6517*3PW(4uBm1I{ ;TvSumfNRzzcQ#&j7#{ V$J^q4pTPhC002ovPDHLkV1i`jyJi3Y literal 0 HcmV?d00001 diff --git a/samples/JetBoy/res/drawable/asteroid04.png b/samples/JetBoy/res/drawable/asteroid04.png new file mode 100755 index 0000000000000000000000000000000000000000..e89e6f13f0bd7aa64040a755656cb7bbaadf8558 GIT binary patch literal 6803 zcmV;E8f@i>P) KLZ*U+ IBfRsybQWXdwQbLP>6p Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh f59&ghTmgWD0l;*T zI7 09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&nehQ1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_ LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ 0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 z fg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vF IcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a (?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-k iKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BK T#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000lZNkl QYupJz15M~QOkObryk|36Z zNG3#}d;pP1hKK|t7Qq+D2T;f&fq)PM#&RIofCylFP#7DJXT~1S*dEXH^mNZmZ?(SV z-jffn?HCloHf=1quT-mEmFoWPIsbFcJ-0+vc{&fn(|l|K*aWZ%U=zS5fK33K05$<^ z0(iQP;OAbDT=9Rt?>)Tk>Vz#V! ;+ER|*)=e*}&{*^?^!2Y%se z<>wVcKMMeWD-=9LH5tnb{!FaARh`=h86b#>4;drx2EP7F&Y`isI4c_s;MZ~i8wxg- zHx^#L2mT{yci)w>9o~L*#&c(Lj14YxrN32GzW`hd$j|x8XRGpFSNI<|uippW1B`8? zwfs63uovWm&g%`h0sAI0UV8~VXT~z#3>li4=HBumK6UF!{`=lJ@S2;@+$qAhfO~;e zzyo#QB9K?O!o3h{8@snPIlI)Oy)r;TbHo^VKk&t;k_-G1$VXl2whq<$y!JB3EB0EN zv7t5EV0^qmQVWRcqb%q&x7^d_OW%5g`yO6Fod61gUw>l30gkIK+rrB(4tU)QXE@P` z`SgFD;r9KfC wK8)*L~0T|#Wul%i+g}G#^&!1l<>=`x0Y0Q?{5$Z{V_X;Sk zD6v6IIzG)gKf-PMPjcJ$k8`#MSqVl2(UL^kY_I41$!o9X+AFrRa_l~m;bF4+6kj{2 zeBvv|dH9iYn818Xgf|0ozX<>q ZYatb9K3Ibh^T$ph96*^dKnT^G^~%> PzDWTBA+#MZNL zdYOk$wF#_YW_$>X=SO$m%O#V-hi`l~Nj=6peGBlGCnFVZdL@mmGTVUMfhvT7#Ri6Y z8jzRD$Z(yRiD7KsrR;YB!G?mdLR7Qt*wRF7K)YWe0$!`{LBJ^#UZ~ds%*tt2mb&Dn zFenuX1JnkbJ>TKf+!C+6VwktSYBySV6h2Ue(2WI9h*0DXR=OTRaizx?!3Kt{vrUpT z!eiLGeVFM+PSzV#nIKi5bIwzXEYH~1VyGVBoyU1kR(jffhgad^ougcJ`809pNt1wP z%^*PTlv1JaN-^k@ug>$1*X-mumyY8zHv_!?7f7&vEe#Mryb4Ygq*}Q$SIWXsPb|;8 zc$|Dt62$>wY{>iW@eiv)F>t6;hSGqGca5;H)MGFxut2Gh)Iw$^>(m<&9;G#0V|ArZ zHYjMuhP5Qbn}DcTqqA_9@f~&E^T!wQ<`1q=cz=U2@&(}L4HQ98JT?%*&=PnL3f>uP zEg_U1VZDW^4N)x56GT!8pem{gkD0nxl6uIV)(FmdRKeIv6U0=oM1>>`*s-(4!a|2$ zuVCxs5L06*N!h_=p4GYIy!7%*x&9?v`TT!8VyW481K$Mt8{q;WXkbOLBB+8_WqGZ~ zk>g98b;HE7`v`}pDZ3p&C`+Np9Io)V!h=ZV5+anjUk3wPdh%Y0_tk6kG1!nKA=`Jf z*tva#OLmShIhvr}Q5KN3+Z5+c@fWYl&PCSNdy!S8tRCq@b}io&d;mqzb7#67 zJ$8og-1=Yq=)ehFkRoA1Fg%4#>fjacDy0+A#~5I&;0jNfdCEdjr)1rtaud}mcYw-r zJXoo;rV`A`)xCq2xzk)UQu6wjY=cro;V*$`0{}>(>Z8y?8XMaElC^$`2?K_Q>+}X0 zcYNnA?mcjn+W0JGdj*OPVG c=a1=O4F%N?j^4WnNi}Y6VL~9=}FR6-@ww z&=5BpNEp#uc$7C@H^tW3Ccf}50A98c7BGrxYEeQ_`dPJ70wlG7@m8HAvK+bR5KF5a zf?9%>CB{^f5L4ZdbpiG3lCW+KkFU0ZE7w=wRgcCR;xr(xTcUbEShJu?&>SObj?iCQ zX3vD<4KLpg&RgL18v$Sfd|-_d#fB&pLL+!poL9!15ySO}tl#JC!YW~Fil8-(hINA2 z64eZz2=6Vv^i{2}9<+R^>#r5?sCxXm>nJ?#4wcz^ia|-%&2Ub@XGF~*N`)J)8Dqze z5nSPa8)#i<07Iyf#)evCNRxniC`3|4NEM-xhD2eA7=zFHcyB4ofMVTRY7;X=t%)jY z)oR6k>G0lR!jN?P9vZv$Az_LDHmY&}1YGIK`wju3dO|wA6 D~PEAy;w`S^%>YO#Aj=?S9+|@ukz6S#~5$Dn2CCmqH~rY2vM(? z(2$iS4;@{k-#d+z1t%6eoL(LfrwO|+-ph3_xRgOzU<0Gx`Tm8rfP;v8-LWM{r*AO^ zMu$R1h9gSnnHZ}xIgyg20WRy2_twBz0HT^DY)zuUFb+eK4q?S3>gYUj3=;@J9MBq0 zsU 14<5Li$+|G#+l6<2N#LFf z4dCk%*uOclsOh04xMqi?mxD1727-zsPJ(sO0!6@AwSrgS{Ho`~{3%W^EHm6}uxIZq zvr`H2_!e+ETemuf>QPlOHbROlL!^rP#=!E@fTi<&tTiBztqWwc9+5_txy4luA34Eo z3l{bMw6SvX0*j#DV D!2f6*Lw{!6D8RD7Uph^^2w(OdrIod?k<8o!tF35WYzEqZ$`#+f? zQdvg7@T9eX$!5%bC%fEr?`e!R-~VOP;a?;QI4~bKVVd1{+Vj1KN+P?y+Fo%^Sv=P! z%gPFZK$rxqbu!ML@1qFA&4is>M%X&t!YS eHjV)%AuTdJteYLZXZULPPbt0 z^eXyTPVbb}wVah+$)Hqffe>0@tPwIfRtN7mvi|_N6ST}|A3H?R?SNEPWCH<#GI!u1 zjSP`p&ng8%18Hcehp;dRxo>G0tT_bSv4Ooo`H&52%O}q(UpZV7#Z|2KPQfeZ&UaZ} z>QQEnV&HIIi37o|m(QVr(89z}#OP3s)s;0?&Mgtw6XL1uNMi=E7Lh7-4kAMoS;DXq zRAV3tgl5e$R5LVVp_9WW_XnI_6>klH2Mjh4fF3j^`mh8M-#C(U?-@^8t2%%|Y%qav zcB#vHrA%70B%zQ-hV?n1Kxl=u7T~;6I0aYW+N&7f! h&7+Bw(;~o_ysTuD1f}aAlS9QW+NGt%Nj<@ZQreJR*wo!l!=} z={JrVF_!y)zkZV1 S Ro41SHnf#!dMCa#7^4`0yytMa2US8KNdoSghnv0~aK|G?Ou$_tyn4OQ z_~bQ5MT9sCtoPX$`<> $v2~XR&7@plmM^)FMFWtz~rEUG6^7<+BF{+;P$Z4Yfh=NznKG ztoHeaH%CmJ@&*%g^KB0ndvdQ_w_DjU1mg{%-|cgvmoeN(Xf|p@Q9#-Vt6d;pRd~~5b-I1W z$jA^=t%$|NWwN})l?6u^3qE_G e5_>3?0 z`B=x+rf~U; )AG3aK%i?vnL(fhhZoZ(lo?| zhO+czSyf&~v8A6m?tIj7^AX|Ur5f0H$r}Cv^dms$DR)NbrvN +fUaRUlX5 zy$J%x>`=zu(UQI6!uC;198{Yl{ekDys yfcu}ahopWQfO86k z5~YT%qai2H7g15@^K2l$=T%;;UN6J@6r)6;V2yw}y!T|zg4**okT0S7DSpYC{x=T5 zJ7s1h;PqEGx#}4S&)ODqcrNF?|F+1n`5Y5UxZcFPLXo unAxjz|(g8&j8&1+YZ>DE93wG002ovPDHLkV1gwq B)%gGb literal 0 HcmV?d00001 diff --git a/samples/JetBoy/res/drawable/asteroid05.png b/samples/JetBoy/res/drawable/asteroid05.png new file mode 100755 index 0000000000000000000000000000000000000000..b0a78d7729f936c4b036729d4374c6974f3c081f GIT binary patch literal 6636 zcmV KLZ*U+ IBfRsybQWXdwQbLP>6p Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh f59&ghTmgWD0l;*T zI7 09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&nehQ1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_ LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ