| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.net.ip; |
| |
| import android.annotation.Hide; |
| import android.annotation.NonNull; |
| import android.net.NattKeepalivePacketData; |
| import android.net.ProxyInfo; |
| import android.net.TcpKeepalivePacketData; |
| import android.net.shared.Layer2Information; |
| import android.net.shared.ProvisioningConfiguration; |
| import android.net.util.KeepalivePacketDataUtil; |
| import android.os.Binder; |
| import android.os.RemoteException; |
| import android.util.Log; |
| |
| /** |
| * A convenience wrapper for IpClient. |
| * |
| * Wraps IIpClient calls, making them a bit more friendly to use. Currently handles: |
| * - Clearing calling identity |
| * - Ignoring RemoteExceptions |
| * - Converting to stable parcelables |
| * |
| * By design, all methods on IIpClient are asynchronous oneway IPCs and are thus void. All the |
| * wrapper methods in this class return a boolean that callers can use to determine whether |
| * RemoteException was thrown. |
| */ |
| @Hide |
| public class IpClientManager { |
| @NonNull private final IIpClient mIpClient; |
| @NonNull private final String mTag; |
| |
| public IpClientManager(@NonNull IIpClient ipClient, @NonNull String tag) { |
| mIpClient = ipClient; |
| mTag = tag; |
| } |
| |
| public IpClientManager(@NonNull IIpClient ipClient) { |
| this(ipClient, IpClientManager.class.getSimpleName()); |
| } |
| |
| private void log(String s, Throwable e) { |
| Log.e(mTag, s, e); |
| } |
| |
| /** |
| * For clients using {@link ProvisioningConfiguration.Builder#withPreDhcpAction()}, must be |
| * called after {@link IIpClientCallbacks#onPreDhcpAction} to indicate that DHCP is clear to |
| * proceed. |
| */ |
| public boolean completedPreDhcpAction() { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.completedPreDhcpAction(); |
| return true; |
| } catch (RemoteException e) { |
| log("Error completing PreDhcpAction", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Confirm the provisioning configuration. |
| */ |
| public boolean confirmConfiguration() { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.confirmConfiguration(); |
| return true; |
| } catch (RemoteException e) { |
| log("Error confirming IpClient configuration", e); |
| return false; |
| } |
| } |
| |
| /** |
| * Indicate that packet filter read is complete. |
| */ |
| public boolean readPacketFilterComplete(byte[] data) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.readPacketFilterComplete(data); |
| return true; |
| } catch (RemoteException e) { |
| log("Error notifying IpClient of packet filter read", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Shut down this IpClient instance altogether. |
| */ |
| public boolean shutdown() { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.shutdown(); |
| return true; |
| } catch (RemoteException e) { |
| log("Error shutting down IpClient", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Start provisioning with the provided parameters. |
| */ |
| public boolean startProvisioning(ProvisioningConfiguration prov) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.startProvisioning(prov.toStableParcelable()); |
| return true; |
| } catch (RemoteException e) { |
| log("Error starting IpClient provisioning", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Stop this IpClient. |
| * |
| * <p>This does not shut down the StateMachine itself, which is handled by {@link #shutdown()}. |
| */ |
| public boolean stop() { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.stop(); |
| return true; |
| } catch (RemoteException e) { |
| log("Error stopping IpClient", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Set the TCP buffer sizes to use. |
| * |
| * This may be called, repeatedly, at any time before or after a call to |
| * #startProvisioning(). The setting is cleared upon calling #stop(). |
| */ |
| public boolean setTcpBufferSizes(String tcpBufferSizes) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.setTcpBufferSizes(tcpBufferSizes); |
| return true; |
| } catch (RemoteException e) { |
| log("Error setting IpClient TCP buffer sizes", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Set the HTTP Proxy configuration to use. |
| * |
| * This may be called, repeatedly, at any time before or after a call to |
| * #startProvisioning(). The setting is cleared upon calling #stop(). |
| */ |
| public boolean setHttpProxy(ProxyInfo proxyInfo) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.setHttpProxy(proxyInfo); |
| return true; |
| } catch (RemoteException e) { |
| log("Error setting IpClient proxy", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Enable or disable the multicast filter. Attempts to use APF to accomplish the filtering, |
| * if not, Callback.setFallbackMulticastFilter() is called. |
| */ |
| public boolean setMulticastFilter(boolean enabled) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.setMulticastFilter(enabled); |
| return true; |
| } catch (RemoteException e) { |
| log("Error setting multicast filter", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Add a TCP keepalive packet filter before setting up keepalive offload. |
| */ |
| public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.addKeepalivePacketFilter(slot, pkt.toStableParcelable()); |
| return true; |
| } catch (RemoteException e) { |
| log("Error adding Keepalive Packet Filter ", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Add a NAT-T keepalive packet filter before setting up keepalive offload. |
| */ |
| public boolean addKeepalivePacketFilter(int slot, NattKeepalivePacketData pkt) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.addNattKeepalivePacketFilter( |
| slot, KeepalivePacketDataUtil.toStableParcelable(pkt)); |
| return true; |
| } catch (RemoteException e) { |
| log("Error adding NAT-T Keepalive Packet Filter ", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Remove a keepalive packet filter after stopping keepalive offload. |
| */ |
| public boolean removeKeepalivePacketFilter(int slot) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.removeKeepalivePacketFilter(slot); |
| return true; |
| } catch (RemoteException e) { |
| log("Error removing Keepalive Packet Filter ", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Set the L2 key and group hint for storing info into the memory store. |
| */ |
| public boolean setL2KeyAndGroupHint(String l2Key, String groupHint) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.setL2KeyAndGroupHint(l2Key, groupHint); |
| return true; |
| } catch (RemoteException e) { |
| log("Failed setL2KeyAndGroupHint", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Notify IpClient that preconnection is complete and that the link is ready for use. |
| * The success parameter indicates whether the packets passed in by 'onPreconnectionStart' |
| * were successfully sent to the network or not. |
| */ |
| public boolean notifyPreconnectionComplete(boolean success) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.notifyPreconnectionComplete(success); |
| return true; |
| } catch (RemoteException e) { |
| log("Error notifying IpClient Preconnection completed", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| |
| /** |
| * Update the bssid, L2 key and group hint layer2 information. |
| */ |
| public boolean updateLayer2Information(Layer2Information info) { |
| final long token = Binder.clearCallingIdentity(); |
| try { |
| mIpClient.updateLayer2Information(info.toStableParcelable()); |
| return true; |
| } catch (RemoteException e) { |
| log("Error updating layer2 information", e); |
| return false; |
| } finally { |
| Binder.restoreCallingIdentity(token); |
| } |
| } |
| } |