/*
 * Copyright (C) 2011 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.tools.lint.checks;

import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_ALLOW_BACKUP;
import static com.android.SdkConstants.ATTR_ICON;
import static com.android.SdkConstants.ATTR_MIN_SDK_VERSION;
import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.ATTR_PACKAGE;
import static com.android.SdkConstants.ATTR_TARGET_SDK_VERSION;
import static com.android.SdkConstants.ATTR_VERSION_CODE;
import static com.android.SdkConstants.ATTR_VERSION_NAME;
import static com.android.SdkConstants.DRAWABLE_PREFIX;
import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
import static com.android.SdkConstants.TAG_ACTIVITY;
import static com.android.SdkConstants.TAG_APPLICATION;
import static com.android.SdkConstants.TAG_INTENT_FILTER;
import static com.android.SdkConstants.TAG_PERMISSION;
import static com.android.SdkConstants.TAG_PROVIDER;
import static com.android.SdkConstants.TAG_RECEIVER;
import static com.android.SdkConstants.TAG_SERVICE;
import static com.android.SdkConstants.TAG_USES_FEATURE;
import static com.android.SdkConstants.TAG_USES_LIBRARY;
import static com.android.SdkConstants.TAG_USES_PERMISSION;
import static com.android.SdkConstants.TAG_USES_SDK;
import static com.android.xml.AndroidManifest.NODE_ACTION;
import static com.android.xml.AndroidManifest.NODE_DATA;
import static com.android.xml.AndroidManifest.NODE_METADATA;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.builder.model.AndroidProject;
import com.android.builder.model.ApiVersion;
import com.android.builder.model.BuildTypeContainer;
import com.android.builder.model.ProductFlavor;
import com.android.builder.model.ProductFlavorContainer;
import com.android.builder.model.SourceProviderContainer;
import com.android.builder.model.Variant;
import com.android.ide.common.res2.AbstractResourceRepository;
import com.android.ide.common.resources.ResourceUrl;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Detector;
import com.android.tools.lint.detector.api.Implementation;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.LintUtils;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Project;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.Speed;
import com.android.tools.lint.detector.api.XmlContext;
import com.google.common.collect.Maps;

import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Checks for issues in AndroidManifest files such as declaring elements in the
 * wrong order.
 */
public class ManifestDetector extends Detector implements Detector.XmlScanner {
    private static final Implementation IMPLEMENTATION = new Implementation(
            ManifestDetector.class,
            Scope.MANIFEST_SCOPE
    );

    /** Wrong order of elements in the manifest */
    public static final Issue ORDER = Issue.create(
            "ManifestOrder", //$NON-NLS-1$
            "Incorrect order of elements in manifest",
            "The <application> tag should appear after the elements which declare " +
            "which version you need, which features you need, which libraries you " +
            "need, and so on. In the past there have been subtle bugs (such as " +
            "themes not getting applied correctly) when the `<application>` tag appears " +
            "before some of these other elements, so it's best to order your " +
            "manifest in the logical dependency order.",
            Category.CORRECTNESS,
            5,
            Severity.WARNING,
            IMPLEMENTATION);

    /** Missing a {@code <uses-sdk>} element */
    public static final Issue USES_SDK = Issue.create(
            "UsesMinSdkAttributes", //$NON-NLS-1$
            "Minimum SDK and target SDK attributes not defined",

            "The manifest should contain a `<uses-sdk>` element which defines the " +
            "minimum API Level required for the application to run, " +
            "as well as the target version (the highest API level you have tested " +
            "the version for.)",

            Category.CORRECTNESS,
            9,
            Severity.WARNING,
            IMPLEMENTATION).addMoreInfo(
            "http://developer.android.com/guide/topics/manifest/uses-sdk-element.html"); //$NON-NLS-1$

    /** Using a targetSdkVersion that isn't recent */
    public static final Issue TARGET_NEWER = Issue.create(
            "OldTargetApi", //$NON-NLS-1$
            "Target SDK attribute is not targeting latest version",

            "When your application runs on a version of Android that is more recent than your " +
            "`targetSdkVersion` specifies that it has been tested with, various compatibility " +
            "modes kick in. This ensures that your application continues to work, but it may " +
            "look out of place. For example, if the `targetSdkVersion` is less than 14, your " +
            "app may get an option button in the UI.\n" +
            "\n" +
            "To fix this issue, set the `targetSdkVersion` to the highest available value. Then " +
            "test your app to make sure everything works correctly. You may want to consult " +
            "the compatibility notes to see what changes apply to each version you are adding " +
            "support for: " +
            "http://developer.android.com/reference/android/os/Build.VERSION_CODES.html",

            Category.CORRECTNESS,
            6,
            Severity.WARNING,
            IMPLEMENTATION).addMoreInfo(
            "http://developer.android.com/reference/android/os/Build.VERSION_CODES.html"); //$NON-NLS-1$

    /** Using multiple {@code <uses-sdk>} elements */
    public static final Issue MULTIPLE_USES_SDK = Issue.create(
            "MultipleUsesSdk", //$NON-NLS-1$
            "Multiple `<uses-sdk>` elements in the manifest",

            "The `<uses-sdk>` element should appear just once; the tools will *not* merge the " +
            "contents of all the elements so if you split up the attributes across multiple " +
            "elements, only one of them will take effect. To fix this, just merge all the " +
            "attributes from the various elements into a single <uses-sdk> element.",

            Category.CORRECTNESS,
            6,
            Severity.FATAL,
            IMPLEMENTATION).addMoreInfo(
            "http://developer.android.com/guide/topics/manifest/uses-sdk-element.html"); //$NON-NLS-1$

    /** Missing a {@code <uses-sdk>} element */
    public static final Issue WRONG_PARENT = Issue.create(
            "WrongManifestParent", //$NON-NLS-1$
            "Wrong manifest parent",

            "The `<uses-library>` element should be defined as a direct child of the " +
            "`<application>` tag, not the `<manifest>` tag or an `<activity>` tag. Similarly, " +
            "a `<uses-sdk>` tag much be declared at the root level, and so on. This check " +
            "looks for incorrect declaration locations in the manifest, and complains " +
            "if an element is found in the wrong place.",

            Category.CORRECTNESS,
            6,
            Severity.FATAL,
            IMPLEMENTATION).addMoreInfo(
            "http://developer.android.com/guide/topics/manifest/manifest-intro.html"); //$NON-NLS-1$

    /** Missing a {@code <uses-sdk>} element */
    public static final Issue DUPLICATE_ACTIVITY = Issue.create(
            "DuplicateActivity", //$NON-NLS-1$
            "Activity registered more than once",

            "An activity should only be registered once in the manifest. If it is " +
            "accidentally registered more than once, then subtle errors can occur, " +
            "since attribute declarations from the two elements are not merged, so " +
            "you may accidentally remove previous declarations.",

            Category.CORRECTNESS,
            5,
            Severity.FATAL,
            IMPLEMENTATION);

    /** Not explicitly defining allowBackup */
    public static final Issue ALLOW_BACKUP = Issue.create(
            "AllowBackup", //$NON-NLS-1$
            "Missing `allowBackup` attribute",

            "The allowBackup attribute determines if an application's data can be backed up " +
            "and restored. It is documented at " +
            "http://developer.android.com/reference/android/R.attr.html#allowBackup\n" +
            "\n" +
            "By default, this flag is set to `true`. When this flag is set to `true`, " +
            "application data can be backed up and restored by the user using `adb backup` " +
            "and `adb restore`.\n" +
            "\n" +
            "This may have security consequences for an application. `adb backup` allows " +
            "users who have enabled USB debugging to copy application data off of the " +
            "device. Once backed up, all application data can be read by the user. " +
            "`adb restore` allows creation of application data from a source specified " +
            "by the user. Following a restore, applications should not assume that the " +
            "data, file permissions, and directory permissions were created by the " +
            "application itself.\n" +
            "\n" +
            "Setting `allowBackup=\"false\"` opts an application out of both backup and " +
            "restore.\n" +
            "\n" +
            "To fix this warning, decide whether your application should support backup, " +
            "and explicitly set `android:allowBackup=(true|false)\"`",

            Category.SECURITY,
            3,
            Severity.WARNING,
            IMPLEMENTATION).addMoreInfo(
            "http://developer.android.com/reference/android/R.attr.html#allowBackup");

    /** Conflicting permission names */
    public static final Issue UNIQUE_PERMISSION = Issue.create(
            "UniquePermission", //$NON-NLS-1$
            "Permission names are not unique",

            "The unqualified names or your permissions must be unique. The reason for this " +
            "is that at build time, the `aapt` tool will generate a class named `Manifest` " +
            "which contains a field for each of your permissions. These fields are named " +
            "using your permission unqualified names (i.e. the name portion after the last " +
            "dot).\n" +
            "\n" +
            "If more than one permission maps to the same field name, that field will " +
            "arbitrarily name just one of them.",

            Category.CORRECTNESS,
            6,
            Severity.FATAL,
            IMPLEMENTATION);

    /** Using a resource for attributes that do not allow it */
    public static final Issue SET_VERSION = Issue.create(
            "MissingVersion", //$NON-NLS-1$
            "Missing application name/version",

            "You should define the version information for your application.\n" +
            "`android:versionCode`: An integer value that represents the version of the " +
            "application code, relative to other versions.\n" +
            "\n" +
            "`android:versionName`: A string value that represents the release version of " +
            "the application code, as it should be shown to users.",

            Category.CORRECTNESS,
            2,
            Severity.WARNING,
            IMPLEMENTATION).addMoreInfo(
            "http://developer.android.com/tools/publishing/versioning.html#appversioning");

    /** Using a resource for attributes that do not allow it */
    public static final Issue ILLEGAL_REFERENCE = Issue.create(
            "IllegalResourceRef", //$NON-NLS-1$
            "Name and version must be integer or string, not resource",

            "For the `versionCode` attribute, you have to specify an actual integer " +
            "literal; you cannot use an indirection with a `@dimen/name` resource. " +
            "Similarly, the `versionName` attribute should be an actual string, not " +
            "a string resource url.",

            Category.CORRECTNESS,
            8,
            Severity.WARNING,
            IMPLEMENTATION);

    /** Declaring a uses-feature multiple time */
    public static final Issue DUPLICATE_USES_FEATURE = Issue.create(
            "DuplicateUsesFeature", //$NON-NLS-1$
            "Feature declared more than once",

            "A given feature should only be declared once in the manifest.",

            Category.CORRECTNESS,
            5,
            Severity.WARNING,
            IMPLEMENTATION);

    /** Not explicitly defining application icon */
    public static final Issue APPLICATION_ICON = Issue.create(
            "MissingApplicationIcon", //$NON-NLS-1$
            "Missing application icon",

            "You should set an icon for the application as whole because there is no " +
            "default. This attribute must be set as a reference to a drawable resource " +
            "containing the image (for example `@drawable/icon`).",

            Category.ICONS,
            5,
            Severity.WARNING,
            IMPLEMENTATION).addMoreInfo(
            "http://developer.android.com/tools/publishing/preparing.html#publishing-configure"); //$NON-NLS-1$

    /** Malformed Device Admin */
    public static final Issue DEVICE_ADMIN = Issue.create(
            "DeviceAdmin", //$NON-NLS-1$
            "Malformed Device Admin",
            "If you register a broadcast receiver which acts as a device admin, you must also " +
            "register an `<intent-filter>` for the action " +
            "`android.app.action.DEVICE_ADMIN_ENABLED`, without any `<data>`, such that the " +
            "device admin can be activated/deactivated.\n" +
            "\n" +
            "To do this, add\n" +
            "`<intent-filter>`\n" +
            "    `<action android:name=\"android.app.action.DEVICE_ADMIN_ENABLED\" />`\n" +
            "`</intent-filter>`\n" +
            "to your `<receiver>`.",
            Category.CORRECTNESS,
            7,
            Severity.WARNING,
            IMPLEMENTATION);

    /** Using a mock location in a non-debug-specific manifest file */
    public static final Issue MOCK_LOCATION = Issue.create(
            "MockLocation", //$NON-NLS-1$
            "Using mock location provider in production",

            "Using a mock location provider (by requiring the permission " +
            "`android.permission.ACCESS_MOCK_LOCATION`) should *only* be done " +
            "in debug builds (or from tests). In Gradle projects, that means you should only " +
            "request this permission in a test or debug source set specific manifest file.\n" +
            "\n" +
            "To fix this, create a new manifest file in the debug folder and move " +
            "the `<uses-permission>` element there. A typical path to a debug manifest " +
            "override file in a Gradle project is src/debug/AndroidManifest.xml.",

            Category.CORRECTNESS,
            8,
            Severity.FATAL,
            IMPLEMENTATION);

    /** Defining a value that is overridden by Gradle */
    public static final Issue GRADLE_OVERRIDES = Issue.create(
            "GradleOverrides", //$NON-NLS-1$
            "Value overridden by Gradle build script",

            "The value of (for example) `minSdkVersion` is only used if it is not specified in " +
            "the `build.gradle` build scripts. When specified in the Gradle build scripts, " +
            "the manifest value is ignored and can be misleading, so should be removed to " +
            "avoid ambiguity.",

            Category.CORRECTNESS,
            4,
            Severity.WARNING,
            IMPLEMENTATION);

    /** Using drawable rather than mipmap launcher icons */
    public static final Issue MIPMAP = Issue.create(
            "MipmapIcons", //$NON-NLS-1$
            "Use Mipmap Launcher Icons",

            "Launcher icons should be provided in the `mipmap` resource directory. " +
            "This is the same as the `drawable` resource directory, except resources in " +
            "the `mipmap` directory will not get stripped out when creating density-specific " +
            "APKs.\n" +
            "\n" +
            "In certain cases, the Launcher app may use a higher resolution asset (than " +
            "would normally be computed for the device) to display large app shortcuts. " +
            "If drawables for densities other than the device's resolution have been " +
            "stripped out, then the app shortcut could appear blurry.\n" +
            "\n" +
            "To fix this, move your launcher icons from `drawable-`dpi to `mipmap-`dpi " +
            "and change references from @drawable/ and R.drawable to @mipmap/ and R.mipmap.\n" +
            "In Android Studio this lint warning has a quickfix to perform this automatically.",
            Category.ICONS,
            5,
            Severity.WARNING,
            IMPLEMENTATION);

    /** Permission name of mock location permission */
    public static final String MOCK_LOCATION_PERMISSION =
            "android.permission.ACCESS_MOCK_LOCATION";   //$NON-NLS-1$

    /** Constructs a new {@link ManifestDetector} check */
    public ManifestDetector() {
    }

    private boolean mSeenApplication;

    /** Number of times we've seen the <uses-sdk> element */
    private int mSeenUsesSdk;

    /** Activities we've encountered */
    private Set<String> mActivities;

    /** Features we've encountered */
    private Set<String> mUsesFeatures;

    /** Permission basenames */
    private Map<String, String> mPermissionNames;

    /** Handle to the {@code <application>} tag */
    private Location.Handle mApplicationTagHandle;

    /** Whether we've seen an application icon definition in any of the manifest files (or
     * if a manifest tag warning for this has been explicitly disabled) */
    private boolean mSeenAppIcon;

    /** Whether we've seen an allow backup definition in any of the manifest files (or
     * if a manifest tag warning for this has been explicitly disabled) */
    private boolean mSeenAllowBackup;

    @NonNull
    @Override
    public Speed getSpeed() {
        return Speed.FAST;
    }

    @Override
    public boolean appliesTo(@NonNull Context context, @NonNull File file) {
        return file.getName().equals(ANDROID_MANIFEST_XML);
    }

    @Override
    public void beforeCheckFile(@NonNull Context context) {
        mSeenApplication = false;
        mSeenUsesSdk = 0;
        mActivities = new HashSet<String>();
        mUsesFeatures = new HashSet<String>();
    }

    @Override
    public void afterCheckFile(@NonNull Context context) {
        XmlContext xmlContext = (XmlContext) context;
        Element element = xmlContext.document.getDocumentElement();
        if (element != null) {
            checkDocumentElement(xmlContext, element);
        }

        if (mSeenUsesSdk == 0 && context.isEnabled(USES_SDK)
                // Not required in Gradle projects; typically defined in build.gradle instead
                // and inserted at build time
                && !context.getMainProject().isGradleProject()) {
            context.report(USES_SDK, Location.create(context.file),
                    "Manifest should specify a minimum API level with " +
                    "`<uses-sdk android:minSdkVersion=\"?\" />`; if it really supports " +
                    "all versions of Android set it to 1.");
        }
    }

    @Override
    public void afterCheckProject(@NonNull Context context) {
        if (!mSeenAllowBackup && context.isEnabled(ALLOW_BACKUP)
                && !context.getProject().isLibrary()
                && context.getMainProject().getMinSdk() >= 4) {
            Location location = getMainApplicationTagLocation(context);
            context.report(ALLOW_BACKUP, location,
                    "Should explicitly set `android:allowBackup` to `true` or " +
                            "`false` (it's `true` by default, and that can have some security " +
                            "implications for the application's data)");
        }

        if (!context.getMainProject().isLibrary()
                && !mSeenAppIcon && context.isEnabled(APPLICATION_ICON)) {
            Location location = getMainApplicationTagLocation(context);
            context.report(APPLICATION_ICON, location,
                    "Should explicitly set `android:icon`, there is no default");
        }
    }

    @Nullable
    private Location getMainApplicationTagLocation(@NonNull Context context) {
        if (mApplicationTagHandle != null) {
            return mApplicationTagHandle.resolve();
        }

        List<File> manifestFiles = context.getMainProject().getManifestFiles();
        if (!manifestFiles.isEmpty()) {
            return Location.create(manifestFiles.get(0));
        }

        return null;
    }

    private static void checkDocumentElement(XmlContext context, Element element) {
        Attr codeNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_VERSION_CODE);
        if (codeNode != null && codeNode.getValue().startsWith(PREFIX_RESOURCE_REF)
                && context.isEnabled(ILLEGAL_REFERENCE)) {
            context.report(ILLEGAL_REFERENCE, element, context.getLocation(codeNode),
                    "The `android:versionCode` cannot be a resource url, it must be "
                            + "a literal integer");
        } else if (codeNode == null && context.isEnabled(SET_VERSION)
                // Not required in Gradle projects; typically defined in build.gradle instead
                // and inserted at build time
                && !context.getMainProject().isGradleProject()) {
            context.report(SET_VERSION, element, context.getLocation(element),
                    "Should set `android:versionCode` to specify the application version");
        }
        Attr nameNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_VERSION_NAME);
        if (nameNode == null && context.isEnabled(SET_VERSION)
                // Not required in Gradle projects; typically defined in build.gradle instead
                // and inserted at build time
                && !context.getMainProject().isGradleProject()) {
            context.report(SET_VERSION, element, context.getLocation(element),
                    "Should set `android:versionName` to specify the application version");
        }

        checkOverride(context, element, ATTR_VERSION_CODE);
        checkOverride(context, element, ATTR_VERSION_NAME);

        Attr pkgNode = element.getAttributeNode(ATTR_PACKAGE);
        if (pkgNode != null) {
            String pkg = pkgNode.getValue();
            if (pkg.contains("${") && context.getMainProject().isGradleProject()) {
                context.report(GRADLE_OVERRIDES, pkgNode, context.getLocation(pkgNode),
                        "Cannot use placeholder for the package in the manifest; "
                                + "set `applicationId` in `build.gradle` instead");
            }
        }
    }

    private static void checkOverride(XmlContext context, Element element, String attributeName) {
        Project project = context.getProject();
        Attr attribute = element.getAttributeNodeNS(ANDROID_URI, attributeName);
        if (project.isGradleProject() && attribute != null && context.isEnabled(GRADLE_OVERRIDES)) {
            Variant variant = project.getCurrentVariant();
            if (variant != null) {
                ProductFlavor flavor = variant.getMergedFlavor();
                String gradleValue = null;
                if (ATTR_MIN_SDK_VERSION.equals(attributeName)) {
                    try {
                        ApiVersion minSdkVersion = flavor.getMinSdkVersion();
                        gradleValue = minSdkVersion != null ? minSdkVersion.getApiString() : null;
                    } catch (Throwable e) {
                        // TODO: REMOVE ME
                        // This method was added in the 0.11 model. We'll need to drop support
                        // for 0.10 shortly but until 0.11 is available this is a stopgap measure
                    }
                } else if (ATTR_TARGET_SDK_VERSION.equals(attributeName)) {
                    try {
                        ApiVersion targetSdkVersion = flavor.getTargetSdkVersion();
                        gradleValue = targetSdkVersion != null ? targetSdkVersion.getApiString() : null;
                    } catch (Throwable e) {
                        // TODO: REMOVE ME
                        // This method was added in the 0.11 model. We'll need to drop support
                        // for 0.10 shortly but until 0.11 is available this is a stopgap measure
                    }
                } else if (ATTR_VERSION_CODE.equals(attributeName)) {
                    Integer versionCode = flavor.getVersionCode();
                    if (versionCode != null) {
                        gradleValue = versionCode.toString();
                    }
                } else if (ATTR_VERSION_NAME.equals(attributeName)) {
                    gradleValue = flavor.getVersionName();
                } else {
                    assert false : attributeName;
                    return;
                }

                if (gradleValue != null) {
                    String manifestValue = attribute.getValue();

                    String message = String.format("This `%1$s` value (`%2$s`) is not used; it is "
                            + "always overridden by the value specified in the Gradle build "
                            + "script (`%3$s`)", attributeName,  manifestValue, gradleValue);
                    context.report(GRADLE_OVERRIDES, attribute, context.getLocation(attribute),
                            message);
                }
            }
        }
    }

    // ---- Implements Detector.XmlScanner ----

    @Override
    public Collection<String> getApplicableElements() {
        return Arrays.asList(
                TAG_APPLICATION,
                TAG_USES_PERMISSION,
                TAG_PERMISSION,
                "permission-tree",         //$NON-NLS-1$
                "permission-group",        //$NON-NLS-1$
                TAG_USES_SDK,
                "uses-configuration",      //$NON-NLS-1$
                TAG_USES_FEATURE,
                "supports-screens",        //$NON-NLS-1$
                "compatible-screens",      //$NON-NLS-1$
                "supports-gl-texture",     //$NON-NLS-1$
                TAG_USES_LIBRARY,
                TAG_ACTIVITY,
                TAG_SERVICE,
                TAG_PROVIDER,
                TAG_RECEIVER
        );
    }

    @Override
    public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
        String tag = element.getTagName();
        Node parentNode = element.getParentNode();

        boolean isReceiver = tag.equals(TAG_RECEIVER);
        if (isReceiver) {
            checkDeviceAdmin(context, element);
        }

        if (tag.equals(TAG_USES_LIBRARY) || tag.equals(TAG_ACTIVITY) || tag.equals(TAG_SERVICE)
                || tag.equals(TAG_PROVIDER) || isReceiver) {
            if (!TAG_APPLICATION.equals(parentNode.getNodeName())
                    && context.isEnabled(WRONG_PARENT)) {
                context.report(WRONG_PARENT, element, context.getLocation(element),
                        String.format(
                        "The `<%1$s>` element must be a direct child of the <application> element",
                        tag));
            }

            if (tag.equals(TAG_ACTIVITY)) {
                Attr nameNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
                if (nameNode != null) {
                    String name = nameNode.getValue();
                    if (!name.isEmpty()) {
                        String pkg = context.getMainProject().getPackage();
                        if (name.charAt(0) == '.') {
                            name = pkg + name;
                        } else if (name.indexOf('.') == -1) {
                            name = pkg + '.' + name;
                        }
                        if (mActivities.contains(name)) {
                            String message = String.format(
                                    "Duplicate registration for activity `%1$s`", name);
                            context.report(DUPLICATE_ACTIVITY, element,
                                    context.getLocation(nameNode), message);
                        } else {
                            mActivities.add(name);
                        }
                    }
                }

                checkMipmapIcon(context, element);
            }

            return;
        }

        if (parentNode != element.getOwnerDocument().getDocumentElement()
                && context.isEnabled(WRONG_PARENT)) {
            context.report(WRONG_PARENT, element, context.getLocation(element),
                    String.format(
                    "The `<%1$s>` element must be a direct child of the " +
                    "`<manifest>` root element", tag));
        }

        if (tag.equals(TAG_USES_SDK)) {
            mSeenUsesSdk++;

            if (mSeenUsesSdk == 2) { // Only warn when we encounter the first one
                Location location = context.getLocation(element);

                // Link up *all* encountered locations in the document
                NodeList elements = element.getOwnerDocument().getElementsByTagName(TAG_USES_SDK);
                Location secondary = null;
                for (int i = elements.getLength() - 1; i >= 0; i--) {
                    Element e = (Element) elements.item(i);
                    if (e != element) {
                        Location l = context.getLocation(e);
                        l.setSecondary(secondary);
                        l.setMessage("Also appears here");
                        secondary = l;
                    }
                }
                location.setSecondary(secondary);

                if (context.isEnabled(MULTIPLE_USES_SDK)) {
                    context.report(MULTIPLE_USES_SDK, element, location,
                        "There should only be a single `<uses-sdk>` element in the manifest:" +
                        " merge these together");
                }
                return;
            }

            if (!element.hasAttributeNS(ANDROID_URI, ATTR_MIN_SDK_VERSION)) {
                if (context.isEnabled(USES_SDK) && !context.getMainProject().isGradleProject()) {
                    context.report(USES_SDK, element, context.getLocation(element),
                        "`<uses-sdk>` tag should specify a minimum API level with " +
                        "`android:minSdkVersion=\"?\"`");
                }
            } else {
                Attr codeNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_MIN_SDK_VERSION);
                if (codeNode != null && codeNode.getValue().startsWith(PREFIX_RESOURCE_REF)
                        && context.isEnabled(ILLEGAL_REFERENCE)) {
                    context.report(ILLEGAL_REFERENCE, element, context.getLocation(codeNode),
                            "The `android:minSdkVersion` cannot be a resource url, it must be "
                                    + "a literal integer (or string if a preview codename)");
                }

                checkOverride(context, element, ATTR_MIN_SDK_VERSION);
            }

            if (!element.hasAttributeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION)) {
                // Warn if not setting target SDK -- but only if the min SDK is somewhat
                // old so there's some compatibility stuff kicking in (such as the menu
                // button etc)
                if (context.isEnabled(USES_SDK) && !context.getMainProject().isGradleProject()) {
                    context.report(USES_SDK, element, context.getLocation(element),
                        "`<uses-sdk>` tag should specify a target API level (the " +
                        "highest verified version; when running on later versions, " +
                        "compatibility behaviors may be enabled) with " +
                        "`android:targetSdkVersion=\"?\"`");
                }
            } else {
                checkOverride(context, element, ATTR_TARGET_SDK_VERSION);

                if (context.isEnabled(TARGET_NEWER)) {
                    Attr targetSdkVersionNode = element.getAttributeNodeNS(ANDROID_URI,
                            ATTR_TARGET_SDK_VERSION);
                    if (targetSdkVersionNode != null) {
                        String target = targetSdkVersionNode.getValue();
                        try {
                            int api = Integer.parseInt(target);
                            if (api < context.getClient().getHighestKnownApiLevel()) {
                                context.report(TARGET_NEWER, element,
                                  context.getLocation(targetSdkVersionNode),
                                  "Not targeting the latest versions of Android; compatibility " +
                                  "modes apply. Consider testing and updating this version. " +
                                  "Consult the `android.os.Build.VERSION_CODES` javadoc for details.");
                            }
                        } catch (NumberFormatException nufe) {
                            // Ignore: AAPT will enforce this.
                        }
                    }
                }
            }

            Attr nameNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION);
            if (nameNode != null && nameNode.getValue().startsWith(PREFIX_RESOURCE_REF)
                    && context.isEnabled(ILLEGAL_REFERENCE)) {
                context.report(ILLEGAL_REFERENCE, element, context.getLocation(nameNode),
                        "The `android:targetSdkVersion` cannot be a resource url, it must be "
                                + "a literal integer (or string if a preview codename)");
            }
        }
        if (tag.equals(TAG_PERMISSION)) {
            Attr nameNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
            if (nameNode != null) {
                String name = nameNode.getValue();
                String base = name.substring(name.lastIndexOf('.') + 1);
                if (mPermissionNames == null) {
                    mPermissionNames = Maps.newHashMap();
                } else if (mPermissionNames.containsKey(base)) {
                    String prevName = mPermissionNames.get(base);
                    Location location = context.getLocation(nameNode);
                    NodeList siblings = element.getParentNode().getChildNodes();
                    for (int i = 0, n = siblings.getLength(); i < n; i++) {
                        Node node = siblings.item(i);
                        if (node == element) {
                            break;
                        } else if (node.getNodeType() == Node.ELEMENT_NODE) {
                            Element sibling = (Element) node;
                            String suffix = '.' + base;
                            if (sibling.getTagName().equals(TAG_PERMISSION)) {
                                String b = element.getAttributeNS(ANDROID_URI, ATTR_NAME);
                                if (b.endsWith(suffix)) {
                                    Location prevLocation = context.getLocation(node);
                                    prevLocation.setMessage("Previous permission here");
                                    location.setSecondary(prevLocation);
                                    break;
                                }

                            }
                        }
                    }

                    String message = String.format("Permission name `%1$s` is not unique " +
                            "(appears in both `%2$s` and `%3$s`)", base, prevName, name);
                    context.report(UNIQUE_PERMISSION, element, location, message);
                }

                mPermissionNames.put(base, name);
            }
        }

        if (tag.equals(TAG_USES_PERMISSION)) {
            Attr name = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
            if (name != null && name.getValue().equals(MOCK_LOCATION_PERMISSION)
                    && context.getMainProject().isGradleProject()
                    && !isDebugOrTestManifest(context, context.file)
                    && context.isEnabled(MOCK_LOCATION)) {
                String message = "Mock locations should only be requested in a test or " +
                        "debug-specific manifest file (typically `src/debug/AndroidManifest.xml`)";
                Location location = context.getLocation(name);
                context.report(MOCK_LOCATION, element, location, message);
            }
        }

        if (tag.equals(TAG_APPLICATION)) {
            mSeenApplication = true;
            boolean recordLocation = false;
            if (element.hasAttributeNS(ANDROID_URI, ATTR_ALLOW_BACKUP)
                    || context.getDriver().isSuppressed(context, ALLOW_BACKUP, element)) {
                mSeenAllowBackup = true;
            } else {
                recordLocation = true;
            }
            if (element.hasAttributeNS(ANDROID_URI, ATTR_ICON)
                    || context.getDriver().isSuppressed(context, APPLICATION_ICON, element)) {
                checkMipmapIcon(context, element);
                mSeenAppIcon = true;
            } else {
                recordLocation = true;
            }
            if (recordLocation && !context.getProject().isLibrary() &&
                    (mApplicationTagHandle == null || isMainManifest(context, context.file))) {
                mApplicationTagHandle = context.createLocationHandle(element);
            }
            Attr fullBackupNode = element.getAttributeNodeNS(ANDROID_URI, "fullBackupContent");
            if (fullBackupNode != null &&
                    fullBackupNode.getValue().startsWith(PREFIX_RESOURCE_REF) &&
                    context.getClient().supportsProjectResources()) {
                AbstractResourceRepository resources = context.getClient()
                        .getProjectResources(context.getProject(), true);
                ResourceUrl url = ResourceUrl.parse(fullBackupNode.getValue());
                if (url != null && !url.framework
                        && resources != null
                        && !resources.hasResourceItem(url.type, url.name)) {
                    Location location = context.getValueLocation(fullBackupNode);
                    context.report(ALLOW_BACKUP, fullBackupNode, location,
                            "Missing `<full-backup-content>` resource");
                }
            } else if (fullBackupNode == null && context.getMainProject().getTargetSdk() >= 23) {
                Location location = context.getLocation(element);
                context.report(ALLOW_BACKUP, element, location,
                        "Should explicitly set `android:fullBackupContent` to `true` or `false` "
                                + "to opt-in to or out of full app data back-up and restore, or "
                                + "alternatively to an `@xml` resource which specifies which "
                                + "files to backup");
            } else if (fullBackupNode == null && hasGcmReceiver(element)) {
                Location location = context.getLocation(element);
                context.report(ALLOW_BACKUP, element, location,
                        "Should explicitly set `android:fullBackupContent` to avoid backing up "
                                + "the GCM device specific regId.");
            }
        } else if (mSeenApplication) {
            if (context.isEnabled(ORDER)) {
                context.report(ORDER, element, context.getLocation(element),
                    String.format("`<%1$s>` tag appears after `<application>` tag", tag));
            }

            // Don't complain for *every* element following the <application> tag
            mSeenApplication = false;
        }

        if (tag.equals(TAG_USES_FEATURE)) {
            Attr nameNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
            if (nameNode != null) {
                String name = nameNode.getValue();
                if (!name.isEmpty()) {
                    if (mUsesFeatures.contains(name)) {
                        String message = String.format(
                                "Duplicate declaration of uses-feature `%1$s`", name);
                        context.report(DUPLICATE_USES_FEATURE, element,
                                context.getLocation(nameNode), message);
                    } else {
                        mUsesFeatures.add(name);
                    }
                }
            }
        }
    }

    /**
     * Returns true if the given application element has a receiver with an intent filter
     * action for GCM receive
     */
    private static boolean hasGcmReceiver(@NonNull Element application) {
        NodeList applicationChildren = application.getChildNodes();
        for (int i1 = 0, n1 = applicationChildren.getLength(); i1 < n1; i1++) {
            Node applicationChild = applicationChildren.item(i1);
            if (applicationChild.getNodeType() == Node.ELEMENT_NODE
                    && TAG_RECEIVER.equals(applicationChild.getNodeName())) {
                NodeList receiverChildren = applicationChild.getChildNodes();
                for (int i2 = 0, n2 = receiverChildren.getLength(); i2 < n2; i2++) {
                    Node receiverChild = receiverChildren.item(i2);
                    if (receiverChild.getNodeType() == Node.ELEMENT_NODE
                            && TAG_INTENT_FILTER.equals(receiverChild.getNodeName())) {
                        NodeList filterChildren = receiverChild.getChildNodes();
                        for (int i3 = 0, n3 = filterChildren.getLength(); i3 < n3; i3++) {
                            Node filterChild = filterChildren.item(i3);
                            if (filterChild.getNodeType() == Node.ELEMENT_NODE
                                    && NODE_ACTION.equals(filterChild.getNodeName())) {
                                Element action = (Element) filterChild;
                                String name = action.getAttributeNS(ANDROID_URI, ATTR_NAME);
                                if ("com.google.android.c2dm.intent.RECEIVE".equals(name)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }

        return false;
    }

    private static void checkMipmapIcon(@NonNull XmlContext context, @NonNull Element element) {
        Attr attribute = element.getAttributeNodeNS(ANDROID_URI, ATTR_ICON);
        if (attribute == null) {
            return;
        }
        String icon = attribute.getValue();
        if (icon.startsWith(DRAWABLE_PREFIX)) {
            if (TAG_ACTIVITY.equals(element.getTagName()) && !isLaunchableActivity(element)) {
                return;
            }

            if (context.isEnabled(MIPMAP)
                    // Only complain if this app is skipping some densities
                    && context.getProject().getApplicableDensities() != null) {
                context.report(MIPMAP, element, context.getLocation(attribute),
                        "Should use `@mipmap` instead of `@drawable` for launcher icons");
            }
        }
    }

    @SuppressWarnings("SpellCheckingInspection")
    private static boolean isLaunchableActivity(@NonNull Element element) {
        if (!TAG_ACTIVITY.equals(element.getTagName())) {
            return false;
        }

        for (Element child : LintUtils.getChildren(element)) {
            if (child.getTagName().equals(TAG_INTENT_FILTER)) {
                for (Element innerChild : LintUtils.getChildren(child)) {
                    if (innerChild.getTagName().equals("category")) { //$NON-NLS-1$
                        String categoryString = innerChild.getAttributeNS(ANDROID_URI, ATTR_NAME);
                        return "android.intent.category.LAUNCHER".equals(categoryString);
                    }
                }
            }
        }

        return false;
    }

    /** Returns true iff the given manifest file is the main manifest file */
    private static boolean isMainManifest(XmlContext context, File manifestFile) {
        if (!context.getProject().isGradleProject()) {
            // In non-gradle projects, just one manifest per project
            return true;
        }

        AndroidProject model = context.getProject().getGradleProjectModel();
        return model == null || manifestFile
                .equals(model.getDefaultConfig().getSourceProvider().getManifestFile());
    }

    /**
     * Returns true iff the given manifest file is in a debug-specific source set,
     * or a test source set
     */
    private static boolean isDebugOrTestManifest(
            @NonNull XmlContext context,
            @NonNull File manifestFile) {
        AndroidProject model = context.getProject().getGradleProjectModel();
        if (model != null) {
            // Quickly check if it's the main manifest first; that's the most likely scenario
            if (manifestFile.equals(model.getDefaultConfig().getSourceProvider().getManifestFile())) {
                return false;
            }

            // Debug build type?
            for (BuildTypeContainer container : model.getBuildTypes()) {
                if (container.getBuildType().isDebuggable()) {
                    if (manifestFile.equals(container.getSourceProvider().getManifestFile())) {
                        return true;
                    }
                }
            }

            // Test source set?
            for (ProductFlavorContainer container : model.getProductFlavors()) {
                for (SourceProviderContainer extra : container.getExtraSourceProviders()) {
                    String artifactName = extra.getArtifactName();
                    if (AndroidProject.ARTIFACT_ANDROID_TEST.equals(artifactName)
                            && manifestFile.equals(extra.getSourceProvider().getManifestFile())) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    private static void checkDeviceAdmin(XmlContext context, Element element) {
        List<Element> children = LintUtils.getChildren(element);
        boolean requiredIntentFilterFound = false;
        boolean deviceAdmin = false;
        Attr locationNode = null;
        for (Element child : children) {
            String tagName = child.getTagName();
            if (tagName.equals(TAG_INTENT_FILTER) && !requiredIntentFilterFound) {
                boolean dataFound = false;
                boolean actionFound = false;
                for (Element filterChild : LintUtils.getChildren(child)) {
                    String filterTag = filterChild.getTagName();
                    if (filterTag.equals(NODE_ACTION)) {
                        String name = filterChild.getAttributeNS(ANDROID_URI, ATTR_NAME);
                        if ("android.app.action.DEVICE_ADMIN_ENABLED".equals(name)) { //$NON-NLS-1$
                            actionFound = true;
                        }
                    } else if (filterTag.equals(NODE_DATA)) {
                        dataFound = true;
                    }
                }
                if (actionFound && !dataFound) {
                    requiredIntentFilterFound = true;
                }
            } else if (tagName.equals(NODE_METADATA)) {
                Attr valueNode = child.getAttributeNodeNS(ANDROID_URI, ATTR_NAME);
                if (valueNode != null) {
                    String name = valueNode.getValue();
                    if ("android.app.device_admin".equals(name)) { //$NON-NLS-1$
                        deviceAdmin = true;
                        locationNode = valueNode;
                    }
                }
            }
        }

        if (deviceAdmin && !requiredIntentFilterFound && context.isEnabled(DEVICE_ADMIN)) {
            context.report(DEVICE_ADMIN, locationNode, context.getLocation(locationNode),
                "You must have an intent filter for action "
                        + "`android.app.action.DEVICE_ADMIN_ENABLED`");
        }
    }
}
