137237839e87988208296a57d70767ebbd9c6880bJohn Grossman/* 237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Copyright (C) 2012 The Android Open Source Project 337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Licensed under the Apache License, Version 2.0 (the "License"); 537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * you may not use this file except in compliance with the License. 637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * You may obtain a copy of the License at 737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * http://www.apache.org/licenses/LICENSE-2.0 937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 1037237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Unless required by applicable law or agreed to in writing, software 1137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * distributed under the License is distributed on an "AS IS" BASIS, 1237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * See the License for the specific language governing permissions and 1437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * limitations under the License. 1537237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 1637237839e87988208296a57d70767ebbd9c6880bJohn Grossmanpackage android.os; 1737237839e87988208296a57d70767ebbd9c6880bJohn Grossman 1837237839e87988208296a57d70767ebbd9c6880bJohn Grossmanimport java.net.InetSocketAddress; 1937237839e87988208296a57d70767ebbd9c6880bJohn Grossmanimport java.util.NoSuchElementException; 2037237839e87988208296a57d70767ebbd9c6880bJohn Grossmanimport android.os.Binder; 2137237839e87988208296a57d70767ebbd9c6880bJohn Grossmanimport android.os.CommonTimeUtils; 2237237839e87988208296a57d70767ebbd9c6880bJohn Grossmanimport android.os.IBinder; 2337237839e87988208296a57d70767ebbd9c6880bJohn Grossmanimport android.os.Parcel; 2437237839e87988208296a57d70767ebbd9c6880bJohn Grossmanimport android.os.RemoteException; 2537237839e87988208296a57d70767ebbd9c6880bJohn Grossmanimport android.os.ServiceManager; 2637237839e87988208296a57d70767ebbd9c6880bJohn Grossman 2737237839e87988208296a57d70767ebbd9c6880bJohn Grossman/** 2837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Used for accessing the android common time service's common clock and receiving notifications 2937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * about common time synchronization status changes. 3037237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @hide 3137237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 3237237839e87988208296a57d70767ebbd9c6880bJohn Grossmanpublic class CommonClock { 3337237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 3437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Sentinel value returned by {@link #getTime()} and {@link #getEstimatedError()} when the 3537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * common time service is not able to determine the current common time due to a lack of 3637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * synchronization. 3737237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 3837237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final long TIME_NOT_SYNCED = -1; 3937237839e87988208296a57d70767ebbd9c6880bJohn Grossman 4037237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 4137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Sentinel value returned by {@link #getTimelineId()} when the common time service is not 4237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * currently synced to any timeline. 4337237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 4437237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final long INVALID_TIMELINE_ID = 0; 4537237839e87988208296a57d70767ebbd9c6880bJohn Grossman 4637237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 4737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Sentinel value returned by {@link #getEstimatedError()} when the common time service is not 4837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * currently synced to any timeline. 4937237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 5037237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final int ERROR_ESTIMATE_UNKNOWN = 0x7FFFFFFF; 5137237839e87988208296a57d70767ebbd9c6880bJohn Grossman 5237237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 5337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Value used by {@link #getState()} to indicate that there was an internal error while 5437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * attempting to determine the state of the common time service. 5537237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 5637237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final int STATE_INVALID = -1; 5737237839e87988208296a57d70767ebbd9c6880bJohn Grossman 5837237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 5937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Value used by {@link #getState()} to indicate that the common time service is in its initial 6037237839e87988208296a57d70767ebbd9c6880bJohn Grossman * state and attempting to find the current timeline master, if any. The service will 6137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * transition to either {@link #STATE_CLIENT} if it finds an active master, or to 6237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * {@link #STATE_MASTER} if no active master is found and this client becomes the master of a 6337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * new timeline. 6437237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 6537237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final int STATE_INITIAL = 0; 6637237839e87988208296a57d70767ebbd9c6880bJohn Grossman 6737237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 6837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Value used by {@link #getState()} to indicate that the common time service is in its client 6937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * state and is synchronizing its time to a different timeline master on the network. 7037237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 7137237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final int STATE_CLIENT = 1; 7237237839e87988208296a57d70767ebbd9c6880bJohn Grossman 7337237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 7437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Value used by {@link #getState()} to indicate that the common time service is in its master 7537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * state and is serving as the timeline master for other common time service clients on the 7637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * network. 7737237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 7837237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final int STATE_MASTER = 2; 7937237839e87988208296a57d70767ebbd9c6880bJohn Grossman 8037237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 8137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Value used by {@link #getState()} to indicate that the common time service is in its Ronin 8237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * state. Common time service instances in the client state enter the Ronin state after their 8337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * timeline master becomes unreachable on the network. Common time services who enter the Ronin 8437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * state will begin a new master election for the timeline they were recently clients of. As 8537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * clients detect they are not the winner and drop out of the election, they will transition to 8637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * the {@link #STATE_WAIT_FOR_ELECTION} state. When there is only one client remaining in the 8737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * election, it will assume ownership of the timeline and transition to the 8837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * {@link #STATE_MASTER} state. During the election, all clients will allow their timeline to 8937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * drift without applying correction. 9037237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 9137237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final int STATE_RONIN = 3; 9237237839e87988208296a57d70767ebbd9c6880bJohn Grossman 9337237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 9437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Value used by {@link #getState()} to indicate that the common time service is waiting for a 9537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * master election to conclude and for the new master to announce itself before transitioning to 9637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * the {@link #STATE_CLIENT} state. If no new master announces itself within the timeout 9737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * threshold, the time service will transition back to the {@link #STATE_RONIN} state in order 9837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * to restart the election. 9937237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 10037237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final int STATE_WAIT_FOR_ELECTION = 4; 10137237839e87988208296a57d70767ebbd9c6880bJohn Grossman 10237237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 10337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Name of the underlying native binder service 10437237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 10537237839e87988208296a57d70767ebbd9c6880bJohn Grossman public static final String SERVICE_NAME = "common_time.clock"; 10637237839e87988208296a57d70767ebbd9c6880bJohn Grossman 10737237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 10837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Class constructor. 10937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @throws android.os.RemoteException 11037237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 11137237839e87988208296a57d70767ebbd9c6880bJohn Grossman public CommonClock() 11237237839e87988208296a57d70767ebbd9c6880bJohn Grossman throws RemoteException { 11337237839e87988208296a57d70767ebbd9c6880bJohn Grossman mRemote = ServiceManager.getService(SERVICE_NAME); 11437237839e87988208296a57d70767ebbd9c6880bJohn Grossman if (null == mRemote) 11537237839e87988208296a57d70767ebbd9c6880bJohn Grossman throw new RemoteException(); 11637237839e87988208296a57d70767ebbd9c6880bJohn Grossman 11737237839e87988208296a57d70767ebbd9c6880bJohn Grossman mInterfaceDesc = mRemote.getInterfaceDescriptor(); 11837237839e87988208296a57d70767ebbd9c6880bJohn Grossman mUtils = new CommonTimeUtils(mRemote, mInterfaceDesc); 11937237839e87988208296a57d70767ebbd9c6880bJohn Grossman mRemote.linkToDeath(mDeathHandler, 0); 12037237839e87988208296a57d70767ebbd9c6880bJohn Grossman registerTimelineChangeListener(); 12137237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 12237237839e87988208296a57d70767ebbd9c6880bJohn Grossman 12337237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 12437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Handy class factory method. 12537237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 12637237839e87988208296a57d70767ebbd9c6880bJohn Grossman static public CommonClock create() { 12737237839e87988208296a57d70767ebbd9c6880bJohn Grossman CommonClock retVal; 12837237839e87988208296a57d70767ebbd9c6880bJohn Grossman 12937237839e87988208296a57d70767ebbd9c6880bJohn Grossman try { 13037237839e87988208296a57d70767ebbd9c6880bJohn Grossman retVal = new CommonClock(); 13137237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 13237237839e87988208296a57d70767ebbd9c6880bJohn Grossman catch (RemoteException e) { 13337237839e87988208296a57d70767ebbd9c6880bJohn Grossman retVal = null; 13437237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 13537237839e87988208296a57d70767ebbd9c6880bJohn Grossman 13637237839e87988208296a57d70767ebbd9c6880bJohn Grossman return retVal; 13737237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 13837237839e87988208296a57d70767ebbd9c6880bJohn Grossman 13937237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 14037237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Release all native resources held by this {@link android.os.CommonClock} instance. Once 14137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * resources have been released, the {@link android.os.CommonClock} instance is disconnected from 14237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * the native service and will throw a {@link android.os.RemoteException} if any of its 14337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * methods are called. Clients should always call release on their client instances before 14437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * releasing their last Java reference to the instance. Failure to do this will cause 14537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * non-deterministic native resource reclamation and may cause the common time service to remain 14637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * active on the network for longer than it should. 14737237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 14837237839e87988208296a57d70767ebbd9c6880bJohn Grossman public void release() { 14937237839e87988208296a57d70767ebbd9c6880bJohn Grossman unregisterTimelineChangeListener(); 15037237839e87988208296a57d70767ebbd9c6880bJohn Grossman if (null != mRemote) { 15137237839e87988208296a57d70767ebbd9c6880bJohn Grossman try { 15237237839e87988208296a57d70767ebbd9c6880bJohn Grossman mRemote.unlinkToDeath(mDeathHandler, 0); 15337237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 15437237839e87988208296a57d70767ebbd9c6880bJohn Grossman catch (NoSuchElementException e) { } 15537237839e87988208296a57d70767ebbd9c6880bJohn Grossman mRemote = null; 15637237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 15737237839e87988208296a57d70767ebbd9c6880bJohn Grossman mUtils = null; 15837237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 15937237839e87988208296a57d70767ebbd9c6880bJohn Grossman 16037237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 16137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Gets the common clock's current time. 16237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 16337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @return a signed 64-bit value representing the current common time in microseconds, or the 16437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * special value {@link #TIME_NOT_SYNCED} if the common time service is currently not 16537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * synchronized. 16637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @throws android.os.RemoteException 16737237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 16837237839e87988208296a57d70767ebbd9c6880bJohn Grossman public long getTime() 16937237839e87988208296a57d70767ebbd9c6880bJohn Grossman throws RemoteException { 17037237839e87988208296a57d70767ebbd9c6880bJohn Grossman throwOnDeadServer(); 17137237839e87988208296a57d70767ebbd9c6880bJohn Grossman return mUtils.transactGetLong(METHOD_GET_COMMON_TIME, TIME_NOT_SYNCED); 17237237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 17337237839e87988208296a57d70767ebbd9c6880bJohn Grossman 17437237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 17537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Gets the current estimation of common clock's synchronization accuracy from the common time 17637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * service. 17737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 17837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @return a signed 32-bit value representing the common time service's estimation of 17937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * synchronization accuracy in microseconds, or the special value 18037237839e87988208296a57d70767ebbd9c6880bJohn Grossman * {@link #ERROR_ESTIMATE_UNKNOWN} if the common time service is currently not synchronized. 18137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Negative values indicate that the local server estimates that the nominal common time is 18237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * behind the local server's time (in other words, the local clock is running fast) Positive 18337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * values indicate that the local server estimates that the nominal common time is ahead of the 18437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * local server's time (in other words, the local clock is running slow) 18537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @throws android.os.RemoteException 18637237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 18737237839e87988208296a57d70767ebbd9c6880bJohn Grossman public int getEstimatedError() 18837237839e87988208296a57d70767ebbd9c6880bJohn Grossman throws RemoteException { 18937237839e87988208296a57d70767ebbd9c6880bJohn Grossman throwOnDeadServer(); 19037237839e87988208296a57d70767ebbd9c6880bJohn Grossman return mUtils.transactGetInt(METHOD_GET_ESTIMATED_ERROR, ERROR_ESTIMATE_UNKNOWN); 19137237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 19237237839e87988208296a57d70767ebbd9c6880bJohn Grossman 19337237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 19437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Gets the ID of the timeline the common time service is currently synchronizing its clock to. 19537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 19637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @return a long representing the unique ID of the timeline the common time service is 19737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * currently synchronizing with, or {@link #INVALID_TIMELINE_ID} if the common time service is 19837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * currently not synchronized. 19937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @throws android.os.RemoteException 20037237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 20137237839e87988208296a57d70767ebbd9c6880bJohn Grossman public long getTimelineId() 20237237839e87988208296a57d70767ebbd9c6880bJohn Grossman throws RemoteException { 20337237839e87988208296a57d70767ebbd9c6880bJohn Grossman throwOnDeadServer(); 20437237839e87988208296a57d70767ebbd9c6880bJohn Grossman return mUtils.transactGetLong(METHOD_GET_TIMELINE_ID, INVALID_TIMELINE_ID); 20537237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 20637237839e87988208296a57d70767ebbd9c6880bJohn Grossman 20737237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 20837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Gets the current state of this clock's common time service in the the master election 20937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * algorithm. 21037237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 21137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @return a integer indicating the current state of the this clock's common time service in the 21237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * master election algorithm or {@link #STATE_INVALID} if there is an internal error. 21337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @throws android.os.RemoteException 21437237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 21537237839e87988208296a57d70767ebbd9c6880bJohn Grossman public int getState() 21637237839e87988208296a57d70767ebbd9c6880bJohn Grossman throws RemoteException { 21737237839e87988208296a57d70767ebbd9c6880bJohn Grossman throwOnDeadServer(); 21837237839e87988208296a57d70767ebbd9c6880bJohn Grossman return mUtils.transactGetInt(METHOD_GET_STATE, STATE_INVALID); 21937237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 22037237839e87988208296a57d70767ebbd9c6880bJohn Grossman 22137237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 22237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Gets the IP address and UDP port of the current timeline master. 22337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 22437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @return an InetSocketAddress containing the IP address and UDP port of the current timeline 22537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * master, or null if there is no current master. 22637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @throws android.os.RemoteException 22737237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 22837237839e87988208296a57d70767ebbd9c6880bJohn Grossman public InetSocketAddress getMasterAddr() 22937237839e87988208296a57d70767ebbd9c6880bJohn Grossman throws RemoteException { 23037237839e87988208296a57d70767ebbd9c6880bJohn Grossman throwOnDeadServer(); 23137237839e87988208296a57d70767ebbd9c6880bJohn Grossman return mUtils.transactGetSockaddr(METHOD_GET_MASTER_ADDRESS); 23237237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 23337237839e87988208296a57d70767ebbd9c6880bJohn Grossman 23437237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 23537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * The OnTimelineChangedListener interface defines a method called by the 23637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * {@link android.os.CommonClock} instance to indicate that the time synchronization service has 23737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * either synchronized with a new timeline, or is no longer a member of any timeline. The 23837237839e87988208296a57d70767ebbd9c6880bJohn Grossman * client application can implement this interface and register the listener with the 23937237839e87988208296a57d70767ebbd9c6880bJohn Grossman * {@link #setTimelineChangedListener(OnTimelineChangedListener)} method. 24037237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 24137237839e87988208296a57d70767ebbd9c6880bJohn Grossman public interface OnTimelineChangedListener { 24237237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 24337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Method called when the time service's timeline has changed. 24437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * 24537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * @param newTimelineId a long which uniquely identifies the timeline the time 24637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * synchronization service is now a member of, or {@link #INVALID_TIMELINE_ID} if the the 24737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * service is not synchronized to any timeline. 24837237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 24937237839e87988208296a57d70767ebbd9c6880bJohn Grossman void onTimelineChanged(long newTimelineId); 25037237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 25137237839e87988208296a57d70767ebbd9c6880bJohn Grossman 25237237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 25337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Registers an OnTimelineChangedListener interface. 25437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * <p>Call this method with a null listener to stop receiving server death notifications. 25537237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 25637237839e87988208296a57d70767ebbd9c6880bJohn Grossman public void setTimelineChangedListener(OnTimelineChangedListener listener) { 25737237839e87988208296a57d70767ebbd9c6880bJohn Grossman synchronized (mListenerLock) { 25837237839e87988208296a57d70767ebbd9c6880bJohn Grossman mTimelineChangedListener = listener; 25937237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 26037237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 26137237839e87988208296a57d70767ebbd9c6880bJohn Grossman 26237237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 26337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * The OnServerDiedListener interface defines a method called by the 26437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * {@link android.os.CommonClock} instance to indicate that the connection to the native media 26537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * server has been broken and that the {@link android.os.CommonClock} instance will need to be 26637237839e87988208296a57d70767ebbd9c6880bJohn Grossman * released and re-created. The client application can implement this interface and register 26737237839e87988208296a57d70767ebbd9c6880bJohn Grossman * the listener with the {@link #setServerDiedListener(OnServerDiedListener)} method. 26837237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 26937237839e87988208296a57d70767ebbd9c6880bJohn Grossman public interface OnServerDiedListener { 27037237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 27137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Method called when the native media server has died. <p>If the native common time 27237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * service encounters a fatal error and needs to restart, the binder connection from the 27337237839e87988208296a57d70767ebbd9c6880bJohn Grossman * {@link android.os.CommonClock} instance to the common time service will be broken. To 27437237839e87988208296a57d70767ebbd9c6880bJohn Grossman * restore functionality, clients should {@link #release()} their old visualizer and create 27537237839e87988208296a57d70767ebbd9c6880bJohn Grossman * a new instance. 27637237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 27737237839e87988208296a57d70767ebbd9c6880bJohn Grossman void onServerDied(); 27837237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 27937237839e87988208296a57d70767ebbd9c6880bJohn Grossman 28037237839e87988208296a57d70767ebbd9c6880bJohn Grossman /** 28137237839e87988208296a57d70767ebbd9c6880bJohn Grossman * Registers an OnServerDiedListener interface. 28237237839e87988208296a57d70767ebbd9c6880bJohn Grossman * <p>Call this method with a null listener to stop receiving server death notifications. 28337237839e87988208296a57d70767ebbd9c6880bJohn Grossman */ 28437237839e87988208296a57d70767ebbd9c6880bJohn Grossman public void setServerDiedListener(OnServerDiedListener listener) { 28537237839e87988208296a57d70767ebbd9c6880bJohn Grossman synchronized (mListenerLock) { 28637237839e87988208296a57d70767ebbd9c6880bJohn Grossman mServerDiedListener = listener; 28737237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 28837237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 28937237839e87988208296a57d70767ebbd9c6880bJohn Grossman 29037237839e87988208296a57d70767ebbd9c6880bJohn Grossman protected void finalize() throws Throwable { release(); } 29137237839e87988208296a57d70767ebbd9c6880bJohn Grossman 29237237839e87988208296a57d70767ebbd9c6880bJohn Grossman private void throwOnDeadServer() throws RemoteException { 29337237839e87988208296a57d70767ebbd9c6880bJohn Grossman if ((null == mRemote) || (null == mUtils)) 29437237839e87988208296a57d70767ebbd9c6880bJohn Grossman throw new RemoteException(); 29537237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 29637237839e87988208296a57d70767ebbd9c6880bJohn Grossman 29737237839e87988208296a57d70767ebbd9c6880bJohn Grossman private final Object mListenerLock = new Object(); 29837237839e87988208296a57d70767ebbd9c6880bJohn Grossman private OnTimelineChangedListener mTimelineChangedListener = null; 29937237839e87988208296a57d70767ebbd9c6880bJohn Grossman private OnServerDiedListener mServerDiedListener = null; 30037237839e87988208296a57d70767ebbd9c6880bJohn Grossman 30137237839e87988208296a57d70767ebbd9c6880bJohn Grossman private IBinder mRemote = null; 30237237839e87988208296a57d70767ebbd9c6880bJohn Grossman private String mInterfaceDesc = ""; 30337237839e87988208296a57d70767ebbd9c6880bJohn Grossman private CommonTimeUtils mUtils; 30437237839e87988208296a57d70767ebbd9c6880bJohn Grossman 30537237839e87988208296a57d70767ebbd9c6880bJohn Grossman private IBinder.DeathRecipient mDeathHandler = new IBinder.DeathRecipient() { 30637237839e87988208296a57d70767ebbd9c6880bJohn Grossman public void binderDied() { 30737237839e87988208296a57d70767ebbd9c6880bJohn Grossman synchronized (mListenerLock) { 30837237839e87988208296a57d70767ebbd9c6880bJohn Grossman if (null != mServerDiedListener) 30937237839e87988208296a57d70767ebbd9c6880bJohn Grossman mServerDiedListener.onServerDied(); 31037237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 31137237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 31237237839e87988208296a57d70767ebbd9c6880bJohn Grossman }; 31337237839e87988208296a57d70767ebbd9c6880bJohn Grossman 31437237839e87988208296a57d70767ebbd9c6880bJohn Grossman private class TimelineChangedListener extends Binder { 31537237839e87988208296a57d70767ebbd9c6880bJohn Grossman @Override 31637237839e87988208296a57d70767ebbd9c6880bJohn Grossman protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) 31737237839e87988208296a57d70767ebbd9c6880bJohn Grossman throws RemoteException { 31837237839e87988208296a57d70767ebbd9c6880bJohn Grossman switch (code) { 31937237839e87988208296a57d70767ebbd9c6880bJohn Grossman case METHOD_CBK_ON_TIMELINE_CHANGED: 32037237839e87988208296a57d70767ebbd9c6880bJohn Grossman data.enforceInterface(DESCRIPTOR); 32137237839e87988208296a57d70767ebbd9c6880bJohn Grossman long timelineId = data.readLong(); 32237237839e87988208296a57d70767ebbd9c6880bJohn Grossman synchronized (mListenerLock) { 32337237839e87988208296a57d70767ebbd9c6880bJohn Grossman if (null != mTimelineChangedListener) 32437237839e87988208296a57d70767ebbd9c6880bJohn Grossman mTimelineChangedListener.onTimelineChanged(timelineId); 32537237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 32637237839e87988208296a57d70767ebbd9c6880bJohn Grossman return true; 32737237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 32837237839e87988208296a57d70767ebbd9c6880bJohn Grossman 32937237839e87988208296a57d70767ebbd9c6880bJohn Grossman return super.onTransact(code, data, reply, flags); 33037237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 33137237839e87988208296a57d70767ebbd9c6880bJohn Grossman 33237237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final String DESCRIPTOR = "android.os.ICommonClockListener"; 33337237839e87988208296a57d70767ebbd9c6880bJohn Grossman }; 33437237839e87988208296a57d70767ebbd9c6880bJohn Grossman 33537237839e87988208296a57d70767ebbd9c6880bJohn Grossman private TimelineChangedListener mCallbackTgt = null; 33637237839e87988208296a57d70767ebbd9c6880bJohn Grossman 33737237839e87988208296a57d70767ebbd9c6880bJohn Grossman private void registerTimelineChangeListener() throws RemoteException { 33837237839e87988208296a57d70767ebbd9c6880bJohn Grossman if (null != mCallbackTgt) 33937237839e87988208296a57d70767ebbd9c6880bJohn Grossman return; 34037237839e87988208296a57d70767ebbd9c6880bJohn Grossman 34137237839e87988208296a57d70767ebbd9c6880bJohn Grossman boolean success = false; 34237237839e87988208296a57d70767ebbd9c6880bJohn Grossman android.os.Parcel data = android.os.Parcel.obtain(); 34337237839e87988208296a57d70767ebbd9c6880bJohn Grossman android.os.Parcel reply = android.os.Parcel.obtain(); 34437237839e87988208296a57d70767ebbd9c6880bJohn Grossman mCallbackTgt = new TimelineChangedListener(); 34537237839e87988208296a57d70767ebbd9c6880bJohn Grossman 34637237839e87988208296a57d70767ebbd9c6880bJohn Grossman try { 34737237839e87988208296a57d70767ebbd9c6880bJohn Grossman data.writeInterfaceToken(mInterfaceDesc); 34837237839e87988208296a57d70767ebbd9c6880bJohn Grossman data.writeStrongBinder(mCallbackTgt); 34937237839e87988208296a57d70767ebbd9c6880bJohn Grossman mRemote.transact(METHOD_REGISTER_LISTENER, data, reply, 0); 35037237839e87988208296a57d70767ebbd9c6880bJohn Grossman success = (0 == reply.readInt()); 35137237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 35237237839e87988208296a57d70767ebbd9c6880bJohn Grossman catch (RemoteException e) { 35337237839e87988208296a57d70767ebbd9c6880bJohn Grossman success = false; 35437237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 35537237839e87988208296a57d70767ebbd9c6880bJohn Grossman finally { 35637237839e87988208296a57d70767ebbd9c6880bJohn Grossman reply.recycle(); 35737237839e87988208296a57d70767ebbd9c6880bJohn Grossman data.recycle(); 35837237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 35937237839e87988208296a57d70767ebbd9c6880bJohn Grossman 36037237839e87988208296a57d70767ebbd9c6880bJohn Grossman // Did we catch a remote exception or fail to register our callback target? If so, our 36137237839e87988208296a57d70767ebbd9c6880bJohn Grossman // object must already be dead (or be as good as dead). Clear out all of our state so that 36237237839e87988208296a57d70767ebbd9c6880bJohn Grossman // our other methods will properly indicate a dead object. 36337237839e87988208296a57d70767ebbd9c6880bJohn Grossman if (!success) { 36437237839e87988208296a57d70767ebbd9c6880bJohn Grossman mCallbackTgt = null; 36537237839e87988208296a57d70767ebbd9c6880bJohn Grossman mRemote = null; 36637237839e87988208296a57d70767ebbd9c6880bJohn Grossman mUtils = null; 36737237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 36837237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 36937237839e87988208296a57d70767ebbd9c6880bJohn Grossman 37037237839e87988208296a57d70767ebbd9c6880bJohn Grossman private void unregisterTimelineChangeListener() { 37137237839e87988208296a57d70767ebbd9c6880bJohn Grossman if (null == mCallbackTgt) 37237237839e87988208296a57d70767ebbd9c6880bJohn Grossman return; 37337237839e87988208296a57d70767ebbd9c6880bJohn Grossman 37437237839e87988208296a57d70767ebbd9c6880bJohn Grossman android.os.Parcel data = android.os.Parcel.obtain(); 37537237839e87988208296a57d70767ebbd9c6880bJohn Grossman android.os.Parcel reply = android.os.Parcel.obtain(); 37637237839e87988208296a57d70767ebbd9c6880bJohn Grossman 37737237839e87988208296a57d70767ebbd9c6880bJohn Grossman try { 37837237839e87988208296a57d70767ebbd9c6880bJohn Grossman data.writeInterfaceToken(mInterfaceDesc); 37937237839e87988208296a57d70767ebbd9c6880bJohn Grossman data.writeStrongBinder(mCallbackTgt); 38037237839e87988208296a57d70767ebbd9c6880bJohn Grossman mRemote.transact(METHOD_UNREGISTER_LISTENER, data, reply, 0); 38137237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 38237237839e87988208296a57d70767ebbd9c6880bJohn Grossman catch (RemoteException e) { } 38337237839e87988208296a57d70767ebbd9c6880bJohn Grossman finally { 38437237839e87988208296a57d70767ebbd9c6880bJohn Grossman reply.recycle(); 38537237839e87988208296a57d70767ebbd9c6880bJohn Grossman data.recycle(); 38637237839e87988208296a57d70767ebbd9c6880bJohn Grossman mCallbackTgt = null; 38737237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 38837237839e87988208296a57d70767ebbd9c6880bJohn Grossman } 38937237839e87988208296a57d70767ebbd9c6880bJohn Grossman 39037237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_IS_COMMON_TIME_VALID = IBinder.FIRST_CALL_TRANSACTION; 39137237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_COMMON_TIME_TO_LOCAL_TIME = METHOD_IS_COMMON_TIME_VALID + 1; 39237237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_LOCAL_TIME_TO_COMMON_TIME = METHOD_COMMON_TIME_TO_LOCAL_TIME + 1; 39337237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_GET_COMMON_TIME = METHOD_LOCAL_TIME_TO_COMMON_TIME + 1; 39437237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_GET_COMMON_FREQ = METHOD_GET_COMMON_TIME + 1; 39537237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_GET_LOCAL_TIME = METHOD_GET_COMMON_FREQ + 1; 39637237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_GET_LOCAL_FREQ = METHOD_GET_LOCAL_TIME + 1; 39737237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_GET_ESTIMATED_ERROR = METHOD_GET_LOCAL_FREQ + 1; 39837237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_GET_TIMELINE_ID = METHOD_GET_ESTIMATED_ERROR + 1; 39937237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_GET_STATE = METHOD_GET_TIMELINE_ID + 1; 40037237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_GET_MASTER_ADDRESS = METHOD_GET_STATE + 1; 40137237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_REGISTER_LISTENER = METHOD_GET_MASTER_ADDRESS + 1; 40237237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_UNREGISTER_LISTENER = METHOD_REGISTER_LISTENER + 1; 40337237839e87988208296a57d70767ebbd9c6880bJohn Grossman 40437237839e87988208296a57d70767ebbd9c6880bJohn Grossman private static final int METHOD_CBK_ON_TIMELINE_CHANGED = IBinder.FIRST_CALL_TRANSACTION; 40537237839e87988208296a57d70767ebbd9c6880bJohn Grossman} 406