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