/** * Is this drawable folder for an Android 3.0 drawable? This will be the * case if it specifies -v11+, or if the minimum SDK version declared in the * manifest is at least 11. */ private static boolean isAndroid30(Context context, int folderVersion) { return folderVersion >= 11 || context.getMainProject().getMinSdk() >= 11; }
/** * Is this drawable folder for an Android 3.0 drawable? This will be the * case if it specifies -v11+, or if the minimum SDK version declared in the * manifest is at least 11. */ private static boolean isAndroid30(Context context, int folderVersion) { return folderVersion >= 11 || context.getMainProject().getMinSdk() >= 11; }
protected int getMinSdk(Context context) { if (mMinApi == -1) { AndroidVersion minSdkVersion = context.getMainProject().getMinSdkVersion(); mMinApi = minSdkVersion.getFeatureLevel(); if (mMinApi == 1 && !context.getMainProject().isAndroidProject()) { // Don't flag API checks in non-Android projects mMinApi = Integer.MAX_VALUE; } } return mMinApi; }
@Override public void beforeCheckFile(@NonNull Context context) { mHasLeanbackLauncherActivity = false; mHasLeanbackSupport = false; mHasApplicationBanner = false; mLeanbackActivitiesWithoutBanners = 0; mUnsupportedHardwareImpliedPermissions = Lists.newArrayListWithExpectedSize(2); mUnsupportedTvUsesFeatures = Sets.newHashSetWithExpectedSize(2); mAllUnsupportedTvUsesFeatures = Sets.newHashSetWithExpectedSize(2); // Check gradle dependency Project mainProject = context.getMainProject(); mHasLeanbackDependency = (mainProject.isGradleProject() && Boolean.TRUE.equals(mainProject.dependsOn(LEANBACK_LIB_ARTIFACT))); }
@Override public void beforeCheckProject(@NonNull Context context) { mHasNativeLibs = false; mApplicationTagHandle = null; if (!context.getMainProject().isGradleProject() || context.getMainProject().getGradleModelVersion() == null) { mSuppress = true; return; } //compileSdkVersion must be >= 23 boolean projectSupportsAttribute = context.getMainProject().getBuildSdk() >= 23; //android gradle plugin must be 2.2.0+ GradleVersion gradleVersion = context.getMainProject().getGradleModelVersion(); boolean gradleSupportsAttribute = MIN_GRADLE_VERSION.compareIgnoringQualifiers(gradleVersion) <= 0; //suppress lint check if the compile SDK or the Gradle plugin are too old mSuppress = !projectSupportsAttribute || !gradleSupportsAttribute; }
protected int getMinSdk(Context context) { if (mMinApi == -1) { AndroidVersion minSdkVersion = context.getMainProject().getMinSdkVersion(); mMinApi = minSdkVersion.getFeatureLevel(); } return mMinApi; }
/** * Is this drawable folder for an Android 2.3 drawable? This will be the * case if it specifies -v9 or -v10, or if the minimum SDK version declared in the * manifest is 9 or 10 (and it does not specify some higher version like -v11 */ private static boolean isAndroid23(Context context, int folderVersion) { if (isAndroid30(context, folderVersion)) { return false; } if (folderVersion == 9 || folderVersion == 10) { return true; } int minSdk = context.getMainProject().getMinSdk(); return minSdk == 9 || minSdk == 10; }
/** * Is this drawable folder for an Android 2.3 drawable? This will be the * case if it specifies -v9 or -v10, or if the minimum SDK version declared in the * manifest is 9 or 10 (and it does not specify some higher version like -v11 */ private static boolean isAndroid23(Context context, int folderVersion) { if (isAndroid30(context, folderVersion)) { return false; } if (folderVersion == 9 || folderVersion == 10) { return true; } int minSdk = context.getMainProject().getMinSdk(); return minSdk == 9 || minSdk == 10; }
@Override public void afterCheckProject(@NonNull Context context) { // Don't report issues on libraries if (context.getProject() == context.getMainProject() && !context.getMainProject().isLibrary() && mApplicationTagHandle != null) { if (!mSuppress && mHasNativeLibs) { context.report(ISSUE, mApplicationTagHandle.resolve(), "Missing attribute android:extractNativeLibs=\"false\"" + " on the `<application>` tag."); } } }
@Override public void afterCheckProject(@NonNull Context context) { if (mUsesRtlAttributes && mEnabledRtlSupport == null && rtlApplies(context)) { List<File> manifestFile = context.getMainProject().getManifestFiles(); if (!manifestFile.isEmpty()) { Location location = Location.create(manifestFile.get(0)); context.report(ENABLED, location, "The project references RTL attributes, but does not explicitly enable " + "or disable RTL support with `android:supportsRtl` in the manifest"); } } }
@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; }
@NonNull 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 Location.NONE; }
@Override public void afterCheckProject(@NonNull Context context) { if (mUsesRtlAttributes && mEnabledRtlSupport == null && rtlApplies(context)) { List<File> manifestFile = context.getMainProject().getManifestFiles(); if (!manifestFile.isEmpty()) { Location location = Location.create(manifestFile.get(0)); context.report(ENABLED, location, "The project references RTL attributes, but does not explicitly enable " + "or disable RTL support with `android:supportsRtl` in the manifest"); } } }
private boolean rtlApplies(@NonNull Context context) { Project project = context.getMainProject(); if (project.getTargetSdk() < RTL_API) { return false; } int buildTarget = project.getBuildSdk(); if (buildTarget != -1 && buildTarget < RTL_API) { return false; } //noinspection RedundantIfStatement if (mEnabledRtlSupport != null && !mEnabledRtlSupport) { return false; } return true; }
private boolean rtlApplies(@NonNull Context context) { Project project = context.getMainProject(); if (project.getTargetSdk() < RTL_API) { return false; } int buildTarget = project.getBuildSdk(); if (buildTarget != -1 && buildTarget < RTL_API) { return false; } //noinspection RedundantIfStatement if (mEnabledRtlSupport != null && !mEnabledRtlSupport) { return false; } return true; }
@Override public void afterCheckProject(@NonNull Context context) { if (context.getProject() == context.getMainProject() && // Full analysis? Don't tie check to any specific Gradle DSL element context.getScope().contains(Scope.ALL_RESOURCE_FILES)) { checkConsistentPlayServices(context, null); checkConsistentSupportLibraries(context, null); checkConsistentWearableLibraries(context, null); } }
@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"); } }
@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"); } }
@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."); } /** AMAZON_EDIT_BEGIN */ if (mSeenUsesAmznSdk == 0 && context.isEnabled(USES_AMZN_SDK) && isAmznBuildTarget(xmlContext)) { context.report(USES_AMZN_SDK, Location.create(context.file), "Manifest should specify a minimum API level with " + "`<uses-amzn-sdk android:minSdkVersion=\"?\" />`; if it really supports " + "all versions of Fire OS set it to 1.", null); } /** AMAZON_EDIT_END */ }