• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 package android.os;
17 
18 import java.net.InetAddress;
19 import java.net.InetSocketAddress;
20 import java.util.NoSuchElementException;
21 
22 import android.os.CommonTimeUtils;
23 import android.os.IBinder;
24 import android.os.RemoteException;
25 import android.os.ServiceManager;
26 
27 /**
28  * Used for configuring and controlling the status of the android common time service.
29  * @hide
30  */
31 public class CommonTimeConfig {
32     /**
33      * Successful operation.
34      */
35     public static final int SUCCESS = 0;
36     /**
37      * Unspecified error.
38      */
39     public static final int ERROR = -1;
40     /**
41      * Operation failed due to bad parameter value.
42      */
43     public static final int ERROR_BAD_VALUE = -4;
44     /**
45      * Operation failed due to dead remote object.
46      */
47     public static final int ERROR_DEAD_OBJECT = -7;
48 
49     /**
50      * Sentinel value returned by {@link #getMasterElectionGroupId()} when an error occurs trying to
51      * fetch the master election group.
52      */
53     public static final long INVALID_GROUP_ID = -1;
54 
55     /**
56      * Name of the underlying native binder service
57      */
58     public static final String SERVICE_NAME = "common_time.config";
59 
60     /**
61      * Class constructor.
62      * @throws android.os.RemoteException
63      */
CommonTimeConfig()64     public CommonTimeConfig()
65     throws RemoteException {
66         mRemote = ServiceManager.getService(SERVICE_NAME);
67         if (null == mRemote)
68             throw new RemoteException();
69 
70         mInterfaceDesc = mRemote.getInterfaceDescriptor();
71         mUtils = new CommonTimeUtils(mRemote, mInterfaceDesc);
72         mRemote.linkToDeath(mDeathHandler, 0);
73     }
74 
75     /**
76      * Handy class factory method.
77      */
create()78     static public CommonTimeConfig create() {
79         CommonTimeConfig retVal;
80 
81         try {
82             retVal = new CommonTimeConfig();
83         }
84         catch (RemoteException e) {
85             retVal = null;
86         }
87 
88         return retVal;
89     }
90 
91     /**
92      * Release all native resources held by this {@link android.os.CommonTimeConfig} instance.  Once
93      * resources have been released, the {@link android.os.CommonTimeConfig} instance is
94      * disconnected from the native service and will throw a {@link android.os.RemoteException} if
95      * any of its methods are called.  Clients should always call release on their client instances
96      * before releasing their last Java reference to the instance.  Failure to do this will cause
97      * non-deterministic native resource reclamation and may cause the common time service to remain
98      * active on the network for longer than it should.
99      */
release()100     public void release() {
101         if (null != mRemote) {
102             try {
103                 mRemote.unlinkToDeath(mDeathHandler, 0);
104             }
105             catch (NoSuchElementException e) { }
106             mRemote = null;
107         }
108         mUtils = null;
109     }
110 
111     /**
112      * Gets the current priority of the common time service used in the master election protocol.
113      *
114      * @return an 8 bit value indicating the priority of this common time service relative to other
115      * common time services operating in the same domain.
116      * @throws android.os.RemoteException
117      */
getMasterElectionPriority()118     public byte getMasterElectionPriority()
119     throws RemoteException {
120         throwOnDeadServer();
121         return (byte)mUtils.transactGetInt(METHOD_GET_MASTER_ELECTION_PRIORITY, -1);
122     }
123 
124     /**
125      * Sets the current priority of the common time service used in the master election protocol.
126      *
127      * @param priority priority of the common time service used in the master election protocol.
128      * Lower numbers are lower priority.
129      * @return {@link #SUCCESS} in case of success,
130      * {@link #ERROR} or {@link #ERROR_DEAD_OBJECT} in case of failure.
131      */
setMasterElectionPriority(byte priority)132     public int setMasterElectionPriority(byte priority) {
133         if (checkDeadServer())
134             return ERROR_DEAD_OBJECT;
135         return mUtils.transactSetInt(METHOD_SET_MASTER_ELECTION_PRIORITY, priority);
136     }
137 
138     /**
139      * Gets the IP endpoint used by the time service to participate in the master election protocol.
140      *
141      * @return an InetSocketAddress containing the IP address and UDP port being used by the
142      * system's common time service to participate in the master election protocol.
143      * @throws android.os.RemoteException
144      */
getMasterElectionEndpoint()145     public InetSocketAddress getMasterElectionEndpoint()
146     throws RemoteException {
147         throwOnDeadServer();
148         return mUtils.transactGetSockaddr(METHOD_GET_MASTER_ELECTION_ENDPOINT);
149     }
150 
151     /**
152      * Sets the IP endpoint used by the common time service to participate in the master election
153      * protocol.
154      *
155      * @param ep The IP address and UDP port to be used by the common time service to participate in
156      * the master election protocol.  The supplied IP address must be either the broadcast or
157      * multicast address, unicast addresses are considered to be illegal values.
158      * @return {@link #SUCCESS} in case of success,
159      * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure.
160      */
setMasterElectionEndpoint(InetSocketAddress ep)161     public int setMasterElectionEndpoint(InetSocketAddress ep) {
162         if (checkDeadServer())
163             return ERROR_DEAD_OBJECT;
164         return mUtils.transactSetSockaddr(METHOD_SET_MASTER_ELECTION_ENDPOINT, ep);
165     }
166 
167     /**
168      * Gets the current group ID used by the common time service in the master election protocol.
169      *
170      * @return The 64-bit group ID of the common time service.
171      * @throws android.os.RemoteException
172      */
getMasterElectionGroupId()173     public long getMasterElectionGroupId()
174     throws RemoteException {
175         throwOnDeadServer();
176         return mUtils.transactGetLong(METHOD_GET_MASTER_ELECTION_GROUP_ID, INVALID_GROUP_ID);
177     }
178 
179     /**
180      * Sets the current group ID used by the common time service in the master election protocol.
181      *
182      * @param id The 64-bit group ID of the common time service.
183      * @return {@link #SUCCESS} in case of success,
184      * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure.
185      */
setMasterElectionGroupId(long id)186     public int setMasterElectionGroupId(long id) {
187         if (checkDeadServer())
188             return ERROR_DEAD_OBJECT;
189         return mUtils.transactSetLong(METHOD_SET_MASTER_ELECTION_GROUP_ID, id);
190     }
191 
192     /**
193      * Gets the name of the network interface which the common time service attempts to bind to.
194      *
195      * @return a string with the network interface name which the common time service is bound to,
196      * or null if the service is currently unbound.  Examples of interface names are things like
197      * "eth0", or "wlan0".
198      * @throws android.os.RemoteException
199      */
getInterfaceBinding()200     public String getInterfaceBinding()
201     throws RemoteException {
202         throwOnDeadServer();
203 
204         String ifaceName = mUtils.transactGetString(METHOD_GET_INTERFACE_BINDING, null);
205 
206         if ((null != ifaceName) && (0 == ifaceName.length()))
207                 return null;
208 
209         return ifaceName;
210     }
211 
212     /**
213      * Sets the name of the network interface which the common time service should attempt to bind
214      * to.
215      *
216      * @param ifaceName The name of the network interface ("eth0", "wlan0", etc...) wich the common
217      * time service should attempt to bind to, or null to force the common time service to unbind
218      * from the network and run in networkless mode.
219      * @return {@link #SUCCESS} in case of success,
220      * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure.
221      */
setNetworkBinding(String ifaceName)222     public int setNetworkBinding(String ifaceName) {
223         if (checkDeadServer())
224             return ERROR_DEAD_OBJECT;
225 
226         return mUtils.transactSetString(METHOD_SET_INTERFACE_BINDING,
227                                        (null == ifaceName) ? "" : ifaceName);
228     }
229 
230     /**
231      * Gets the amount of time the common time service will wait between master announcements when
232      * it is the timeline master.
233      *
234      * @return The time (in milliseconds) between master announcements.
235      * @throws android.os.RemoteException
236      */
getMasterAnnounceInterval()237     public int getMasterAnnounceInterval()
238     throws RemoteException {
239         throwOnDeadServer();
240         return mUtils.transactGetInt(METHOD_GET_MASTER_ANNOUNCE_INTERVAL, -1);
241     }
242 
243     /**
244      * Sets the amount of time the common time service will wait between master announcements when
245      * it is the timeline master.
246      *
247      * @param interval The time (in milliseconds) between master announcements.
248      * @return {@link #SUCCESS} in case of success,
249      * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure.
250      */
setMasterAnnounceInterval(int interval)251     public int setMasterAnnounceInterval(int interval) {
252         if (checkDeadServer())
253             return ERROR_DEAD_OBJECT;
254         return mUtils.transactSetInt(METHOD_SET_MASTER_ANNOUNCE_INTERVAL, interval);
255     }
256 
257     /**
258      * Gets the amount of time the common time service will wait between time synchronization
259      * requests when it is the client of another common time service on the network.
260      *
261      * @return The time (in milliseconds) between time sync requests.
262      * @throws android.os.RemoteException
263      */
getClientSyncInterval()264     public int getClientSyncInterval()
265     throws RemoteException {
266         throwOnDeadServer();
267         return mUtils.transactGetInt(METHOD_GET_CLIENT_SYNC_INTERVAL, -1);
268     }
269 
270     /**
271      * Sets the amount of time the common time service will wait between time synchronization
272      * requests when it is the client of another common time service on the network.
273      *
274      * @param interval The time (in milliseconds) between time sync requests.
275      * @return {@link #SUCCESS} in case of success,
276      * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure.
277      */
setClientSyncInterval(int interval)278     public int setClientSyncInterval(int interval) {
279         if (checkDeadServer())
280             return ERROR_DEAD_OBJECT;
281         return mUtils.transactSetInt(METHOD_SET_CLIENT_SYNC_INTERVAL, interval);
282     }
283 
284     /**
285      * Gets the panic threshold for the estimated error level of the common time service.  When the
286      * common time service's estimated error rises above this level, the service will panic and
287      * reset, causing a discontinuity in the currently synchronized timeline.
288      *
289      * @return The threshold (in microseconds) past which the common time service will panic.
290      * @throws android.os.RemoteException
291      */
getPanicThreshold()292     public int getPanicThreshold()
293     throws RemoteException {
294         throwOnDeadServer();
295         return mUtils.transactGetInt(METHOD_GET_PANIC_THRESHOLD, -1);
296     }
297 
298     /**
299      * Sets the panic threshold for the estimated error level of the common time service.  When the
300      * common time service's estimated error rises above this level, the service will panic and
301      * reset, causing a discontinuity in the currently synchronized timeline.
302      *
303      * @param threshold The threshold (in microseconds) past which the common time service will
304      * panic.
305      * @return {@link #SUCCESS} in case of success,
306      * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure.
307      */
setPanicThreshold(int threshold)308     public int setPanicThreshold(int threshold) {
309         if (checkDeadServer())
310             return ERROR_DEAD_OBJECT;
311         return mUtils.transactSetInt(METHOD_SET_PANIC_THRESHOLD, threshold);
312     }
313 
314     /**
315      * Gets the current state of the common time service's auto disable flag.
316      *
317      * @return The current state of the common time service's auto disable flag.
318      * @throws android.os.RemoteException
319      */
getAutoDisable()320     public boolean getAutoDisable()
321     throws RemoteException {
322         throwOnDeadServer();
323         return (1 == mUtils.transactGetInt(METHOD_GET_AUTO_DISABLE, 1));
324     }
325 
326     /**
327      * Sets the current state of the common time service's auto disable flag.  When the time
328      * service's auto disable flag is set, it will automatically cease all network activity when
329      * it has no active local clients, resuming activity the next time the service has interested
330      * local clients.  When the auto disabled flag is cleared, the common time service will continue
331      * to participate the time synchronization group even when it has no active local clients.
332      *
333      * @param autoDisable The desired state of the common time service's auto disable flag.
334      * @return {@link #SUCCESS} in case of success,
335      * {@link #ERROR} or {@link #ERROR_DEAD_OBJECT} in case of failure.
336      */
setAutoDisable(boolean autoDisable)337     public int setAutoDisable(boolean autoDisable) {
338         if (checkDeadServer())
339             return ERROR_DEAD_OBJECT;
340 
341         return mUtils.transactSetInt(METHOD_SET_AUTO_DISABLE, autoDisable ? 1 : 0);
342     }
343 
344     /**
345      * At startup, the time service enters the initial state and remains there until it is given a
346      * network interface to bind to.  Common time will be unavailable to clients of the common time
347      * service until the service joins a network (even an empty network).  Devices may use the
348      * {@link #forceNetworklessMasterMode()} method to force a time service in the INITIAL state
349      * with no network configuration to assume MASTER status for a brand new timeline in order to
350      * allow clients of the common time service to operate, even though the device is isolated and
351      * not on any network.  When a networkless master does join a network, it will defer to any
352      * masters already on the network, or continue to maintain the timeline it made up during its
353      * networkless state if no other masters are detected.  Attempting to force a client into master
354      * mode while it is actively bound to a network will fail with the status code {@link #ERROR}
355      *
356      * @return {@link #SUCCESS} in case of success,
357      * {@link #ERROR} or {@link #ERROR_DEAD_OBJECT} in case of failure.
358      */
forceNetworklessMasterMode()359     public int forceNetworklessMasterMode() {
360         android.os.Parcel data  = android.os.Parcel.obtain();
361         android.os.Parcel reply = android.os.Parcel.obtain();
362 
363         try {
364             data.writeInterfaceToken(mInterfaceDesc);
365             mRemote.transact(METHOD_FORCE_NETWORKLESS_MASTER_MODE, data, reply, 0);
366 
367             return reply.readInt();
368         }
369         catch (RemoteException e) {
370             return ERROR_DEAD_OBJECT;
371         }
372         finally {
373             reply.recycle();
374             data.recycle();
375         }
376     }
377 
378     /**
379      * The OnServerDiedListener interface defines a method called by the
380      * {@link android.os.CommonTimeConfig} instance to indicate that the connection to the native
381      * media server has been broken and that the {@link android.os.CommonTimeConfig} instance will
382      * need to be released and re-created.  The client application can implement this interface and
383      * register the listener with the {@link #setServerDiedListener(OnServerDiedListener)} method.
384      */
385     public interface OnServerDiedListener  {
386         /**
387          * Method called when the native common time service has died.  <p>If the native common time
388          * service encounters a fatal error and needs to restart, the binder connection from the
389          * {@link android.os.CommonTimeConfig} instance to the common time service will be broken.
390          */
onServerDied()391         void onServerDied();
392     }
393 
394     /**
395      * Registers an OnServerDiedListener interface.
396      * <p>Call this method with a null listener to stop receiving server death notifications.
397      */
setServerDiedListener(OnServerDiedListener listener)398     public void setServerDiedListener(OnServerDiedListener listener) {
399         synchronized (mListenerLock) {
400             mServerDiedListener = listener;
401         }
402     }
403 
finalize()404     protected void finalize() throws Throwable { release(); }
405 
checkDeadServer()406     private boolean checkDeadServer() {
407         return ((null == mRemote) || (null == mUtils));
408     }
409 
throwOnDeadServer()410     private void throwOnDeadServer() throws RemoteException {
411         if (checkDeadServer())
412             throw new RemoteException();
413     }
414 
415     private final Object mListenerLock = new Object();
416     private OnServerDiedListener mServerDiedListener = null;
417 
418     private IBinder mRemote = null;
419     private String mInterfaceDesc = "";
420     private CommonTimeUtils mUtils;
421 
422     private IBinder.DeathRecipient mDeathHandler = new IBinder.DeathRecipient() {
423         public void binderDied() {
424             synchronized (mListenerLock) {
425                 if (null != mServerDiedListener)
426                     mServerDiedListener.onServerDied();
427             }
428         }
429     };
430 
431     private static final int METHOD_GET_MASTER_ELECTION_PRIORITY = IBinder.FIRST_CALL_TRANSACTION;
432     private static final int METHOD_SET_MASTER_ELECTION_PRIORITY = METHOD_GET_MASTER_ELECTION_PRIORITY + 1;
433     private static final int METHOD_GET_MASTER_ELECTION_ENDPOINT = METHOD_SET_MASTER_ELECTION_PRIORITY + 1;
434     private static final int METHOD_SET_MASTER_ELECTION_ENDPOINT = METHOD_GET_MASTER_ELECTION_ENDPOINT + 1;
435     private static final int METHOD_GET_MASTER_ELECTION_GROUP_ID = METHOD_SET_MASTER_ELECTION_ENDPOINT + 1;
436     private static final int METHOD_SET_MASTER_ELECTION_GROUP_ID = METHOD_GET_MASTER_ELECTION_GROUP_ID + 1;
437     private static final int METHOD_GET_INTERFACE_BINDING = METHOD_SET_MASTER_ELECTION_GROUP_ID + 1;
438     private static final int METHOD_SET_INTERFACE_BINDING = METHOD_GET_INTERFACE_BINDING + 1;
439     private static final int METHOD_GET_MASTER_ANNOUNCE_INTERVAL = METHOD_SET_INTERFACE_BINDING + 1;
440     private static final int METHOD_SET_MASTER_ANNOUNCE_INTERVAL = METHOD_GET_MASTER_ANNOUNCE_INTERVAL + 1;
441     private static final int METHOD_GET_CLIENT_SYNC_INTERVAL = METHOD_SET_MASTER_ANNOUNCE_INTERVAL + 1;
442     private static final int METHOD_SET_CLIENT_SYNC_INTERVAL = METHOD_GET_CLIENT_SYNC_INTERVAL + 1;
443     private static final int METHOD_GET_PANIC_THRESHOLD = METHOD_SET_CLIENT_SYNC_INTERVAL + 1;
444     private static final int METHOD_SET_PANIC_THRESHOLD = METHOD_GET_PANIC_THRESHOLD + 1;
445     private static final int METHOD_GET_AUTO_DISABLE = METHOD_SET_PANIC_THRESHOLD + 1;
446     private static final int METHOD_SET_AUTO_DISABLE = METHOD_GET_AUTO_DISABLE + 1;
447     private static final int METHOD_FORCE_NETWORKLESS_MASTER_MODE = METHOD_SET_AUTO_DISABLE + 1;
448 }
449