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.net.ip;
18 
19 import android.annotation.Hide;
20 import android.annotation.NonNull;
21 import android.net.NattKeepalivePacketData;
22 import android.net.ProxyInfo;
23 import android.net.TcpKeepalivePacketData;
24 import android.net.TcpKeepalivePacketDataParcelable;
25 import android.net.shared.Layer2Information;
26 import android.net.shared.ProvisioningConfiguration;
27 import android.net.util.KeepalivePacketDataUtil;
28 import android.os.Binder;
29 import android.os.RemoteException;
30 import android.util.Log;
31 
32 /**
33  * A convenience wrapper for IpClient.
34  *
35  * Wraps IIpClient calls, making them a bit more friendly to use. Currently handles:
36  * - Clearing calling identity
37  * - Ignoring RemoteExceptions
38  * - Converting to stable parcelables
39  *
40  * By design, all methods on IIpClient are asynchronous oneway IPCs and are thus void. All the
41  * wrapper methods in this class return a boolean that callers can use to determine whether
42  * RemoteException was thrown.
43  */
44 @Hide
45 public class IpClientManager {
46     @NonNull private final IIpClient mIpClient;
47     @NonNull private final String mTag;
48 
IpClientManager(@onNull IIpClient ipClient, @NonNull String tag)49     public IpClientManager(@NonNull IIpClient ipClient, @NonNull String tag) {
50         mIpClient = ipClient;
51         mTag = tag;
52     }
53 
IpClientManager(@onNull IIpClient ipClient)54     public IpClientManager(@NonNull IIpClient ipClient) {
55         this(ipClient, IpClientManager.class.getSimpleName());
56     }
57 
log(String s, Throwable e)58     private void log(String s, Throwable e) {
59         Log.e(mTag, s, e);
60     }
61 
62     /**
63      * For clients using {@link ProvisioningConfiguration.Builder#withPreDhcpAction()}, must be
64      * called after {@link IIpClientCallbacks#onPreDhcpAction} to indicate that DHCP is clear to
65      * proceed.
66      */
completedPreDhcpAction()67     public boolean completedPreDhcpAction() {
68         final long token = Binder.clearCallingIdentity();
69         try {
70             mIpClient.completedPreDhcpAction();
71             return true;
72         } catch (RemoteException e) {
73             log("Error completing PreDhcpAction", e);
74             return false;
75         } finally {
76             Binder.restoreCallingIdentity(token);
77         }
78     }
79 
80     /**
81      * Confirm the provisioning configuration.
82      */
confirmConfiguration()83     public boolean confirmConfiguration() {
84         final long token = Binder.clearCallingIdentity();
85         try {
86             mIpClient.confirmConfiguration();
87             return true;
88         } catch (RemoteException e) {
89             log("Error confirming IpClient configuration", e);
90             return false;
91         } finally {
92             Binder.restoreCallingIdentity(token);
93         }
94     }
95 
96     /**
97      * Indicate that packet filter read is complete.
98      */
readPacketFilterComplete(byte[] data)99     public boolean readPacketFilterComplete(byte[] data) {
100         final long token = Binder.clearCallingIdentity();
101         try {
102             mIpClient.readPacketFilterComplete(data);
103             return true;
104         } catch (RemoteException e) {
105             log("Error notifying IpClient of packet filter read", e);
106             return false;
107         } finally {
108             Binder.restoreCallingIdentity(token);
109         }
110     }
111 
112     /**
113      * Shut down this IpClient instance altogether.
114      */
shutdown()115     public boolean shutdown() {
116         final long token = Binder.clearCallingIdentity();
117         try {
118             mIpClient.shutdown();
119             return true;
120         } catch (RemoteException e) {
121             log("Error shutting down IpClient", e);
122             return false;
123         } finally {
124             Binder.restoreCallingIdentity(token);
125         }
126     }
127 
128     /**
129      * Start provisioning with the provided parameters.
130      */
startProvisioning(ProvisioningConfiguration prov)131     public boolean startProvisioning(ProvisioningConfiguration prov) {
132         final long token = Binder.clearCallingIdentity();
133         try {
134             mIpClient.startProvisioning(prov.toStableParcelable());
135             return true;
136         } catch (RemoteException e) {
137             log("Error starting IpClient provisioning", e);
138             return false;
139         } finally {
140             Binder.restoreCallingIdentity(token);
141         }
142     }
143 
144     /**
145      * Stop this IpClient.
146      *
147      * <p>This does not shut down the StateMachine itself, which is handled by {@link #shutdown()}.
148      */
stop()149     public boolean stop() {
150         final long token = Binder.clearCallingIdentity();
151         try {
152             mIpClient.stop();
153             return true;
154         } catch (RemoteException e) {
155             log("Error stopping IpClient", e);
156             return false;
157         } finally {
158             Binder.restoreCallingIdentity(token);
159         }
160     }
161 
162     /**
163      * Set the TCP buffer sizes to use.
164      *
165      * This may be called, repeatedly, at any time before or after a call to
166      * #startProvisioning(). The setting is cleared upon calling #stop().
167      */
setTcpBufferSizes(String tcpBufferSizes)168     public boolean setTcpBufferSizes(String tcpBufferSizes) {
169         final long token = Binder.clearCallingIdentity();
170         try {
171             mIpClient.setTcpBufferSizes(tcpBufferSizes);
172             return true;
173         } catch (RemoteException e) {
174             log("Error setting IpClient TCP buffer sizes", e);
175             return false;
176         } finally {
177             Binder.restoreCallingIdentity(token);
178         }
179     }
180 
181     /**
182      * Set the HTTP Proxy configuration to use.
183      *
184      * This may be called, repeatedly, at any time before or after a call to
185      * #startProvisioning(). The setting is cleared upon calling #stop().
186      */
setHttpProxy(ProxyInfo proxyInfo)187     public boolean setHttpProxy(ProxyInfo proxyInfo) {
188         final long token = Binder.clearCallingIdentity();
189         try {
190             mIpClient.setHttpProxy(proxyInfo);
191             return true;
192         } catch (RemoteException e) {
193             log("Error setting IpClient proxy", e);
194             return false;
195         } finally {
196             Binder.restoreCallingIdentity(token);
197         }
198     }
199 
200     /**
201      * Enable or disable the multicast filter.  Attempts to use APF to accomplish the filtering,
202      * if not, Callback.setFallbackMulticastFilter() is called.
203      */
setMulticastFilter(boolean enabled)204     public boolean setMulticastFilter(boolean enabled) {
205         final long token = Binder.clearCallingIdentity();
206         try {
207             mIpClient.setMulticastFilter(enabled);
208             return true;
209         } catch (RemoteException e) {
210             log("Error setting multicast filter", e);
211             return false;
212         } finally {
213             Binder.restoreCallingIdentity(token);
214         }
215     }
216 
217     /**
218      * Add a TCP keepalive packet filter before setting up keepalive offload.
219      */
addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt)220     public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt) {
221         return addKeepalivePacketFilter(slot, KeepalivePacketDataUtil.toStableParcelable(pkt));
222     }
223 
224     /**
225      * Add a TCP keepalive packet filter before setting up keepalive offload.
226      * @deprecated This method is for use on pre-S platforms where TcpKeepalivePacketData is not
227      *             system API. On newer platforms use
228      *             addKeepalivePacketFilter(int, TcpKeepalivePacketData) instead.
229      */
230     @Deprecated
addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt)231     public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) {
232         final long token = Binder.clearCallingIdentity();
233         try {
234             mIpClient.addKeepalivePacketFilter(slot, pkt);
235             return true;
236         } catch (RemoteException e) {
237             log("Error adding Keepalive Packet Filter ", e);
238             return false;
239         } finally {
240             Binder.restoreCallingIdentity(token);
241         }
242     }
243 
244     /**
245      * Add a NAT-T keepalive packet filter before setting up keepalive offload.
246      */
addKeepalivePacketFilter(int slot, NattKeepalivePacketData pkt)247     public boolean addKeepalivePacketFilter(int slot, NattKeepalivePacketData pkt) {
248         final long token = Binder.clearCallingIdentity();
249         try {
250             mIpClient.addNattKeepalivePacketFilter(
251                     slot, KeepalivePacketDataUtil.toStableParcelable(pkt));
252             return true;
253         } catch (RemoteException e) {
254             log("Error adding NAT-T Keepalive Packet Filter ", e);
255             return false;
256         } finally {
257             Binder.restoreCallingIdentity(token);
258         }
259     }
260 
261     /**
262      * Remove a keepalive packet filter after stopping keepalive offload.
263      */
removeKeepalivePacketFilter(int slot)264     public boolean removeKeepalivePacketFilter(int slot) {
265         final long token = Binder.clearCallingIdentity();
266         try {
267             mIpClient.removeKeepalivePacketFilter(slot);
268             return true;
269         } catch (RemoteException e) {
270             log("Error removing Keepalive Packet Filter ", e);
271             return false;
272         } finally {
273             Binder.restoreCallingIdentity(token);
274         }
275     }
276 
277     /**
278      * Set the L2 key and group hint for storing info into the memory store.
279      */
setL2KeyAndGroupHint(String l2Key, String groupHint)280     public boolean setL2KeyAndGroupHint(String l2Key, String groupHint) {
281         final long token = Binder.clearCallingIdentity();
282         try {
283             mIpClient.setL2KeyAndGroupHint(l2Key, groupHint);
284             return true;
285         } catch (RemoteException e) {
286             log("Failed setL2KeyAndGroupHint", e);
287             return false;
288         } finally {
289             Binder.restoreCallingIdentity(token);
290         }
291     }
292 
293     /**
294      * Notify IpClient that preconnection is complete and that the link is ready for use.
295      * The success parameter indicates whether the packets passed in by 'onPreconnectionStart'
296      * were successfully sent to the network or not.
297      */
notifyPreconnectionComplete(boolean success)298     public boolean notifyPreconnectionComplete(boolean success) {
299         final long token = Binder.clearCallingIdentity();
300         try {
301             mIpClient.notifyPreconnectionComplete(success);
302             return true;
303         } catch (RemoteException e) {
304             log("Error notifying IpClient Preconnection completed", e);
305             return false;
306         } finally {
307             Binder.restoreCallingIdentity(token);
308         }
309     }
310 
311     /**
312      * Update the bssid, L2 key and group hint layer2 information.
313      */
updateLayer2Information(Layer2Information info)314     public boolean updateLayer2Information(Layer2Information info) {
315         final long token = Binder.clearCallingIdentity();
316         try {
317             mIpClient.updateLayer2Information(info.toStableParcelable());
318             return true;
319         } catch (RemoteException e) {
320             log("Error updating layer2 information", e);
321             return false;
322         } finally {
323             Binder.restoreCallingIdentity(token);
324         }
325     }
326 }
327