• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 package com.android.server.contentcapture;
17 
18 import static android.view.contentcapture.ContentCaptureHelper.sDebug;
19 import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
20 
21 import static com.android.server.contentcapture.ContentCaptureMetricsLogger.writeServiceEvent;
22 import static com.android.server.contentcapture.ContentCaptureMetricsLogger.writeSessionEvent;
23 
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.content.ComponentName;
27 import android.content.Context;
28 import android.os.IBinder;
29 import android.service.contentcapture.ActivityEvent;
30 import android.service.contentcapture.IContentCaptureService;
31 import android.service.contentcapture.IContentCaptureServiceCallback;
32 import android.service.contentcapture.IDataShareCallback;
33 import android.service.contentcapture.SnapshotData;
34 import android.util.Slog;
35 import android.view.contentcapture.ContentCaptureContext;
36 import android.view.contentcapture.DataRemovalRequest;
37 import android.view.contentcapture.DataShareRequest;
38 
39 import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
40 import com.android.internal.os.IResultReceiver;
41 import com.android.internal.util.FrameworkStatsLog;
42 
43 final class RemoteContentCaptureService
44         extends AbstractMultiplePendingRequestsRemoteService<RemoteContentCaptureService,
45         IContentCaptureService> {
46 
47     private final IBinder mServerCallback;
48     private final int mIdleUnbindTimeoutMs;
49     private final ContentCapturePerUserService mPerUserService;
50 
RemoteContentCaptureService(Context context, String serviceInterface, ComponentName serviceComponentName, IContentCaptureServiceCallback callback, int userId, ContentCapturePerUserService perUserService, boolean bindInstantServiceAllowed, boolean verbose, int idleUnbindTimeoutMs)51     RemoteContentCaptureService(Context context, String serviceInterface,
52             ComponentName serviceComponentName, IContentCaptureServiceCallback callback, int userId,
53             ContentCapturePerUserService perUserService, boolean bindInstantServiceAllowed,
54             boolean verbose, int idleUnbindTimeoutMs) {
55         super(context, serviceInterface, serviceComponentName, userId, perUserService,
56                 context.getMainThreadHandler(),
57                 Context.BIND_INCLUDE_CAPABILITIES
58                         | (bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0),
59                 verbose,
60                 /* initialCapacity= */ 2);
61         mPerUserService = perUserService;
62         mServerCallback = callback.asBinder();
63         mIdleUnbindTimeoutMs = idleUnbindTimeoutMs;
64 
65         // Bind right away, which will trigger a onConnected() on service's
66         ensureBoundLocked();
67     }
68 
69     @Override // from AbstractRemoteService
getServiceInterface(@onNull IBinder service)70     protected IContentCaptureService getServiceInterface(@NonNull IBinder service) {
71         return IContentCaptureService.Stub.asInterface(service);
72     }
73 
74     @Override // from AbstractRemoteService
getTimeoutIdleBindMillis()75     protected long getTimeoutIdleBindMillis() {
76         return mIdleUnbindTimeoutMs;
77     }
78 
79     @Override // from AbstractRemoteService
handleOnConnectedStateChanged(boolean connected)80     protected void handleOnConnectedStateChanged(boolean connected) {
81         if (connected && getTimeoutIdleBindMillis() != PERMANENT_BOUND_TIMEOUT_MS) {
82             scheduleUnbind();
83         }
84         try {
85             if (connected) {
86                 try {
87                     mService.onConnected(mServerCallback, sVerbose, sDebug);
88                     writeServiceEvent(
89                             FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_CONNECTED,
90                             mComponentName);
91                 } finally {
92                     // Update the system-service state, in case the service reconnected after
93                     // dying
94                     mPerUserService.onConnected();
95                 }
96             } else {
97                 mService.onDisconnected();
98                 writeServiceEvent(
99                         FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_DISCONNECTED,
100                         mComponentName);
101             }
102         } catch (Exception e) {
103             Slog.w(mTag, "Exception calling onConnectedStateChanged(" + connected + "): " + e);
104         }
105     }
106 
ensureBoundLocked()107     public void ensureBoundLocked() {
108         scheduleBind();
109     }
110 
111     /**
112      * Called by {@link ContentCaptureServerSession} to generate a call to the
113      * {@link RemoteContentCaptureService} to indicate the session was created.
114      */
onSessionStarted(@ullable ContentCaptureContext context, int sessionId, int uid, @NonNull IResultReceiver clientReceiver, int initialState)115     public void onSessionStarted(@Nullable ContentCaptureContext context, int sessionId, int uid,
116             @NonNull IResultReceiver clientReceiver, int initialState) {
117         scheduleAsyncRequest(
118                 (s) -> s.onSessionStarted(context, sessionId, uid, clientReceiver, initialState));
119         // Metrics logging.
120         writeSessionEvent(sessionId,
121                 FrameworkStatsLog.CONTENT_CAPTURE_SESSION_EVENTS__EVENT__ON_SESSION_STARTED,
122                 initialState, getComponentName(), context.getActivityComponent(),
123                 /* is_child_session= */ false);
124     }
125 
126     /**
127      * Called by {@link ContentCaptureServerSession} to generate a call to the
128      * {@link RemoteContentCaptureService} to indicate the session was finished.
129      */
onSessionFinished(int sessionId)130     public void onSessionFinished(int sessionId) {
131         scheduleAsyncRequest((s) -> s.onSessionFinished(sessionId));
132         // Metrics logging.
133         writeSessionEvent(sessionId,
134                 FrameworkStatsLog.CONTENT_CAPTURE_SESSION_EVENTS__EVENT__ON_SESSION_FINISHED,
135                 /* flags= */ 0, getComponentName(), /* app= */ null,
136                 /* is_child_session= */ false);
137     }
138 
139     /**
140      * Called by {@link ContentCaptureServerSession} to send snapshot data to the service.
141      */
onActivitySnapshotRequest(int sessionId, @NonNull SnapshotData snapshotData)142     public void onActivitySnapshotRequest(int sessionId, @NonNull SnapshotData snapshotData) {
143         scheduleAsyncRequest((s) -> s.onActivitySnapshot(sessionId, snapshotData));
144     }
145 
146     /**
147      * Called by {@link ContentCaptureServerSession} to request removal of user data.
148      */
onDataRemovalRequest(@onNull DataRemovalRequest request)149     public void onDataRemovalRequest(@NonNull DataRemovalRequest request) {
150         scheduleAsyncRequest((s) -> s.onDataRemovalRequest(request));
151         writeServiceEvent(
152                 FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_USER_DATA_REMOVED,
153                 mComponentName);
154     }
155 
onDataShareRequest(@onNull DataShareRequest request, @NonNull IDataShareCallback.Stub dataShareCallback)156     public void onDataShareRequest(@NonNull DataShareRequest request,
157             @NonNull IDataShareCallback.Stub dataShareCallback) {
158         scheduleAsyncRequest((s) -> s.onDataShared(request, dataShareCallback));
159         writeServiceEvent(
160                 FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_DATA_SHARE_REQUEST,
161                 mComponentName, request.getPackageName());
162     }
163 
164     /**
165      * Called by {@link ContentCaptureServerSession} to notify a high-level activity event.
166      */
onActivityLifecycleEvent(@onNull ActivityEvent event)167     public void onActivityLifecycleEvent(@NonNull ActivityEvent event) {
168         scheduleAsyncRequest((s) -> s.onActivityEvent(event));
169     }
170 
171     public interface ContentCaptureServiceCallbacks
172             extends VultureCallback<RemoteContentCaptureService> {
173         // NOTE: so far we don't need to notify the callback implementation
174         // (ContentCaptureServerSession) of the request results (success, timeouts, etc..), so this
175         // callback interface is empty.
176     }
177 }
178