CarAppPermission.java
/*
* Copyright 2020 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 androidx.car.app;
import static androidx.car.app.utils.LogTags.TAG;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.StringDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Defines all constants for permissions that a car app can use.
*/
public final class CarAppPermission {
/**
* Defines which permissions are ones defined by the car app library.
*
* @hide
*/
@StringDef(value = {ACCESS_SURFACE, NAVIGATION_TEMPLATES})
@Retention(RetentionPolicy.SOURCE)
public @interface LibraryPermission {
}
/**
* Permission that apps can use to get access to a canvas surface.
*
* <p>This surface can be used for drawing custom content like navigation apps can use it to
* draw a map.
*/
public static final String ACCESS_SURFACE = "androidx.car.app.ACCESS_SURFACE";
/**
* Permission that apps can use to get access to the navigation templates of the car app
* library.
*
* <p>This permission should only be declared by apps that belong to one of the categories that
* allow using the navigation templates. See
* <a href="https://developer.android.com/training/cars/apps/navigation#access-navigation-templates">the
* documentation</a> for the list of such categories. An app not in one of those categories
* requesting this permission may be rejected upon submission to the Play Store. See
* {@link CarAppService} for how to declare your app's category.
*/
public static final String NAVIGATION_TEMPLATES = "androidx.car.app.NAVIGATION_TEMPLATES";
/**
* Permission that apps can use to get access to templates that show a map such as
* {@link androidx.car.app.model.PlaceListMapTemplate}. Templates used by navigation apps that
* draw their own maps
* (e.g. {@link androidx.car.app.navigation.model.PlaceListNavigationTemplate}) don't require
* this permission.
*
* <p>This permission should only be declared by apps that belong to one of the categories that
* allow using the map templates. See
* <a href="https://developer.android.com/training/cars/apps/poi#access-map-template">the
* documentation</a> for the list of such categories. An app not in one of those categories
* requesting this permission may be rejected upon submission to the Play Store. See
* {@link CarAppService} for how to declare your app's category.
*/
public static final String MAP_TEMPLATES = "androidx.car.app.MAP_TEMPLATES";
/**
* Checks that the car app has the given {@code permission} granted.
*
* @throws SecurityException if the app does not have a required permission granted
*/
public static void checkHasPermission(@NonNull Context context, @NonNull String permission) {
if (context.getPackageManager().checkPermission(permission, context.getPackageName())
== PackageManager.PERMISSION_GRANTED) {
return;
}
throw new SecurityException(
"The car app does not have the required permission: " + permission);
}
/**
* Checks that the car app has declared the required library {@code permission}.
*
* <p>In contrast to {@link #checkHasPermission}, this method will validate that the app has at
* least declared the permission requested.
*
* @throws SecurityException if the app does not have the required permission declared
*/
public static void checkHasLibraryPermission(
@NonNull Context context, @NonNull @LibraryPermission String permission) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG,
"Checking to see if the car app requested the required library permission: "
+ permission);
}
try {
checkHasPermission(context, permission);
return;
} catch (SecurityException e) {
// Do nothing, we use a fallback for library permissions.
}
// Fallback for devices where permissions may not be granted by the system if the app
// was installed before the host is installed.
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
context.getPackageName(), PackageManager.GET_PERMISSIONS);
if (packageInfo.requestedPermissions != null) {
for (String requestedPermission : packageInfo.requestedPermissions) {
if (requestedPermission.equals(permission)) {
return;
}
}
}
} catch (NameNotFoundException e) {
Log.e(TAG, "Package name not found on the system: " + context.getPackageName(), e);
}
throw new SecurityException(
"The car app does not have a required permission: " + permission);
}
private CarAppPermission() {
}
}