• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.location.injector;
18 
19 import static com.android.server.location.LocationPermissions.PERMISSION_NONE;
20 
21 import android.location.util.identity.CallerIdentity;
22 
23 import com.android.server.location.LocationPermissions;
24 import com.android.server.location.LocationPermissions.PermissionLevel;
25 
26 import java.util.concurrent.CopyOnWriteArrayList;
27 
28 /**
29  * Provides helpers and listeners for appops.
30  */
31 public abstract class LocationPermissionsHelper {
32 
33     /**
34      * Listener for current user changes.
35      */
36     public interface LocationPermissionsListener {
37 
38         /**
39          * Called when something has changed about location permissions for the given package.
40          */
onLocationPermissionsChanged(String packageName)41         void onLocationPermissionsChanged(String packageName);
42 
43         /**
44          * Called when something has changed about location permissions for the given uid.
45          */
onLocationPermissionsChanged(int uid)46         void onLocationPermissionsChanged(int uid);
47     }
48 
49     private final CopyOnWriteArrayList<LocationPermissionsListener> mListeners;
50     private final AppOpsHelper mAppOps;
51 
LocationPermissionsHelper(AppOpsHelper appOps)52     public LocationPermissionsHelper(AppOpsHelper appOps) {
53         mListeners = new CopyOnWriteArrayList<>();
54         mAppOps = appOps;
55 
56         mAppOps.addListener(this::onAppOpsChanged);
57     }
58 
notifyLocationPermissionsChanged(String packageName)59     protected final void notifyLocationPermissionsChanged(String packageName) {
60         for (LocationPermissionsListener listener : mListeners) {
61             listener.onLocationPermissionsChanged(packageName);
62         }
63     }
64 
notifyLocationPermissionsChanged(int uid)65     protected final void notifyLocationPermissionsChanged(int uid) {
66         for (LocationPermissionsListener listener : mListeners) {
67             listener.onLocationPermissionsChanged(uid);
68         }
69     }
70 
onAppOpsChanged(String packageName)71     private void onAppOpsChanged(String packageName) {
72         notifyLocationPermissionsChanged(packageName);
73     }
74 
75     /**
76      * Adds a listener for location permissions events. Callbacks occur on an unspecified thread.
77      */
addListener(LocationPermissionsListener listener)78     public final void addListener(LocationPermissionsListener listener) {
79         mListeners.add(listener);
80     }
81 
82     /**
83      * Removes a listener for location permissions events.
84      */
removeListener(LocationPermissionsListener listener)85     public final void removeListener(LocationPermissionsListener listener) {
86         mListeners.remove(listener);
87     }
88 
89     /**
90      * Returns true if the given identity may access location at the given permissions level, taking
91      * into account both permissions and appops.
92      */
hasLocationPermissions(@ermissionLevel int permissionLevel, CallerIdentity identity)93     public final boolean hasLocationPermissions(@PermissionLevel int permissionLevel,
94             CallerIdentity identity) {
95         if (permissionLevel == PERMISSION_NONE) {
96             return false;
97         }
98 
99         if (!hasPermission(LocationPermissions.asPermission(permissionLevel), identity)) {
100             return false;
101         }
102 
103         return mAppOps.checkOpNoThrow(permissionLevel, identity);
104     }
105 
hasPermission(String permission, CallerIdentity callerIdentity)106     protected abstract boolean hasPermission(String permission, CallerIdentity callerIdentity);
107 }
108