blob: 333f4bec8f7eb09e7c5eb012c0038847a9b18247 [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.
55 */
56 public static final String SERVICE_INTERFACE =
57 "android.service.contentsuggestions.ContentSuggestionsService";
58
59 private final IContentSuggestionsService mInterface = new IContentSuggestionsService.Stub() {
60 @Override
61 public void provideContextImage(int taskId, GraphicBuffer contextImage,
62 Bundle imageContextRequestExtras) {
63 mHandler.sendMessage(
64 obtainMessage(ContentSuggestionsService::processContextImage,
65 ContentSuggestionsService.this, taskId,
Peiyong Lin9d427402019-01-23 18:39:06 -080066 Bitmap.wrapHardwareBuffer(
67 HardwareBuffer.createFromGraphicBuffer(contextImage), null),
Winson Chung3fb0f252019-01-08 17:41:55 -080068 imageContextRequestExtras));
69 }
70
71 @Override
72 public void suggestContentSelections(SelectionsRequest request,
73 ISelectionsCallback callback) {
74 mHandler.sendMessage(obtainMessage(ContentSuggestionsService::suggestContentSelections,
75 ContentSuggestionsService.this, request, wrapSelectionsCallback(callback)));
76
77 }
78
79 @Override
80 public void classifyContentSelections(ClassificationsRequest request,
81 IClassificationsCallback callback) {
82 mHandler.sendMessage(obtainMessage(ContentSuggestionsService::classifyContentSelections,
83 ContentSuggestionsService.this, request, wrapClassificationCallback(callback)));
84 }
85
86 @Override
87 public void notifyInteraction(String requestId, Bundle interaction) {
88 mHandler.sendMessage(
89 obtainMessage(ContentSuggestionsService::notifyInteraction,
90 ContentSuggestionsService.this, requestId, interaction));
91 }
92 };
93
94 @CallSuper
95 @Override
96 public void onCreate() {
97 super.onCreate();
98 mHandler = new Handler(Looper.getMainLooper(), null, true);
99 }
100
101 /** @hide */
102 @Override
103 public final IBinder onBind(Intent intent) {
104 if (SERVICE_INTERFACE.equals(intent.getAction())) {
105 return mInterface.asBinder();
106 }
107 Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
108 return null;
109 }
110
111 /**
112 * Called by the system to provide the snapshot for the task associated with the given
113 * {@param taskId}.
114 */
115 public abstract void processContextImage(
116 int taskId, @Nullable Bitmap contextImage, @NonNull Bundle extras);
117
118 /**
119 * Called by a client app to make a request for content selections.
120 */
121 public abstract void suggestContentSelections(@NonNull SelectionsRequest request,
122 @NonNull ContentSuggestionsManager.SelectionsCallback callback);
123
124 /**
125 * Called by a client app to classify the provided content selections.
126 */
127 public abstract void classifyContentSelections(@NonNull ClassificationsRequest request,
128 @NonNull ContentSuggestionsManager.ClassificationsCallback callback);
129
130 /**
131 * Called by a client app to report an interaction.
132 */
133 public abstract void notifyInteraction(@NonNull String requestId, @NonNull Bundle interaction);
134
135 private ContentSuggestionsManager.SelectionsCallback wrapSelectionsCallback(
136 ISelectionsCallback callback) {
137 return (statusCode, selections) -> {
138 try {
139 callback.onContentSelectionsAvailable(statusCode, selections);
140 } catch (RemoteException e) {
141 Slog.e(TAG, "Error sending result: " + e);
142 }
143 };
144 }
145
146 private ContentSuggestionsManager.ClassificationsCallback wrapClassificationCallback(
147 IClassificationsCallback callback) {
148 return ((statusCode, classifications) -> {
149 try {
150 callback.onContentClassificationsAvailable(statusCode, classifications);
151 } catch (RemoteException e) {
152 Slog.e(TAG, "Error sending result: " + e);
153 }
154 });
155 }
156}