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