/* * Copyright (C) 2015 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 com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.annotations.VisibleForTesting; import com.android.sdklib.AndroidVersion; import java.util.Collections; import java.util.Set; /** * A {@linkplain PermissionHolder} knows which permissions are held/granted and can look up * individual permissions and respond to queries about whether they are held or not. */ public interface PermissionHolder { /** Returns true if the permission holder has been granted the given permission */ boolean hasPermission(@NonNull String permission); /** Returns true if the given permission is known to be revocable for targetSdkVersion >= M */ boolean isRevocable(@NonNull String permission); @NonNull AndroidVersion getMinSdkVersion(); @NonNull AndroidVersion getTargetSdkVersion(); /** * A convenience implementation of {@link PermissionHolder} backed by a set */ class SetPermissionLookup implements PermissionHolder { private Set<String> mGrantedPermissions; private Set<String> mRevocablePermissions; private AndroidVersion mMinSdkVersion; private AndroidVersion mTargetSdkVersion; public SetPermissionLookup( @NonNull Set<String> grantedPermissions, @NonNull Set<String> revocablePermissions, @NonNull AndroidVersion minSdkVersion, @NonNull AndroidVersion targetSdkVersion) { mGrantedPermissions = grantedPermissions; mRevocablePermissions = revocablePermissions; mMinSdkVersion = minSdkVersion; mTargetSdkVersion = targetSdkVersion; } @VisibleForTesting public SetPermissionLookup(@NonNull Set<String> grantedPermissions, @NonNull Set<String> revocablePermissions) { this(grantedPermissions, revocablePermissions, AndroidVersion.DEFAULT, AndroidVersion.DEFAULT); } @VisibleForTesting public SetPermissionLookup(@NonNull Set<String> grantedPermissions) { this(grantedPermissions, Collections.<String>emptySet()); } @Override public boolean hasPermission(@NonNull String permission) { return mGrantedPermissions.contains(permission); } @Override public boolean isRevocable(@NonNull String permission) { return mRevocablePermissions.contains(permission); } @NonNull @Override public AndroidVersion getMinSdkVersion() { return mMinSdkVersion; } @NonNull @Override public AndroidVersion getTargetSdkVersion() { return mTargetSdkVersion; } /** * Creates a {@linkplain PermissionHolder} which combines the permissions * held by the given holder, with the permissions implied by the given * {@link PermissionRequirement} */ @NonNull public static PermissionHolder join(@NonNull PermissionHolder lookup, @NonNull PermissionRequirement requirement) { SetPermissionLookup empty = new SetPermissionLookup(Collections.<String>emptySet(), Collections.<String>emptySet(), lookup.getMinSdkVersion(), lookup.getTargetSdkVersion()); return join(lookup, requirement.getMissingPermissions(empty)); } /** * Creates a {@linkplain PermissionHolder} which combines the permissions * held by the given holder, along with a set of additional permission names */ @NonNull public static PermissionHolder join(@NonNull final PermissionHolder lookup, @Nullable final Set<String> permissions) { if (permissions != null && !permissions.isEmpty()) { return new PermissionHolder() { @Override public boolean hasPermission(@NonNull String permission) { return lookup.hasPermission(permission) || permissions.contains(permission); } @Override public boolean isRevocable(@NonNull String permission) { return lookup.isRevocable(permission); } @NonNull @Override public AndroidVersion getMinSdkVersion() { return lookup.getMinSdkVersion(); } @NonNull @Override public AndroidVersion getTargetSdkVersion() { return lookup.getTargetSdkVersion(); } }; } return lookup; } } }