blob: 45a8466bfca1c8171450ad74c5e6dbcf3d352b52 [file] [log] [blame]
Winson Chung3fb0f252019-01-08 17:41:55 -08001/*
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
17package android.service.contentsuggestions;
18
19import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
20
21import android.annotation.CallSuper;
22import android.annotation.NonNull;
23import android.annotation.Nullable;
24import android.annotation.SystemApi;
25import android.app.Service;
26import android.app.contentsuggestions.ClassificationsRequest;
27import android.app.contentsuggestions.ContentSuggestionsManager;
28import android.app.contentsuggestions.IClassificationsCallback;
29import android.app.contentsuggestions.ISelectionsCallback;
30import android.app.contentsuggestions.SelectionsRequest;
31import android.content.Intent;
32import android.graphics.Bitmap;
33import android.graphics.GraphicBuffer;
Peiyong Lin9d427402019-01-23 18:39:06 -080034import android.hardware.HardwareBuffer;
Winson Chung3fb0f252019-01-08 17:41:55 -080035import android.os.Bundle;
36import android.os.Handler;
37import android.os.IBinder;
38import android.os.Looper;
39import android.os.RemoteException;
40import android.util.Log;
41import android.util.Slog;
42
43/**
44 * @hide
45 */
46@SystemApi
47public abstract class ContentSuggestionsService extends Service {
48
49 private static final String TAG = ContentSuggestionsService.class.getSimpleName();
50
51 private Handler mHandler;
52
53 /**
54 * The action for the intent used to define the content suggestions service.
Zak Cohen969d39d2019-03-01 14:53:09 -080055 *
56 * <p>To be supported, the service must also require the
Zak Cohena78076e2019-03-05 11:41:12 -080057 * * {@link android.Manifest.permission#BIND_CONTENT_SUGGESTIONS_SERVICE} permission so
58 * * that other applications can not abuse it.
Winson Chung3fb0f252019-01-08 17:41:55 -080059 */
60 public static final String SERVICE_INTERFACE =
61 "android.service.contentsuggestions.ContentSuggestionsService";
62
63 private final IContentSuggestionsService mInterface = new IContentSuggestionsService.Stub() {
64 @Override
65 public void provideContextImage(int taskId, GraphicBuffer contextImage,
66 Bundle imageContextRequestExtras) {
Zak Cohen47b581d2019-02-27 11:47:52 -080067
68 Bitmap wrappedBuffer = null;
69 if (contextImage != null) {
70 wrappedBuffer = Bitmap.wrapHardwareBuffer(
71 HardwareBuffer.createFromGraphicBuffer(contextImage), null);
72 }
73
Winson Chung3fb0f252019-01-08 17:41:55 -080074 mHandler.sendMessage(
Zak Cohena78076e2019-03-05 11:41:12 -080075 obtainMessage(ContentSuggestionsService::onProcessContextImage,
Winson Chung3fb0f252019-01-08 17:41:55 -080076 ContentSuggestionsService.this, taskId,
Zak Cohen47b581d2019-02-27 11:47:52 -080077 wrappedBuffer,
Winson Chung3fb0f252019-01-08 17:41:55 -080078 imageContextRequestExtras));
79 }
80
81 @Override
82 public void suggestContentSelections(SelectionsRequest request,
83 ISelectionsCallback callback) {
Zak Cohena78076e2019-03-05 11:41:12 -080084 mHandler.sendMessage(obtainMessage(
85 ContentSuggestionsService::onSuggestContentSelections,
Winson Chung3fb0f252019-01-08 17:41:55 -080086 ContentSuggestionsService.this, request, wrapSelectionsCallback(callback)));
87
88 }
89
90 @Override
91 public void classifyContentSelections(ClassificationsRequest request,
92 IClassificationsCallback callback) {
Zak Cohena78076e2019-03-05 11:41:12 -080093 mHandler.sendMessage(obtainMessage(
94 ContentSuggestionsService::onClassifyContentSelections,
Winson Chung3fb0f252019-01-08 17:41:55 -080095 ContentSuggestionsService.this, request, wrapClassificationCallback(callback)));
96 }
97
98 @Override
99 public void notifyInteraction(String requestId, Bundle interaction) {
100 mHandler.sendMessage(
Zak Cohena78076e2019-03-05 11:41:12 -0800101 obtainMessage(ContentSuggestionsService::onNotifyInteraction,
Winson Chung3fb0f252019-01-08 17:41:55 -0800102 ContentSuggestionsService.this, requestId, interaction));
103 }
104 };
105
106 @CallSuper
107 @Override
108 public void onCreate() {
109 super.onCreate();
110 mHandler = new Handler(Looper.getMainLooper(), null, true);
111 }
112
113 /** @hide */
114 @Override
115 public final IBinder onBind(Intent intent) {
116 if (SERVICE_INTERFACE.equals(intent.getAction())) {
117 return mInterface.asBinder();
118 }
119 Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
120 return null;
121 }
122
123 /**
124 * Called by the system to provide the snapshot for the task associated with the given
125 * {@param taskId}.
126 */
Zak Cohena78076e2019-03-05 11:41:12 -0800127 public void onProcessContextImage(
128 int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras) {
129 // TODO(b/127532182): remove after next prebuilt drop.
130 processContextImage(taskId, contextImage, extras);
131 }
Winson Chung3fb0f252019-01-08 17:41:55 -0800132
133 /**
Zak Cohena78076e2019-03-05 11:41:12 -0800134 * Content selections have been request through {@link ContentSuggestionsManager}, implementer
135 * should reply on the callback with selections.
Winson Chung3fb0f252019-01-08 17:41:55 -0800136 */
Zak Cohena78076e2019-03-05 11:41:12 -0800137 public void onSuggestContentSelections(@NonNull SelectionsRequest request,
138 @NonNull ContentSuggestionsManager.SelectionsCallback callback) {
139 // TODO(b/127532182): remove after next prebuilt drop.
140 suggestContentSelections(request, callback);
141 }
Winson Chung3fb0f252019-01-08 17:41:55 -0800142
143 /**
Zak Cohena78076e2019-03-05 11:41:12 -0800144 * Content classifications have been request through {@link ContentSuggestionsManager},
145 * implementer should reply on the callback with classifications.
Winson Chung3fb0f252019-01-08 17:41:55 -0800146 */
Zak Cohena78076e2019-03-05 11:41:12 -0800147 public void onClassifyContentSelections(@NonNull ClassificationsRequest request,
148 @NonNull ContentSuggestionsManager.ClassificationsCallback callback) {
149 // TODO(b/127532182): remove after next prebuilt drop.
150 classifyContentSelections(request, callback);
151 }
Winson Chung3fb0f252019-01-08 17:41:55 -0800152
153 /**
Zak Cohena78076e2019-03-05 11:41:12 -0800154 * User interactions have been reported through {@link ContentSuggestionsManager}, implementer
155 * should handle those interactions.
Winson Chung3fb0f252019-01-08 17:41:55 -0800156 */
Zak Cohena78076e2019-03-05 11:41:12 -0800157 public void onNotifyInteraction(
158 @NonNull String requestId, @NonNull Bundle interaction) {
159 // TODO(b/127532182): remove after next prebuilt drop.
160 notifyInteraction(requestId, interaction);
161 }
Winson Chung3fb0f252019-01-08 17:41:55 -0800162
163 private ContentSuggestionsManager.SelectionsCallback wrapSelectionsCallback(
164 ISelectionsCallback callback) {
165 return (statusCode, selections) -> {
166 try {
167 callback.onContentSelectionsAvailable(statusCode, selections);
168 } catch (RemoteException e) {
169 Slog.e(TAG, "Error sending result: " + e);
170 }
171 };
172 }
173
174 private ContentSuggestionsManager.ClassificationsCallback wrapClassificationCallback(
175 IClassificationsCallback callback) {
176 return ((statusCode, classifications) -> {
177 try {
178 callback.onContentClassificationsAvailable(statusCode, classifications);
179 } catch (RemoteException e) {
180 Slog.e(TAG, "Error sending result: " + e);
181 }
182 });
183 }
Zak Cohena78076e2019-03-05 11:41:12 -0800184
185
186 /**
187 * For temporary compat reason, remove with b/127532182
Zak Cohen4b2e80c2019-03-08 13:06:07 -0800188 * @deprecated use {@link #onProcessContextImage(int, Bitmap, Bundle)} instead.
Zak Cohena78076e2019-03-05 11:41:12 -0800189 */
190 @Deprecated
191 public void processContextImage(
192 int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras) {
193 }
194
195 /**
196 * For temporary compat reason, remove with b/127532182
Zak Cohen4b2e80c2019-03-08 13:06:07 -0800197 * @deprecated use {@link #onSuggestContentSelections(SelectionsRequest,
198 * ContentSuggestionsManager.SelectionsCallback)} instead.
Zak Cohena78076e2019-03-05 11:41:12 -0800199 */
200 @Deprecated
201 public void suggestContentSelections(@NonNull SelectionsRequest request,
202 @NonNull ContentSuggestionsManager.SelectionsCallback callback) {
203 }
204
205 /**
206 * For temporary compat reason, remove with b/127532182
Zak Cohen4b2e80c2019-03-08 13:06:07 -0800207 * @deprecated use {@link #onClassifyContentSelections(ClassificationsRequest,
208 * ContentSuggestionsManager.ClassificationsCallback)} instead.
Zak Cohena78076e2019-03-05 11:41:12 -0800209 */
210 @Deprecated
211 public void classifyContentSelections(@NonNull ClassificationsRequest request,
212 @NonNull ContentSuggestionsManager.ClassificationsCallback callback) {
213 }
214
215 /**
216 * For temporary compat reason, remove with b/127532182
Zak Cohen4b2e80c2019-03-08 13:06:07 -0800217 * @deprecated use {@link #onNotifyInteraction(String, Bundle)} instead.
Zak Cohena78076e2019-03-05 11:41:12 -0800218 */
219 @Deprecated
220 public void notifyInteraction(@NonNull String requestId, @NonNull Bundle interaction) {
221 }
Winson Chung3fb0f252019-01-08 17:41:55 -0800222}