1 /*
2  * Copyright (C) 2021 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.ambientcontext;
18 
19 import static android.provider.DeviceConfig.NAMESPACE_AMBIENT_CONTEXT_MANAGER_SERVICE;
20 import static android.provider.DeviceConfig.NAMESPACE_WEARABLE_SENSING;
21 
22 import android.Manifest;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.UserIdInt;
26 import android.app.PendingIntent;
27 import android.app.ambientcontext.AmbientContextEvent;
28 import android.app.ambientcontext.AmbientContextEventRequest;
29 import android.app.ambientcontext.AmbientContextManager;
30 import android.app.ambientcontext.IAmbientContextManager;
31 import android.app.ambientcontext.IAmbientContextObserver;
32 import android.content.ComponentName;
33 import android.content.Context;
34 import android.content.pm.PackageManagerInternal;
35 import android.os.RemoteCallback;
36 import android.os.RemoteException;
37 import android.os.ResultReceiver;
38 import android.os.ShellCallback;
39 import android.os.UserHandle;
40 import android.provider.DeviceConfig;
41 import android.util.ArraySet;
42 import android.util.Slog;
43 
44 import com.android.internal.R;
45 import com.android.internal.util.DumpUtils;
46 import com.android.server.LocalServices;
47 import com.android.server.SystemService;
48 import com.android.server.ambientcontext.AmbientContextManagerPerUserService.ServiceType;
49 import com.android.server.infra.AbstractMasterSystemService;
50 import com.android.server.infra.FrameworkResourcesServiceNameResolver;
51 import com.android.server.pm.KnownPackages;
52 
53 import com.google.android.collect.Sets;
54 
55 import java.io.FileDescriptor;
56 import java.io.PrintWriter;
57 import java.util.ArrayList;
58 import java.util.Arrays;
59 import java.util.HashSet;
60 import java.util.List;
61 import java.util.Objects;
62 import java.util.Set;
63 import java.util.concurrent.ConcurrentHashMap;
64 
65 /**
66  * System service for managing {@link AmbientContextEvent}s.
67  */
68 public class AmbientContextManagerService extends
69         AbstractMasterSystemService<AmbientContextManagerService,
70                 AmbientContextManagerPerUserService> {
71     private static final String TAG = AmbientContextManagerService.class.getSimpleName();
72     private static final String KEY_SERVICE_ENABLED = "service_enabled";
73     private static final Set<Integer> DEFAULT_EVENT_SET = Sets.newHashSet(
74             AmbientContextEvent.EVENT_COUGH,
75             AmbientContextEvent.EVENT_SNORE,
76             AmbientContextEvent.EVENT_BACK_DOUBLE_TAP);
77 
78     /** Default value in absence of {@link DeviceConfig} override. */
79     private static final boolean DEFAULT_SERVICE_ENABLED = true;
80     public static final int MAX_TEMPORARY_SERVICE_DURATION_MS = 30000;
81 
82     static class ClientRequest {
83         private final int mUserId;
84         private final AmbientContextEventRequest mRequest;
85         private final String mPackageName;
86         private final IAmbientContextObserver mObserver;
87 
ClientRequest(int userId, AmbientContextEventRequest request, String packageName, IAmbientContextObserver observer)88         ClientRequest(int userId, AmbientContextEventRequest request,
89                 String packageName, IAmbientContextObserver observer) {
90             this.mUserId = userId;
91             this.mRequest = request;
92             this.mPackageName = packageName;
93             this.mObserver = observer;
94         }
95 
getPackageName()96         String getPackageName() {
97             return mPackageName;
98         }
99 
getRequest()100         AmbientContextEventRequest getRequest() {
101             return mRequest;
102         }
103 
getObserver()104         IAmbientContextObserver getObserver() {
105             return mObserver;
106         }
107 
hasUserId(int userId)108         boolean hasUserId(int userId) {
109             return mUserId == userId;
110         }
111 
hasUserIdAndPackageName(int userId, String packageName)112         boolean hasUserIdAndPackageName(int userId, String packageName) {
113             return (userId == mUserId) && packageName.equals(getPackageName());
114         }
115     }
116 
117     private final Context mContext;
118     boolean mIsServiceEnabled;
119     boolean mIsWearableServiceEnabled;
120     private Set<ClientRequest> mExistingClientRequests;
121 
AmbientContextManagerService(Context context)122     public AmbientContextManagerService(Context context) {
123         super(context,
124                 new FrameworkResourcesServiceNameResolver(
125                         context,
126                         R.array.config_defaultAmbientContextServices,
127                         /*isMultiple=*/ true),
128                 /*disallowProperty=*/null,
129                 PACKAGE_UPDATE_POLICY_REFRESH_EAGER
130                         | /*To avoid high latency*/ PACKAGE_RESTART_POLICY_REFRESH_EAGER);
131         mContext = context;
132         mExistingClientRequests = new ArraySet<>();
133     }
134 
135     @Override
onStart()136     public void onStart() {
137         publishBinderService(Context.AMBIENT_CONTEXT_SERVICE, new AmbientContextManagerInternal());
138     }
139 
140     @Override
onBootPhase(int phase)141     public void onBootPhase(int phase) {
142         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
143             DeviceConfig.addOnPropertiesChangedListener(
144                     NAMESPACE_AMBIENT_CONTEXT_MANAGER_SERVICE,
145                     getContext().getMainExecutor(),
146                     (properties) -> onDeviceConfigChange(properties.getKeyset()));
147 
148             mIsServiceEnabled = DeviceConfig.getBoolean(
149                     NAMESPACE_AMBIENT_CONTEXT_MANAGER_SERVICE,
150                     KEY_SERVICE_ENABLED, DEFAULT_SERVICE_ENABLED);
151             mIsWearableServiceEnabled = DeviceConfig.getBoolean(
152                     NAMESPACE_WEARABLE_SENSING,
153                     KEY_SERVICE_ENABLED, DEFAULT_SERVICE_ENABLED);
154         }
155     }
156 
newClientAdded(int userId, AmbientContextEventRequest request, String callingPackage, IAmbientContextObserver observer)157     void newClientAdded(int userId, AmbientContextEventRequest request,
158             String callingPackage, IAmbientContextObserver observer) {
159         Slog.d(TAG, "New client added: " + callingPackage);
160 
161         // Remove any existing ClientRequest for this user and package.
162         mExistingClientRequests.removeAll(
163                 findExistingRequests(userId, callingPackage));
164 
165         // Add to existing ClientRequests
166         mExistingClientRequests.add(
167                 new ClientRequest(userId, request, callingPackage, observer));
168     }
169 
clientRemoved(int userId, String packageName)170     void clientRemoved(int userId, String packageName) {
171         Slog.d(TAG, "Remove client: " + packageName);
172         mExistingClientRequests.removeAll(findExistingRequests(userId, packageName));
173     }
174 
findExistingRequests(int userId, String packageName)175     private Set<ClientRequest> findExistingRequests(int userId, String packageName) {
176         Set<ClientRequest> existingRequests = new ArraySet<>();
177         for (ClientRequest clientRequest : mExistingClientRequests) {
178             if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
179                 existingRequests.add(clientRequest);
180             }
181         }
182         return existingRequests;
183     }
184 
185     @Nullable
getClientRequestObserver(int userId, String packageName)186     IAmbientContextObserver getClientRequestObserver(int userId, String packageName) {
187         for (ClientRequest clientRequest : mExistingClientRequests) {
188             if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
189                 return clientRequest.getObserver();
190             }
191         }
192         return null;
193     }
194 
onDeviceConfigChange(@onNull Set<String> keys)195     private void onDeviceConfigChange(@NonNull Set<String> keys) {
196         if (keys.contains(KEY_SERVICE_ENABLED)) {
197             mIsServiceEnabled = DeviceConfig.getBoolean(
198                     NAMESPACE_AMBIENT_CONTEXT_MANAGER_SERVICE,
199                     KEY_SERVICE_ENABLED, DEFAULT_SERVICE_ENABLED);
200             mIsWearableServiceEnabled = DeviceConfig.getBoolean(
201                     NAMESPACE_WEARABLE_SENSING,
202                     KEY_SERVICE_ENABLED, DEFAULT_SERVICE_ENABLED);
203         }
204     }
205 
206     @Override
newServiceLocked(int resolvedUserId, boolean disabled)207     protected AmbientContextManagerPerUserService newServiceLocked(int resolvedUserId,
208             boolean disabled) {
209         // This service uses newServiceListLocked, it is configured in multiple mode.
210         return null;
211     }
212 
213     @Override // from AbstractMasterSystemService
newServiceListLocked(int resolvedUserId, boolean disabled, String[] serviceNames)214     protected List<AmbientContextManagerPerUserService> newServiceListLocked(int resolvedUserId,
215             boolean disabled, String[] serviceNames) {
216         if (serviceNames == null || serviceNames.length == 0) {
217             Slog.i(TAG, "serviceNames sent in newServiceListLocked is null, or empty");
218             return new ArrayList<>();
219         }
220 
221         List<AmbientContextManagerPerUserService> serviceList =
222                 new ArrayList<>(serviceNames.length);
223         if (serviceNames.length == 2) {
224             Slog.i(TAG, "Not using default services, "
225                     + "services provided for testing should be exactly two services.");
226             if (!isDefaultService(serviceNames[0]) && !isDefaultWearableService(serviceNames[1])) {
227                 serviceList.add(new DefaultAmbientContextManagerPerUserService(
228                         this, mLock, resolvedUserId,
229                         AmbientContextManagerPerUserService.ServiceType.DEFAULT, serviceNames[0]));
230                 serviceList.add(new WearableAmbientContextManagerPerUserService(
231                         this, mLock, resolvedUserId,
232                         AmbientContextManagerPerUserService.ServiceType.WEARABLE,
233                         serviceNames[1]));
234             }
235             return serviceList;
236         } else {
237             Slog.i(TAG, "Incorrect number of services provided for testing.");
238         }
239 
240         for (String serviceName : serviceNames) {
241             Slog.d(TAG, "newServicesListLocked with service name: " + serviceName);
242             if (getServiceType(serviceName)
243                     == AmbientContextManagerPerUserService.ServiceType.WEARABLE) {
244                 serviceList.add(new
245                         WearableAmbientContextManagerPerUserService(
246                         this, mLock, resolvedUserId,
247                         AmbientContextManagerPerUserService.ServiceType.WEARABLE, serviceName));
248             } else {
249                 serviceList.add(new DefaultAmbientContextManagerPerUserService(
250                         this, mLock, resolvedUserId,
251                         AmbientContextManagerPerUserService.ServiceType.DEFAULT, serviceName));
252             }
253 
254         }
255         return serviceList;
256     }
257 
258     @Override
onServiceRemoved( AmbientContextManagerPerUserService service, @UserIdInt int userId)259     protected void onServiceRemoved(
260             AmbientContextManagerPerUserService service, @UserIdInt int userId) {
261         Slog.d(TAG, "onServiceRemoved");
262         service.destroyLocked();
263     }
264 
265     @Override
onServicePackageRestartedLocked(@serIdInt int userId)266     protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
267         Slog.d(TAG, "Restoring remote request. Reason: Service package restarted.");
268         restorePreviouslyEnabledClients(userId);
269     }
270 
271     @Override
onServicePackageUpdatedLocked(@serIdInt int userId)272     protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
273         Slog.d(TAG, "Restoring remote request. Reason: Service package updated.");
274         restorePreviouslyEnabledClients(userId);
275     }
276 
277     @Override
enforceCallingPermissionForManagement()278     protected void enforceCallingPermissionForManagement() {
279         getContext().enforceCallingPermission(
280                 Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
281     }
282 
283     @Override
getMaximumTemporaryServiceDurationMs()284     protected int getMaximumTemporaryServiceDurationMs() {
285         return MAX_TEMPORARY_SERVICE_DURATION_MS;
286     }
287 
288     /** Returns {@code true} if the detection service is configured on this device. */
isDetectionServiceConfigured()289     public static boolean isDetectionServiceConfigured() {
290         final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
291         final String[] packageNames = pmi.getKnownPackageNames(
292                 KnownPackages.PACKAGE_AMBIENT_CONTEXT_DETECTION, UserHandle.USER_SYSTEM);
293         boolean isServiceConfigured = (packageNames.length != 0);
294         Slog.i(TAG, "Detection service configured: " + isServiceConfigured);
295         return isServiceConfigured;
296     }
297 
298     /**
299      * Send request to the remote AmbientContextDetectionService impl to start detecting the
300      * specified events. Intended for use by shell command for testing.
301      * Requires ACCESS_AMBIENT_CONTEXT_EVENT permission.
302      */
startDetection(@serIdInt int userId, AmbientContextEventRequest request, String packageName, IAmbientContextObserver observer)303     void startDetection(@UserIdInt int userId, AmbientContextEventRequest request,
304             String packageName, IAmbientContextObserver observer) {
305         mContext.enforceCallingOrSelfPermission(
306                 Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
307         synchronized (mLock) {
308             AmbientContextManagerPerUserService service =
309                     getAmbientContextManagerPerUserServiceForEventTypes(
310                             userId,
311                             request.getEventTypes());
312             if (service != null) {
313                 service.startDetection(request, packageName, observer);
314             } else {
315                 Slog.i(TAG, "service not available for user_id: " + userId);
316             }
317         }
318     }
319 
320     /**
321      * Send request to the remote AmbientContextDetectionService impl to stop detecting the
322      * specified events. Intended for use by shell command for testing.
323      * Requires ACCESS_AMBIENT_CONTEXT_EVENT permission.
324      */
stopAmbientContextEvent(@serIdInt int userId, String packageName)325     void stopAmbientContextEvent(@UserIdInt int userId, String packageName) {
326         mContext.enforceCallingOrSelfPermission(
327                 Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
328         synchronized (mLock) {
329             for (ClientRequest cr : mExistingClientRequests) {
330                 Slog.i(TAG, "Looping through clients");
331                 if (cr.hasUserIdAndPackageName(userId, packageName)) {
332                     Slog.i(TAG, "we have an existing client");
333                     AmbientContextManagerPerUserService service =
334                             getAmbientContextManagerPerUserServiceForEventTypes(
335                                     userId, cr.getRequest().getEventTypes());
336                     if (service != null) {
337                         service.stopDetection(packageName);
338                     } else {
339                         Slog.i(TAG, "service not available for user_id: " + userId);
340                     }
341                 }
342             }
343         }
344     }
345 
346     /**
347      * Send request to the remote AmbientContextDetectionService impl to query the status of the
348      * specified events. Intended for use by shell command for testing.
349      * Requires ACCESS_AMBIENT_CONTEXT_EVENT permission.
350      */
queryServiceStatus(@serIdInt int userId, String packageName, int[] eventTypes, RemoteCallback callback)351     void queryServiceStatus(@UserIdInt int userId, String packageName,
352             int[] eventTypes, RemoteCallback callback) {
353         mContext.enforceCallingOrSelfPermission(
354                 Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
355         synchronized (mLock) {
356             AmbientContextManagerPerUserService service =
357                     getAmbientContextManagerPerUserServiceForEventTypes(
358                             userId, intArrayToIntegerSet(eventTypes));
359             if (service != null) {
360                 service.onQueryServiceStatus(eventTypes, packageName, callback);
361             } else {
362                 Slog.i(TAG, "query service not available for user_id: " + userId);
363             }
364         }
365     }
366 
restorePreviouslyEnabledClients(int userId)367     private void restorePreviouslyEnabledClients(int userId) {
368         synchronized (mLock) {
369             final List<AmbientContextManagerPerUserService> services =
370                     getServiceListForUserLocked(userId);
371             for (AmbientContextManagerPerUserService service : services) {
372                 for (ClientRequest clientRequest : mExistingClientRequests) {
373                     // Start detection for previously enabled clients
374                     if (clientRequest.hasUserId(userId)) {
375                         Slog.d(TAG, "Restoring detection for "
376                                 + clientRequest.getPackageName());
377                         service.startDetection(clientRequest.getRequest(),
378                                 clientRequest.getPackageName(),
379                                 clientRequest.getObserver());
380                     }
381                 }
382             }
383         }
384     }
385 
386     /**
387      * Returns the AmbientContextManagerPerUserService component for this user.
388      */
getComponentName( @serIdInt int userId, AmbientContextManagerPerUserService.ServiceType serviceType)389     public ComponentName getComponentName(
390             @UserIdInt int userId,
391             AmbientContextManagerPerUserService.ServiceType serviceType) {
392         synchronized (mLock) {
393             final AmbientContextManagerPerUserService service =
394                     getServiceForType(userId, serviceType);
395             if (service != null) {
396                 return service.getComponentName();
397             }
398         }
399         return null;
400     }
401 
getAmbientContextManagerPerUserServiceForEventTypes( @serIdInt int userId, Set<Integer> eventTypes)402     private AmbientContextManagerPerUserService getAmbientContextManagerPerUserServiceForEventTypes(
403               @UserIdInt int userId, Set<Integer> eventTypes) {
404         if (isWearableEventTypesOnly(eventTypes)) {
405             return getServiceForType(userId,
406                     AmbientContextManagerPerUserService.ServiceType.WEARABLE);
407         } else {
408             return getServiceForType(userId,
409                     AmbientContextManagerPerUserService.ServiceType.DEFAULT);
410         }
411     }
412 
getServiceType(String serviceName)413     private AmbientContextManagerPerUserService.ServiceType getServiceType(String serviceName) {
414         final String wearableService = mContext.getResources()
415                 .getString(R.string.config_defaultWearableSensingService);
416         if (wearableService != null && wearableService.equals(serviceName)) {
417             return AmbientContextManagerPerUserService.ServiceType.WEARABLE;
418         }
419 
420         return AmbientContextManagerPerUserService.ServiceType.DEFAULT;
421     }
422 
isDefaultService(String serviceName)423     private boolean isDefaultService(String serviceName) {
424         final String defaultService = mContext.getResources()
425                 .getString(R.string.config_defaultAmbientContextDetectionService);
426         if (defaultService != null && defaultService.equals(serviceName)) {
427             return true;
428         }
429         return false;
430     }
431 
isDefaultWearableService(String serviceName)432     private boolean isDefaultWearableService(String serviceName) {
433         final String wearableService = mContext.getResources()
434                 .getString(R.string.config_defaultWearableSensingService);
435         if (wearableService != null && wearableService.equals(serviceName)) {
436             return true;
437         }
438         return false;
439     }
440 
getServiceForType(int userId, AmbientContextManagerPerUserService.ServiceType serviceType)441     private AmbientContextManagerPerUserService getServiceForType(int userId,
442             AmbientContextManagerPerUserService.ServiceType serviceType) {
443         Slog.d(TAG, "getServiceForType with userid: "
444                 + userId + " service type: " + serviceType.name());
445         synchronized (mLock) {
446             final List<AmbientContextManagerPerUserService> services =
447                     getServiceListForUserLocked(userId);
448             Slog.d(TAG, "Services that are available: "
449                     + (services == null ? "null services" : services.size()
450                     + " number of services"));
451             if (services == null) {
452                 return null;
453             }
454 
455             for (AmbientContextManagerPerUserService service : services) {
456                 if (service.getServiceType() == serviceType) {
457                     return service;
458                 }
459             }
460         }
461         return null;
462     }
463 
isWearableEventTypesOnly(Set<Integer> eventTypes)464     private boolean isWearableEventTypesOnly(Set<Integer> eventTypes) {
465         if (eventTypes.isEmpty()) {
466             Slog.d(TAG, "empty event types.");
467             return false;
468         }
469         for (Integer eventType : eventTypes) {
470             if (eventType < AmbientContextEvent.EVENT_VENDOR_WEARABLE_START) {
471                 Slog.d(TAG, "Not all events types are wearable events.");
472                 return false;
473             }
474         }
475         Slog.d(TAG, "only wearable events.");
476         return true;
477     }
478 
isWearableEventTypesOnly(int[] eventTypes)479     private boolean isWearableEventTypesOnly(int[] eventTypes) {
480         Integer[] events = intArrayToIntegerArray(eventTypes);
481         return isWearableEventTypesOnly(new HashSet<>(Arrays.asList(events)));
482     }
483 
containsMixedEvents(int[] eventTypes)484     private boolean containsMixedEvents(int[] eventTypes) {
485         if (isWearableEventTypesOnly(eventTypes)) {
486             return false;
487         }
488         // It's not only wearable events so check if it's only default events.
489         for (Integer event : eventTypes) {
490             if (!DEFAULT_EVENT_SET.contains(event)) {
491                 // mixed events.
492                 Slog.w(TAG, "Received mixed event types, this is not supported.");
493                 return true;
494             }
495         }
496         // Only default events.
497         return false;
498     }
499 
integerSetToIntArray(@onNull Set<Integer> integerSet)500     private static int[] integerSetToIntArray(@NonNull Set<Integer> integerSet) {
501         int[] intArray = new int[integerSet.size()];
502         int i = 0;
503         for (Integer type : integerSet) {
504             intArray[i++] = type;
505         }
506         return intArray;
507     }
508 
intArrayToIntegerSet(int[] eventTypes)509     private Set<Integer> intArrayToIntegerSet(int[] eventTypes) {
510         Set<Integer> types = new HashSet<>();
511         for (Integer i : eventTypes) {
512             types.add(i);
513         }
514         return types;
515     }
516 
517     @NonNull
intArrayToIntegerArray(@onNull int[] integerSet)518     private static Integer[] intArrayToIntegerArray(@NonNull int[] integerSet) {
519         Integer[] intArray = new Integer[integerSet.length];
520         int i = 0;
521         for (Integer type : integerSet) {
522             intArray[i++] = type;
523         }
524         return intArray;
525     }
526 
527     private final class AmbientContextManagerInternal extends IAmbientContextManager.Stub {
528         @Override
registerObserver( AmbientContextEventRequest request, PendingIntent resultPendingIntent, RemoteCallback statusCallback)529         public void registerObserver(
530                 AmbientContextEventRequest request, PendingIntent resultPendingIntent,
531                 RemoteCallback statusCallback) {
532             Objects.requireNonNull(request);
533             Objects.requireNonNull(resultPendingIntent);
534             Objects.requireNonNull(statusCallback);
535             AmbientContextManagerPerUserService service =
536                     getAmbientContextManagerPerUserServiceForEventTypes(
537                             UserHandle.getCallingUserId(),
538                             request.getEventTypes());
539             // Wrap the PendingIntent and statusCallback in a IAmbientContextObserver to make the
540             // code unified
541             IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
542                 @Override
543                 public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
544                     service.sendDetectionResultIntent(resultPendingIntent, events);
545                 }
546 
547                 @Override
548                 public void onRegistrationComplete(int statusCode) throws RemoteException {
549                     service.sendStatusCallback(statusCallback,
550                             statusCode);
551                 }
552             };
553             registerObserverWithCallback(request, resultPendingIntent.getCreatorPackage(),
554                     observer);
555         }
556 
557         /**
558          * Register an observer for Ambient Context events.
559          */
560         @Override
registerObserverWithCallback(AmbientContextEventRequest request, String packageName, IAmbientContextObserver observer)561         public void registerObserverWithCallback(AmbientContextEventRequest request,
562                 String packageName,
563                 IAmbientContextObserver observer) {
564             Slog.i(TAG, "AmbientContextManagerService registerObserverWithCallback.");
565             Objects.requireNonNull(request);
566             Objects.requireNonNull(packageName);
567             Objects.requireNonNull(observer);
568             mContext.enforceCallingOrSelfPermission(
569                     Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
570             assertCalledByPackageOwner(packageName);
571 
572             AmbientContextManagerPerUserService service =
573                     getAmbientContextManagerPerUserServiceForEventTypes(
574                             UserHandle.getCallingUserId(),
575                             request.getEventTypes());
576             if (service == null) {
577                 Slog.w(TAG, "onRegisterObserver unavailable user_id: "
578                         + UserHandle.getCallingUserId());
579                 return;
580             }
581 
582             int statusCode = checkStatusCode(
583                     service, integerSetToIntArray(request.getEventTypes()));
584             if (statusCode == AmbientContextManager.STATUS_SUCCESS) {
585                 service.onRegisterObserver(request, packageName, observer);
586             } else {
587                 service.completeRegistration(observer, statusCode);
588             }
589         }
590 
591         @Override
unregisterObserver(String callingPackage)592         public void unregisterObserver(String callingPackage) {
593             mContext.enforceCallingOrSelfPermission(
594                     Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
595             assertCalledByPackageOwner(callingPackage);
596 
597             synchronized (mLock) {
598                 for (ClientRequest cr : mExistingClientRequests) {
599                     if ((cr != null) && cr.getPackageName().equals(callingPackage)) {
600                         AmbientContextManagerPerUserService service =
601                                 getAmbientContextManagerPerUserServiceForEventTypes(
602                                         UserHandle.getCallingUserId(),
603                                         cr.getRequest().getEventTypes());
604                         if (service != null) {
605                             service.onUnregisterObserver(callingPackage);
606                         } else {
607                             Slog.w(TAG, "onUnregisterObserver unavailable user_id: "
608                                     + UserHandle.getCallingUserId());
609                         }
610                     }
611                 }
612             }
613         }
614 
615         @Override
queryServiceStatus(int[] eventTypes, String callingPackage, RemoteCallback statusCallback)616         public void queryServiceStatus(int[] eventTypes, String callingPackage,
617                 RemoteCallback statusCallback) {
618             Objects.requireNonNull(eventTypes);
619             Objects.requireNonNull(callingPackage);
620             Objects.requireNonNull(statusCallback);
621             mContext.enforceCallingOrSelfPermission(
622                     Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
623             assertCalledByPackageOwner(callingPackage);
624             synchronized (mLock) {
625                 AmbientContextManagerPerUserService service =
626                         getAmbientContextManagerPerUserServiceForEventTypes(
627                                 UserHandle.getCallingUserId(), intArrayToIntegerSet(eventTypes));
628                 if (service == null) {
629                     Slog.w(TAG, "queryServiceStatus unavailable user_id: "
630                             + UserHandle.getCallingUserId());
631                     return;
632                 }
633 
634                 int statusCode = checkStatusCode(service, eventTypes);
635                 if (statusCode == AmbientContextManager.STATUS_SUCCESS) {
636                     service.onQueryServiceStatus(eventTypes, callingPackage,
637                             statusCallback);
638                 } else {
639                     service.sendStatusCallback(statusCallback, statusCode);
640                 }
641             }
642         }
643 
644         @Override
startConsentActivity(int[] eventTypes, String callingPackage)645         public void startConsentActivity(int[] eventTypes, String callingPackage) {
646             Objects.requireNonNull(eventTypes);
647             Objects.requireNonNull(callingPackage);
648             assertCalledByPackageOwner(callingPackage);
649             mContext.enforceCallingOrSelfPermission(
650                     Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
651 
652             if (containsMixedEvents(eventTypes)) {
653                 Slog.d(TAG, "AmbientContextEventRequest contains mixed events,"
654                         + " this is not supported.");
655                 return;
656             }
657 
658             AmbientContextManagerPerUserService service =
659                     getAmbientContextManagerPerUserServiceForEventTypes(
660                             UserHandle.getCallingUserId(), intArrayToIntegerSet(eventTypes));
661 
662             if (service != null) {
663                 service.onStartConsentActivity(eventTypes, callingPackage);
664             } else {
665                 Slog.w(TAG, "startConsentActivity unavailable user_id: "
666                         + UserHandle.getCallingUserId());
667             }
668         }
669 
670         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)671         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
672             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
673                 return;
674             }
675             synchronized (mLock) {
676                 dumpLocked("", pw);
677             }
678         }
679 
680         @Override
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)681         public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
682                 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
683             new AmbientContextShellCommand(AmbientContextManagerService.this).exec(
684                     this, in, out, err, args, callback, resultReceiver);
685         }
686 
checkStatusCode(AmbientContextManagerPerUserService service, int[] eventTypes)687         private int checkStatusCode(AmbientContextManagerPerUserService service, int[] eventTypes) {
688             if (service.getServiceType() == ServiceType.DEFAULT && !mIsServiceEnabled) {
689                 Slog.d(TAG, "Service not enabled.");
690                 return AmbientContextManager.STATUS_SERVICE_UNAVAILABLE;
691             }
692             if (service.getServiceType() == ServiceType.WEARABLE && !mIsWearableServiceEnabled) {
693                 Slog.d(TAG, "Wearable Service not available.");
694                 return AmbientContextManager.STATUS_SERVICE_UNAVAILABLE;
695             }
696             if (containsMixedEvents(eventTypes)) {
697                 Slog.d(TAG, "AmbientContextEventRequest contains mixed events,"
698                         + " this is not supported.");
699                 return AmbientContextManager.STATUS_NOT_SUPPORTED;
700             }
701             return AmbientContextManager.STATUS_SUCCESS;
702         }
703     }
704 }
705