19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.tools.layoutlib.create;
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static org.junit.Assert.assertArrayEquals;
224f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Guptaimport static org.junit.Assert.assertFalse;
231cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport static org.junit.Assert.assertTrue;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.junit.After;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.junit.Before;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.junit.Test;
281cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport org.objectweb.asm.ClassReader;
291cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport org.objectweb.asm.ClassVisitor;
301cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport org.objectweb.asm.FieldVisitor;
311cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport org.objectweb.asm.MethodVisitor;
321cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport org.objectweb.asm.Opcodes;
331cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport org.objectweb.asm.Type;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
3758037a4404e639d28695a0f1c17053b53b96b970Deepanshu Guptaimport java.io.InputStream;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.URL;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
404f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Guptaimport java.util.Collections;
411cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport java.util.Enumeration;
421cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport java.util.HashSet;
431cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport java.util.Map;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
451cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport java.util.TreeMap;
461cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport java.util.zip.ZipEntry;
471cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Guptaimport java.util.zip.ZipFile;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unit tests for some methods of {@link AsmGenerator}.
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class AsmGeneratorTest {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MockLog mLog;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<String> mOsJarPath;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mOsDestJar;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private File mTempFile;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
591cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    // ASM internal name for the the class in java package that should be refactored.
601cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    private static final String JAVA_CLASS_NAME = "java/lang/JavaClass";
611cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Before
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setUp() throws Exception {
64bc101806249eb883f89c4a770a8c27f9ac315837Raphael        mLog = new MockLog();
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        URL url = this.getClass().getClassLoader().getResource("data/mock_android.jar");
66bc101806249eb883f89c4a770a8c27f9ac315837Raphael
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOsJarPath = new ArrayList<String>();
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOsJarPath.add(url.getFile());
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
701cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        mTempFile = File.createTempFile("mock", ".jar");
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOsDestJar = mTempFile.getAbsolutePath();
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTempFile.deleteOnExit();
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @After
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void tearDown() throws Exception {
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mTempFile != null) {
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTempFile.delete();
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTempFile = null;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Test
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void testClassRenaming() throws IOException, LogAbortException {
85bc101806249eb883f89c4a770a8c27f9ac315837Raphael
86bc101806249eb883f89c4a770a8c27f9ac315837Raphael        ICreateInfo ci = new ICreateInfo() {
8746d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet            @Override
88bc101806249eb883f89c4a770a8c27f9ac315837Raphael            public Class<?>[] getInjectedClasses() {
89bc101806249eb883f89c4a770a8c27f9ac315837Raphael                // classes to inject in the final JAR
90bc101806249eb883f89c4a770a8c27f9ac315837Raphael                return new Class<?>[0];
91bc101806249eb883f89c4a770a8c27f9ac315837Raphael            }
92bc101806249eb883f89c4a770a8c27f9ac315837Raphael
9346d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet            @Override
94bc101806249eb883f89c4a770a8c27f9ac315837Raphael            public String[] getDelegateMethods() {
95bc101806249eb883f89c4a770a8c27f9ac315837Raphael                return new String[0];
96bc101806249eb883f89c4a770a8c27f9ac315837Raphael            }
97bc101806249eb883f89c4a770a8c27f9ac315837Raphael
9846d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet            @Override
99bc101806249eb883f89c4a770a8c27f9ac315837Raphael            public String[] getDelegateClassNatives() {
100bc101806249eb883f89c4a770a8c27f9ac315837Raphael                return new String[0];
101bc101806249eb883f89c4a770a8c27f9ac315837Raphael            }
102bc101806249eb883f89c4a770a8c27f9ac315837Raphael
10346d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet            @Override
104bc101806249eb883f89c4a770a8c27f9ac315837Raphael            public String[] getOverriddenMethods() {
105bc101806249eb883f89c4a770a8c27f9ac315837Raphael                // methods to force override
106bc101806249eb883f89c4a770a8c27f9ac315837Raphael                return new String[0];
107bc101806249eb883f89c4a770a8c27f9ac315837Raphael            }
108bc101806249eb883f89c4a770a8c27f9ac315837Raphael
10946d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet            @Override
110bc101806249eb883f89c4a770a8c27f9ac315837Raphael            public String[] getRenamedClasses() {
111bc101806249eb883f89c4a770a8c27f9ac315837Raphael                // classes to rename (so that we can replace them)
112bc101806249eb883f89c4a770a8c27f9ac315837Raphael                return new String[] {
113bc101806249eb883f89c4a770a8c27f9ac315837Raphael                        "mock_android.view.View", "mock_android.view._Original_View",
114bc101806249eb883f89c4a770a8c27f9ac315837Raphael                        "not.an.actual.ClassName", "anoter.fake.NewClassName",
115bc101806249eb883f89c4a770a8c27f9ac315837Raphael                };
116bc101806249eb883f89c4a770a8c27f9ac315837Raphael            }
117bc101806249eb883f89c4a770a8c27f9ac315837Raphael
11846d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet            @Override
1191cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            public String[] getJavaPkgClasses() {
1201cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta              return new String[0];
1211cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
1221cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1231cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            @Override
1244f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public Set<String> getExcludedClasses() {
1254f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return null;
1264f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
1274f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
1284f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
129bc101806249eb883f89c4a770a8c27f9ac315837Raphael            public String[] getDeleteReturns() {
130bc101806249eb883f89c4a770a8c27f9ac315837Raphael                 // methods deleted from their return type.
131bc101806249eb883f89c4a770a8c27f9ac315837Raphael                return new String[0];
132bc101806249eb883f89c4a770a8c27f9ac315837Raphael            }
133bc101806249eb883f89c4a770a8c27f9ac315837Raphael        };
134bc101806249eb883f89c4a770a8c27f9ac315837Raphael
135bc101806249eb883f89c4a770a8c27f9ac315837Raphael        AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                null,                 // derived from
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new String[] {        // include classes
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "**"
1411cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                },
14258037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                new HashSet<String>(0) /* excluded classes */,
14358037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                new String[]{} /* include files */);
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        aa.analyze();
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        agen.generate();
146bc101806249eb883f89c4a770a8c27f9ac315837Raphael
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Set<String> notRenamed = agen.getClassesNotRenamed();
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assertArrayEquals(new String[] { "not/an/actual/ClassName" }, notRenamed.toArray());
1491cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1501cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    }
1511cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1521cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    @Test
1531cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    public void testClassRefactoring() throws IOException, LogAbortException {
1541cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        ICreateInfo ci = new ICreateInfo() {
1551cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            @Override
1561cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            public Class<?>[] getInjectedClasses() {
1571cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                // classes to inject in the final JAR
1581cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return new Class<?>[] {
1591cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                        com.android.tools.layoutlib.create.dataclass.JavaClass.class
1601cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                };
1611cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
1621cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1631cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            @Override
1641cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            public String[] getDelegateMethods() {
1651cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return new String[0];
1661cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
1671cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1681cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            @Override
1691cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            public String[] getDelegateClassNatives() {
1701cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return new String[0];
1711cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
1721cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1731cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            @Override
1741cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            public String[] getOverriddenMethods() {
1751cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                // methods to force override
1761cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return new String[0];
1771cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
1781cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1791cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            @Override
1801cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            public String[] getRenamedClasses() {
1811cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                // classes to rename (so that we can replace them)
1821cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return new String[0];
1831cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
1841cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1851cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            @Override
1861cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            public String[] getJavaPkgClasses() {
1871cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta             // classes to refactor (so that we can replace them)
1881cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return new String[] {
1891cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                        "java.lang.JavaClass", "com.android.tools.layoutlib.create.dataclass.JavaClass",
1901cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                };
1911cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
1921cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
1931cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            @Override
1944f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public Set<String> getExcludedClasses() {
1954f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return Collections.singleton("java.lang.JavaClass");
1964f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
1974f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
1984f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
1991cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            public String[] getDeleteReturns() {
2001cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                 // methods deleted from their return type.
2011cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return new String[0];
2021cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
2031cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        };
2041cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
2051cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
2061cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
2071cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
2081cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                null,                 // derived from
2091cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                new String[] {        // include classes
2101cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    "**"
2111cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                },
21258037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                new HashSet<String>(1),
21358037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                new String[] {        /* include files */
21458037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                    "mock_android/data/data*"
21558037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                });
2161cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        aa.analyze();
2171cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        agen.generate();
21858037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta        Map<String, ClassReader> output = new TreeMap<String, ClassReader>();
21958037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta        Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
22058037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta        parseZip(mOsDestJar, output, filesFound);
2211cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        boolean injectedClassFound = false;
2221cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        for (ClassReader cr: output.values()) {
2231cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            TestClassVisitor cv = new TestClassVisitor();
2241cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            cr.accept(cv, 0);
2251cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            injectedClassFound |= cv.mInjectedClassFound;
2261cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        }
2271cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        assertTrue(injectedClassFound);
22858037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta        assertArrayEquals(new String[] {"mock_android/data/dataFile"},
22958037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                filesFound.keySet().toArray());
2301cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    }
2311cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
2324f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta    @Test
2334f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta    public void testClassExclusion() throws IOException, LogAbortException {
2344f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        ICreateInfo ci = new ICreateInfo() {
2354f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
2364f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public Class<?>[] getInjectedClasses() {
2374f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return new Class<?>[0];
2384f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
2394f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
2404f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
2414f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public String[] getDelegateMethods() {
2424f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return new String[0];
2434f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
2444f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
2454f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
2464f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public String[] getDelegateClassNatives() {
2474f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return new String[0];
2484f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
2494f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
2504f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
2514f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public String[] getOverriddenMethods() {
2524f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                // methods to force override
2534f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return new String[0];
2544f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
2554f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
2564f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
2574f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public String[] getRenamedClasses() {
2584f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                // classes to rename (so that we can replace them)
2594f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return new String[0];
2604f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
2614f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
2624f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
2634f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public String[] getJavaPkgClasses() {
2644f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                // classes to refactor (so that we can replace them)
2654f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return new String[0];
2664f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
2674f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
2684f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
2694f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public Set<String> getExcludedClasses() {
2704f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                Set<String> set = new HashSet<String>(2);
2714f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                set.add("mock_android.dummy.InnerTest");
2724f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                set.add("java.lang.JavaClass");
2734f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return set;
2744f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
2754f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
2764f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            @Override
2774f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            public String[] getDeleteReturns() {
2784f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                // methods deleted from their return type.
2794f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                return new String[0];
2804f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            }
2814f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        };
2824f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
2834f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
2844f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        Set<String> excludedClasses = ci.getExcludedClasses();
2854f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
2864f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                null,                 // derived from
2874f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                new String[] {        // include classes
2884f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                        "**"
2894f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                },
2904f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                excludedClasses,
2914f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                new String[] {        /* include files */
2924f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                        "mock_android/data/data*"
2934f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                });
2944f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        aa.analyze();
2954f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        agen.generate();
2964f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        Map<String, ClassReader> output = new TreeMap<String, ClassReader>();
2974f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
2984f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        parseZip(mOsDestJar, output, filesFound);
2994f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        for (String s : output.keySet()) {
3004f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta            assertFalse(excludedClasses.contains(s));
3014f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        }
3024f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta        assertArrayEquals(new String[] {"mock_android/data/dataFile"},
3034f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta                filesFound.keySet().toArray());
3044f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta    }
3054f133894a6e98d8d30557ea42cec92cfb21fa5c9Deepanshu Gupta
30658037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta    private void parseZip(String jarPath,
30758037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta            Map<String, ClassReader> classes,
30858037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta            Map<String, InputStream> filesFound) throws IOException {
3091cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3101cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            ZipFile zip = new ZipFile(jarPath);
3111cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            Enumeration<? extends ZipEntry> entries = zip.entries();
3121cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            ZipEntry entry;
3131cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            while (entries.hasMoreElements()) {
3141cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                entry = entries.nextElement();
3151cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                if (entry.getName().endsWith(".class")) {
3161cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    ClassReader cr = new ClassReader(zip.getInputStream(entry));
3171cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    String className = classReaderToClassName(cr);
3181cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    classes.put(className, cr);
31958037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                } else {
32058037a4404e639d28695a0f1c17053b53b96b970Deepanshu Gupta                    filesFound.put(entry.getName(), zip.getInputStream(entry));
3211cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                }
3221cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
3231cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3241cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    }
3251cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3261cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    private String classReaderToClassName(ClassReader classReader) {
3271cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        if (classReader == null) {
3281cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            return null;
3291cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        } else {
3301cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            return classReader.getClassName().replace('/', '.');
3311cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        }
3321cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    }
3331cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3341cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta    private class TestClassVisitor extends ClassVisitor {
3351cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3361cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        boolean mInjectedClassFound = false;
3371cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3381cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        TestClassVisitor() {
3391cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            super(Opcodes.ASM4);
3401cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        }
3411cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3421cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        @Override
3431cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        public void visit(int version, int access, String name, String signature,
3441cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                String superName, String[] interfaces) {
3451cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            assertTrue(!getBase(name).equals(JAVA_CLASS_NAME));
3461cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            if (name.equals("com/android/tools/layoutlib/create/dataclass/JavaClass")) {
3471cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                mInjectedClassFound = true;
3481cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
3491cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            super.visit(version, access, name, signature, superName, interfaces);
3501cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        }
3511cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3521cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        @Override
3531cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        public FieldVisitor visitField(int access, String name, String desc,
3541cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                String signature, Object value) {
3551cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            assertTrue(testType(Type.getType(desc)));
3561cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            return super.visitField(access, name, desc, signature, value);
3571cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        }
3581cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3591cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        @SuppressWarnings("hiding")
3601cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        @Override
3611cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        public MethodVisitor visitMethod(int access, String name, String desc,
3621cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                String signature, String[] exceptions) {
3631cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
3641cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            return new MethodVisitor(Opcodes.ASM4, mv) {
3651cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3661cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                @Override
3671cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                public void visitFieldInsn(int opcode, String owner, String name,
3681cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                        String desc) {
3691cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
3701cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    assertTrue(testType(Type.getType(desc)));
3711cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    super.visitFieldInsn(opcode, owner, name, desc);
3721cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                }
3731cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3741cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                @Override
3751cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                public void visitLdcInsn(Object cst) {
3761cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    if (cst instanceof Type) {
3771cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                        assertTrue(testType((Type)cst));
3781cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    }
3791cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    super.visitLdcInsn(cst);
3801cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                }
3811cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3821cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                @Override
3831cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                public void visitTypeInsn(int opcode, String type) {
3841cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    assertTrue(!getBase(type).equals(JAVA_CLASS_NAME));
3851cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    super.visitTypeInsn(opcode, type);
3861cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                }
3871cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3881cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                @Override
3891cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                public void visitMethodInsn(int opcode, String owner, String name,
3901cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                        String desc) {
3911cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
3921cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    assertTrue(testType(Type.getType(desc)));
3931cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    super.visitMethodInsn(opcode, owner, name, desc);
3941cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                }
3951cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3961cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            };
3971cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        }
3981cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
3991cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        private boolean testType(Type type) {
4001cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            int sort = type.getSort();
4011cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            if (sort == Type.OBJECT) {
4021cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                assertTrue(!getBase(type.getInternalName()).equals(JAVA_CLASS_NAME));
4031cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            } else if (sort == Type.ARRAY) {
4041cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                assertTrue(!getBase(type.getElementType().getInternalName())
4051cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                        .equals(JAVA_CLASS_NAME));
4061cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            } else if (sort == Type.METHOD) {
4071cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                boolean r = true;
4081cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                for (Type t : type.getArgumentTypes()) {
4091cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                    r &= testType(t);
4101cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                }
4111cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return r & testType(type.getReturnType());
4121cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
4131cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            return true;
4141cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        }
4151cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta
4161cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        private String getBase(String className) {
4171cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            if (className == null) {
4181cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return null;
4191cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
4201cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            int pos = className.indexOf('$');
4211cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            if (pos > 0) {
4221cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta                return className.substring(0, pos);
4231cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            }
4241cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta            return className;
4251cf5df38f4bdafa1beb2674ca548ad6d9650766bDeepanshu Gupta        }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
428