1c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline/*
2c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * Copyright (C) 2016 The Android Open Source Project
3c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline *
4c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * Licensed under the Apache License, Version 2.0 (the "License");
5c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * you may not use this file except in compliance with the License.
6c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * You may obtain a copy of the License at
7c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline *
8c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline *      http://www.apache.org/licenses/LICENSE-2.0
9c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline *
10c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * Unless required by applicable law or agreed to in writing, software
11c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * distributed under the License is distributed on an "AS IS" BASIS,
12c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * See the License for the specific language governing permissions and
14c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * limitations under the License.
15c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline */
16c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline
17c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Klinepackage android.net.util;
18c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline
19c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Klineimport android.net.INetd;
20af39244a34f4449c12a5f925222c9bc8d8049320Erik Klineimport android.os.RemoteException;
21c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Klineimport android.os.ServiceManager;
22af39244a34f4449c12a5f925222c9bc8d8049320Erik Klineimport android.os.ServiceSpecificException;
23af39244a34f4449c12a5f925222c9bc8d8049320Erik Klineimport android.os.SystemClock;
24c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Klineimport android.util.Log;
25c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline
26c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline
27c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline/**
28c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline * @hide
29c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline */
30c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Klinepublic class NetdService {
31c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline    private static final String TAG = NetdService.class.getSimpleName();
32c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline    private static final String NETD_SERVICE_NAME = "netd";
33af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    private static final long BASE_TIMEOUT_MS = 100;
34af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    private static final long MAX_TIMEOUT_MS = 1000;
35af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
36c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline
37c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline    /**
38af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * Return an INetd instance, or null if not available.
39af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
40c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline     * It is the caller's responsibility to check for a null return value
41c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline     * and to handle RemoteException errors from invocations on the returned
42c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline     * interface if, for example, netd dies and is restarted.
43c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline     *
44af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * Returned instances of INetd should not be cached.
45af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
46c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline     * @return an INetd instance or null.
47c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline     */
48c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline    public static INetd getInstance() {
49af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        // NOTE: ServiceManager does no caching for the netd service,
50af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        // because netd is not one of the defined common services.
51c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline        final INetd netdInstance = INetd.Stub.asInterface(
52c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline                ServiceManager.getService(NETD_SERVICE_NAME));
53c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline        if (netdInstance == null) {
54c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline            Log.w(TAG, "WARNING: returning null INetd instance.");
55c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline        }
56c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline        return netdInstance;
57c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline    }
58af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
59af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    /**
60af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * Blocks for a specified time until an INetd instance is available.
61af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
62af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * It is the caller's responsibility to handle RemoteException errors
63af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * from invocations on the returned interface if, for example, netd
64af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * dies after this interface was returned.
65af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
66af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * Returned instances of INetd should not be cached.
67af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
68af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * Special values of maxTimeoutMs include: 0, meaning try to obtain an
69af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * INetd instance only once, and -1 (or any value less than 0), meaning
70af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * try to obtain an INetd instance indefinitely.
71af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
72af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * @param maxTimeoutMs the maximum time to spend getting an INetd instance
73af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * @return an INetd instance or null if no instance is available
74af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * within |maxTimeoutMs| milliseconds.
75af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     */
76af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    public static INetd get(long maxTimeoutMs) {
77af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        if (maxTimeoutMs == 0) return getInstance();
78af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
79af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        final long stop = (maxTimeoutMs > 0)
80af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline                ? SystemClock.elapsedRealtime() + maxTimeoutMs
81af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline                : Long.MAX_VALUE;
82af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
83af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        long timeoutMs = 0;
84af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        while (true) {
85af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            final INetd netdInstance = getInstance();
86af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            if (netdInstance != null) {
87af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline                return netdInstance;
88af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            }
89af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
90af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            final long remaining = stop - SystemClock.elapsedRealtime();
91af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            if (remaining <= 0) break;
92af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
93af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            // No netdInstance was received; sleep and retry.
94af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            timeoutMs = Math.min(timeoutMs + BASE_TIMEOUT_MS, MAX_TIMEOUT_MS);
95af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            timeoutMs = Math.min(timeoutMs, remaining);
96af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            try {
97af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline                Thread.sleep(timeoutMs);
98af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            } catch (InterruptedException e) {}
99af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        }
100af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        return null;
101af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    }
102af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
103af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    /**
104af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * Blocks until an INetd instance is available.
105af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
106af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * It is the caller's responsibility to handle RemoteException errors
107af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * from invocations on the returned interface if, for example, netd
108af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * dies after this interface was returned.
109af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
110af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * Returned instances of INetd should not be cached.
111af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     *
112af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * @return an INetd instance.
113af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     */
114af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    public static INetd get() {
115af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        return get(-1);
116af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    }
117af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
118af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    public static interface NetdCommand {
119af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        void run(INetd netd) throws RemoteException;
120af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    }
121af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline
122af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    /**
123af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * Blocks until an INetd instance is availabe, and retries until either
124af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     * the command succeeds or a runtime exception is thrown.
125af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline     */
126af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    public static void run(NetdCommand cmd) {
127af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        while (true) {
128af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            try {
129af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline                cmd.run(get());
130af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline                return;
131af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            } catch (RemoteException re) {
132af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline                Log.e(TAG, "error communicating with netd: " + re);
133af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline            }
134af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline        }
135af39244a34f4449c12a5f925222c9bc8d8049320Erik Kline    }
136c1bc0be161f5be3b7f26938fc163cf6f6778b753Erik Kline}
137