• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 
17 package android.car;
18 
19 import android.annotation.SystemApi;
20 import android.content.Intent;
21 import android.os.Handler;
22 import android.os.IBinder;
23 import android.os.Looper;
24 import android.os.RemoteException;
25 
26 import java.lang.ref.WeakReference;
27 
28 /**
29  * CarProjectionManager allows applications implementing projection to register/unregister itself
30  * with projection manager, listen for voice notification.
31  * @hide
32  */
33 @SystemApi
34 public class CarProjectionManager implements CarManagerBase {
35     /**
36      * Listener to get projected notifications.
37      *
38      * Currently only voice search request is supported.
39      */
40     public interface CarProjectionListener {
41         /**
42          * Voice search was requested by the user.
43          */
onVoiceAssistantRequest(boolean fromLongPress)44         void onVoiceAssistantRequest(boolean fromLongPress);
45     }
46 
47     /**
48      * Flag for voice search request.
49      */
50     public static final int PROJECTION_VOICE_SEARCH = 0x1;
51     /**
52      * Flag for long press voice search request.
53      */
54     public static final int PROJECTION_LONG_PRESS_VOICE_SEARCH = 0x2;
55 
56     private final ICarProjection mService;
57     private final Handler mHandler;
58     private final ICarProjectionListenerImpl mBinderListener;
59 
60     private CarProjectionListener mListener;
61     private int mVoiceSearchFilter;
62 
63     /**
64      * @hide
65      */
CarProjectionManager(IBinder service, Looper looper)66     CarProjectionManager(IBinder service, Looper looper) {
67         mService = ICarProjection.Stub.asInterface(service);
68         mHandler = new Handler(looper);
69         mBinderListener = new ICarProjectionListenerImpl(this);
70     }
71 
72     /**
73      * Register listener to monitor projection. Only one listener can be registered and
74      * registering multiple times will lead into only the last listener to be active.
75      * @param listener
76      * @param voiceSearchFilter Flags of voice search requests to get notification.
77      * @throws CarNotConnectedException
78      */
regsiterProjectionListener(CarProjectionListener listener, int voiceSearchFilter)79     public void regsiterProjectionListener(CarProjectionListener listener, int voiceSearchFilter)
80             throws CarNotConnectedException {
81         if (listener == null) {
82             throw new IllegalArgumentException("null listener");
83         }
84         synchronized (this) {
85             if (mListener == null || mVoiceSearchFilter != voiceSearchFilter) {
86                 try {
87                     mService.regsiterProjectionListener(mBinderListener, voiceSearchFilter);
88                 } catch (RemoteException e) {
89                     throw new CarNotConnectedException(e);
90                 }
91             }
92             mListener = listener;
93             mVoiceSearchFilter = voiceSearchFilter;
94         }
95     }
96 
97     /**
98      * Unregister listener and stop listening projection events.
99      * @throws CarNotConnectedException
100      */
unregsiterProjectionListener()101     public void unregsiterProjectionListener() throws CarNotConnectedException {
102         synchronized (this) {
103             try {
104                 mService.unregsiterProjectionListener(mBinderListener);
105             } catch (RemoteException e) {
106                 throw new CarNotConnectedException(e);
107             }
108             mListener = null;
109             mVoiceSearchFilter = 0;
110         }
111     }
112 
113     /**
114      * Registers projection runner on projection start with projection service
115      * to create reverse binding.
116      * @param serviceIntent
117      * @throws CarNotConnectedException
118      */
registerProjectionRunner(Intent serviceIntent)119     public void registerProjectionRunner(Intent serviceIntent) throws CarNotConnectedException {
120         if (serviceIntent == null) {
121             throw new IllegalArgumentException("null serviceIntent");
122         }
123         synchronized (this) {
124             try {
125                 mService.registerProjectionRunner(serviceIntent);
126             } catch (RemoteException e) {
127                 throw new CarNotConnectedException(e);
128             }
129         }
130     }
131 
132     /**
133      * Unregisters projection runner on projection stop with projection service to create
134      * reverse binding.
135      * @param serviceIntent
136      * @throws CarNotConnectedException
137      */
unregisterProjectionRunner(Intent serviceIntent)138     public void unregisterProjectionRunner(Intent serviceIntent) throws CarNotConnectedException {
139         if (serviceIntent == null) {
140             throw new IllegalArgumentException("null serviceIntent");
141         }
142         synchronized (this) {
143             try {
144                 mService.unregisterProjectionRunner(serviceIntent);
145             } catch (RemoteException e) {
146                 throw new CarNotConnectedException(e);
147             }
148         }
149     }
150 
151     @Override
onCarDisconnected()152     public void onCarDisconnected() {
153         // nothing to do
154     }
155 
handleVoiceAssistantRequest(boolean fromLongPress)156     private void handleVoiceAssistantRequest(boolean fromLongPress) {
157         CarProjectionListener listener;
158         synchronized (this) {
159             if (mListener == null) {
160                 return;
161             }
162             listener = mListener;
163         }
164         listener.onVoiceAssistantRequest(fromLongPress);
165     }
166 
167     private static class ICarProjectionListenerImpl extends ICarProjectionListener.Stub {
168 
169         private final WeakReference<CarProjectionManager> mManager;
170 
ICarProjectionListenerImpl(CarProjectionManager manager)171         private ICarProjectionListenerImpl(CarProjectionManager manager) {
172             mManager = new WeakReference<>(manager);
173         }
174 
175         @Override
onVoiceAssistantRequest(final boolean fromLongPress)176         public void onVoiceAssistantRequest(final boolean fromLongPress) {
177             final CarProjectionManager manager = mManager.get();
178             if (manager == null) {
179                 return;
180             }
181             manager.mHandler.post(new Runnable() {
182                 @Override
183                 public void run() {
184                     manager.handleVoiceAssistantRequest(fromLongPress);
185                 }
186             });
187         }
188     }
189 }
190