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