• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.testapi;
18 
19 import android.bluetooth.BluetoothDevice;
20 import android.car.CarProjectionManager;
21 import android.car.CarProjectionManager.ProjectionAccessPointCallback;
22 import android.car.ICarProjection;
23 import android.car.ICarProjectionKeyEventHandler;
24 import android.car.ICarProjectionStatusListener;
25 import android.car.projection.ProjectionOptions;
26 import android.car.projection.ProjectionStatus;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.ServiceConnection;
31 import android.net.wifi.SoftApConfiguration;
32 import android.net.wifi.WifiConfiguration;
33 import android.os.Bundle;
34 import android.os.IBinder;
35 import android.os.Message;
36 import android.os.Messenger;
37 import android.os.RemoteException;
38 
39 import java.util.ArrayList;
40 import java.util.BitSet;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44 
45 /**
46  * Fake implementation of {@link ICarProjection} interface.
47  *
48  * @hide
49  */
50 class FakeCarProjectionService extends ICarProjection.Stub implements
51         CarProjectionController {
52 
53     private final Context mContext;
54 
55     private SoftApConfiguration mSoftApConfiguration;
56     private WifiConfiguration mWifiConfiguration;
57     private Messenger mApMessenger;
58     private IBinder mApBinder;
59     private List<ICarProjectionStatusListener> mStatusListeners = new ArrayList<>();
60     private Map<IBinder, ProjectionStatus> mProjectionStatusMap = new HashMap<>();
61     private ProjectionStatus mCurrentProjectionStatus = ProjectionStatus.builder(
62             "", ProjectionStatus.PROJECTION_STATE_INACTIVE).build();
63     private ProjectionOptions mProjectionOptions;
64     private final Map<ICarProjectionKeyEventHandler, BitSet> mKeyEventListeners = new HashMap<>();
65 
66     private final ServiceConnection mServiceConnection = new ServiceConnection() {
67         @Override
68         public void onServiceConnected(ComponentName name, IBinder service) {}
69 
70         @Override
71         public void onServiceDisconnected(ComponentName name) {}
72     };
73 
FakeCarProjectionService(Context context)74     FakeCarProjectionService(Context context) {
75         mContext = context;
76         mProjectionOptions = ProjectionOptions.builder().build();
77     }
78 
79     @Override
registerProjectionRunner(Intent serviceIntent)80     public void registerProjectionRunner(Intent serviceIntent) throws RemoteException {
81         mContext.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
82     }
83 
84     @Override
unregisterProjectionRunner(Intent serviceIntent)85     public void unregisterProjectionRunner(Intent serviceIntent) throws RemoteException {
86         mContext.unbindService(mServiceConnection);
87     }
88 
89     @Override
registerKeyEventHandler(ICarProjectionKeyEventHandler callback, byte[] events)90     public void registerKeyEventHandler(ICarProjectionKeyEventHandler callback, byte[] events) {
91         mKeyEventListeners.put(callback, BitSet.valueOf(events));
92     }
93 
94     @Override
unregisterKeyEventHandler(ICarProjectionKeyEventHandler callback)95     public void unregisterKeyEventHandler(ICarProjectionKeyEventHandler callback) {
96         mKeyEventListeners.remove(callback);
97     }
98 
99     @Override
fireKeyEvent(int event)100     public void fireKeyEvent(int event) {
101         for (Map.Entry<ICarProjectionKeyEventHandler, BitSet> entry :
102                 mKeyEventListeners.entrySet()) {
103             if (entry.getValue().get(event)) {
104                 try {
105                     entry.getKey().onKeyEvent(event);
106                 } catch (RemoteException e) {
107                     throw e.rethrowFromSystemServer();
108                 }
109             }
110         }
111     }
112 
113     @Override
startProjectionAccessPoint(Messenger messenger, IBinder binder)114     public void startProjectionAccessPoint(Messenger messenger, IBinder binder)
115             throws RemoteException {
116         mApMessenger = messenger;
117         mApBinder = binder;
118 
119         Message message = Message.obtain();
120         if (mSoftApConfiguration != null) {
121             message.what = CarProjectionManager.PROJECTION_AP_STARTED;
122             message.obj = mSoftApConfiguration;
123         } else if (mWifiConfiguration != null) {
124             message.what = CarProjectionManager.PROJECTION_AP_STARTED;
125             message.obj = mWifiConfiguration;
126         } else {
127             message.what = CarProjectionManager.PROJECTION_AP_FAILED;
128             message.arg1 = ProjectionAccessPointCallback.ERROR_GENERIC;
129         }
130         messenger.send(message);
131     }
132 
133     @Override
stopProjectionAccessPoint(IBinder binder)134     public void stopProjectionAccessPoint(IBinder binder) throws RemoteException {
135         if (mApBinder == binder) {
136             Message message = Message.obtain();
137             message.what = CarProjectionManager.PROJECTION_AP_STOPPED;
138             mApMessenger.send(message);
139         }
140     }
141 
142     @Override
requestBluetoothProfileInhibit(BluetoothDevice device, int profile, IBinder token)143     public boolean requestBluetoothProfileInhibit(BluetoothDevice device, int profile,
144             IBinder token) throws RemoteException {
145         return true;
146     }
147 
148     @Override
releaseBluetoothProfileInhibit(BluetoothDevice device, int profile, IBinder token)149     public boolean releaseBluetoothProfileInhibit(BluetoothDevice device, int profile,
150             IBinder token) throws RemoteException {
151         return true;
152     }
153 
154     @Override
updateProjectionStatus(ProjectionStatus status, IBinder token)155     public void updateProjectionStatus(ProjectionStatus status, IBinder token)
156             throws RemoteException {
157         mCurrentProjectionStatus = status;
158         mProjectionStatusMap.put(token, status);
159         notifyStatusListeners(status,
160                 mStatusListeners.toArray(new ICarProjectionStatusListener[0]));
161     }
162 
notifyStatusListeners(ProjectionStatus status, ICarProjectionStatusListener... listeners)163     private void notifyStatusListeners(ProjectionStatus status,
164             ICarProjectionStatusListener... listeners) throws RemoteException {
165         for (ICarProjectionStatusListener listener : listeners) {
166             listener.onProjectionStatusChanged(
167                     status.getState(),
168                     status.getPackageName(),
169                     new ArrayList<>(mProjectionStatusMap.values()));
170         }
171     }
172 
173     @Override
registerProjectionStatusListener(ICarProjectionStatusListener listener)174     public void registerProjectionStatusListener(ICarProjectionStatusListener listener)
175             throws RemoteException {
176         mStatusListeners.add(listener);
177         notifyStatusListeners(mCurrentProjectionStatus, listener);
178     }
179 
180     @Override
unregisterProjectionStatusListener(ICarProjectionStatusListener listener)181     public void unregisterProjectionStatusListener(ICarProjectionStatusListener listener)
182             throws RemoteException {
183         mStatusListeners.remove(listener);
184     }
185 
186     @Override
setSoftApConfiguration(SoftApConfiguration softApConfiguration)187     public void setSoftApConfiguration(SoftApConfiguration softApConfiguration) {
188         mSoftApConfiguration = softApConfiguration;
189     }
190 
191     @Override
setWifiConfiguration(WifiConfiguration wifiConfiguration)192     public void setWifiConfiguration(WifiConfiguration wifiConfiguration) {
193         mWifiConfiguration = wifiConfiguration;
194     }
195 
196     @Override
getProjectionOptions()197     public Bundle getProjectionOptions() throws RemoteException {
198         return mProjectionOptions.toBundle();
199     }
200 
201     @Override
getAvailableWifiChannels(int band)202     public int[] getAvailableWifiChannels(int band) throws RemoteException {
203         return new int[] {2412 /* Channel 1 */, 5180 /* Channel 36 */};
204     }
205 
206     @Override
resetProjectionAccessPointCredentials()207     public void resetProjectionAccessPointCredentials() throws RemoteException {
208         // Nothing to do.
209     }
210 
211     @Override
setProjectionOptions(ProjectionOptions projectionOptions)212     public void setProjectionOptions(ProjectionOptions projectionOptions) {
213         mProjectionOptions = projectionOptions;
214     }
215 }
216