aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/tools.atree7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java158
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java7
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java3
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java233
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java58
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/DynamicIdMap.java75
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java51
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java9
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java15
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java26
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/icons/networkstats.pngbin0 -> 476 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/plugin.properties1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NetworkStatisticsView.java47
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/plugin.xml2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTracePerspective.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLState.java31
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLStateType.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/StateTransformFactory.java148
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/DetailsPage.java (renamed from eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsPage.java)42
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/DetailsView.java (renamed from eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsView.java)3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/GlDrawCallDetailProvider.java77
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ICallDetailProvider.java31
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/IDetailProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/IStateDetailsProvider.java)11
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/IStateDetailProvider.java27
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ShaderSourceDetailsProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderSourceDetailsProvider.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ShaderUniformDetailsProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderUniformDetailsProvider.java)4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/TextureImageDetailsProvider.java (renamed from eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/TextureImageDetailsProvider.java)5
-rw-r--r--files/ant/build.xml13
-rw-r--r--files/proguard-android.txt77
-rw-r--r--files/proguard-project.txt20
-rw-r--r--ide_common/src/com/android/ide/common/resources/ResourceRepository.java4
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java63
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java5
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java14
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java5
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ColorUsageDetector.java2
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java107
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java54
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.pro (renamed from files/proguard.cfg)0
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.properties2
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties114
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties214
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties311
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties414
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java7
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java3
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java3
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java10
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java18
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java3
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java3
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-addon-4.xsd15
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-repository-6.xsd52
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java39
64 files changed, 1481 insertions, 244 deletions
diff --git a/build/tools.atree b/build/tools.atree
index f1d46d478..8fc262c1f 100644
--- a/build/tools.atree
+++ b/build/tools.atree
@@ -65,7 +65,8 @@ bin/lint tools/lint
# sdk.git Ant templates for project build files
sdk/templates/build.template tools/lib/build.template
-sdk/files/proguard.cfg tools/lib/proguard.cfg
+sdk/files/proguard-project.txt tools/lib/proguard-project.txt
+sdk/files/proguard-android.txt tools/proguard/proguard-android.txt
# Ant Build Rules
sdk/files/ant tools/ant
@@ -145,7 +146,9 @@ prebuilts/tools/common/proguard/proguard4.7/bin/retrace.sh tools/proguard/bi
prebuilts/tools/common/proguard/proguard4.7/src/proguard/ant/task.properties tools/proguard/ant/task.properties
# SDK Controller
-sdk/apps/SdkController tools/apps/SdkController
+#sdk/apps/SdkController tools/apps/SdkController
+sdk/apps/SdkController/SdkControllerLib tools/apps/SdkController/SdkControllerLib
+sdk/apps/SdkController/SdkControllerSensor tools/apps/SdkController/SdkControllerSensor
# tools specific support jar
framework/annotations.jar tools/support/annotations.jar
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 258493367..f6fe09f19 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -20,7 +20,9 @@ import com.android.AndroidConstants;
import com.android.ide.common.log.ILogger;
import com.android.ide.common.resources.ResourceFile;
import com.android.ide.common.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler.Solution;
import com.android.ide.eclipse.adt.internal.VersionCheck;
+import com.android.ide.eclipse.adt.internal.actions.SdkManagerAction;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.IconFactory;
import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
@@ -42,6 +44,7 @@ import com.android.resources.ResourceFolderType;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
+import org.eclipse.core.commands.Command;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
@@ -59,8 +62,10 @@ import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.util.IPropertyChangeListener;
@@ -78,11 +83,14 @@ import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
+import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.texteditor.AbstractTextEditor;
@@ -162,15 +170,23 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
* checkSdkLocationAndId.
*/
public static abstract class CheckSdkErrorHandler {
+
+ public enum Solution {
+ NONE,
+ OPEN_SDK_MANAGER,
+ OPEN_ANDROID_PREFS,
+ OPEN_P2_UPDATE
+ }
+
/** Handle an error message during sdk location check. Returns whatever
* checkSdkLocationAndId() should returns.
*/
- public abstract boolean handleError(String message);
+ public abstract boolean handleError(Solution solution, String message);
/** Handle a warning message during sdk location check. Returns whatever
* checkSdkLocationAndId() should returns.
*/
- public abstract boolean handleWarning(String message);
+ public abstract boolean handleWarning(Solution solution, String message);
}
/**
@@ -1064,17 +1080,133 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
}
return checkSdkLocationAndId(sdkLocation, new CheckSdkErrorHandler() {
+ private String mTitle = "Android SDK Verification";
@Override
- public boolean handleError(String message) {
- AdtPlugin.displayError("Android SDK Verification", message);
+ public boolean handleError(Solution solution, String message) {
+ displayMessage(solution, message, MessageDialog.ERROR);
return false;
}
@Override
- public boolean handleWarning(String message) {
- AdtPlugin.displayWarning("Android SDK Verification", message);
+ public boolean handleWarning(Solution solution, String message) {
+ displayMessage(solution, message, MessageDialog.WARNING);
return true;
}
+
+ private void displayMessage(
+ final Solution solution,
+ final String message,
+ final int dialogImageType) {
+ final Display disp = getDisplay();
+ disp.asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ Shell shell = disp.getActiveShell();
+ if (shell == null) {
+ return;
+ }
+
+ String customLabel = null;
+ switch(solution) {
+ case OPEN_ANDROID_PREFS:
+ customLabel = "Open Preferences";
+ break;
+ case OPEN_P2_UPDATE:
+ customLabel = "Check for Updates";
+ break;
+ case OPEN_SDK_MANAGER:
+ customLabel = "Open SDK Manager";
+ break;
+ }
+
+ String btnLabels[] = new String[customLabel == null ? 1 : 2];
+ btnLabels[0] = customLabel;
+ btnLabels[btnLabels.length - 1] = IDialogConstants.CLOSE_LABEL;
+
+ MessageDialog dialog = new MessageDialog(
+ shell, // parent
+ mTitle,
+ null, // dialogTitleImage
+ message,
+ dialogImageType,
+ btnLabels,
+ btnLabels.length - 1);
+ int index = dialog.open();
+
+ if (customLabel != null && index == 0) {
+ switch(solution) {
+ case OPEN_ANDROID_PREFS:
+ openAndroidPrefs();
+ break;
+ case OPEN_P2_UPDATE:
+ openP2Update();
+ break;
+ case OPEN_SDK_MANAGER:
+ openSdkManager();
+ break;
+ }
+ }
+ }
+ });
+ }
+
+ private void openSdkManager() {
+ // Windows only: open the standalone external SDK Manager since we know
+ // that ADT on Windows is bound to be locking some SDK folders.
+ if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) {
+ if (SdkManagerAction.openExternalSdkManager()) {
+ return;
+ }
+ }
+
+ // Otherwise open the regular SDK Manager bundled within ADT
+ if (!SdkManagerAction.openAdtSdkManager()) {
+ // We failed because the SDK location is undefined. In this case
+ // let's open the preferences instead.
+ openAndroidPrefs();
+ }
+ }
+
+ private void openP2Update() {
+ Display disp = getDisplay();
+ if (disp == null) {
+ return;
+ }
+ disp.asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ String cmdId = "org.eclipse.equinox.p2.ui.sdk.update"; //$NON-NLS-1$
+ IWorkbench wb = PlatformUI.getWorkbench();
+ if (wb == null) {
+ return;
+ }
+
+ ICommandService cs = (ICommandService) wb.getService(ICommandService.class);
+ IHandlerService is = (IHandlerService) wb.getService(IHandlerService.class);
+ if (cs == null || is == null) {
+ return;
+ }
+
+ Command cmd = cs.getCommand(cmdId);
+ if (cmd != null && cmd.isDefined()) {
+ try {
+ is.executeCommand(cmdId, null/*event*/);
+ } catch (Exception ignore) {
+ AdtPlugin.log(ignore, "Failed to execute command %s", cmdId);
+ }
+ }
+ }
+ });
+ }
+
+ private void openAndroidPrefs() {
+ PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(
+ getDisplay().getActiveShell(),
+ "com.android.ide.eclipse.preferences.main", //$NON-NLS-1$ preferencePageId
+ null, // displayedIds
+ null); // data
+ dialog.open();
+ }
});
}
@@ -1093,6 +1225,7 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
File osSdkFolder = new File(osSdkLocation);
if (osSdkFolder.isDirectory() == false) {
return errorHandler.handleError(
+ Solution.OPEN_ANDROID_PREFS,
String.format(Messages.Could_Not_Find_Folder, osSdkLocation));
}
@@ -1100,6 +1233,7 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
File toolsFolder = new File(osTools);
if (toolsFolder.isDirectory() == false) {
return errorHandler.handleError(
+ Solution.OPEN_ANDROID_PREFS,
String.format(Messages.Could_Not_Find_Folder_In_SDK,
SdkConstants.FD_TOOLS, osSdkLocation));
}
@@ -1113,13 +1247,17 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
// check that we have both the tools component and the platform-tools component.
String platformTools = osSdkLocation + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER;
if (checkFolder(platformTools) == false) {
- return errorHandler.handleWarning("SDK Platform Tools component is missing!\n" +
+ return errorHandler.handleWarning(
+ Solution.OPEN_SDK_MANAGER,
+ "SDK Platform Tools component is missing!\n" +
"Please use the SDK Manager to install it.");
}
String tools = osSdkLocation + SdkConstants.OS_SDK_TOOLS_FOLDER;
if (checkFolder(tools) == false) {
- return errorHandler.handleError("SDK Tools component is missing!\n" +
+ return errorHandler.handleError(
+ Solution.OPEN_SDK_MANAGER,
+ "SDK Tools component is missing!\n" +
"Please use the SDK Manager to install it.");
}
@@ -1131,7 +1269,9 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
};
for (String file : filesToCheck) {
if (checkFile(file) == false) {
- return errorHandler.handleError(String.format(Messages.Could_Not_Find, file));
+ return errorHandler.handleError(
+ Solution.OPEN_ANDROID_PREFS,
+ String.format(Messages.Could_Not_Find, file));
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
index 9055b2973..b468c5e2d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler.Solution;
import com.android.ide.eclipse.adt.Messages;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.repository.PkgProps;
@@ -103,7 +104,9 @@ public final class VersionCheck {
// Failed to get the min plugin version number?
if (minMajorVersion == -1 || minMinorVersion == -1 || minMicroVersion ==-1) {
- return errorHandler.handleWarning(Messages.VersionCheck_Plugin_Version_Failed);
+ return errorHandler.handleWarning(
+ Solution.OPEN_SDK_MANAGER,
+ Messages.VersionCheck_Plugin_Version_Failed);
}
// test the plugin number
@@ -126,6 +129,7 @@ public final class VersionCheck {
if (valid == false) {
return errorHandler.handleError(
+ Solution.OPEN_P2_UPDATE,
String.format(Messages.VersionCheck_Plugin_Too_Old,
minMajorVersion, minMinorVersion, minMicroVersion, versionString));
}
@@ -163,6 +167,7 @@ public final class VersionCheck {
// this is a warning only as we need to parse the SDK to allow updating
// of the tools!
return errorHandler.handleWarning(
+ Solution.OPEN_SDK_MANAGER,
String.format(Messages.VersionCheck_Tools_Too_Old,
MIN_TOOLS_REV, toolsRevision));
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java
index 970bc473c..f8a080a29 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java
@@ -22,6 +22,7 @@ import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.util.GrabProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
@@ -175,7 +176,7 @@ public class DexDumpAction implements IObjectActionDelegate {
int err = GrabProcessOutput.grabProcessOutput(
process,
- true /*waitForReaders*/,
+ Wait.WAIT_FOR_READERS,
new IProcessOutput() {
@Override
public void out(String line) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java
index ddf180fa8..0ff50b55e 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java
@@ -20,6 +20,11 @@ import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.build.DexWrapper;
import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.io.FileOp;
+import com.android.sdklib.util.GrabProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import com.android.sdkuilib.repository.ISdkChangeListener;
import com.android.sdkuilib.repository.SdkUpdaterWindow;
import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext;
@@ -31,6 +36,8 @@ import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import java.io.File;
+
/**
* Delegate for the toolbar/menu action "Android SDK Manager".
* It displays the Android SDK Manager.
@@ -49,93 +56,161 @@ public class SdkManagerAction implements IWorkbenchWindowActionDelegate, IObject
@Override
public void run(IAction action) {
- final Sdk sdk = Sdk.getCurrent();
- if (sdk != null) {
+ if (!openAdtSdkManager()) {
+ AdtPlugin.displayError(
+ "Android SDK",
+ "Location of the Android SDK has not been setup in the preferences.");
+ }
+ }
- // Runs the updater window, directing only warning/errors logs to the ADT console
- // (normal log is just dropped, which is fine since the SDK Manager has its own
- // log window now.)
+ /**
+ * Opens the SDK Manager as an external application.
+ * This call is asynchronous, it doesn't wait for the manager to be closed.
+ *
+ * @return True if the application was found and executed. False if it could not
+ * be located or could not be launched.
+ */
+ public static boolean openExternalSdkManager() {
+ final Sdk sdk = Sdk.getCurrent();
+ if (sdk == null) {
+ return false;
+ }
- SdkUpdaterWindow window = new SdkUpdaterWindow(
- AdtPlugin.getDisplay().getActiveShell(),
- new AdtConsoleSdkLog() {
- @Override
- public void printf(String msgFormat, Object... args) {
- // Do not show non-error/warning log in Eclipse.
- };
- },
- sdk.getSdkLocation(),
- SdkInvocationContext.IDE);
-
- ISdkChangeListener listener = new ISdkChangeListener() {
- @Override
- public void onSdkLoaded() {
- // Ignore initial load of the SDK.
- }
+ File androidBat = FileOp.append(
+ sdk.getSdkLocation(),
+ SdkConstants.FD_TOOLS,
+ SdkConstants.androidCmdName());
- /**
- * Unload all we can from the SDK before new packages are installed.
- * Typically we need to get rid of references to dx from platform-tools
- * and to any platform resource data.
- * <p/>
- * {@inheritDoc}
- */
- @Override
- public void preInstallHook() {
-
- // TODO we need to unload as much of as SDK as possible. Otherwise
- // on Windows we end up with Eclipse locking some files and we can't
- // replace them.
- //
- // At this point, we know what the user wants to install so it would be
- // possible to pass in flags to know what needs to be unloaded. Typically
- // we need to:
- // - unload dex if platform-tools is going to be updated. There's a vague
- // attempt below at removing any references to dex and GCing. Seems
- // to do the trick.
- // - unload any target that is going to be updated since it may have
- // resource data used by a current layout editor (e.g. data/*.ttf
- // and various data/res/*.xml).
- //
- // Most important we need to make sure there isn't a build going on
- // and if there is one, either abort it or wait for it to complete and
- // then we want to make sure we don't get any attempt to use the SDK
- // before the postInstallHook is called.
-
- if (sdk != null) {
- sdk.unloadTargetData(true /*preventReload*/);
-
- DexWrapper dx = sdk.getDexWrapper();
- dx.unload();
- }
- }
+ if (!androidBat.exists()) {
+ return false;
+ }
- /**
- * Nothing to do. We'll reparse the SDK later in onSdkReload.
- * <p/>
- * {@inheritDoc}
- */
- @Override
- public void postInstallHook() {
- }
+ try {
+ final AdtConsoleSdkLog logger = new AdtConsoleSdkLog();
- /**
- * Reparse the SDK in case anything was add/removed.
- * <p/>
- * {@inheritDoc}
- */
- @Override
- public void onSdkReload() {
- AdtPlugin.getDefault().reparseSdk();
- }
+ String command[] = new String[] {
+ androidBat.getAbsolutePath(),
+ "sdk" //$NON-NLS-1$
};
+ Process process = Runtime.getRuntime().exec(command);
+ GrabProcessOutput.grabProcessOutput(
+ process,
+ Wait.ASYNC,
+ new IProcessOutput() {
+ @Override
+ public void out(String line) {
+ // Ignore stdout
+ }
- window.addListener(listener);
- window.open();
- } else {
- AdtPlugin.displayError("Android SDK",
- "Location of the Android SDK has not been setup in the preferences.");
+ @Override
+ public void err(String line) {
+ if (line != null) {
+ logger.printf("[SDK Manager] %s", line);
+ }
+ }
+ });
+ } catch (Exception ignore) {
}
+
+ return true;
+ }
+
+ /**
+ * Opens the SDK Manager bundled within ADT.
+ * The call is blocking and does not return till the SD Manager window is closed.
+ *
+ * @return True if the SDK location is known and the SDK Manager was started.
+ * False if the SDK location is not set and we can't open a SDK Manager to
+ * manage files in an unknown location.
+ */
+ public static boolean openAdtSdkManager() {
+ final Sdk sdk = Sdk.getCurrent();
+ if (sdk == null) {
+ return false;
+ }
+
+ // Runs the updater window, directing only warning/errors logs to the ADT console
+ // (normal log is just dropped, which is fine since the SDK Manager has its own
+ // log window now.)
+
+ SdkUpdaterWindow window = new SdkUpdaterWindow(
+ AdtPlugin.getDisplay().getActiveShell(),
+ new AdtConsoleSdkLog() {
+ @Override
+ public void printf(String msgFormat, Object... args) {
+ // Do not show non-error/warning log in Eclipse.
+ };
+ },
+ sdk.getSdkLocation(),
+ SdkInvocationContext.IDE);
+
+ ISdkChangeListener listener = new ISdkChangeListener() {
+ @Override
+ public void onSdkLoaded() {
+ // Ignore initial load of the SDK.
+ }
+
+ /**
+ * Unload all we can from the SDK before new packages are installed.
+ * Typically we need to get rid of references to dx from platform-tools
+ * and to any platform resource data.
+ * <p/>
+ * {@inheritDoc}
+ */
+ @Override
+ public void preInstallHook() {
+
+ // TODO we need to unload as much of as SDK as possible. Otherwise
+ // on Windows we end up with Eclipse locking some files and we can't
+ // replace them.
+ //
+ // At this point, we know what the user wants to install so it would be
+ // possible to pass in flags to know what needs to be unloaded. Typically
+ // we need to:
+ // - unload dex if platform-tools is going to be updated. There's a vague
+ // attempt below at removing any references to dex and GCing. Seems
+ // to do the trick.
+ // - unload any target that is going to be updated since it may have
+ // resource data used by a current layout editor (e.g. data/*.ttf
+ // and various data/res/*.xml).
+ //
+ // Most important we need to make sure there isn't a build going on
+ // and if there is one, either abort it or wait for it to complete and
+ // then we want to make sure we don't get any attempt to use the SDK
+ // before the postInstallHook is called.
+
+ if (sdk != null) {
+ sdk.unloadTargetData(true /*preventReload*/);
+
+ DexWrapper dx = sdk.getDexWrapper();
+ dx.unload();
+ }
+ }
+
+ /**
+ * Nothing to do. We'll reparse the SDK later in onSdkReload.
+ * <p/>
+ * {@inheritDoc}
+ */
+ @Override
+ public void postInstallHook() {
+ }
+
+ /**
+ * Reparse the SDK in case anything was add/removed.
+ * <p/>
+ * {@inheritDoc}
+ */
+ @Override
+ public void onSdkReload() {
+ AdtPlugin.getDefault().reparseSdk();
+ }
+ };
+
+ window.addListener(listener);
+ window.open();
+
+ return true;
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
index 3ae9f6439..7536c2fca 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
@@ -41,6 +41,7 @@ import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
import com.android.sdklib.internal.build.SignedJarBuilder;
import com.android.sdklib.util.GrabProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -512,7 +513,7 @@ public class BuildHelper {
return compiledPaths;
}
- public void runProguard(File proguardConfig, File inputJar, String[] jarFiles,
+ public void runProguard(List<File> proguardConfigs, File inputJar, String[] jarFiles,
File obfuscatedJar, File logOutput)
throws ProguardResultException, ProguardExecException, IOException {
IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
@@ -521,7 +522,10 @@ public class BuildHelper {
List<String> command = new ArrayList<String>();
command.add(AdtPlugin.getOsAbsoluteProguard());
- command.add("@" + quotePath(proguardConfig.getAbsolutePath())); //$NON-NLS-1$
+ for (File configFile : proguardConfigs) {
+ command.add("-include"); //$NON-NLS-1$
+ command.add(quotePath(configFile.getAbsolutePath()));
+ }
command.add("-injars"); //$NON-NLS-1$
StringBuilder sb = new StringBuilder(quotePath(inputJar.getAbsolutePath()));
@@ -1196,7 +1200,7 @@ public class BuildHelper {
return GrabProcessOutput.grabProcessOutput(
process,
- false /*waitForReaders*/,
+ Wait.WAIT_FOR_PROCESS,
new IProcessOutput() {
@SuppressWarnings("unused")
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java
index 426149e65..eff883b4b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.adt.internal.preferences;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener;
import com.android.sdklib.IAndroidTarget;
@@ -140,13 +141,17 @@ public class AndroidPreferencePage extends FieldEditorPreferencePage implements
boolean ok = AdtPlugin.getDefault().checkSdkLocationAndId(fileName,
new AdtPlugin.CheckSdkErrorHandler() {
@Override
- public boolean handleError(String message) {
+ public boolean handleError(
+ CheckSdkErrorHandler.Solution solution,
+ String message) {
setErrorMessage(message.replaceAll("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$
return false; // Apply/OK must be disabled
}
@Override
- public boolean handleWarning(String message) {
+ public boolean handleWarning(
+ CheckSdkErrorHandler.Solution solution,
+ String message) {
showMessage(message.replaceAll("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$
return true; // Apply/OK must be enabled
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
index 1e5171cb1..93fe43d68 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.adt.internal.project;
+import static com.android.sdklib.internal.project.ProjectProperties.PROPERTY_SDK;
+
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtUtils;
@@ -25,6 +27,7 @@ import com.android.ide.eclipse.adt.internal.build.DexException;
import com.android.ide.eclipse.adt.internal.build.NativeLibInJarException;
import com.android.ide.eclipse.adt.internal.build.ProguardExecException;
import com.android.ide.eclipse.adt.internal.build.ProguardResultException;
+import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.io.IFileWrapper;
@@ -58,6 +61,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -66,8 +70,10 @@ import java.util.jar.JarOutputStream;
* Export helper to export release version of APKs.
*/
public final class ExportHelper {
-
- private final static String TEMP_PREFIX = "android_"; //$NON-NLS-1$
+ private static final String HOME_PROPERTY = "user.home"; //$NON-NLS-1$
+ private static final String HOME_PROPERTY_REF = "${" + HOME_PROPERTY + '}'; //$NON-NLS-1$
+ private static final String SDK_PROPERTY_REF = "${" + PROPERTY_SDK + '}'; //$NON-NLS-1$
+ private final static String TEMP_PREFIX = "android_"; //$NON-NLS-1$
/**
* Exports a release version of the application created by the given project.
@@ -75,7 +81,8 @@ public final class ExportHelper {
* @param outputFile the file to write
* @param key the key to used for signing. Can be null.
* @param certificate the certificate used for signing. Can be null.
- * @param monitor
+ * @param monitor progress monitor
+ * @throws CoreException if an error occurs
*/
public static void exportReleaseApk(IProject project, File outputFile, PrivateKey key,
X509Certificate certificate, IProgressMonitor monitor) throws CoreException {
@@ -151,13 +158,46 @@ public final class ExportHelper {
ProjectProperties.PROPERTY_PROGUARD_CONFIG);
boolean runProguard = false;
- File proguardConfigFile = null;
+ List<File> proguardConfigFiles = null;
if (proguardConfig != null && proguardConfig.length() > 0) {
- proguardConfigFile = new File(proguardConfig);
- if (proguardConfigFile.isAbsolute() == false) {
- proguardConfigFile = new File(project.getLocation().toFile(), proguardConfig);
+ // Be tolerant with respect to file and path separators just like
+ // Ant is. Allow "/" in the property file to mean whatever the file
+ // separator character is:
+ if (File.separatorChar != '/' && proguardConfig.indexOf('/') != -1) {
+ proguardConfig = proguardConfig.replace('/', File.separatorChar);
+ }
+ // Also split path: no need to convert to File.pathSeparator because we'll
+ // be splitting the path ourselves right here, so just ensure that both
+ // ':' and ';' work:
+ if (proguardConfig.indexOf(';') != -1) {
+ proguardConfig = proguardConfig.replace(';', ':');
+ }
+ String[] paths = proguardConfig.split(":"); //$NON-NLS-1$
+
+ for (String path : paths) {
+ if (path.startsWith(SDK_PROPERTY_REF)) {
+ path = AdtPrefs.getPrefs().getOsSdkFolder() +
+ path.substring(SDK_PROPERTY_REF.length());
+ } else if (path.startsWith(HOME_PROPERTY_REF)) {
+ path = System.getProperty(HOME_PROPERTY) +
+ path.substring(HOME_PROPERTY_REF.length());
+ }
+ File proguardConfigFile = new File(path);
+ if (proguardConfigFile.isAbsolute() == false) {
+ proguardConfigFile = new File(project.getLocation().toFile(), path);
+ }
+ if (proguardConfigFile.isFile()) {
+ if (proguardConfigFiles == null) {
+ proguardConfigFiles = new ArrayList<File>();
+ }
+ proguardConfigFiles.add(proguardConfigFile);
+ runProguard = true;
+ } else {
+ throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
+ "Invalid proguard configuration file path " + proguardConfigFile
+ + " does not exist or is not a regular file", null));
+ }
}
- runProguard = proguardConfigFile.isFile();
}
String[] dxInput;
@@ -188,7 +228,7 @@ public final class ExportHelper {
obfuscatedJar.deleteOnExit();
// run proguard
- helper.runProguard(proguardConfigFile, inputJar, jarFiles, obfuscatedJar,
+ helper.runProguard(proguardConfigFiles, inputJar, jarFiles, obfuscatedJar,
new File(project.getLocation().toFile(), SdkConstants.FD_PROGUARD));
// dx input is proguard's output
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/DynamicIdMap.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/DynamicIdMap.java
new file mode 100644
index 000000000..702f8f62a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/DynamicIdMap.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.internal.resources.manager;
+
+import com.android.resources.ResourceType;
+import com.android.sdklib.util.SparseArray;
+import com.android.util.Pair;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class DynamicIdMap {
+
+ private final Map<Pair<ResourceType, String>, Integer> mDynamicIds = new HashMap<Pair<ResourceType, String>, Integer>();
+ private final SparseArray<Pair<ResourceType, String>> mRevDynamicIds = new SparseArray<Pair<ResourceType, String>>();
+ private int mDynamicSeed;
+
+ public DynamicIdMap(int seed) {
+ mDynamicSeed = seed;
+ }
+
+ public void reset(int seed) {
+ mDynamicIds.clear();
+ mRevDynamicIds.clear();
+ mDynamicSeed = seed;
+ }
+
+ /**
+ * Returns a dynamic integer for the given resource type/name, creating it if it doesn't
+ * already exist.
+ *
+ * @param type the type of the resource
+ * @param name the name of the resource
+ * @return an integer.
+ */
+ public Integer getId(ResourceType type, String name) {
+ return getId(Pair.of(type, name));
+ }
+
+ /**
+ * Returns a dynamic integer for the given resource type/name, creating it if it doesn't
+ * already exist.
+ *
+ * @param resource the type/name of the resource
+ * @return an integer.
+ */
+ public Integer getId(Pair<ResourceType, String> resource) {
+ Integer value = mDynamicIds.get(resource);
+ if (value == null) {
+ value = Integer.valueOf(++mDynamicSeed);
+ mDynamicIds.put(resource, value);
+ mRevDynamicIds.put(value, resource);
+ }
+
+ return value;
+ }
+
+ public Pair<ResourceType, String> resolveId(int id) {
+ return mRevDynamicIds.get(id);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
index 780d72f20..e6e3acb18 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java
@@ -32,7 +32,6 @@ import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import java.util.EnumMap;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -61,14 +60,7 @@ public class ProjectResources extends ResourceRepository {
/** Map of (int[], name) for styleable resources coming from R.java */
private Map<IntArrayWrapper, String> mStyleableValueToNameMap;
- /**
- * This list is used by {@link #getResourceId(String, String)} when the resource
- * query is an ID that doesn't exist (for example for ID automatically generated in
- * layout files that are not saved yet).
- */
- private final Map<String, Integer> mDynamicIds = new HashMap<String, Integer>();
- private final Map<Integer, String> mRevDynamicIds = new HashMap<Integer, String>();
- private int mDynamicSeed = DYNAMIC_ID_SEED_START;
+ private final DynamicIdMap mDynamicIdMap = new DynamicIdMap(DYNAMIC_ID_SEED_START);
private final IProject mProject;
@@ -182,9 +174,8 @@ public class ProjectResources extends ResourceRepository {
}
if (result == null) {
- String name = mRevDynamicIds.get(id);
- if (name != null) {
- result = Pair.of(ResourceType.ID, name);
+ synchronized (mDynamicIdMap) {
+ result = mDynamicIdMap.resolveId(id);
}
}
@@ -218,8 +209,10 @@ public class ProjectResources extends ResourceRepository {
}
}
- if (result == null && ResourceType.ID == type) {
- result = getDynamicId(name);
+ if (result == null) {
+ synchronized (mDynamicIdMap) {
+ result = mDynamicIdMap.getId(type, name);
+ }
}
return result;
@@ -233,10 +226,8 @@ public class ProjectResources extends ResourceRepository {
* change.
*/
public void resetDynamicIds() {
- synchronized (mDynamicIds) {
- mDynamicIds.clear();
- mRevDynamicIds.clear();
- mDynamicSeed = DYNAMIC_ID_SEED_START;
+ synchronized (mDynamicIdMap) {
+ mDynamicIdMap.reset(DYNAMIC_ID_SEED_START);
}
}
@@ -246,28 +237,6 @@ public class ProjectResources extends ResourceRepository {
}
/**
- * Returns a dynamic integer for the given resource name, creating it if it doesn't
- * already exist.
- *
- * @param name the name of the resource
- * @return an integer.
- *
- * @see #resetDynamicIds()
- */
- private Integer getDynamicId(String name) {
- synchronized (mDynamicIds) {
- Integer value = mDynamicIds.get(name);
- if (value == null) {
- value = Integer.valueOf(++mDynamicSeed);
- mDynamicIds.put(name, value);
- mRevDynamicIds.put(value, name);
- }
-
- return value;
- }
- }
-
- /**
* Sets compiled resource information.
*
* @param resIdValueToNameMap a map of compiled resource id to resource name.
@@ -283,5 +252,7 @@ public class ProjectResources extends ResourceRepository {
mResourceValueMap = resourceValueMap;
mResIdValueToNameMap = resIdValueToNameMap;
mStyleableValueToNameMap = styleableValueMap;
+
+ resetDynamicIds();
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java
index eb4c1e908..ecc588f7c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ResourceManager.java
@@ -167,6 +167,19 @@ public final class ResourceManager {
* as a place to stash errors encountered
*/
public void processDelta(IResourceDelta delta, IdeScanningContext context) {
+ doProcessDelta(delta, context);
+
+ context.getRepository().postUpdateCleanUp();
+ }
+
+ /**
+ * Update the resource repository with a delta
+ *
+ * @param delta the resource changed delta to process.
+ * @param context a context object with state for the current update, such
+ * as a place to stash errors encountered
+ */
+ private void doProcessDelta(IResourceDelta delta, IdeScanningContext context) {
// Skip over deltas that don't fit our mask
int mask = IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED;
int kind = delta.getKind();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java
index 2b3e2c272..96add7117 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.adt.internal.welcome;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.sdkstats.DdmsPreferenceStore;
import com.android.sdkstats.SdkStatsService;
@@ -83,12 +84,16 @@ public class AdtStartup implements IStartup {
boolean ok = AdtPlugin.getDefault().checkSdkLocationAndId(osSdkPath,
new AdtPlugin.CheckSdkErrorHandler() {
@Override
- public boolean handleError(String message) {
+ public boolean handleError(
+ CheckSdkErrorHandler.Solution solution,
+ String message) {
return false;
}
@Override
- public boolean handleWarning(String message) {
+ public boolean handleWarning(
+ CheckSdkErrorHandler.Solution solution,
+ String message) {
return true;
}
});
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java
index d41843219..4e580fefb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.adt.internal.welcome;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
@@ -262,14 +263,18 @@ public class WelcomeWizardPage extends WizardPage implements ModifyListener, Sel
AdtPlugin.getDefault().checkSdkLocationAndId(path,
new AdtPlugin.CheckSdkErrorHandler() {
@Override
- public boolean handleError(String message) {
+ public boolean handleError(
+ CheckSdkErrorHandler.Solution solution,
+ String message) {
message = message.replaceAll("\n", " "); //$NON-NLS-1$ //$NON-NLS-2$
errorReference.set(message);
return false; // Apply/OK must be disabled
}
@Override
- public boolean handleWarning(String message) {
+ public boolean handleWarning(
+ CheckSdkErrorHandler.Solution solution,
+ String message) {
message = message.replaceAll("\n", " "); //$NON-NLS-1$ //$NON-NLS-2$
warningReference.set(message);
return true; // Apply/OK must be enabled
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java
index 4ce8230ec..8fcf90289 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java
@@ -24,6 +24,7 @@ import com.android.sdklib.internal.build.DebugKeyProvider.IKeyGenOutput;
import com.android.sdklib.internal.build.KeystoreHelper;
import com.android.sdklib.util.GrabProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@@ -543,7 +544,7 @@ public final class ExportWizard extends Wizard implements IExportWizard {
int status = GrabProcessOutput.grabProcessOutput(
process,
- true /*waitForReaders*/,
+ Wait.WAIT_FOR_READERS,
new IProcessOutput() {
@Override
public void out(String line) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java
index 97da3abd7..7424d6cc4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java
@@ -606,7 +606,10 @@ public class NewProjectCreator {
File libFolder = new File((String) parameters.get(PARAM_SDK_TOOLS_DIR),
SdkConstants.FD_LIB);
addLocalFile(project,
- new File(libFolder, SdkConstants.FN_PROGUARD_CFG),
+ new File(libFolder, SdkConstants.FN_PROJECT_PROGUARD_FILE),
+ // Write ProGuard config files with the extension .pro which
+ // is what is used in the ProGuard documentation and samples
+ SdkConstants.FN_PROJECT_PROGUARD_FILE,
monitor);
// Set output location
@@ -1080,13 +1083,14 @@ public class NewProjectCreator {
/**
* Adds a file to the root of the project
* @param project the project to add the file to.
+ * @param destName the name to write the file as
* @param source the file to add. It'll keep the same filename once copied into the project.
* @throws FileNotFoundException
* @throws CoreException
*/
- private void addLocalFile(IProject project, File source, IProgressMonitor monitor)
- throws FileNotFoundException, CoreException {
- IFile dest = project.getFile(source.getName());
+ private void addLocalFile(IProject project, File source, String destName,
+ IProgressMonitor monitor) throws FileNotFoundException, CoreException {
+ IFile dest = project.getFile(destName);
if (dest.exists() == false) {
FileInputStream stream = new FileInputStream(source);
dest.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
index d5bd8950e..ea78127a2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
@@ -15,6 +15,9 @@
*/
package com.android.ide.eclipse.adt.internal.wizards.newproject;
+import static com.android.sdklib.SdkConstants.FN_PROJECT_PROGUARD_FILE;
+import static com.android.sdklib.SdkConstants.OS_SDK_TOOLS_LIB_FOLDER;
+
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
@@ -26,6 +29,8 @@ import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
+import java.io.File;
+
/**
* A "New Android Project" Wizard.
@@ -105,6 +110,16 @@ public class NewProjectWizard extends Wizard implements INewWizard {
@Override
public boolean performFinish() {
+ File file = new File(AdtPlugin.getOsSdkFolder(), OS_SDK_TOOLS_LIB_FOLDER + File.separator
+ + FN_PROJECT_PROGUARD_FILE);
+ if (!file.exists()) {
+ AdtPlugin.displayError("Tools Out of Date?",
+ String.format("It looks like you do not have the latest version of the "
+ + "SDK Tools installed. Make sure you update via the SDK Manager "
+ + "first. (Could not find %1$s)", file.getPath()));
+ return false;
+ }
+
NewProjectCreator creator = new NewProjectCreator(mValues, getContainer());
if (!(creator.createAndroidProjects())) {
return false;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java
index 3db335300..6de65567f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java
@@ -18,8 +18,11 @@ package com.android.ide.eclipse.adt.internal.wizards.newproject;
import static com.android.ide.eclipse.adt.AdtUtils.capitalize;
import static com.android.ide.eclipse.adt.AdtUtils.stripWhitespace;
import static com.android.ide.eclipse.adt.internal.wizards.newproject.ApplicationInfoPage.ACTIVITY_NAME_SUFFIX;
+import static com.android.sdklib.SdkConstants.FN_PROJECT_PROGUARD_FILE;
+import static com.android.sdklib.SdkConstants.OS_SDK_TOOLS_LIB_FOLDER;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.VersionCheck;
import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
import com.android.sdklib.SdkConstants;
@@ -85,6 +88,15 @@ class ProjectNamePage extends WizardPage implements SelectionListener, ModifyLis
private Button mBrowseButton;
private Label mLocationLabel;
private WorkingSetGroup mWorkingSetGroup;
+ /**
+ * Whether we've made sure the Tools are up to date (enough that all the
+ * resources required by the New Project wizard are present -- we don't
+ * necessarily check for newer versions than that here; that's done by
+ * {@link VersionCheck}, though that check doesn't <b>enforce</b> an update
+ * since it needs to allow the user to proceed to access the SDK manager
+ * etc.)
+ */
+ private boolean mCheckedSdkUptodate;
/**
* Create the wizard.
@@ -446,6 +458,20 @@ class ProjectNamePage extends WizardPage implements SelectionListener, ModifyLis
}
}
+ if (!mCheckedSdkUptodate) {
+ // Ensure that we have a recent enough version of the Tools that the right templates
+ // are available
+ File file = new File(AdtPlugin.getOsSdkFolder(), OS_SDK_TOOLS_LIB_FOLDER
+ + File.separator + FN_PROJECT_PROGUARD_FILE);
+ if (!file.exists()) {
+ status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
+ String.format("You do not have the latest version of the "
+ + "SDK Tools installed: Please update. (Missing %1$s)", file.getPath()));
+ } else {
+ mCheckedSdkUptodate = true;
+ }
+ }
+
// -- update UI & enable finish if there's no error
setPageComplete(status == null || status.getSeverity() != IStatus.ERROR);
if (status != null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/icons/networkstats.png b/eclipse/plugins/com.android.ide.eclipse.ddms/icons/networkstats.png
new file mode 100644
index 000000000..7018705f2
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/icons/networkstats.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.properties b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.properties
index 5a37fd5b3..6fd8e50e3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.properties
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.properties
@@ -9,6 +9,7 @@ view.name.Heap = Heap
view.name.File_Explorer = File Explorer
view.name.Emulator_Control = Emulator Control
view.name.Allocation_Tracker = Allocation Tracker
+view.name.Network_Stats = Network Statistics
perspective.name.DDMS = DDMS
page.name.DDMS = DDMS
page.name.LogCat = LogCat
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml
index 1255b6215..c1d43ae13 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml
@@ -79,6 +79,14 @@
icon="icons/heap.png"
id="com.android.ide.eclipse.ddms.views.AllocTrackerView"
name="%view.name.Allocation_Tracker"/>
+ <view
+ category="com.android.ide.eclipse.ddms.views.category"
+ class="com.android.ide.eclipse.ddms.views.NetworkStatisticsView"
+ icon="icons/networkstats.png"
+ id="com.android.ide.eclipse.ddms.views.NetworkStatsView"
+ name="%view.name.Network_Stats"
+ restorable="true">
+ </view>
</extension>
<extension
point="org.eclipse.ui.perspectives">
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java
index 4f3494c84..d86a52632 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/Perspective.java
@@ -22,6 +22,7 @@ import com.android.ide.eclipse.ddms.views.EmulatorControlView;
import com.android.ide.eclipse.ddms.views.FileExplorerView;
import com.android.ide.eclipse.ddms.views.HeapView;
import com.android.ide.eclipse.ddms.views.LogCatView;
+import com.android.ide.eclipse.ddms.views.NetworkStatisticsView;
import com.android.ide.eclipse.ddms.views.ThreadView;
import org.eclipse.ui.IFolderLayout;
@@ -63,6 +64,7 @@ public class Perspective implements IPerspectiveFactory {
folder.addView(ThreadView.ID);
folder.addView(HeapView.ID);
folder.addView(AllocTrackerView.ID);
+ folder.addView(NetworkStatisticsView.ID);
folder.addView(FileExplorerView.ID);
layout.addPerspectiveShortcut("org.eclipse.ui.resourcePerspective"); //$NON-NLS-1$
@@ -75,6 +77,7 @@ public class Perspective implements IPerspectiveFactory {
layout.addShowViewShortcut(AllocTrackerView.ID);
layout.addShowViewShortcut(LogCatView.ID);
layout.addShowViewShortcut(ThreadView.ID);
+ layout.addShowViewShortcut(NetworkStatisticsView.ID);
layout.addShowViewShortcut(IPageLayout.ID_RES_NAV);
layout.addShowViewShortcut(IPageLayout.ID_BOOKMARKS);
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NetworkStatisticsView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NetworkStatisticsView.java
new file mode 100644
index 000000000..f90189c6d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/NetworkStatisticsView.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.ddms.views;
+
+import com.android.ddmuilib.net.NetworkPanel;
+
+import org.eclipse.swt.widgets.Composite;
+
+public class NetworkStatisticsView extends TableView {
+ public static final String ID = "com.android.ide.eclipse.ddms.views.NetworkStatsView";
+
+ private NetworkPanel mPanel;
+
+ public NetworkStatisticsView() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ mPanel = new NetworkPanel();
+ mPanel.createPanel(parent);
+
+ setSelectionDependentPanel(mPanel);
+
+ // listen to focus changes for table(s) of the panel.
+ setupTableFocusListener(mPanel, parent);
+ }
+
+ @Override
+ public void setFocus() {
+ mPanel.setFocus();
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.gldebugger/plugin.xml
index 66f7fa662..ff2799fcb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/plugin.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/plugin.xml
@@ -33,7 +33,7 @@
</view>
<view
category="com.android.ide.eclipse.gltrace"
- class="com.android.ide.eclipse.gltrace.views.DetailsView"
+ class="com.android.ide.eclipse.gltrace.views.detail.DetailsView"
icon="icons/opengl.png"
id="com.android.ide.eclipse.gltrace.views.Details"
name="Details"
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTracePerspective.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTracePerspective.java
index bc41e335b..30bb1d532 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTracePerspective.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/GLTracePerspective.java
@@ -16,9 +16,9 @@
package com.android.ide.eclipse.gltrace;
-import com.android.ide.eclipse.gltrace.views.DetailsView;
import com.android.ide.eclipse.gltrace.views.FrameSummaryView;
import com.android.ide.eclipse.gltrace.views.StateView;
+import com.android.ide.eclipse.gltrace.views.detail.DetailsView;
import org.eclipse.ui.IFolderLayout;
import org.eclipse.ui.IPageLayout;
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
index ece472397..4d1da1fa8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
@@ -24,8 +24,8 @@ import com.android.ide.eclipse.gltrace.editors.GLCallGroups.GLCallNode;
import com.android.ide.eclipse.gltrace.model.GLCall;
import com.android.ide.eclipse.gltrace.model.GLFrame;
import com.android.ide.eclipse.gltrace.model.GLTrace;
-import com.android.ide.eclipse.gltrace.views.DetailsPage;
import com.android.ide.eclipse.gltrace.views.FrameSummaryViewPage;
+import com.android.ide.eclipse.gltrace.views.detail.DetailsPage;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLState.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLState.java
index dfc922a6d..690fb7e87 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLState.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLState.java
@@ -25,6 +25,9 @@ public class GLState {
/** # of texture units modelled in the GL State. */
public static final int TEXTURE_UNIT_COUNT = 8;
+ /** # of vertex attributes */
+ private static final int MAX_VERTEX_ATTRIBS = 8;
+
private static GLState sGLState = new GLState();
private IGLProperty createBufferBindings() {
@@ -32,11 +35,11 @@ public class GLState {
array = new GLIntegerProperty(GLStateType.ARRAY_BUFFER_BINDING, 0);
eArray = new GLIntegerProperty(GLStateType.ELEMENT_ARRAY_BUFFER_BINDING, 0);
+
vArray = new GLIntegerProperty(
GLStateType.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_PER_INDEX, 0);
-
IGLProperty vArray8 = new GLListProperty(GLStateType.VERTEX_ATTRIB_ARRAY_BUFFER_BINDINGS,
- vArray, 8);
+ vArray, MAX_VERTEX_ATTRIBS);
return new GLCompositeProperty(
GLStateType.BUFFER_BINDINGS,
@@ -67,14 +70,36 @@ public class GLState {
return new GLListProperty(
GLStateType.VERTEX_ATTRIB_ARRAY,
perVertexAttribArrayState,
- 8);
+ MAX_VERTEX_ATTRIBS);
+ }
+
+ private IGLProperty createGenericVertexAttributeState() {
+ IGLProperty v0 = new GLFloatProperty(GLStateType.GENERIC_VERTEX_ATTRIB_V0,
+ Float.valueOf(0));
+ IGLProperty v1 = new GLFloatProperty(GLStateType.GENERIC_VERTEX_ATTRIB_V1,
+ Float.valueOf(0));
+ IGLProperty v2 = new GLFloatProperty(GLStateType.GENERIC_VERTEX_ATTRIB_V2,
+ Float.valueOf(0));
+ IGLProperty v3 = new GLFloatProperty(GLStateType.GENERIC_VERTEX_ATTRIB_V3,
+ Float.valueOf(0));
+
+ IGLProperty perGenericVertexAttribState = new GLCompositeProperty(
+ GLStateType.GENERIC_VERTEX_ATTRIBUTE_DATA_COMPOSITE,
+ v0, v1, v2, v3);
+
+ return new GLListProperty(
+ GLStateType.GENERIC_VERTEX_ATTRIBUTES,
+ perGenericVertexAttribState,
+ MAX_VERTEX_ATTRIBS);
}
private IGLProperty createVertexArrayData() {
IGLProperty vertexAttribArrays = createVertexAttribArrays();
IGLProperty bufferBindings = createBufferBindings();
+ IGLProperty genericAttribs = createGenericVertexAttributeState();
return new GLCompositeProperty(GLStateType.VERTEX_ARRAY_DATA,
+ genericAttribs,
vertexAttribArrays,
bufferBindings);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLStateType.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLStateType.java
index 42016fa45..9d367be7c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLStateType.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/GLStateType.java
@@ -25,6 +25,13 @@ public enum GLStateType {
GL_STATE_ES2("OpenGL ES 2.0 State"),
VERTEX_ARRAY_DATA("Vertex Array Data"),
+ GENERIC_VERTEX_ATTRIBUTES("Generic Vertex Attributes"),
+ GENERIC_VERTEX_ATTRIBUTE_DATA_COMPOSITE("Generic Vertex Attribute Data"),
+ GENERIC_VERTEX_ATTRIB_V0("x"),
+ GENERIC_VERTEX_ATTRIB_V1("y"),
+ GENERIC_VERTEX_ATTRIB_V2("z"),
+ GENERIC_VERTEX_ATTRIB_V3("w"),
+
VERTEX_ATTRIB_ARRAY("Vertex Attrib Array Properties"),
VERTEX_ATTRIB_ARRAY_COMPOSITE("Vertex Attrib Array #n Properties"),
VERTEX_ATTRIB_ARRAY_ENABLED("Vertex Attrib Array Enable"),
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/StateTransformFactory.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/StateTransformFactory.java
index 3cc1004c1..0afd2e1fb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/StateTransformFactory.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/state/transforms/StateTransformFactory.java
@@ -41,14 +41,38 @@ public class StateTransformFactory {
switch (msg.getFunction()) {
case eglCreateContext:
return transformsForEglCreateContext(msg);
- case glVertexAttribPointer:
- return transformsForGlVertexAttribPointer(msg);
case glBindFramebuffer:
return transformsForGlBindFramebuffer(msg);
+
+ // vertex data
+ case glVertexAttribPointer:
+ return transformsForGlVertexAttribPointer(msg);
+ case glVertexAttrib1f:
+ case glVertexAttrib2f:
+ case glVertexAttrib3f:
+ case glVertexAttrib4f:
+ return transformsForGlVertexAttribxf(msg);
+ case glVertexAttrib1fv:
+ case glVertexAttrib2fv:
+ case glVertexAttrib3fv:
+ case glVertexAttrib4fv:
+ return transformsForGlVertexAttribxfv(msg);
+ case glEnableVertexAttribArray:
+ return transformsForGlEnableVertexAttribArray(msg);
+ case glDisableVertexAttribArray:
+ return transformsForGlDisableVertexAttribArray(msg);
+
+ // VBO's
+ case glBindBuffer:
+ return transformsForGlBindBuffer(msg);
+
+ // transformation state
case glViewport:
return transformsForGlViewport(msg);
case glDepthRangef:
return transformsForGlDepthRangef(msg);
+
+ // rasterization
case glLineWidth:
return transformsForGlLineWidth(msg);
case glCullFace:
@@ -57,6 +81,8 @@ public class StateTransformFactory {
return transformsForGlFrontFace(msg);
case glPolygonOffset:
return transformsForGlPolygonOffset(msg);
+
+ // pixel operations
case glScissor:
return transformsForGlScissor(msg);
case glStencilFunc:
@@ -194,6 +220,124 @@ public class StateTransformFactory {
return transforms;
}
+ private static List<IStateTransform> transformsForGlVertexAttrib(int context,
+ int index, float v0, float v1, float v2, float v3) {
+ List<IStateTransform> transforms = new ArrayList<IStateTransform>(4);
+ transforms.add(new PropertyChangeTransform(
+ GLPropertyAccessor.makeAccessor(context,
+ GLStateType.VERTEX_ARRAY_DATA,
+ GLStateType.GENERIC_VERTEX_ATTRIBUTES,
+ Integer.valueOf(index),
+ GLStateType.GENERIC_VERTEX_ATTRIB_V0),
+ Float.valueOf(v0)));
+ transforms.add(new PropertyChangeTransform(
+ GLPropertyAccessor.makeAccessor(context,
+ GLStateType.VERTEX_ARRAY_DATA,
+ GLStateType.GENERIC_VERTEX_ATTRIBUTES,
+ Integer.valueOf(index),
+ GLStateType.GENERIC_VERTEX_ATTRIB_V1),
+ Float.valueOf(v1)));
+ transforms.add(new PropertyChangeTransform(
+ GLPropertyAccessor.makeAccessor(context,
+ GLStateType.VERTEX_ARRAY_DATA,
+ GLStateType.GENERIC_VERTEX_ATTRIBUTES,
+ Integer.valueOf(index),
+ GLStateType.GENERIC_VERTEX_ATTRIB_V2),
+ Float.valueOf(v2)));
+ transforms.add(new PropertyChangeTransform(
+ GLPropertyAccessor.makeAccessor(context,
+ GLStateType.VERTEX_ARRAY_DATA,
+ GLStateType.GENERIC_VERTEX_ATTRIBUTES,
+ Integer.valueOf(index),
+ GLStateType.GENERIC_VERTEX_ATTRIB_V3),
+ Float.valueOf(v3)));
+ return transforms;
+ }
+
+ private static List<IStateTransform> transformsForGlVertexAttribxf(GLMessage msg) {
+ // void glVertexAttrib1f(GLuint index, GLfloat v0);
+ // void glVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
+ // void glVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
+ // void glVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+
+ int index = msg.getArgs(0).getIntValue(0);
+ float v0 = msg.getArgs(1).getFloatValue(0);
+ float v1 = msg.getArgsCount() > 2 ? msg.getArgs(2).getFloatValue(0) : 0;
+ float v2 = msg.getArgsCount() > 3 ? msg.getArgs(3).getFloatValue(0) : 0;
+ float v3 = msg.getArgsCount() > 4 ? msg.getArgs(4).getFloatValue(0) : 0;
+
+ return transformsForGlVertexAttrib(msg.getContextId(), index, v0, v1, v2, v3);
+ }
+
+ private static List<IStateTransform> transformsForGlVertexAttribxfv(GLMessage msg) {
+ // void glVertexAttrib1fv(GLuint index, const GLfloat *v);
+ // void glVertexAttrib2fv(GLuint index, const GLfloat *v);
+ // void glVertexAttrib3fv(GLuint index, const GLfloat *v);
+ // void glVertexAttrib4fv(GLuint index, const GLfloat *v);
+
+ int index = msg.getArgs(0).getIntValue(0);
+ float v[] = new float[4];
+
+ for (int i = 0; i < msg.getArgs(1).getFloatValueList().size(); i++) {
+ v[i] = msg.getArgs(1).getFloatValue(i);
+ }
+
+ return transformsForGlVertexAttrib(msg.getContextId(), index, v[0], v[1], v[2], v[3]);
+ }
+
+ private static List<IStateTransform> transformsForGlEnableVertexAttribArray(GLMessage msg) {
+ // void glEnableVertexAttribArray(GLuint index);
+ // void glDisableVertexAttribArray(GLuint index);
+
+ int index = msg.getArgs(0).getIntValue(0);
+ IStateTransform transform = new PropertyChangeTransform(
+ GLPropertyAccessor.makeAccessor(msg.getContextId(),
+ GLStateType.VERTEX_ARRAY_DATA,
+ GLStateType.VERTEX_ATTRIB_ARRAY,
+ Integer.valueOf(index),
+ GLStateType.VERTEX_ATTRIB_ARRAY_ENABLED),
+ Boolean.TRUE);
+ return Collections.singletonList(transform);
+ }
+
+ private static List<IStateTransform> transformsForGlDisableVertexAttribArray(GLMessage msg) {
+ // void glEnableVertexAttribArray(GLuint index);
+ // void glDisableVertexAttribArray(GLuint index);
+
+ int index = msg.getArgs(0).getIntValue(0);
+ IStateTransform transform = new PropertyChangeTransform(
+ GLPropertyAccessor.makeAccessor(msg.getContextId(),
+ GLStateType.VERTEX_ARRAY_DATA,
+ GLStateType.VERTEX_ATTRIB_ARRAY,
+ Integer.valueOf(index),
+ GLStateType.VERTEX_ATTRIB_ARRAY_ENABLED),
+ Boolean.FALSE);
+ return Collections.singletonList(transform);
+ }
+
+ private static List<IStateTransform> transformsForGlBindBuffer(GLMessage msg) {
+ // void glBindBuffer(GLenum target, GLuint buffer);
+ // target is one of GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER.
+
+ GLEnum target = GLEnum.valueOf(msg.getArgs(0).getIntValue(0));
+ int buffer = msg.getArgs(1).getIntValue(0);
+ GLStateType bufferType;
+
+ if (target == GLEnum.GL_ARRAY_BUFFER) {
+ bufferType = GLStateType.ARRAY_BUFFER_BINDING;
+ } else {
+ bufferType = GLStateType.ELEMENT_ARRAY_BUFFER_BINDING;
+ }
+
+ IStateTransform transform = new PropertyChangeTransform(
+ GLPropertyAccessor.makeAccessor(msg.getContextId(),
+ GLStateType.VERTEX_ARRAY_DATA,
+ GLStateType.BUFFER_BINDINGS,
+ bufferType),
+ Integer.valueOf(buffer));
+ return Collections.singletonList(transform);
+ }
+
private static List<IStateTransform> transformsForGlBindFramebuffer(GLMessage msg) {
// void glBindFramebuffer(GLenum target, GLuint framebuffer);
int fb = msg.getArgs(1).getIntValue(0);
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsPage.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/DetailsPage.java
index 88e7b05b7..6d6f00de5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/DetailsPage.java
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.gltrace.views;
+package com.android.ide.eclipse.gltrace.views.detail;
import com.android.ide.eclipse.gltrace.editors.GLCallGroups.GLCallNode;
import com.android.ide.eclipse.gltrace.editors.GLFunctionTraceViewer;
import com.android.ide.eclipse.gltrace.model.GLCall;
import com.android.ide.eclipse.gltrace.model.GLTrace;
import com.android.ide.eclipse.gltrace.state.IGLProperty;
+import com.android.ide.eclipse.gltrace.views.StateView;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IToolBarManager;
@@ -48,10 +49,11 @@ public class DetailsPage extends Page implements ISelectionListener {
private StackLayout mStackLayout;
private Composite mBlankComposite;
- private List<IStateDetailsProvider> mStateDetailProviders = Arrays.asList(
+ private List<IDetailProvider> mDetailProviders = Arrays.asList(
new ShaderSourceDetailsProvider(),
new ShaderUniformDetailsProvider(),
- new TextureImageDetailsProvider());
+ new TextureImageDetailsProvider(),
+ new GlDrawCallDetailProvider());
public DetailsPage(GLTrace trace) {
mTrace = trace;
@@ -68,7 +70,7 @@ public class DetailsPage extends Page implements ISelectionListener {
mToolBarManager = getSite().getActionBars().getToolBarManager();
- for (IStateDetailsProvider provider : mStateDetailProviders) {
+ for (IDetailProvider provider : mDetailProviders) {
provider.createControl(mTopComposite);
for (IContributionItem item: provider.getToolBarItems()) {
@@ -79,7 +81,7 @@ public class DetailsPage extends Page implements ISelectionListener {
setDetailsProvider(null);
}
- private void setDetailsProvider(IStateDetailsProvider provider) {
+ private void setDetailsProvider(IDetailProvider provider) {
for (IContributionItem item: mToolBarManager.getItems()) {
item.setVisible(false);
}
@@ -117,7 +119,7 @@ public class DetailsPage extends Page implements ISelectionListener {
public void dispose() {
getSite().getPage().removeSelectionListener(this);
- for (IStateDetailsProvider provider : mStateDetailProviders) {
+ for (IDetailProvider provider : mDetailProviders) {
provider.disposeControl();
}
@@ -152,10 +154,15 @@ public class DetailsPage extends Page implements ISelectionListener {
}
private void stateVariableSelected(IGLProperty property) {
- for (IStateDetailsProvider p : mStateDetailProviders) {
- if (p.isApplicable(property)) {
- p.updateControl(property);
- setDetailsProvider(p);
+ for (IDetailProvider p : mDetailProviders) {
+ if (!(p instanceof IStateDetailProvider)) {
+ continue;
+ }
+
+ IStateDetailProvider sp = (IStateDetailProvider) p;
+ if (sp.isApplicable(property)) {
+ sp.updateControl(property);
+ setDetailsProvider(sp);
return;
}
}
@@ -165,6 +172,21 @@ public class DetailsPage extends Page implements ISelectionListener {
}
private void callSelected(GLCall selectedCall) {
+ for (IDetailProvider p : mDetailProviders) {
+ if (!(p instanceof ICallDetailProvider)) {
+ continue;
+ }
+
+ ICallDetailProvider cp = (ICallDetailProvider) p;
+ if (cp.isApplicable(selectedCall)) {
+ cp.updateControl(mTrace, selectedCall);
+ setDetailsProvider(cp);
+ return;
+ }
+ }
+
+ setDetailsProvider(null);
+ return;
}
private GLCall getSelectedCall(GLFunctionTraceViewer part, ISelection selection) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsView.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/DetailsView.java
index 015cf61ec..0a2d88e52 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsView.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/DetailsView.java
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.gltrace.views;
+package com.android.ide.eclipse.gltrace.views.detail;
import com.android.ide.eclipse.gltrace.editors.GLFunctionTraceViewer;
+import com.android.ide.eclipse.gltrace.views.GLPageBookView;
import org.eclipse.ui.IWorkbenchPart;
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/GlDrawCallDetailProvider.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/GlDrawCallDetailProvider.java
new file mode 100644
index 000000000..c3cabb09e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/GlDrawCallDetailProvider.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gltrace.views.detail;
+
+import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.Function;
+import com.android.ide.eclipse.gltrace.model.GLCall;
+import com.android.ide.eclipse.gltrace.model.GLTrace;
+import com.android.ide.eclipse.gltrace.views.FitToCanvasAction;
+import com.android.ide.eclipse.gltrace.widgets.ImageCanvas;
+
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+import java.util.Collections;
+import java.util.List;
+
+public class GlDrawCallDetailProvider implements ICallDetailProvider {
+ private ImageCanvas mImageCanvas;
+ private FitToCanvasAction mFitToCanvasAction;
+ private List<IContributionItem> mToolBarItems;
+
+ @Override
+ public boolean isApplicable(GLCall call) {
+ return (call.getFunction() == Function.glDrawArrays
+ || call.getFunction() == Function.glDrawElements) && call.hasFb();
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ mImageCanvas = new ImageCanvas(parent);
+ mImageCanvas.setFitToCanvas(false);
+
+ mFitToCanvasAction = new FitToCanvasAction(false, mImageCanvas);
+ mToolBarItems = Collections.singletonList(
+ (IContributionItem) new ActionContributionItem(mFitToCanvasAction));
+ }
+
+ @Override
+ public void disposeControl() {
+ if (mImageCanvas != null) {
+ mImageCanvas.dispose();
+ mImageCanvas = null;
+ }
+ }
+
+ @Override
+ public Control getControl() {
+ return mImageCanvas;
+ }
+
+ @Override
+ public void updateControl(GLTrace trace, GLCall call) {
+ mImageCanvas.setImage(trace.getImage(call));
+ mImageCanvas.setFitToCanvas(true);
+ }
+
+ @Override
+ public List<IContributionItem> getToolBarItems() {
+ return mToolBarItems;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ICallDetailProvider.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ICallDetailProvider.java
new file mode 100644
index 000000000..51770f35b
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ICallDetailProvider.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gltrace.views.detail;
+
+import com.android.ide.eclipse.gltrace.model.GLCall;
+import com.android.ide.eclipse.gltrace.model.GLTrace;
+
+public interface ICallDetailProvider extends IDetailProvider {
+ /** Is this provider applicable for given {@link GLCall}? */
+ boolean isApplicable(GLCall call);
+
+ /**
+ * Update the detail view for given {@link GLCall} that is part of the given
+ * {@link GLTrace}.
+ */
+ void updateControl(GLTrace trace, GLCall call);
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/IStateDetailsProvider.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/IDetailProvider.java
index 7fe7c5609..1fc5174d3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/IStateDetailsProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/IDetailProvider.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.gltrace.views;
-
-import com.android.ide.eclipse.gltrace.state.IGLProperty;
+package com.android.ide.eclipse.gltrace.views.detail;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.swt.widgets.Composite;
@@ -24,10 +22,7 @@ import org.eclipse.swt.widgets.Control;
import java.util.List;
-public interface IStateDetailsProvider {
- /** Is this provider applicable for given GL state property? */
- boolean isApplicable(IGLProperty state);
-
+public interface IDetailProvider {
/** Create the controls to display the details. */
void createControl(Composite parent);
@@ -37,8 +32,6 @@ public interface IStateDetailsProvider {
/** Obtain the top level control used by this detail provider. */
Control getControl();
- /** Update the detail view for given GL state property. */
- void updateControl(IGLProperty state);
/** Obtain a list of tool bar items to be displayed when this provider is active. */
List<IContributionItem> getToolBarItems();
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/IStateDetailProvider.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/IStateDetailProvider.java
new file mode 100644
index 000000000..4ad06beba
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/IStateDetailProvider.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gltrace.views.detail;
+
+import com.android.ide.eclipse.gltrace.state.IGLProperty;
+
+public interface IStateDetailProvider extends IDetailProvider {
+ /** Is this provider applicable for given GL state property? */
+ boolean isApplicable(IGLProperty state);
+
+ /** Update the detail view for given GL state property. */
+ void updateControl(IGLProperty state);
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderSourceDetailsProvider.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ShaderSourceDetailsProvider.java
index bad3042d3..a3ee5780c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderSourceDetailsProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ShaderSourceDetailsProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.gltrace.views;
+package com.android.ide.eclipse.gltrace.views.detail;
import com.android.ide.eclipse.gltrace.state.GLCompositeProperty;
import com.android.ide.eclipse.gltrace.state.GLStateType;
@@ -30,7 +30,7 @@ import org.eclipse.swt.widgets.Text;
import java.util.Collections;
import java.util.List;
-public class ShaderSourceDetailsProvider implements IStateDetailsProvider {
+public class ShaderSourceDetailsProvider implements IStateDetailProvider {
private Text mTextControl;
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderUniformDetailsProvider.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ShaderUniformDetailsProvider.java
index 4111b7747..f156c0009 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderUniformDetailsProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/ShaderUniformDetailsProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.gltrace.views;
+package com.android.ide.eclipse.gltrace.views.detail;
import com.android.ide.eclipse.gldebugger.GLEnum;
import com.android.ide.eclipse.gltrace.state.GLCompositeProperty;
@@ -31,7 +31,7 @@ import org.eclipse.swt.widgets.Text;
import java.util.Collections;
import java.util.List;
-public class ShaderUniformDetailsProvider implements IStateDetailsProvider {
+public class ShaderUniformDetailsProvider implements IStateDetailProvider {
private Text mTextControl;
private static final Joiner JOINER = Joiner.on(", ");
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/TextureImageDetailsProvider.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/TextureImageDetailsProvider.java
index 2b0034b0b..0c17d4c2c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/TextureImageDetailsProvider.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/detail/TextureImageDetailsProvider.java
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.gltrace.views;
+package com.android.ide.eclipse.gltrace.views.detail;
import com.android.ide.eclipse.gltrace.state.GLCompositeProperty;
import com.android.ide.eclipse.gltrace.state.GLStateType;
import com.android.ide.eclipse.gltrace.state.GLStringProperty;
import com.android.ide.eclipse.gltrace.state.IGLProperty;
+import com.android.ide.eclipse.gltrace.views.FitToCanvasAction;
import com.android.ide.eclipse.gltrace.widgets.ImageCanvas;
import org.eclipse.jface.action.ActionContributionItem;
@@ -32,7 +33,7 @@ import org.eclipse.swt.widgets.Display;
import java.util.Collections;
import java.util.List;
-public class TextureImageDetailsProvider implements IStateDetailsProvider {
+public class TextureImageDetailsProvider implements IStateDetailProvider {
private ImageCanvas mImageCanvas;
private FitToCanvasAction mFitToCanvasAction;
private List<IContributionItem> mToolBarItems;
diff --git a/files/ant/build.xml b/files/ant/build.xml
index 622d5584e..e47c3fe53 100644
--- a/files/ant/build.xml
+++ b/files/ant/build.xml
@@ -766,13 +766,24 @@
</firstmatchmapper>
</pathconvert>
+ <!-- Turn the path property ${proguard.config} from an A:B:C property
+ into a series of includes: -include A -include B -include C
+ suitable for processing by the ProGuard task. Note - this does
+ not include the leading '-include "' or the closing '"'; those
+ are added under the <proguard> call below.
+ -->
+ <path id="proguard.configpath">
+ <pathelement path="${proguard.config}"/>
+ </path>
+ <pathconvert pathsep='" -include "' property="proguard.configcmd" refid="proguard.configpath"/>
+
<mkdir dir="${obfuscate.absolute.dir}" />
<delete file="${preobfuscate.jar.file}"/>
<delete file="${obfuscated.jar.file}"/>
<jar basedir="${out.classes.absolute.dir}"
destfile="${preobfuscate.jar.file}" />
<proguard>
- @${proguard.config}
+ -include "${proguard.configcmd}"
-injars ${project.jars}
-outjars "${obfuscated.jar.file}"
-libraryjars ${android.libraryjars}
diff --git a/files/proguard-android.txt b/files/proguard-android.txt
new file mode 100644
index 000000000..b3d2fe156
--- /dev/null
+++ b/files/proguard-android.txt
@@ -0,0 +1,77 @@
+# This is a configuration file for ProGuard.
+# http://proguard.sourceforge.net/index.html#manual/usage.html
+
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-verbose
+
+# Optimization is turned off by default. Dex does not like code run
+# through the ProGuard optimize and preverify steps (and performs some
+# of these optimizations on its own).
+-dontoptimize
+-dontpreverify
+
+# If you want to enable optimization, you should include the
+# following:
+# -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
+# -optimizationpasses 5
+# -allowaccessmodification
+#
+# Note that you cannot just include these flags in your own
+# configuration file; if you are including this file, optimization
+# will be turned off. You'll need to either edit this file, or
+# duplicate the contents of this file and remove the include of this
+# file from your project's proguard.config path property.
+
+-keepattributes *Annotation*
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgent
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keep public class * extends android.view.View {
+ public <init>(android.content.Context);
+ public <init>(android.content.Context, android.util.AttributeSet);
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+ public void set*(...);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+
+# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
+
+-keepclassmembers class **.R$* {
+ public static <fields>;
+}
+
+# The support library contains references to newer platform versions.
+# Don't warn about those in case this app is linking against an older
+# platform version. We know about them, and they are safe.
+-dontwarn android.support.**
diff --git a/files/proguard-project.txt b/files/proguard-project.txt
new file mode 100644
index 000000000..f2fe1559a
--- /dev/null
+++ b/files/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/ide_common/src/com/android/ide/common/resources/ResourceRepository.java b/ide_common/src/com/android/ide/common/resources/ResourceRepository.java
index d78f1d102..87d729d2e 100644
--- a/ide_common/src/com/android/ide/common/resources/ResourceRepository.java
+++ b/ide_common/src/com/android/ide/common/resources/ResourceRepository.java
@@ -598,9 +598,9 @@ public abstract class ResourceRepository {
/**
- * Called after a resource change event, when the resource delta has been processed.
+ * Cleans up the repository of resource items that have no source file anymore.
*/
- protected void postUpdate() {
+ public void postUpdateCleanUp() {
// Since removed files/folders remove source files from existing ResourceItem, loop through
// all resource items and remove the ones that have no source files.
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
index 4ebc9ed70..3f32727ac 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
@@ -21,7 +21,8 @@ import static com.android.tools.lint.detector.api.LintConstants.ATTR_IGNORE;
import static com.android.tools.lint.detector.api.LintConstants.DOT_CLASS;
import static com.android.tools.lint.detector.api.LintConstants.DOT_JAR;
import static com.android.tools.lint.detector.api.LintConstants.DOT_JAVA;
-import static com.android.tools.lint.detector.api.LintConstants.PROGUARD_CFG;
+import static com.android.tools.lint.detector.api.LintConstants.OLD_PROGUARD_FILE;
+import static com.android.tools.lint.detector.api.LintConstants.PROGUARD_FILE;
import static com.android.tools.lint.detector.api.LintConstants.RES_FOLDER;
import static com.android.tools.lint.detector.api.LintConstants.SUPPRESS_ALL;
import static com.android.tools.lint.detector.api.LintConstants.SUPPRESS_LINT;
@@ -46,6 +47,8 @@ import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.XmlContext;
import com.google.common.annotations.Beta;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.io.ByteStreams;
@@ -215,7 +218,7 @@ public class LintDriver {
mScope.add(Scope.MANIFEST);
} else if (name.endsWith(".xml")) {
mScope.add(Scope.RESOURCE_FILE);
- } else if (name.equals(PROGUARD_CFG)) {
+ } else if (name.equals(PROGUARD_FILE) || name.equals(OLD_PROGUARD_FILE)) {
mScope.add(Scope.PROGUARD_FILE);
} else if (name.equals(RES_FOLDER)
|| file.getParent().equals(RES_FOLDER)) {
@@ -225,6 +228,8 @@ public class LintDriver {
mScope.add(Scope.JAVA_FILE);
} else if (name.endsWith(DOT_CLASS)) {
mScope.add(Scope.CLASS_FILE);
+ } else if (name.equals(OLD_PROGUARD_FILE) || name.equals(PROGUARD_FILE)) {
+ mScope.add(Scope.PROGUARD_FILE);
}
}
} else {
@@ -740,18 +745,50 @@ public class LintDriver {
}
if (project == main && mScope.contains(Scope.PROGUARD_FILE)) {
- List<Detector> detectors = mScopeDetectors.get(Scope.PROGUARD_FILE);
- if (detectors != null) {
- File file = new File(project.getDir(), PROGUARD_CFG);
+ checkProGuard(project, main);
+ }
+ }
+
+ private void checkProGuard(Project project, Project main) {
+ List<Detector> detectors = mScopeDetectors.get(Scope.PROGUARD_FILE);
+ if (detectors != null) {
+ Project p = main != null ? main : project;
+ List<File> files = new ArrayList<File>();
+ String paths = p.getProguardPath();
+ if (paths != null) {
+ Splitter splitter = Splitter.on(CharMatcher.anyOf(":;")); //$NON-NLS-1$
+ for (String path : splitter.split(paths)) {
+ if (path.contains("${")) { //$NON-NLS-1$
+ // Don't analyze the global/user proguard files
+ continue;
+ }
+ File file = new File(path);
+ if (!file.isAbsolute()) {
+ file = new File(project.getDir(), path);
+ }
+ if (file.exists()) {
+ files.add(file);
+ }
+ }
+ }
+ if (files.isEmpty()) {
+ File file = new File(project.getDir(), OLD_PROGUARD_FILE);
if (file.exists()) {
- Context context = new Context(this, project, main, file);
- fireEvent(EventType.SCANNING_FILE, context);
- for (Detector detector : detectors) {
- if (detector.appliesTo(context, file)) {
- detector.beforeCheckFile(context);
- detector.run(context);
- detector.afterCheckFile(context);
- }
+ files.add(file);
+ }
+ file = new File(project.getDir(), PROGUARD_FILE);
+ if (file.exists()) {
+ files.add(file);
+ }
+ }
+ for (File file : files) {
+ Context context = new Context(this, project, main, file);
+ fireEvent(EventType.SCANNING_FILE, context);
+ for (Detector detector : detectors) {
+ if (detector.appliesTo(context, file)) {
+ detector.beforeCheckFile(context);
+ detector.run(context);
+ detector.afterCheckFile(context);
}
}
}
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
index cb47f9282..678865274 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
@@ -242,7 +242,9 @@ public class LintConstants {
// Filenames and folder names
public static final String ANDROID_MANIFEST_XML = "AndroidManifest.xml"; //$NON-NLS-1$
- public static final String PROGUARD_CFG = "proguard.cfg"; //$NON-NLS-1$
+ public static final String OLD_PROGUARD_FILE = "proguard.cfg"; //$NON-NLS-1$
+ public static final String PROGUARD_FILE = "proguard-project.txt"; //$NON-NLS-1$
+
public static final String RES_FOLDER = "res"; //$NON-NLS-1$
public static final String DOT_XML = ".xml"; //$NON-NLS-1$
public static final String DOT_GIF = ".gif"; //$NON-NLS-1$
@@ -283,6 +285,7 @@ public class LintConstants {
// Project properties
public static final String ANDROID_LIBRARY = "android.library"; //$NON-NLS-1$
+ public static final String PROGUARD_CONFIG = "proguard.config"; //$NON-NLS-1$
public static final String ANDROID_LIBRARY_REFERENCE_FORMAT = "android.library.reference.%1$d";//$NON-NLS-1$
public static final String PROJECT_PROPERTIES = "project.properties";//$NON-NLS-1$
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
index 910ee2f9e..d0de34c3e 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
@@ -23,6 +23,7 @@ import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI;
import static com.android.tools.lint.detector.api.LintConstants.ATTR_MIN_SDK_VERSION;
import static com.android.tools.lint.detector.api.LintConstants.ATTR_PACKAGE;
import static com.android.tools.lint.detector.api.LintConstants.ATTR_TARGET_SDK_VERSION;
+import static com.android.tools.lint.detector.api.LintConstants.PROGUARD_CONFIG;
import static com.android.tools.lint.detector.api.LintConstants.PROJECT_PROPERTIES;
import static com.android.tools.lint.detector.api.LintConstants.TAG_USES_SDK;
import static com.android.tools.lint.detector.api.LintConstants.VALUE_TRUE;
@@ -71,6 +72,7 @@ public class Project {
private int mTargetSdk = -1;
private boolean mLibrary;
private String mName;
+ private String mProguardPath;
/** The SDK info, if any */
private SdkInfo mSdkInfo;
@@ -121,6 +123,7 @@ public class Project {
properties.load(is);
String value = properties.getProperty(ANDROID_LIBRARY);
mLibrary = VALUE_TRUE.equals(value);
+ mProguardPath = properties.getProperty(PROGUARD_CONFIG);
for (int i = 1; i < 1000; i++) {
String key = String.format(ANDROID_LIBRARY_REFERENCE_FORMAT, i);
@@ -545,6 +548,17 @@ public class Project {
}
/**
+ * Returns the proguard path configured for this project, or null if ProGuard is
+ * not configured.
+ *
+ * @return the proguard path, or null
+ */
+ @Nullable
+ public String getProguardPath() {
+ return mProguardPath;
+ }
+
+ /**
* Returns the name of the project
*
* @return the name of the project, never null
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
index 258a267a1..3af53ade1 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
@@ -53,7 +53,7 @@ public class BuiltinIssueRegistry extends IssueRegistry {
private static final List<Issue> sIssues;
static {
- final int initialCapacity = 81;
+ final int initialCapacity = 82;
List<Issue> issues = new ArrayList<Issue>(initialCapacity);
issues.add(AccessibilityDetector.ISSUE);
@@ -89,7 +89,8 @@ public class BuiltinIssueRegistry extends IssueRegistry {
issues.add(TranslationDetector.MISSING);
issues.add(HardcodedValuesDetector.ISSUE);
issues.add(Utf8Detector.ISSUE);
- issues.add(ProguardDetector.ISSUE);
+ issues.add(ProguardDetector.WRONGKEEP);
+ issues.add(ProguardDetector.SPLITCONFIG);
issues.add(PxUsageDetector.ISSUE);
issues.add(TextFieldDetector.ISSUE);
issues.add(TextViewDetector.ISSUE);
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ColorUsageDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ColorUsageDetector.java
index f380784a9..07a1f03a2 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ColorUsageDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ColorUsageDetector.java
@@ -49,7 +49,7 @@ public class ColorUsageDetector extends Detector implements Detector.JavaScanner
"an RGB triple, not the actual color resource id. You must call " +
"getResources().getColor(resource) to resolve the actual color value first.",
- Category.PERFORMANCE,
+ Category.CORRECTNESS,
7,
Severity.ERROR,
ColorUsageDetector.class,
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java
index 95de73948..c062507e1 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java
@@ -16,6 +16,9 @@
package com.android.tools.lint.checks;
+import static com.android.tools.lint.detector.api.LintConstants.PROGUARD_CONFIG;
+import static com.android.tools.lint.detector.api.LintConstants.PROJECT_PROPERTIES;
+
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Detector;
@@ -34,10 +37,10 @@ import java.util.EnumSet;
public class ProguardDetector extends Detector {
/** The main issue discovered by this detector */
- public static final Issue ISSUE = Issue.create(
+ public static final Issue WRONGKEEP = Issue.create(
"Proguard", //$NON-NLS-1$
- "Looks for problems in proguard.cfg files",
- "Using -keepclasseswithmembernames in a proguard.cfg file is not " +
+ "Looks for problems in proguard config files",
+ "Using -keepclasseswithmembernames in a proguard config file is not " +
"correct; it can cause some symbols to be renamed which should not be.\n" +
"Earlier versions of ADT used to create proguard.cfg files with the " +
"wrong format. Instead of -keepclasseswithmembernames use " +
@@ -51,25 +54,105 @@ public class ProguardDetector extends Detector {
EnumSet.of(Scope.PROGUARD_FILE)).setMoreInfo(
"http://http://code.google.com/p/android/issues/detail?id=16384"); //$NON-NLS-1$
+ /** Finds ProGuard files that contain non-project specific configuration
+ * locally and suggests replacing it with an include path */
+ public static final Issue SPLITCONFIG = Issue.create(
+ "ProguardSplit", //$NON-NLS-1$
+ "Checks for old proguard.cfg files that contain generic Android rules",
+
+ "Earlier versions of the Android tools bundled a single \"proguard.cfg\" file " +
+ "containing a ProGuard configuration file suitable for Android shrinking and " +
+ "obfuscation. However, that version was copied into new projects, which " +
+ "means that it does not continue to get updated as we improve the default " +
+ "ProGuard rules for Android.\n" +
+ "\n" +
+ "In the new version of the tools, we have split the ProGuard configuration " +
+ "into two halves:\n" +
+ "* A simple configuration file containing only project-specific flags, in " +
+ "your project\n" +
+ "* A generic configuration file containing the recommended set of ProGuard " +
+ "options for Android projects. This generic file lives in the SDK install " +
+ "directory which means that it gets updated along with the tools.\n" +
+ "\n" +
+ "In order for this to work, the proguard.config property in the " +
+ "project.properties file now refers to a path, so you can reference both " +
+ "the generic file as well as your own (and any additional files too).\n" +
+ "\n" +
+ "To migrate your project to the new setup, create a new proguard-project.txt file " +
+ "in your project containing any project specific ProGuard flags as well as " +
+ "any customizations you have made, then update your project.properties file " +
+ "to contain:\n" +
+ "proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt",
+
+ Category.CORRECTNESS,
+ 3,
+ Severity.WARNING,
+ ProguardDetector.class,
+ EnumSet.of(Scope.PROGUARD_FILE));
+
@Override
public void run(Context context) {
String contents = context.getContents();
if (contents != null) {
- int index = contents.indexOf(
- // Old pattern:
- "-keepclasseswithmembernames class * {\n" + //$NON-NLS-1$
- " public <init>(android."); //$NON-NLS-1$
- if (index != -1) {
- context.report(ISSUE,
- Location.create(context.file, contents, index, index),
- "Obsolete proguard file; use -keepclasseswithmembers instead of -keepclasseswithmembernames", null);
+ if (context.isEnabled(WRONGKEEP)) {
+ int index = contents.indexOf(
+ // Old pattern:
+ "-keepclasseswithmembernames class * {\n" + //$NON-NLS-1$
+ " public <init>(android."); //$NON-NLS-1$
+ if (index != -1) {
+ context.report(WRONGKEEP,
+ Location.create(context.file, contents, index, index),
+ "Obsolete ProGuard file; use -keepclasseswithmembers instead of " +
+ "-keepclasseswithmembernames", null);
+ }
+ }
+ if (context.isEnabled(SPLITCONFIG)) {
+ int index = contents.indexOf("-keep public class * extends android.app.Activity");
+ if (index != -1) {
+ // Only complain if project.properties actually references this file;
+ // no need to bother the users who got a default proguard.cfg file
+ // when they created their projects but haven't actually hooked it up
+ // to shrinking & obfuscation.
+ File propertyFile = new File(context.file.getParentFile(), PROJECT_PROPERTIES);
+ if (!propertyFile.exists()) {
+ return;
+ }
+ String properties = context.getClient().readFile(propertyFile);
+ int i = properties.indexOf(PROGUARD_CONFIG);
+ if (i == -1) {
+ return;
+ }
+ // Make sure the entry isn't just commented out, such as
+ // # To enable ProGuard to shrink and obfuscate your code, uncomment this:
+ // #proguard.config=proguard.cfg
+ for (; i >= 0; i--) {
+ char c = properties.charAt(i);
+ if (c == '#') {
+ return;
+ }
+ if (c == '\n') {
+ break;
+ }
+ }
+ if (properties.contains(PROGUARD_CONFIG)) {
+ context.report(SPLITCONFIG,
+ Location.create(context.file, contents, index, index),
+ String.format(
+ "Local ProGuard configuration contains general Android " +
+ "configuration: Inherit these settings instead? " +
+ "Modify project.properties to define " +
+ "proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:%1$s" +
+ " and then keep only project-specific configuration here",
+ context.file.getName()), null);
+ }
+ }
}
}
}
@Override
public boolean appliesTo(Context context, File file) {
- return file.getName().equals("proguard.cfg"); //$NON-NLS-1$
+ return true;
}
@Override
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java
index 019effdd6..f3d872b21 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java
@@ -27,8 +27,60 @@ public class ProguardDetectorTest extends AbstractCheckTest {
public void testProguard() throws Exception {
assertEquals(
- "proguard.cfg:21: Error: Obsolete proguard file; use -keepclasseswithmembers " +
+ "proguard.cfg:21: Error: Obsolete ProGuard file; use -keepclasseswithmembers " +
"instead of -keepclasseswithmembernames",
lintFiles("proguard.cfg"));
}
+
+ public void testProguardNewPath() throws Exception {
+ assertEquals(
+ "proguard-project.txt:21: Error: Obsolete ProGuard file; use " +
+ "-keepclasseswithmembers instead of -keepclasseswithmembernames",
+ lintFiles("proguard.cfg=>proguard-project.txt"));
+ }
+
+ public void testProguardRandomName() throws Exception {
+ assertEquals(
+ "myfile.txt:21: Error: Obsolete ProGuard file; use -keepclasseswithmembers " +
+ "instead of -keepclasseswithmembernames\n" +
+ "myfile.txt:8: Warning: Local ProGuard configuration contains general " +
+ "Android configuration: Inherit these settings instead? Modify " +
+ "project.properties to define proguard.config=${sdk.dir}/tools/proguard/" +
+ "proguard-android.txt:myfile.txt and then keep only project-specific " +
+ "configuration here",
+ lintProject(
+ "proguard.cfg=>myfile.txt",
+ "proguard.properties=>project.properties"));
+ }
+
+ public void testSilent() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles(
+ "proguard.pro=>proguard.cfg",
+ "project.properties1=>project.properties"));
+ }
+
+ public void testSilent2() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintFiles(
+ "proguard.pro=>proguard.cfg",
+ "project.properties3=>project.properties"));
+ }
+
+ public void testSplit() throws Exception {
+ assertEquals(
+ "proguard.cfg:14: Warning: Local ProGuard configuration contains general " +
+ "Android configuration: Inherit these settings instead? Modify " +
+ "project.properties to define " +
+ "proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard.cfg " +
+ "and then keep only project-specific configuration here",
+
+ lintFiles(
+ "proguard.pro=>proguard.cfg",
+ "project.properties2=>project.properties"));
+ }
}
diff --git a/files/proguard.cfg b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.pro
index 53f41fea9..53f41fea9 100644
--- a/files/proguard.cfg
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.pro
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.properties b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.properties
new file mode 100644
index 000000000..989c3c753
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.properties
@@ -0,0 +1,2 @@
+target=android-14
+proguard.config=${sdk.dir}/foo.cfg:${user.home}/bar.pro;myfile.txt
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties1 b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties1
new file mode 100644
index 000000000..2b783dd94
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties1
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+#proguard.config=proguard.cfg
+
+# Project target.
+target=android-3
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties2 b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties2
new file mode 100644
index 000000000..d9a28ecbd
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties2
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+proguard.config=proguard.cfg
+
+# Project target.
+target=android-3
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties3 b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties3
new file mode 100644
index 000000000..3cb9d31cf
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties3
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-3
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties4 b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties4
new file mode 100644
index 000000000..fca931138
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties4
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+proguard.config=${sdk.dir}/tools/proguard/android-defaults.pro:proguard.pro
+
+# Project target.
+target=android-3
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
index 4f3ed9fe4..e21e14f23 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
@@ -166,8 +166,10 @@ public final class SdkConstants {
*/
public final static String FN_GDBSERVER = "gdbserver"; //$NON-NLS-1$
- /** default proguard config file */
- public final static String FN_PROGUARD_CFG = "proguard.cfg"; //$NON-NLS-1$
+ /** global Android proguard config file */
+ public final static String FN_ANDROID_PROGUARD_FILE = "proguard-android.txt"; //$NON-NLS-1$
+ /** default proguard config file with new file extension (for project specific stuff) */
+ public final static String FN_PROJECT_PROGUARD_FILE = "proguard-project.txt"; //$NON-NLS-1$
/* Folder Names for Android Projects . */
@@ -385,7 +387,6 @@ public final class SdkConstants {
/** SDK property: default skin */
public final static String PROP_SDK_DEFAULT_SKIN = "sdk.skin.default"; //$NON-NLS-1$
-
/* Android Class Constants */
public final static String CLASS_ACTIVITY = "android.app.Activity"; //$NON-NLS-1$
public final static String CLASS_APPLICATION = "android.app.Application"; //$NON-NLS-1$
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
index 436f2e8a3..db3cc33c4 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
@@ -28,6 +28,7 @@ import com.android.sdklib.internal.avd.AvdInfo.AvdStatus;
import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdklib.util.GrabProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import com.android.util.Pair;
import java.io.File;
@@ -1398,7 +1399,7 @@ public class AvdManager {
int status = GrabProcessOutput.grabProcessOutput(
process,
- true /*waitForReaders*/,
+ Wait.WAIT_FOR_READERS,
new IProcessOutput() {
@Override
public void out(String line) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java
index 06f53513c..af5b401f0 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java
@@ -20,6 +20,7 @@ import com.android.sdklib.internal.build.DebugKeyProvider.IKeyGenOutput;
import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
import com.android.sdklib.util.GrabProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import java.io.File;
import java.io.IOException;
@@ -107,7 +108,7 @@ public final class KeystoreHelper {
Process process = Runtime.getRuntime().exec(commandArray);
result = GrabProcessOutput.grabProcessOutput(
process,
- true /*waitForReaders*/,
+ Wait.WAIT_FOR_READERS,
new IProcessOutput() {
@Override
public void out(String line) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
index c3d7993c0..721d165c9 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
@@ -369,8 +369,8 @@ public class ProjectCreator {
keywords);
// install the proguard config file.
- installTemplate(SdkConstants.FN_PROGUARD_CFG,
- new File(projectFolder, SdkConstants.FN_PROGUARD_CFG),
+ installTemplate(SdkConstants.FN_PROJECT_PROGUARD_FILE,
+ new File(projectFolder, SdkConstants.FN_PROJECT_PROGUARD_FILE),
null /*keywords*/);
} catch (Exception e) {
mLog.error(e, null);
@@ -751,8 +751,10 @@ public class ProjectCreator {
if (hasProguard == false) {
try {
- installTemplate(SdkConstants.FN_PROGUARD_CFG,
- new File(projectFolder, SdkConstants.FN_PROGUARD_CFG),
+ installTemplate(SdkConstants.FN_PROJECT_PROGUARD_FILE,
+ // Write ProGuard config files with the extension .pro which
+ // is what is used in the ProGuard documentation and samples
+ new File(projectFolder, SdkConstants.FN_PROJECT_PROGUARD_FILE),
null /*placeholderMap*/);
} catch (ProjectCreateException e) {
mLog.error(e, null);
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
index 3a73befd2..2bb6b7198 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
@@ -16,6 +16,11 @@
package com.android.sdklib.internal.project;
+import static com.android.sdklib.SdkConstants.FD_PROGUARD;
+import static com.android.sdklib.SdkConstants.FD_TOOLS;
+import static com.android.sdklib.SdkConstants.FN_ANDROID_PROGUARD_FILE;
+import static com.android.sdklib.SdkConstants.FN_PROJECT_PROGUARD_FILE;
+
import com.android.io.FolderWrapper;
import com.android.io.IAbstractFile;
import com.android.io.IAbstractFolder;
@@ -24,6 +29,7 @@ import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import java.io.BufferedReader;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -163,7 +169,7 @@ public class ProjectProperties {
"# This file is automatically generated by Android Tools.\n" +
"# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
"#\n" +
- "# This file must *NOT* be checked in Version Control Systems,\n" +
+ "# This file must *NOT* be checked into Version Control Systems,\n" +
"# as it contains information specific to your local configuration.\n" +
"\n";
@@ -174,16 +180,22 @@ public class ProjectProperties {
"#\n" +
"# This file must be checked in Version Control Systems.\n" +
"#\n" +
- "# To customize properties used by the Ant build system use,\n" +
+ "# To customize properties used by the Ant build system edit\n" +
"# \"ant.properties\", and override values to adapt the script to your\n" +
"# project structure.\n" +
+ "#\n" +
+ "# To enable ProGuard to shrink and obfuscate your code, uncomment this "
+ + "(available properties: sdk.dir, user.home):\n" +
+ "#" + PROPERTY_PROGUARD_CONFIG + "=${" + PROPERTY_SDK +"}" + File.separator
+ + FD_TOOLS + File.separator + FD_PROGUARD + File.separator
+ + FN_ANDROID_PROGUARD_FILE + ':' + FN_PROJECT_PROGUARD_FILE +'\n' +
"\n";
private final static String BUILD_HEADER =
// 1-------10--------20--------30--------40--------50--------60--------70--------80
"# This file is used to override default values used by the Ant build system.\n" +
"#\n" +
- "# This file must be checked in Version Control Systems, as it is\n" +
+ "# This file must be checked into Version Control Systems, as it is\n" +
"# integral to the build system of your project.\n" +
"\n" +
"# This file is only used by the Ant script.\n" +
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
index 9e50430b9..2e2396ff4 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
@@ -25,6 +25,7 @@ import com.android.sdklib.io.IFileOp;
import com.android.sdklib.repository.RepoConstants;
import com.android.sdklib.util.GrabProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
@@ -598,7 +599,7 @@ public class ArchiveInstaller {
Process process = Runtime.getRuntime().exec(command);
int retCode = GrabProcessOutput.grabProcessOutput(
process,
- true /*waitForReaders*/,
+ Wait.WAIT_FOR_READERS,
new IProcessOutput() {
@Override
public void out(String line) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
index ffd561f27..3ddacb471 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
@@ -25,6 +25,7 @@ import com.android.sdklib.internal.repository.Archive.Os;
import com.android.sdklib.repository.SdkRepoConstants;
import com.android.sdklib.util.GrabProcessOutput;
import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
import org.w3c.dom.Node;
@@ -276,7 +277,7 @@ public class ToolPackage extends Package implements IMinPlatformToolsDependency
final String tag = scriptName;
status = GrabProcessOutput.grabProcessOutput(
proc,
- false /*waitForReaders*/,
+ Wait.WAIT_FOR_PROCESS,
new IProcessOutput() {
@Override
public void out(String line) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-addon-4.xsd b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-addon-4.xsd
index 9289e1c88..ef92bde2a 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-addon-4.xsd
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-addon-4.xsd
@@ -124,7 +124,12 @@
<!-- An optional element indicating the package is obsolete.
The string content is however currently not defined and ignored. -->
- <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
<!-- Optional information on the layoutlib packaged in this platform. -->
<xsd:element name="layoutlib" type="sdk:layoutlibType" minOccurs="0" />
@@ -218,9 +223,15 @@
<!-- The minimal API level required by this package.
Optional. If present, must be an int > 0. -->
<xsd:element name="min-api-level" type="xsd:positiveInteger" minOccurs="0" />
+
<!-- An optional element indicating the package is obsolete.
The string content is however currently not defined and ignored. -->
- <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
<!-- A list of project files contributed by this package. Optional. -->
<xsd:element name="project-files" type="sdk:projectFilesType" minOccurs="0" />
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-repository-6.xsd b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-repository-6.xsd
index 149f8c591..d4cc1cb11 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-repository-6.xsd
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-repository-6.xsd
@@ -134,6 +134,11 @@
<!-- An optional element indicating the package is obsolete.
The string content is however currently not defined and ignored. -->
<xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
</xsd:all>
</xsd:complexType>
@@ -194,6 +199,15 @@
<!-- A list of file archives for this package. -->
<xsd:element name="archives" type="sdk:archivesType" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
</xsd:all>
</xsd:complexType>
@@ -245,6 +259,15 @@
<!-- A list of file archives for this package. -->
<xsd:element name="archives" type="sdk:archivesType" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
</xsd:all>
</xsd:complexType>
@@ -272,13 +295,19 @@
<xsd:element name="release-url" type="xsd:token" minOccurs="0" />
<!-- A list of file archives for this package. -->
<xsd:element name="archives" type="sdk:archivesType" />
- <!-- An optional element indicating the package is obsolete.
- The string content is however currently not defined and ignored. -->
- <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
<!-- The minimal revision of platform-tools required by this package.
Mandatory. Must be an int > 0. -->
<xsd:element name="min-platform-tools-rev" type="xsd:positiveInteger" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
</xsd:all>
</xsd:complexType>
@@ -310,6 +339,11 @@
<!-- An optional element indicating the package is obsolete.
The string content is however currently not defined and ignored. -->
<xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
</xsd:all>
</xsd:complexType>
@@ -343,9 +377,15 @@
<!-- A list of file archives for this package. -->
<xsd:element name="archives" type="sdk:archivesType" />
+
<!-- An optional element indicating the package is obsolete.
The string content is however currently not defined and ignored. -->
<xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
</xsd:all>
</xsd:complexType>
@@ -382,9 +422,15 @@
Optional. If present, must be an int > 0. -->
<xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
+
<!-- An optional element indicating the package is obsolete.
The string content is however currently not defined and ignored. -->
<xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- An optional element indicating the package is a beta/preview.
+ When present, it indicates the release-candidate number.
+ When the element is absent, it indicates this is a released package. -->
+ <xsd:element name="beta-rc" type="xsd:positiveInteger" minOccurs="0" />
</xsd:all>
</xsd:complexType>
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java
index b4701537c..2935493f8 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java
@@ -25,6 +25,35 @@ import java.io.InputStreamReader;
public class GrabProcessOutput {
+ public enum Wait {
+ /**
+ * Doesn't wait for the exec to complete.
+ * This still monitors the output but does not wait for the process to finish.
+ * In this mode the process return code is unknown and always 0.
+ */
+ ASYNC,
+ /**
+ * This waits for the process to finish.
+ * In this mode, {@link GrabProcessOutput#grabProcessOutput} returns the
+ * error code from the process.
+ * In some rare cases and depending on the OS, the process might not have
+ * finished dumping data into stdout/stderr.
+ * <p/>
+ * Use this when you don't particularly care for the output but instead
+ * care for the return code of the executed process.
+ */
+ WAIT_FOR_PROCESS,
+ /**
+ * This waits for the process to finish <em>and</em> for the stdout/stderr
+ * threads to complete.
+ * In this mode, {@link GrabProcessOutput#grabProcessOutput} returns the
+ * error code from the process.
+ * <p/>
+ * Use this one when capturing all the output from the process is important.
+ */
+ WAIT_FOR_READERS,
+ }
+
public interface IProcessOutput {
/**
* Processes an stdout message line.
@@ -46,13 +75,13 @@ public class GrabProcessOutput {
* @param output Optional object to capture stdout/stderr.
* Note that on Windows capturing the output is not optional. If output is null
* the stdout/stderr will be captured and discarded.
- * @param waitForReaders True to wait for the reader threads to finish.
+ * @param waitMode Whether to wait for the process and/or the readers to finish.
* @return the process return code.
* @throws InterruptedException if {@link Process#waitFor()} was interrupted.
*/
public static int grabProcessOutput(
@NonNull final Process process,
- boolean waitForReaders,
+ Wait waitMode,
@Nullable final IProcessOutput output) throws InterruptedException {
// read the lines as they come. if null is returned, it's
// because the process finished
@@ -104,10 +133,14 @@ public class GrabProcessOutput {
threadErr.start();
threadOut.start();
+ if (waitMode == Wait.ASYNC) {
+ return 0;
+ }
+
// it looks like on windows process#waitFor() can return
// before the thread have filled the arrays, so we wait for both threads and the
// process itself.
- if (waitForReaders) {
+ if (waitMode == Wait.WAIT_FOR_READERS) {
try {
threadErr.join();
} catch (InterruptedException e) {