/** * Check if any error occurred during initialization. If it did, display an error message. * * @return True if an error occurred, false if we should continue. */ public boolean checkIfInitFailed() { if (mAvdManagerInitError != null) { String example; if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_WINDOWS) { example = "%USERPROFILE%"; // $NON-NLS-1$ } else { example = "~"; // $NON-NLS-1$ } String error = String.format( "The AVD manager normally uses the user's profile directory to store " + "AVD files. However it failed to find the default profile directory. " + "\n" + "To fix this, please set the environment variable ANDROID_SDK_HOME to " + "a valid path such as \"%s\".", example); // We may not have any UI. Only display a dialog if there's a window shell available. if (mWindowShell != null && !mWindowShell.isDisposed()) { MessageDialog.openError(mWindowShell, "Android Virtual Devices Manager", error); } else { mSdkLog.error(null /* Throwable */, "%s", error); // $NON-NLS-1$ } return true; } return false; }
/** * Reloads the AVDs. * * <p>This does not notify the listeners. */ public void reloadAvds() { // reload AVDs if (mAvdManager != null) { try { mAvdManager.reloadAvds(mSdkLog); } catch (AndroidLocationException e) { mSdkLog.error(e, null); } } }
/** * Initializes the {@link SdkManager} and the {@link AvdManager}. Extracted so that we can * override this in unit tests. */ @VisibleForTesting(visibility = Visibility.PRIVATE) protected void initSdk() { setSdkManager(SdkManager.createManager(mOsSdkRoot, mSdkLog)); try { mAvdManager = null; mAvdManager = AvdManager.getInstance(mSdkManager, mSdkLog); } catch (AndroidLocationException e) { mSdkLog.error(e, "Unable to read AVDs: " + e.getMessage()); // $NON-NLS-1$ // Note: we used to continue here, but the thing is that // mAvdManager==null so nothing is really going to work as // expected. Let's just display an error later in checkIfInitFailed() // and abort right there. This step is just too early in the SWT // setup process to display a message box yet. mAvdManagerInitError = e; } // notify listeners. broadcastOnSdkReload(); }
/** * Tries to update all the *existing* local packages. This version is intended to run without a * GUI and only outputs to the current {@link ILogger}. * * @param pkgFilter A list of {@link SdkRepoConstants#NODES} or {@link Package#installId()} or * package indexes to limit the packages we can update or install. A null or empty list means * to update everything possible. * @param includeAll True to list and install all packages, including obsolete ones. * @param dryMode True to check what would be updated/installed but do not actually download or * install anything. * @return A list of archives that have been installed. Can be null if nothing was done. */ public List<Archive> updateOrInstallAll_NoGUI( Collection<String> pkgFilter, boolean includeAll, boolean dryMode) { List<ArchiveInfo> archives = getRemoteArchives_NoGUI(includeAll); // Filter the selected archives to only keep the ones matching the filter if (pkgFilter != null && pkgFilter.size() > 0 && archives != null && archives.size() > 0) { // Map filter types to an SdkRepository Package type, // e.g. create a map "platform" => PlatformPackage.class HashMap<String, Class<? extends Package>> pkgMap = new HashMap<String, Class<? extends Package>>(); mapFilterToPackageClass(pkgMap, SdkRepoConstants.NODES); mapFilterToPackageClass(pkgMap, SdkAddonConstants.NODES); // Prepare a map install-id => package instance HashMap<String, Package> installIdMap = new HashMap<String, Package>(); for (ArchiveInfo ai : archives) { Archive a = ai.getNewArchive(); if (a != null) { Package p = a.getParentPackage(); if (p != null) { String id = p.installId(); if (id != null && id.length() > 0 && !installIdMap.containsKey(id)) { installIdMap.put(id, p); } } } } // Now intersect this with the pkgFilter requested by the user, in order to // only keep the classes that the user wants to install. // We also create a set with the package indices requested by the user // and a set of install-ids requested by the user. HashSet<Class<? extends Package>> userFilteredClasses = new HashSet<Class<? extends Package>>(); SparseIntArray userFilteredIndices = new SparseIntArray(); Set<String> userFilteredInstallIds = new HashSet<String>(); for (String type : pkgFilter) { if (installIdMap.containsKey(type)) { userFilteredInstallIds.add(type); } else if (type.replaceAll("[0-9]+", "").length() == 0) { // $NON-NLS-1$ //$NON-NLS-2$ // An all-digit number is a package index requested by the user. int index = Integer.parseInt(type); userFilteredIndices.put(index, index); } else if (pkgMap.containsKey(type)) { userFilteredClasses.add(pkgMap.get(type)); } else { // This should not happen unless there's a mismatch in the package map. mSdkLog.error(null, "Ignoring unknown package filter '%1$s'", type); } } // we don't need the maps anymore pkgMap = null; installIdMap = null; // Now filter the remote archives list to keep: // - any package which class matches userFilteredClasses // - any package index which matches userFilteredIndices // - any package install id which matches userFilteredInstallIds int index = 1; for (Iterator<ArchiveInfo> it = archives.iterator(); it.hasNext(); ) { boolean keep = false; ArchiveInfo ai = it.next(); Archive a = ai.getNewArchive(); if (a != null) { Package p = a.getParentPackage(); if (p != null) { if (userFilteredInstallIds.contains(p.installId()) || userFilteredClasses.contains(p.getClass()) || userFilteredIndices.get(index) > 0) { keep = true; } index++; } } if (!keep) { it.remove(); } } if (archives.size() == 0) { mSdkLog.info( LineUtil.reflowLine( "Warning: The package filter removed all packages. There is nothing to install.\nPlease consider trying to update again without a package filter.\n")); return null; } } if (archives != null && archives.size() > 0) { if (dryMode) { mSdkLog.info("Packages selected for install:\n"); for (ArchiveInfo ai : archives) { Archive a = ai.getNewArchive(); if (a != null) { Package p = a.getParentPackage(); if (p != null) { mSdkLog.info("- %1$s\n", p.getShortDescription()); } } } mSdkLog.info("\nDry mode is on so nothing is actually being installed.\n"); } else { return installArchives(archives, NO_TOOLS_MSG); } } else { mSdkLog.info("There is nothing to install or update.\n"); } return null; }
/** * Reads the public.xml file in data/res/values/ for a given resource folder and builds up a map * of public resources. * * <p>This map is a subset of the full resource map that only contains framework resources that * are public. * * @param logger a logger to report issues to */ public void loadPublicResources(@Nullable ILogger logger) { IAbstractFolder valueFolder = getResFolder().getFolder(SdkConstants.FD_RES_VALUES); if (valueFolder.exists() == false) { return; } IAbstractFile publicXmlFile = valueFolder.getFile("public.xml"); // $NON-NLS-1$ if (publicXmlFile.exists()) { Reader reader = null; try { reader = new BufferedReader(new InputStreamReader(publicXmlFile.getContents(), Charsets.UTF_8)); KXmlParser parser = new KXmlParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setInput(reader); ResourceType lastType = null; String lastTypeName = ""; while (true) { int event = parser.next(); if (event == XmlPullParser.START_TAG) { // As of API 15 there are a number of "java-symbol" entries here if (!parser.getName().equals("public")) { // $NON-NLS-1$ continue; } String name = null; String typeName = null; for (int i = 0, n = parser.getAttributeCount(); i < n; i++) { String attribute = parser.getAttributeName(i); if (attribute.equals("name")) { // $NON-NLS-1$ name = parser.getAttributeValue(i); if (typeName != null) { // Skip id attribute processing break; } } else if (attribute.equals("type")) { // $NON-NLS-1$ typeName = parser.getAttributeValue(i); } } if (name != null && typeName != null) { ResourceType type = null; if (typeName.equals(lastTypeName)) { type = lastType; } else { type = ResourceType.getEnum(typeName); lastType = type; lastTypeName = typeName; } if (type != null) { ResourceItem match = null; Map<String, ResourceItem> map = mResourceMap.get(type); if (map != null) { match = map.get(name); } if (match != null) { List<ResourceItem> publicList = mPublicResourceMap.get(type); if (publicList == null) { // Pick initial size for the list to hold the public // resources. We could just use map.size() here, // but they're usually much bigger; for example, // in one platform version, there are 1500 drawables // and 1200 strings but only 175 and 25 public ones // respectively. int size; switch (type) { case STYLE: size = 500; break; case ATTR: size = 1000; break; case DRAWABLE: size = 200; break; case ID: size = 50; break; case LAYOUT: case COLOR: case STRING: case ANIM: case INTERPOLATOR: size = 30; break; default: size = 10; break; } publicList = new ArrayList<ResourceItem>(size); mPublicResourceMap.put(type, publicList); } publicList.add(match); } else { // log that there's a public resource that doesn't actually // exist? } } else { // log that there was a reference to a typo that doesn't actually // exist? } } } else if (event == XmlPullParser.END_DOCUMENT) { break; } } } catch (Exception e) { if (logger != null) { logger.error(e, "Can't read and parse public attribute list"); } } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { // Nothing to be done here - we don't care if it closed or not. } } } } // put unmodifiable list for all res type in the public resource map // this will simplify access for (ResourceType type : ResourceType.values()) { List<ResourceItem> list = mPublicResourceMap.get(type); if (list == null) { list = Collections.emptyList(); } else { list = Collections.unmodifiableList(list); } // put the new list in the map mPublicResourceMap.put(type, list); } }
@Override public void error(@Nullable Throwable t, @Nullable String msgFormat, Object... args) { mLogger.error(t, mGradleMessageRewriter.rewriteMessages(Strings.nullToEmpty(msgFormat)), args); }
protected void displayInitError(String error) { mSdkLog.error(null /* Throwable */, "%s", error); // $NON-NLS-1$ }