upload android base code part9
This commit is contained in:
parent
5425409085
commit
071cdf34cd
2679 changed files with 329442 additions and 0 deletions
6
android/sdk/attribute_stats/.classpath
Normal file
6
android/sdk/attribute_stats/.classpath
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
17
android/sdk/attribute_stats/.project
Normal file
17
android/sdk/attribute_stats/.project
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>attribute_stats</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,98 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled
|
||||
org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable
|
||||
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deadCode=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
|
||||
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
|
||||
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
|
||||
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
|
||||
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
|
||||
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
|
||||
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
|
||||
org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error
|
||||
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
|
||||
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
|
||||
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
|
||||
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error
|
||||
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
13
android/sdk/attribute_stats/README.txt
Normal file
13
android/sdk/attribute_stats/README.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
Attribute Statistics
|
||||
---------------------
|
||||
|
||||
This program gathers statistics about attribute usage in layout
|
||||
files. This is how the "topAttrs" attributes listed in ADT's
|
||||
extra-view-metadata.xml file (which drives the common attributes
|
||||
listed in the top of the context menu) is determined by running this
|
||||
script on a body of sample Android code, such as the AOSP repository.
|
||||
|
||||
This program takes one or more directory paths, and then it searches
|
||||
all of them recursively for layout files that are not in folders
|
||||
containing the string "test", and computes and prints frequency
|
||||
statistics.
|
663
android/sdk/attribute_stats/src/Analyzer.java
Normal file
663
android/sdk/attribute_stats/src/Analyzer.java
Normal file
|
@ -0,0 +1,663 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
/**
|
||||
* Gathers statistics about attribute usage in layout files. This is how the "topAttrs"
|
||||
* attributes listed in ADT's extra-view-metadata.xml (which drives the common attributes
|
||||
* listed in the top of the context menu) is determined by running this script on a body
|
||||
* of sample layout code.
|
||||
* <p>
|
||||
* This program takes one or more directory paths, and then it searches all of them recursively
|
||||
* for layout files that are not in folders containing the string "test", and computes and
|
||||
* prints frequency statistics.
|
||||
*/
|
||||
public class Analyzer {
|
||||
/** Number of attributes to print for each view */
|
||||
public static final int ATTRIBUTE_COUNT = 6;
|
||||
/** Separate out any attributes that constitute less than N percent of the total */
|
||||
public static final int THRESHOLD = 10; // percent
|
||||
|
||||
private List<File> mDirectories;
|
||||
private File mCurrentFile;
|
||||
private boolean mListAdvanced;
|
||||
|
||||
/** Map from view id to map from attribute to frequency count */
|
||||
private Map<String, Map<String, Usage>> mFrequencies =
|
||||
new HashMap<String, Map<String, Usage>>(100);
|
||||
|
||||
private Map<String, Map<String, Usage>> mLayoutAttributeFrequencies =
|
||||
new HashMap<String, Map<String, Usage>>(100);
|
||||
|
||||
private Map<String, String> mTopAttributes = new HashMap<String, String>(100);
|
||||
private Map<String, String> mTopLayoutAttributes = new HashMap<String, String>(100);
|
||||
|
||||
private int mFileVisitCount;
|
||||
private int mLayoutFileCount;
|
||||
private File mXmlMetadataFile;
|
||||
|
||||
private Analyzer(List<File> directories, File xmlMetadataFile, boolean listAdvanced) {
|
||||
mDirectories = directories;
|
||||
mXmlMetadataFile = xmlMetadataFile;
|
||||
mListAdvanced = listAdvanced;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length < 1) {
|
||||
System.err.println("Usage: " + Analyzer.class.getSimpleName()
|
||||
+ " <directory1> [directory2 [directory3 ...]]\n");
|
||||
System.err.println("Recursively scans for layouts in the given directory and");
|
||||
System.err.println("computes statistics about attribute frequencies.");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
File metadataFile = null;
|
||||
List<File> directories = new ArrayList<File>();
|
||||
boolean listAdvanced = false;
|
||||
for (int i = 0, n = args.length; i < n; i++) {
|
||||
String arg = args[i];
|
||||
|
||||
if (arg.equals("--list")) {
|
||||
// List ALL encountered attributes
|
||||
listAdvanced = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The -metadata flag takes a pointer to an ADT extra-view-metadata.xml file
|
||||
// and attempts to insert topAttrs attributes into it (and saves it as same
|
||||
// file +.mod as an extension). This isn't listed on the usage flag because
|
||||
// it's pretty brittle and requires some manual fixups to the file afterwards.
|
||||
if (arg.equals("--metadata")) {
|
||||
i++;
|
||||
File file = new File(args[i]);
|
||||
if (!file.exists()) {
|
||||
System.err.println(file.getName() + " does not exist");
|
||||
System.exit(-5);
|
||||
}
|
||||
if (!file.isFile() || !file.getName().endsWith(".xml")) {
|
||||
System.err.println(file.getName() + " must be an XML file");
|
||||
System.exit(-4);
|
||||
}
|
||||
metadataFile = file;
|
||||
continue;
|
||||
}
|
||||
File directory = new File(arg);
|
||||
if (!directory.exists()) {
|
||||
System.err.println(directory.getName() + " does not exist");
|
||||
System.exit(-2);
|
||||
}
|
||||
|
||||
if (!directory.isDirectory()) {
|
||||
System.err.println(directory.getName() + " is not a directory");
|
||||
System.exit(-3);
|
||||
}
|
||||
|
||||
directories.add(directory);
|
||||
}
|
||||
|
||||
new Analyzer(directories, metadataFile, listAdvanced).analyze();
|
||||
}
|
||||
|
||||
private void analyze() {
|
||||
for (File directory : mDirectories) {
|
||||
scanDirectory(directory);
|
||||
}
|
||||
|
||||
if (mListAdvanced) {
|
||||
listAdvanced();
|
||||
}
|
||||
|
||||
printStatistics();
|
||||
|
||||
if (mXmlMetadataFile != null) {
|
||||
printMergedMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
private void scanDirectory(File directory) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (File file : files) {
|
||||
mFileVisitCount++;
|
||||
if (mFileVisitCount % 50000 == 0) {
|
||||
System.out.println("Analyzed " + mFileVisitCount + " files...");
|
||||
}
|
||||
|
||||
if (file.isFile()) {
|
||||
scanFile(file);
|
||||
} else if (file.isDirectory()) {
|
||||
// Skip stuff related to tests
|
||||
if (file.getName().contains("test")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Recurse over subdirectories
|
||||
scanDirectory(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scanFile(File file) {
|
||||
if (file.getName().endsWith(".xml")) {
|
||||
File parent = file.getParentFile();
|
||||
if (parent.getName().startsWith("layout")) {
|
||||
analyzeLayout(file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void analyzeLayout(File file) {
|
||||
mCurrentFile = file;
|
||||
mLayoutFileCount++;
|
||||
Document document = null;
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
InputSource is = new InputSource(new StringReader(readFile(file)));
|
||||
try {
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setValidating(false);
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
document = builder.parse(is);
|
||||
|
||||
analyzeDocument(document);
|
||||
|
||||
} catch (ParserConfigurationException e) {
|
||||
// pass -- ignore files we can't parse
|
||||
} catch (SAXException e) {
|
||||
// pass -- ignore files we can't parse
|
||||
} catch (IOException e) {
|
||||
// pass -- ignore files we can't parse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void analyzeDocument(Document document) {
|
||||
analyzeElement(document.getDocumentElement());
|
||||
}
|
||||
|
||||
private void analyzeElement(Element element) {
|
||||
if (element.getTagName().equals("item")) {
|
||||
// Resource files shouldn't be in the layout/ folder but I came across
|
||||
// some cases
|
||||
System.out.println("Warning: found <item> tag in a layout file in "
|
||||
+ mCurrentFile.getPath());
|
||||
return;
|
||||
}
|
||||
|
||||
countAttributes(element);
|
||||
countLayoutAttributes(element);
|
||||
|
||||
// Recurse over children
|
||||
NodeList childNodes = element.getChildNodes();
|
||||
for (int i = 0, n = childNodes.getLength(); i < n; i++) {
|
||||
Node child = childNodes.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
analyzeElement((Element) child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void countAttributes(Element element) {
|
||||
String tag = element.getTagName();
|
||||
Map<String, Usage> attributeMap = mFrequencies.get(tag);
|
||||
if (attributeMap == null) {
|
||||
attributeMap = new HashMap<String, Usage>(70);
|
||||
mFrequencies.put(tag, attributeMap);
|
||||
}
|
||||
|
||||
NamedNodeMap attributes = element.getAttributes();
|
||||
for (int i = 0, n = attributes.getLength(); i < n; i++) {
|
||||
Node attribute = attributes.item(i);
|
||||
String name = attribute.getNodeName();
|
||||
|
||||
if (name.startsWith("android:layout_")) {
|
||||
// Skip layout attributes; they are a function of the parent layout that this
|
||||
// view is embedded within, not the view itself.
|
||||
// TODO: Consider whether we should incorporate this info or make statistics
|
||||
// about that as well?
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name.equals("android:id")) {
|
||||
// Skip ids: they are (mostly) unrelated to the view type and the tool
|
||||
// already offers id editing prominently
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name.startsWith("xmlns:")) {
|
||||
// Unrelated to frequency counts
|
||||
continue;
|
||||
}
|
||||
|
||||
Usage usage = attributeMap.get(name);
|
||||
if (usage == null) {
|
||||
usage = new Usage(name);
|
||||
} else {
|
||||
usage.incrementCount();
|
||||
}
|
||||
attributeMap.put(name, usage);
|
||||
}
|
||||
}
|
||||
|
||||
private void countLayoutAttributes(Element element) {
|
||||
String parentTag = element.getParentNode().getNodeName();
|
||||
Map<String, Usage> attributeMap = mLayoutAttributeFrequencies.get(parentTag);
|
||||
if (attributeMap == null) {
|
||||
attributeMap = new HashMap<String, Usage>(70);
|
||||
mLayoutAttributeFrequencies.put(parentTag, attributeMap);
|
||||
}
|
||||
|
||||
NamedNodeMap attributes = element.getAttributes();
|
||||
for (int i = 0, n = attributes.getLength(); i < n; i++) {
|
||||
Node attribute = attributes.item(i);
|
||||
String name = attribute.getNodeName();
|
||||
|
||||
if (!name.startsWith("android:layout_")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip layout_width and layout_height; they are mandatory in all but GridLayout so not
|
||||
// very interesting
|
||||
if (name.equals("android:layout_width") || name.equals("android:layout_height")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Usage usage = attributeMap.get(name);
|
||||
if (usage == null) {
|
||||
usage = new Usage(name);
|
||||
} else {
|
||||
usage.incrementCount();
|
||||
}
|
||||
attributeMap.put(name, usage);
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from AdtUtils
|
||||
private static String readFile(File file) {
|
||||
try {
|
||||
return readFile(new FileReader(file));
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String readFile(Reader inputStream) {
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(inputStream);
|
||||
StringBuilder sb = new StringBuilder(2000);
|
||||
while (true) {
|
||||
int c = reader.read();
|
||||
if (c == -1) {
|
||||
return sb.toString();
|
||||
} else {
|
||||
sb.append((char)c);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// pass -- ignore files we can't read
|
||||
} finally {
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void printStatistics() {
|
||||
System.out.println("Analyzed " + mLayoutFileCount
|
||||
+ " layouts (in a directory trees containing " + mFileVisitCount + " files)");
|
||||
System.out.println("Top " + ATTRIBUTE_COUNT
|
||||
+ " for each view (excluding layout_ attributes) :");
|
||||
System.out.println("\n");
|
||||
System.out.println(" Rank Count Share Attribute");
|
||||
System.out.println("=========================================================");
|
||||
List<String> views = new ArrayList<String>(mFrequencies.keySet());
|
||||
Collections.sort(views);
|
||||
for (String view : views) {
|
||||
String top = processUageMap(view, mFrequencies.get(view));
|
||||
if (top != null) {
|
||||
mTopAttributes.put(view, top);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\n\n\nTop " + ATTRIBUTE_COUNT + " layout attributes (excluding "
|
||||
+ "mandatory layout_width and layout_height):");
|
||||
System.out.println("\n");
|
||||
System.out.println(" Rank Count Share Attribute");
|
||||
System.out.println("=========================================================");
|
||||
views = new ArrayList<String>(mLayoutAttributeFrequencies.keySet());
|
||||
Collections.sort(views);
|
||||
for (String view : views) {
|
||||
String top = processUageMap(view, mLayoutAttributeFrequencies.get(view));
|
||||
if (top != null) {
|
||||
mTopLayoutAttributes.put(view, top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String processUageMap(String view, Map<String, Usage> map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (view.indexOf('.') != -1 && !view.startsWith("android.")) {
|
||||
// Skip custom views
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Usage> values = new ArrayList<Usage>(map.values());
|
||||
if (values.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Collections.sort(values);
|
||||
int totalCount = 0;
|
||||
for (Usage usage : values) {
|
||||
totalCount += usage.count;
|
||||
}
|
||||
|
||||
System.out.println("\n<" + view + ">:");
|
||||
if (view.equals("#document")) {
|
||||
System.out.println("(Set on root tag, probably intended for included context)");
|
||||
}
|
||||
|
||||
int place = 1;
|
||||
int count = 0;
|
||||
int prevCount = -1;
|
||||
float prevPercentage = 0f;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Usage usage : values) {
|
||||
if (count++ >= ATTRIBUTE_COUNT && usage.count < prevCount) {
|
||||
break;
|
||||
}
|
||||
|
||||
float percentage = 100 * usage.count/(float)totalCount;
|
||||
if (percentage < THRESHOLD && prevPercentage >= THRESHOLD) {
|
||||
System.out.println(" -----Less than 10%-------------------------------------");
|
||||
}
|
||||
System.out.printf(" %1d. %5d %5.1f%% %s\n", place, usage.count,
|
||||
percentage, usage.attribute);
|
||||
|
||||
prevPercentage = percentage;
|
||||
if (prevCount != usage.count) {
|
||||
prevCount = usage.count;
|
||||
place++;
|
||||
}
|
||||
|
||||
if (percentage >= THRESHOLD /*&& usage.count > 1*/) { // 1:Ignore when not enough data?
|
||||
if (sb.length() > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
String name = usage.attribute;
|
||||
if (name.startsWith("android:")) {
|
||||
name = name.substring("android:".length());
|
||||
}
|
||||
sb.append(name);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.length() > 0 ? sb.toString() : null;
|
||||
}
|
||||
|
||||
private void printMergedMetadata() {
|
||||
assert mXmlMetadataFile != null;
|
||||
String metadata = readFile(mXmlMetadataFile);
|
||||
if (metadata == null || metadata.length() == 0) {
|
||||
System.err.println("Invalid metadata file");
|
||||
System.exit(-6);
|
||||
}
|
||||
|
||||
System.err.flush();
|
||||
System.out.println("\n\nUpdating layout metadata file...");
|
||||
System.out.flush();
|
||||
|
||||
StringBuilder sb = new StringBuilder((int) (2 * mXmlMetadataFile.length()));
|
||||
String[] lines = metadata.split("\n");
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
sb.append(line).append('\n');
|
||||
int classIndex = line.indexOf("class=\"");
|
||||
if (classIndex != -1) {
|
||||
int start = classIndex + "class=\"".length();
|
||||
int end = line.indexOf('"', start + 1);
|
||||
if (end != -1) {
|
||||
String view = line.substring(start, end);
|
||||
if (view.startsWith("android.widget.")) {
|
||||
view = view.substring("android.widget.".length());
|
||||
} else if (view.startsWith("android.view.")) {
|
||||
view = view.substring("android.view.".length());
|
||||
} else if (view.startsWith("android.webkit.")) {
|
||||
view = view.substring("android.webkit.".length());
|
||||
}
|
||||
String top = mTopAttributes.get(view);
|
||||
if (top == null) {
|
||||
System.err.println("Warning: No frequency data for view " + view);
|
||||
} else {
|
||||
sb.append(line.substring(0, classIndex)); // Indentation
|
||||
|
||||
sb.append("topAttrs=\"");
|
||||
sb.append(top);
|
||||
sb.append("\"\n");
|
||||
}
|
||||
|
||||
top = mTopLayoutAttributes.get(view);
|
||||
if (top != null) {
|
||||
// It's a layout attribute
|
||||
sb.append(line.substring(0, classIndex)); // Indentation
|
||||
|
||||
sb.append("topLayoutAttrs=\"");
|
||||
sb.append(top);
|
||||
sb.append("\"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\nTop attributes:");
|
||||
System.out.println("--------------------------");
|
||||
List<String> views = new ArrayList<String>(mTopAttributes.keySet());
|
||||
Collections.sort(views);
|
||||
for (String view : views) {
|
||||
String top = mTopAttributes.get(view);
|
||||
System.out.println(view + ": " + top);
|
||||
}
|
||||
|
||||
System.out.println("\nTop layout attributes:");
|
||||
System.out.println("--------------------------");
|
||||
views = new ArrayList<String>(mTopLayoutAttributes.keySet());
|
||||
Collections.sort(views);
|
||||
for (String view : views) {
|
||||
String top = mTopLayoutAttributes.get(view);
|
||||
System.out.println(view + ": " + top);
|
||||
}
|
||||
|
||||
System.out.println("\nModified XML metadata file:\n");
|
||||
String newContent = sb.toString();
|
||||
File output = new File(mXmlMetadataFile.getParentFile(), mXmlMetadataFile.getName() + ".mod");
|
||||
if (output.exists()) {
|
||||
output.delete();
|
||||
}
|
||||
try {
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(output));
|
||||
writer.write(newContent);
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("Done - wrote " + output.getPath());
|
||||
}
|
||||
|
||||
//private File mPublicFile = new File(location, "data/res/values/public.xml");
|
||||
private File mPublicFile = new File("/Volumes/AndroidWork/git/frameworks/base/core/res/res/values/public.xml");
|
||||
|
||||
private void listAdvanced() {
|
||||
Set<String> keys = new HashSet<String>(1000);
|
||||
|
||||
// Merged usages across view types
|
||||
Map<String, Usage> mergedUsages = new HashMap<String, Usage>(100);
|
||||
|
||||
for (Entry<String,Map<String,Usage>> entry : mFrequencies.entrySet()) {
|
||||
String view = entry.getKey();
|
||||
if (view.indexOf('.') != -1 && !view.startsWith("android.")) {
|
||||
// Skip custom views etc
|
||||
continue;
|
||||
}
|
||||
Map<String, Usage> map = entry.getValue();
|
||||
for (Usage usage : map.values()) {
|
||||
// if (usage.count == 1) {
|
||||
// System.out.println("Only found *one* usage of " + usage.attribute);
|
||||
// }
|
||||
// if (usage.count < 4) {
|
||||
// System.out.println("Only found " + usage.count + " usage of " + usage.attribute);
|
||||
// }
|
||||
|
||||
String attribute = usage.attribute;
|
||||
int index = attribute.indexOf(':');
|
||||
if (index == -1 || attribute.startsWith("android:")) {
|
||||
Usage merged = mergedUsages.get(attribute);
|
||||
if (merged == null) {
|
||||
merged = new Usage(attribute);
|
||||
merged.count = usage.count;
|
||||
mergedUsages.put(attribute, merged);
|
||||
} else {
|
||||
merged.count += usage.count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Usage usage : mergedUsages.values()) {
|
||||
String attribute = usage.attribute;
|
||||
if (usage.count < 4) {
|
||||
System.out.println("Only found " + usage.count + " usage of " + usage.attribute);
|
||||
continue;
|
||||
}
|
||||
int index = attribute.indexOf(':');
|
||||
if (index != -1) {
|
||||
attribute = attribute.substring(index + 1); // +1: skip ':'
|
||||
}
|
||||
keys.add(attribute);
|
||||
}
|
||||
|
||||
List<String> sorted = new ArrayList<String>(keys);
|
||||
Collections.sort(sorted);
|
||||
System.out.println("\nEncountered Attributes");
|
||||
System.out.println("-----------------------------");
|
||||
for (String attribute : sorted) {
|
||||
System.out.println(attribute);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static class Usage implements Comparable<Usage> {
|
||||
public String attribute;
|
||||
public int count;
|
||||
|
||||
|
||||
public Usage(String attribute) {
|
||||
super();
|
||||
this.attribute = attribute;
|
||||
|
||||
count = 1;
|
||||
}
|
||||
|
||||
public void incrementCount() {
|
||||
count++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Usage o) {
|
||||
// Sort by decreasing frequency, then sort alphabetically
|
||||
int frequencyDelta = o.count - count;
|
||||
if (frequencyDelta != 0) {
|
||||
return frequencyDelta;
|
||||
} else {
|
||||
return attribute.compareTo(o.attribute);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return attribute + ": " + count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((attribute == null) ? 0 : attribute.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Usage other = (Usage) obj;
|
||||
if (attribute == null) {
|
||||
if (other.attribute != null)
|
||||
return false;
|
||||
} else if (!attribute.equals(other.attribute))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue