• 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.gnss;
18 
19 import static android.location.LocationManager.GPS_PROVIDER;
20 
21 import static com.android.server.location.LocationPermissions.PERMISSION_FINE;
22 import static com.android.server.location.gnss.GnssManagerService.TAG;
23 
24 import android.annotation.Nullable;
25 import android.location.LocationManagerInternal;
26 import android.location.LocationManagerInternal.ProviderEnabledListener;
27 import android.location.util.identity.CallerIdentity;
28 import android.os.Binder;
29 import android.os.Build;
30 import android.os.IBinder;
31 import android.os.IInterface;
32 import android.os.Process;
33 import android.util.ArraySet;
34 
35 import com.android.internal.util.Preconditions;
36 import com.android.server.LocalServices;
37 import com.android.server.location.injector.AppForegroundHelper;
38 import com.android.server.location.injector.Injector;
39 import com.android.server.location.injector.LocationPermissionsHelper;
40 import com.android.server.location.injector.SettingsHelper;
41 import com.android.server.location.injector.UserInfoHelper;
42 import com.android.server.location.injector.UserInfoHelper.UserListener;
43 import com.android.server.location.listeners.BinderListenerRegistration;
44 import com.android.server.location.listeners.ListenerMultiplexer;
45 
46 import java.util.Collection;
47 import java.util.Objects;
48 
49 /**
50  * Manager for all GNSS related listeners. This class handles deactivating listeners that do not
51  * belong to the current user, that do not have the appropriate permissions, or that are not
52  * currently in the foreground. It will also disable listeners if the GNSS provider is disabled.
53  * Listeners must be registered with the associated IBinder as the key, if the IBinder dies, the
54  * registration will automatically be removed.
55  *
56  * @param <TRequest>            request type
57  * @param <TListener>           listener type
58  * @param <TMergedRegistration> merged registration type
59  */
60 public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInterface,
61         TMergedRegistration> extends
62         ListenerMultiplexer<IBinder, TListener,
63                 GnssListenerMultiplexer<TRequest, TListener, TMergedRegistration>
64                         .GnssListenerRegistration, TMergedRegistration> {
65 
66     /**
67      * Registration object for GNSS listeners.
68      */
69     protected class GnssListenerRegistration extends
70             BinderListenerRegistration<TRequest, TListener> {
71 
72         // we store these values because we don't trust the listeners not to give us dupes, not to
73         // spam us, and because checking the values may be more expensive
74         private boolean mForeground;
75         private boolean mPermitted;
76 
GnssListenerRegistration(@ullable TRequest request, CallerIdentity callerIdentity, TListener listener)77         protected GnssListenerRegistration(@Nullable TRequest request,
78                 CallerIdentity callerIdentity, TListener listener) {
79             super(request, callerIdentity, listener);
80         }
81 
82         @Override
getOwner()83         protected GnssListenerMultiplexer<TRequest, TListener, TMergedRegistration> getOwner() {
84             return GnssListenerMultiplexer.this;
85         }
86 
87         /**
88          * Returns true if this registration is currently in the foreground.
89          */
isForeground()90         public boolean isForeground() {
91             return mForeground;
92         }
93 
isPermitted()94         boolean isPermitted() {
95             return mPermitted;
96         }
97 
98         @Override
onBinderListenerRegister()99         protected final void onBinderListenerRegister() {
100             mPermitted = mLocationPermissionsHelper.hasLocationPermissions(PERMISSION_FINE,
101                     getIdentity());
102             mForeground = mAppForegroundHelper.isAppForeground(getIdentity().getUid());
103 
104             onGnssListenerRegister();
105         }
106 
107         @Override
onBinderListenerUnregister()108         protected final void onBinderListenerUnregister() {
109             onGnssListenerUnregister();
110         }
111 
112         /**
113          * May be overridden in place of {@link #onBinderListenerRegister()}.
114          */
onGnssListenerRegister()115         protected void onGnssListenerRegister() {}
116 
117         /**
118          * May be overridden in place of {@link #onBinderListenerUnregister()}.
119          */
onGnssListenerUnregister()120         protected void onGnssListenerUnregister() {}
121 
onLocationPermissionsChanged(String packageName)122         boolean onLocationPermissionsChanged(String packageName) {
123             if (getIdentity().getPackageName().equals(packageName)) {
124                 return onLocationPermissionsChanged();
125             }
126 
127             return false;
128         }
129 
onLocationPermissionsChanged(int uid)130         boolean onLocationPermissionsChanged(int uid) {
131             if (getIdentity().getUid() == uid) {
132                 return onLocationPermissionsChanged();
133             }
134 
135             return false;
136         }
137 
onLocationPermissionsChanged()138         private boolean onLocationPermissionsChanged() {
139             boolean permitted = mLocationPermissionsHelper.hasLocationPermissions(PERMISSION_FINE,
140                     getIdentity());
141             if (permitted != mPermitted) {
142                 mPermitted = permitted;
143                 return true;
144             }
145 
146             return false;
147         }
148 
onForegroundChanged(int uid, boolean foreground)149         boolean onForegroundChanged(int uid, boolean foreground) {
150             if (getIdentity().getUid() == uid && foreground != mForeground) {
151                 mForeground = foreground;
152                 return true;
153             }
154 
155             return false;
156         }
157 
158         @Override
toString()159         public String toString() {
160             StringBuilder builder = new StringBuilder();
161             builder.append(getIdentity());
162 
163             ArraySet<String> flags = new ArraySet<>(2);
164             if (!mForeground) {
165                 flags.add("bg");
166             }
167             if (!mPermitted) {
168                 flags.add("na");
169             }
170             if (!flags.isEmpty()) {
171                 builder.append(" ").append(flags);
172             }
173 
174             if (getRequest() != null) {
175                 builder.append(" ").append(getRequest());
176             }
177             return builder.toString();
178         }
179     }
180 
181     protected final UserInfoHelper mUserInfoHelper;
182     protected final SettingsHelper mSettingsHelper;
183     protected final LocationPermissionsHelper mLocationPermissionsHelper;
184     protected final AppForegroundHelper mAppForegroundHelper;
185     protected final LocationManagerInternal mLocationManagerInternal;
186 
187     private final UserListener mUserChangedListener = this::onUserChanged;
188     private final ProviderEnabledListener mProviderEnabledChangedListener =
189             this::onProviderEnabledChanged;
190     private final SettingsHelper.GlobalSettingChangedListener
191             mBackgroundThrottlePackageWhitelistChangedListener =
192             this::onBackgroundThrottlePackageWhitelistChanged;
193     private final SettingsHelper.UserSettingChangedListener
194             mLocationPackageBlacklistChangedListener =
195             this::onLocationPackageBlacklistChanged;
196     private final LocationPermissionsHelper.LocationPermissionsListener
197             mLocationPermissionsListener =
198             new LocationPermissionsHelper.LocationPermissionsListener() {
199                 @Override
200                 public void onLocationPermissionsChanged(String packageName) {
201                     GnssListenerMultiplexer.this.onLocationPermissionsChanged(packageName);
202                 }
203 
204                 @Override
205                 public void onLocationPermissionsChanged(int uid) {
206                     GnssListenerMultiplexer.this.onLocationPermissionsChanged(uid);
207                 }
208             };
209     private final AppForegroundHelper.AppForegroundListener mAppForegroundChangedListener =
210             this::onAppForegroundChanged;
211 
GnssListenerMultiplexer(Injector injector)212     protected GnssListenerMultiplexer(Injector injector) {
213         mUserInfoHelper = injector.getUserInfoHelper();
214         mSettingsHelper = injector.getSettingsHelper();
215         mLocationPermissionsHelper = injector.getLocationPermissionsHelper();
216         mAppForegroundHelper = injector.getAppForegroundHelper();
217         mLocationManagerInternal = Objects.requireNonNull(
218                 LocalServices.getService(LocationManagerInternal.class));
219     }
220 
221     @Override
getTag()222     public String getTag() {
223         return TAG;
224     }
225 
226     /**
227      * May be overridden by subclasses to return whether the service is supported or not. This value
228      * should never change for the lifetime of the multiplexer. If the service is unsupported, all
229      * registrations will be treated as inactive and the backing service will never be registered.
230      *
231      */
isSupported()232     public boolean isSupported() {
233         return true;
234     }
235 
236     /**
237      * Adds a listener with the given identity.
238      */
addListener(CallerIdentity identity, TListener listener)239     protected void addListener(CallerIdentity identity, TListener listener) {
240         addListener(null, identity, listener);
241     }
242 
243     /**
244      * Adds a listener with the given identity and request.
245      */
addListener(TRequest request, CallerIdentity callerIdentity, TListener listener)246     protected void addListener(TRequest request, CallerIdentity callerIdentity,
247             TListener listener) {
248         final long identity = Binder.clearCallingIdentity();
249         try {
250             putRegistration(listener.asBinder(),
251                     createRegistration(request, callerIdentity, listener));
252         } finally {
253             Binder.restoreCallingIdentity(identity);
254         }
255     }
256 
257     /**
258      * May be overridden by subclasses to change the registration type.
259      */
createRegistration(TRequest request, CallerIdentity callerIdentity, TListener listener)260     protected GnssListenerRegistration createRegistration(TRequest request,
261             CallerIdentity callerIdentity, TListener listener) {
262         return new GnssListenerRegistration(request, callerIdentity, listener);
263     }
264 
265     /**
266      * Removes the given listener.
267      */
removeListener(TListener listener)268     public void removeListener(TListener listener) {
269         final long identity = Binder.clearCallingIdentity();
270         try {
271             removeRegistration(listener.asBinder());
272         } finally {
273             Binder.restoreCallingIdentity(identity);
274         }
275     }
276 
277     @Override
isActive(GnssListenerRegistration registration)278     protected boolean isActive(GnssListenerRegistration registration) {
279         if (!isSupported()) {
280             return false;
281         }
282 
283         CallerIdentity identity = registration.getIdentity();
284         return registration.isPermitted()
285                 && (registration.isForeground() || isBackgroundRestrictionExempt(identity))
286                 && isActive(identity);
287     }
288 
isActive(CallerIdentity identity)289     private boolean isActive(CallerIdentity identity) {
290         if (identity.isSystemServer()) {
291             if (!mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER,
292                     mUserInfoHelper.getCurrentUserId())) {
293                 return false;
294             }
295         } else {
296             if (!mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER,
297                     identity.getUserId())) {
298                 return false;
299             }
300             if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
301                 return false;
302             }
303             if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
304                     identity.getPackageName())) {
305                 return false;
306             }
307         }
308 
309         return true;
310     }
311 
isBackgroundRestrictionExempt(CallerIdentity identity)312     private boolean isBackgroundRestrictionExempt(CallerIdentity identity) {
313         if (identity.getUid() == Process.SYSTEM_UID) {
314             return true;
315         }
316 
317         if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
318                 identity.getPackageName())) {
319             return true;
320         }
321 
322         return mLocationManagerInternal.isProvider(null, identity);
323     }
324 
325     // this provides a default implementation for all further subclasses which assumes that there is
326     // never an associated request object, and thus nothing interesting to merge. the majority of
327     // gnss listener multiplexers do not current have associated requests, and the ones that do can
328     // override this implementation.
mergeRegistrations( Collection<GnssListenerRegistration> gnssListenerRegistrations)329     protected TMergedRegistration mergeRegistrations(
330             Collection<GnssListenerRegistration> gnssListenerRegistrations) {
331         if (Build.IS_DEBUGGABLE) {
332             for (GnssListenerRegistration registration : gnssListenerRegistrations) {
333                 Preconditions.checkState(registration.getRequest() == null);
334             }
335         }
336 
337         return null;
338     }
339 
340     @Override
onRegister()341     protected void onRegister() {
342         if (!isSupported()) {
343             return;
344         }
345 
346         mUserInfoHelper.addListener(mUserChangedListener);
347         mLocationManagerInternal.addProviderEnabledListener(GPS_PROVIDER,
348                 mProviderEnabledChangedListener);
349         mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener(
350                 mBackgroundThrottlePackageWhitelistChangedListener);
351         mSettingsHelper.addOnLocationPackageBlacklistChangedListener(
352                 mLocationPackageBlacklistChangedListener);
353         mLocationPermissionsHelper.addListener(mLocationPermissionsListener);
354         mAppForegroundHelper.addListener(mAppForegroundChangedListener);
355     }
356 
357     @Override
onUnregister()358     protected void onUnregister() {
359         if (!isSupported()) {
360             return;
361         }
362 
363         mUserInfoHelper.removeListener(mUserChangedListener);
364         mLocationManagerInternal.removeProviderEnabledListener(GPS_PROVIDER,
365                 mProviderEnabledChangedListener);
366         mSettingsHelper.removeOnBackgroundThrottlePackageWhitelistChangedListener(
367                 mBackgroundThrottlePackageWhitelistChangedListener);
368         mSettingsHelper.removeOnLocationPackageBlacklistChangedListener(
369                 mLocationPackageBlacklistChangedListener);
370         mLocationPermissionsHelper.removeListener(mLocationPermissionsListener);
371         mAppForegroundHelper.removeListener(mAppForegroundChangedListener);
372     }
373 
onUserChanged(int userId, int change)374     private void onUserChanged(int userId, int change) {
375         if (change == UserListener.CURRENT_USER_CHANGED) {
376             updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
377         }
378     }
379 
onProviderEnabledChanged(String provider, int userId, boolean enabled)380     private void onProviderEnabledChanged(String provider, int userId, boolean enabled) {
381         Preconditions.checkState(GPS_PROVIDER.equals(provider));
382         updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
383     }
384 
onBackgroundThrottlePackageWhitelistChanged()385     private void onBackgroundThrottlePackageWhitelistChanged() {
386         updateRegistrations(registration -> true);
387     }
388 
onLocationPackageBlacklistChanged(int userId)389     private void onLocationPackageBlacklistChanged(int userId) {
390         updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
391     }
392 
onLocationPermissionsChanged(String packageName)393     private void onLocationPermissionsChanged(String packageName) {
394         updateRegistrations(registration -> registration.onLocationPermissionsChanged(packageName));
395     }
396 
onLocationPermissionsChanged(int uid)397     private void onLocationPermissionsChanged(int uid) {
398         updateRegistrations(registration -> registration.onLocationPermissionsChanged(uid));
399     }
400 
onAppForegroundChanged(int uid, boolean foreground)401     private void onAppForegroundChanged(int uid, boolean foreground) {
402         updateRegistrations(registration -> registration.onForegroundChanged(uid, foreground));
403     }
404 
405     @Override
getServiceState()406     protected String getServiceState() {
407         if (!isSupported()) {
408             return "unsupported";
409         } else {
410             return super.getServiceState();
411         }
412     }
413 }
414