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