1/*
2 * Copyright (C) 2017 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 com.googlecode.android_scripting.facade;
18
19import java.lang.reflect.Method;
20import java.util.ArrayList;
21import java.util.Collection;
22import java.util.HashSet;
23import java.util.List;
24import java.util.Map;
25import java.util.Set;
26import java.util.SortedMap;
27import java.util.TreeMap;
28
29import com.google.common.collect.Maps;
30import com.googlecode.android_scripting.Log;
31import com.googlecode.android_scripting.facade.bluetooth.BluetoothA2dpFacade;
32import com.googlecode.android_scripting.facade.bluetooth.BluetoothA2dpSinkFacade;
33import com.googlecode.android_scripting.facade.bluetooth.BluetoothAvrcpFacade;
34import com.googlecode.android_scripting.facade.bluetooth.BluetoothConnectionFacade;
35import com.googlecode.android_scripting.facade.bluetooth.BluetoothFacade;
36import com.googlecode.android_scripting.facade.bluetooth.BluetoothHealthFacade;
37import com.googlecode.android_scripting.facade.bluetooth.BluetoothHfpClientFacade;
38import com.googlecode.android_scripting.facade.bluetooth.BluetoothHidFacade;
39import com.googlecode.android_scripting.facade.bluetooth.BluetoothHspFacade;
40import com.googlecode.android_scripting.facade.bluetooth.BluetoothLeAdvertiseFacade;
41import com.googlecode.android_scripting.facade.bluetooth.BluetoothLeAdvertisingSetFacade;
42import com.googlecode.android_scripting.facade.bluetooth.BluetoothLeScanFacade;
43import com.googlecode.android_scripting.facade.bluetooth.BluetoothMapClientFacade;
44import com.googlecode.android_scripting.facade.bluetooth.BluetoothMapFacade;
45import com.googlecode.android_scripting.facade.bluetooth.BluetoothMediaFacade;
46import com.googlecode.android_scripting.facade.bluetooth.BluetoothPbapClientFacade;
47import com.googlecode.android_scripting.facade.bluetooth.BluetoothPanFacade;
48import com.googlecode.android_scripting.facade.bluetooth.BluetoothRfcommFacade;
49import com.googlecode.android_scripting.facade.bluetooth.GattClientFacade;
50import com.googlecode.android_scripting.facade.bluetooth.GattServerFacade;
51import com.googlecode.android_scripting.facade.media.AudioManagerFacade;
52import com.googlecode.android_scripting.facade.media.MediaPlayerFacade;
53import com.googlecode.android_scripting.facade.media.MediaRecorderFacade;
54import com.googlecode.android_scripting.facade.media.MediaScannerFacade;
55import com.googlecode.android_scripting.facade.media.MediaSessionFacade;
56import com.googlecode.android_scripting.facade.net.nsd.NsdManagerFacade;
57import com.googlecode.android_scripting.facade.telephony.CarrierConfigFacade;
58import com.googlecode.android_scripting.facade.telephony.ImsManagerFacade;
59import com.googlecode.android_scripting.facade.telephony.SmsFacade;
60import com.googlecode.android_scripting.facade.telephony.SubscriptionManagerFacade;
61import com.googlecode.android_scripting.facade.telephony.TelecomCallFacade;
62import com.googlecode.android_scripting.facade.telephony.TelecomManagerFacade;
63import com.googlecode.android_scripting.facade.telephony.TelephonyManagerFacade;
64import com.googlecode.android_scripting.facade.ui.UiFacade;
65import com.googlecode.android_scripting.facade.wifi.HttpFacade;
66import com.googlecode.android_scripting.facade.wifi.WifiManagerFacade;
67import com.googlecode.android_scripting.facade.wifi.WifiAwareManagerFacade;
68import com.googlecode.android_scripting.facade.wifi.WifiP2pManagerFacade;
69import com.googlecode.android_scripting.facade.wifi.WifiRttManagerFacade;
70import com.googlecode.android_scripting.facade.wifi.WifiScannerFacade;
71import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
72import com.googlecode.android_scripting.rpc.MethodDescriptor;
73import com.googlecode.android_scripting.rpc.RpcDeprecated;
74import com.googlecode.android_scripting.rpc.RpcMinSdk;
75import com.googlecode.android_scripting.rpc.RpcStartEvent;
76import com.googlecode.android_scripting.rpc.RpcStopEvent;
77import com.googlecode.android_scripting.webcam.WebCamFacade;
78
79/**
80 * Encapsulates the list of supported facades and their construction.
81 */
82public class FacadeConfiguration {
83    private final static Set<Class<? extends RpcReceiver>> sFacadeClassList;
84    private final static SortedMap<String, MethodDescriptor> sRpcs =
85            new TreeMap<String, MethodDescriptor>();
86
87    private static int sSdkLevel;
88
89    static {
90        sSdkLevel = android.os.Build.VERSION.SDK_INT;
91
92        sFacadeClassList = new HashSet<Class<? extends RpcReceiver>>();
93        sFacadeClassList.add(ActivityResultFacade.class);
94        sFacadeClassList.add(AndroidFacade.class);
95        sFacadeClassList.add(ApplicationManagerFacade.class);
96        sFacadeClassList.add(AudioManagerFacade.class);
97        sFacadeClassList.add(BatteryManagerFacade.class);
98        sFacadeClassList.add(CallLogFacade.class);
99        sFacadeClassList.add(CameraFacade.class);
100        sFacadeClassList.add(CommonIntentsFacade.class);
101        sFacadeClassList.add(ContactsFacade.class);
102        sFacadeClassList.add(EventFacade.class);
103        sFacadeClassList.add(ImsManagerFacade.class);
104        sFacadeClassList.add(LocationFacade.class);
105        sFacadeClassList.add(TelephonyManagerFacade.class);
106        sFacadeClassList.add(PreferencesFacade.class);
107        sFacadeClassList.add(MediaPlayerFacade.class);
108        sFacadeClassList.add(MediaRecorderFacade.class);
109        sFacadeClassList.add(MediaScannerFacade.class);
110        sFacadeClassList.add(MediaSessionFacade.class);
111        sFacadeClassList.add(SensorManagerFacade.class);
112        sFacadeClassList.add(SettingsFacade.class);
113        sFacadeClassList.add(SmsFacade.class);
114        sFacadeClassList.add(SpeechRecognitionFacade.class);
115        sFacadeClassList.add(ToneGeneratorFacade.class);
116        sFacadeClassList.add(WakeLockFacade.class);
117        sFacadeClassList.add(HttpFacade.class);
118        sFacadeClassList.add(WifiManagerFacade.class);
119        sFacadeClassList.add(UiFacade.class);
120        sFacadeClassList.add(TextToSpeechFacade.class);
121        sFacadeClassList.add(BluetoothFacade.class);
122        sFacadeClassList.add(BluetoothA2dpFacade.class);
123        sFacadeClassList.add(BluetoothAvrcpFacade.class);
124        sFacadeClassList.add(BluetoothConnectionFacade.class);
125        sFacadeClassList.add(BluetoothHealthFacade.class);
126        sFacadeClassList.add(BluetoothHspFacade.class);
127        sFacadeClassList.add(BluetoothHidFacade.class);
128        sFacadeClassList.add(BluetoothMapFacade.class);
129        sFacadeClassList.add(BluetoothPanFacade.class);
130        sFacadeClassList.add(BluetoothMediaFacade.class);
131        sFacadeClassList.add(BluetoothRfcommFacade.class);
132        sFacadeClassList.add(WebCamFacade.class);
133        sFacadeClassList.add(WifiP2pManagerFacade.class);
134        sFacadeClassList.add(BluetoothLeScanFacade.class);
135        sFacadeClassList.add(BluetoothLeAdvertiseFacade.class);
136        sFacadeClassList.add(GattClientFacade.class);
137        sFacadeClassList.add(GattServerFacade.class);
138        sFacadeClassList.add(ConnectivityManagerFacade.class);
139        sFacadeClassList.add(DisplayFacade.class);
140        sFacadeClassList.add(TelecomManagerFacade.class);
141        sFacadeClassList.add(WifiRttManagerFacade.class);
142        sFacadeClassList.add(WifiScannerFacade.class);
143        sFacadeClassList.add(SubscriptionManagerFacade.class);
144        sFacadeClassList.add(TelecomCallFacade.class);
145        sFacadeClassList.add(CarrierConfigFacade.class);
146        sFacadeClassList.add(NfcManagerFacade.class);
147        sFacadeClassList.add(VpnFacade.class);
148
149        /* Compatibility reset to >= Marshmallow */
150        if (sSdkLevel >= 23) {
151            // add new facades here
152            sFacadeClassList.add(WifiAwareManagerFacade.class);
153            sFacadeClassList.add(BluetoothHfpClientFacade.class);
154            sFacadeClassList.add(BluetoothA2dpSinkFacade.class);
155            sFacadeClassList.add(BluetoothPbapClientFacade.class);
156            sFacadeClassList.add(NsdManagerFacade.class);
157            sFacadeClassList.add(BluetoothMapClientFacade.class);
158            sFacadeClassList.add(BluetoothLeAdvertisingSetFacade.class);
159        }
160
161        for (Class<? extends RpcReceiver> recieverClass : sFacadeClassList) {
162            for (MethodDescriptor rpcMethod : MethodDescriptor.collectFrom(recieverClass)) {
163                sRpcs.put(rpcMethod.getName(), rpcMethod);
164            }
165        }
166    }
167
168    private FacadeConfiguration() {
169        // Utility class.
170    }
171
172    public static int getSdkLevel() {
173        return sSdkLevel;
174    }
175
176    /** Returns a list of {@link MethodDescriptor} objects for all facades. */
177    public static List<MethodDescriptor> collectMethodDescriptors() {
178        return new ArrayList<MethodDescriptor>(sRpcs.values());
179    }
180
181    /**
182     * Returns a list of not deprecated {@link MethodDescriptor} objects for facades supported by
183     * the current SDK version.
184     */
185    public static List<MethodDescriptor> collectSupportedMethodDescriptors() {
186        List<MethodDescriptor> list = new ArrayList<MethodDescriptor>();
187        for (MethodDescriptor descriptor : sRpcs.values()) {
188            Method method = descriptor.getMethod();
189            if (method.isAnnotationPresent(RpcDeprecated.class)) {
190                continue;
191            } else if (method.isAnnotationPresent(RpcMinSdk.class)) {
192                int requiredSdkLevel = method.getAnnotation(RpcMinSdk.class).value();
193                if (sSdkLevel < requiredSdkLevel) {
194                    continue;
195                }
196            }
197            list.add(descriptor);
198        }
199        return list;
200    }
201
202    public static Map<String, MethodDescriptor> collectStartEventMethodDescriptors() {
203        Map<String, MethodDescriptor> map = Maps.newHashMap();
204        for (MethodDescriptor descriptor : sRpcs.values()) {
205            Method method = descriptor.getMethod();
206            if (method.isAnnotationPresent(RpcStartEvent.class)) {
207                String eventName = method.getAnnotation(RpcStartEvent.class).value();
208                if (map.containsKey(eventName)) {
209                    Log.d("Duplicate eventName " + eventName);
210                    throw new RuntimeException("Duplicate start event method descriptor found.");
211                }
212                map.put(eventName, descriptor);
213            }
214        }
215        return map;
216    }
217
218    public static Map<String, MethodDescriptor> collectStopEventMethodDescriptors() {
219        Map<String, MethodDescriptor> map = Maps.newHashMap();
220        for (MethodDescriptor descriptor : sRpcs.values()) {
221            Method method = descriptor.getMethod();
222            if (method.isAnnotationPresent(RpcStopEvent.class)) {
223                String eventName = method.getAnnotation(RpcStopEvent.class).value();
224                if (map.containsKey(eventName)) {
225                    throw new RuntimeException("Duplicate stop event method descriptor found.");
226                }
227                map.put(eventName, descriptor);
228            }
229        }
230        return map;
231    }
232
233    /** Returns a method by name. */
234    public static MethodDescriptor getMethodDescriptor(String name) {
235        return sRpcs.get(name);
236    }
237
238    public static Collection<Class<? extends RpcReceiver>> getFacadeClasses() {
239        return sFacadeClassList;
240    }
241}
242