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