diff options
26 files changed, 0 insertions, 6565 deletions
diff --git a/core/java/android/os/CommonClock.java b/core/java/android/os/CommonClock.java deleted file mode 100644 index 2ecf317c2d09..000000000000 --- a/core/java/android/os/CommonClock.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (C) 2012 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.os; - -import java.net.InetSocketAddress; -import java.util.NoSuchElementException; -import android.os.Binder; -import android.os.CommonTimeUtils; -import android.os.IBinder; -import android.os.Parcel; -import android.os.RemoteException; -import android.os.ServiceManager; - -/** - * Used for accessing the android common time service's common clock and receiving notifications - * about common time synchronization status changes. - * @hide - */ -public class CommonClock { - /** - * Sentinel value returned by {@link #getTime()} and {@link #getEstimatedError()} when the - * common time service is not able to determine the current common time due to a lack of - * synchronization. - */ - public static final long TIME_NOT_SYNCED = -1; - - /** - * Sentinel value returned by {@link #getTimelineId()} when the common time service is not - * currently synced to any timeline. - */ - public static final long INVALID_TIMELINE_ID = 0; - - /** - * Sentinel value returned by {@link #getEstimatedError()} when the common time service is not - * currently synced to any timeline. - */ - public static final int ERROR_ESTIMATE_UNKNOWN = 0x7FFFFFFF; - - /** - * Value used by {@link #getState()} to indicate that there was an internal error while - * attempting to determine the state of the common time service. - */ - public static final int STATE_INVALID = -1; - - /** - * Value used by {@link #getState()} to indicate that the common time service is in its initial - * state and attempting to find the current timeline master, if any. The service will - * transition to either {@link #STATE_CLIENT} if it finds an active master, or to - * {@link #STATE_MASTER} if no active master is found and this client becomes the master of a - * new timeline. - */ - public static final int STATE_INITIAL = 0; - - /** - * Value used by {@link #getState()} to indicate that the common time service is in its client - * state and is synchronizing its time to a different timeline master on the network. - */ - public static final int STATE_CLIENT = 1; - - /** - * Value used by {@link #getState()} to indicate that the common time service is in its master - * state and is serving as the timeline master for other common time service clients on the - * network. - */ - public static final int STATE_MASTER = 2; - - /** - * Value used by {@link #getState()} to indicate that the common time service is in its Ronin - * state. Common time service instances in the client state enter the Ronin state after their - * timeline master becomes unreachable on the network. Common time services who enter the Ronin - * state will begin a new master election for the timeline they were recently clients of. As - * clients detect they are not the winner and drop out of the election, they will transition to - * the {@link #STATE_WAIT_FOR_ELECTION} state. When there is only one client remaining in the - * election, it will assume ownership of the timeline and transition to the - * {@link #STATE_MASTER} state. During the election, all clients will allow their timeline to - * drift without applying correction. - */ - public static final int STATE_RONIN = 3; - - /** - * Value used by {@link #getState()} to indicate that the common time service is waiting for a - * master election to conclude and for the new master to announce itself before transitioning to - * the {@link #STATE_CLIENT} state. If no new master announces itself within the timeout - * threshold, the time service will transition back to the {@link #STATE_RONIN} state in order - * to restart the election. - */ - public static final int STATE_WAIT_FOR_ELECTION = 4; - - /** - * Name of the underlying native binder service - */ - public static final String SERVICE_NAME = "common_time.clock"; - - /** - * Class constructor. - * @throws android.os.RemoteException - */ - public CommonClock() - throws RemoteException { - mRemote = ServiceManager.getService(SERVICE_NAME); - if (null == mRemote) - throw new RemoteException(); - - mInterfaceDesc = mRemote.getInterfaceDescriptor(); - mUtils = new CommonTimeUtils(mRemote, mInterfaceDesc); - mRemote.linkToDeath(mDeathHandler, 0); - registerTimelineChangeListener(); - } - - /** - * Handy class factory method. - */ - static public CommonClock create() { - CommonClock retVal; - - try { - retVal = new CommonClock(); - } - catch (RemoteException e) { - retVal = null; - } - - return retVal; - } - - /** - * Release all native resources held by this {@link android.os.CommonClock} instance. Once - * resources have been released, the {@link android.os.CommonClock} instance is disconnected from - * the native service and will throw a {@link android.os.RemoteException} if any of its - * methods are called. Clients should always call release on their client instances before - * releasing their last Java reference to the instance. Failure to do this will cause - * non-deterministic native resource reclamation and may cause the common time service to remain - * active on the network for longer than it should. - */ - public void release() { - unregisterTimelineChangeListener(); - if (null != mRemote) { - try { - mRemote.unlinkToDeath(mDeathHandler, 0); - } - catch (NoSuchElementException e) { } - mRemote = null; - } - mUtils = null; - } - - /** - * Gets the common clock's current time. - * - * @return a signed 64-bit value representing the current common time in microseconds, or the - * special value {@link #TIME_NOT_SYNCED} if the common time service is currently not - * synchronized. - * @throws android.os.RemoteException - */ - public long getTime() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetLong(METHOD_GET_COMMON_TIME, TIME_NOT_SYNCED); - } - - /** - * Gets the current estimation of common clock's synchronization accuracy from the common time - * service. - * - * @return a signed 32-bit value representing the common time service's estimation of - * synchronization accuracy in microseconds, or the special value - * {@link #ERROR_ESTIMATE_UNKNOWN} if the common time service is currently not synchronized. - * Negative values indicate that the local server estimates that the nominal common time is - * behind the local server's time (in other words, the local clock is running fast) Positive - * values indicate that the local server estimates that the nominal common time is ahead of the - * local server's time (in other words, the local clock is running slow) - * @throws android.os.RemoteException - */ - public int getEstimatedError() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetInt(METHOD_GET_ESTIMATED_ERROR, ERROR_ESTIMATE_UNKNOWN); - } - - /** - * Gets the ID of the timeline the common time service is currently synchronizing its clock to. - * - * @return a long representing the unique ID of the timeline the common time service is - * currently synchronizing with, or {@link #INVALID_TIMELINE_ID} if the common time service is - * currently not synchronized. - * @throws android.os.RemoteException - */ - public long getTimelineId() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetLong(METHOD_GET_TIMELINE_ID, INVALID_TIMELINE_ID); - } - - /** - * Gets the current state of this clock's common time service in the the master election - * algorithm. - * - * @return a integer indicating the current state of the this clock's common time service in the - * master election algorithm or {@link #STATE_INVALID} if there is an internal error. - * @throws android.os.RemoteException - */ - public int getState() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetInt(METHOD_GET_STATE, STATE_INVALID); - } - - /** - * Gets the IP address and UDP port of the current timeline master. - * - * @return an InetSocketAddress containing the IP address and UDP port of the current timeline - * master, or null if there is no current master. - * @throws android.os.RemoteException - */ - public InetSocketAddress getMasterAddr() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetSockaddr(METHOD_GET_MASTER_ADDRESS); - } - - /** - * The OnTimelineChangedListener interface defines a method called by the - * {@link android.os.CommonClock} instance to indicate that the time synchronization service has - * either synchronized with a new timeline, or is no longer a member of any timeline. The - * client application can implement this interface and register the listener with the - * {@link #setTimelineChangedListener(OnTimelineChangedListener)} method. - */ - public interface OnTimelineChangedListener { - /** - * Method called when the time service's timeline has changed. - * - * @param newTimelineId a long which uniquely identifies the timeline the time - * synchronization service is now a member of, or {@link #INVALID_TIMELINE_ID} if the the - * service is not synchronized to any timeline. - */ - void onTimelineChanged(long newTimelineId); - } - - /** - * Registers an OnTimelineChangedListener interface. - * <p>Call this method with a null listener to stop receiving server death notifications. - */ - public void setTimelineChangedListener(OnTimelineChangedListener listener) { - synchronized (mListenerLock) { - mTimelineChangedListener = listener; - } - } - - /** - * The OnServerDiedListener interface defines a method called by the - * {@link android.os.CommonClock} instance to indicate that the connection to the native media - * server has been broken and that the {@link android.os.CommonClock} instance will need to be - * released and re-created. The client application can implement this interface and register - * the listener with the {@link #setServerDiedListener(OnServerDiedListener)} method. - */ - public interface OnServerDiedListener { - /** - * Method called when the native media server has died. <p>If the native common time - * service encounters a fatal error and needs to restart, the binder connection from the - * {@link android.os.CommonClock} instance to the common time service will be broken. To - * restore functionality, clients should {@link #release()} their old visualizer and create - * a new instance. - */ - void onServerDied(); - } - - /** - * Registers an OnServerDiedListener interface. - * <p>Call this method with a null listener to stop receiving server death notifications. - */ - public void setServerDiedListener(OnServerDiedListener listener) { - synchronized (mListenerLock) { - mServerDiedListener = listener; - } - } - - protected void finalize() throws Throwable { release(); } - - private void throwOnDeadServer() throws RemoteException { - if ((null == mRemote) || (null == mUtils)) - throw new RemoteException(); - } - - private final Object mListenerLock = new Object(); - private OnTimelineChangedListener mTimelineChangedListener = null; - private OnServerDiedListener mServerDiedListener = null; - - private IBinder mRemote = null; - private String mInterfaceDesc = ""; - private CommonTimeUtils mUtils; - - private IBinder.DeathRecipient mDeathHandler = new IBinder.DeathRecipient() { - public void binderDied() { - synchronized (mListenerLock) { - if (null != mServerDiedListener) - mServerDiedListener.onServerDied(); - } - } - }; - - private class TimelineChangedListener extends Binder { - @Override - protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) - throws RemoteException { - switch (code) { - case METHOD_CBK_ON_TIMELINE_CHANGED: - data.enforceInterface(DESCRIPTOR); - long timelineId = data.readLong(); - synchronized (mListenerLock) { - if (null != mTimelineChangedListener) - mTimelineChangedListener.onTimelineChanged(timelineId); - } - return true; - } - - return super.onTransact(code, data, reply, flags); - } - - private static final String DESCRIPTOR = "android.os.ICommonClockListener"; - }; - - private TimelineChangedListener mCallbackTgt = null; - - private void registerTimelineChangeListener() throws RemoteException { - if (null != mCallbackTgt) - return; - - boolean success = false; - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - mCallbackTgt = new TimelineChangedListener(); - - try { - data.writeInterfaceToken(mInterfaceDesc); - data.writeStrongBinder(mCallbackTgt); - mRemote.transact(METHOD_REGISTER_LISTENER, data, reply, 0); - success = (0 == reply.readInt()); - } - catch (RemoteException e) { - success = false; - } - finally { - reply.recycle(); - data.recycle(); - } - - // Did we catch a remote exception or fail to register our callback target? If so, our - // object must already be dead (or be as good as dead). Clear out all of our state so that - // our other methods will properly indicate a dead object. - if (!success) { - mCallbackTgt = null; - mRemote = null; - mUtils = null; - } - } - - private void unregisterTimelineChangeListener() { - if (null == mCallbackTgt) - return; - - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - - try { - data.writeInterfaceToken(mInterfaceDesc); - data.writeStrongBinder(mCallbackTgt); - mRemote.transact(METHOD_UNREGISTER_LISTENER, data, reply, 0); - } - catch (RemoteException e) { } - finally { - reply.recycle(); - data.recycle(); - mCallbackTgt = null; - } - } - - private static final int METHOD_IS_COMMON_TIME_VALID = IBinder.FIRST_CALL_TRANSACTION; - private static final int METHOD_COMMON_TIME_TO_LOCAL_TIME = METHOD_IS_COMMON_TIME_VALID + 1; - private static final int METHOD_LOCAL_TIME_TO_COMMON_TIME = METHOD_COMMON_TIME_TO_LOCAL_TIME + 1; - private static final int METHOD_GET_COMMON_TIME = METHOD_LOCAL_TIME_TO_COMMON_TIME + 1; - private static final int METHOD_GET_COMMON_FREQ = METHOD_GET_COMMON_TIME + 1; - private static final int METHOD_GET_LOCAL_TIME = METHOD_GET_COMMON_FREQ + 1; - private static final int METHOD_GET_LOCAL_FREQ = METHOD_GET_LOCAL_TIME + 1; - private static final int METHOD_GET_ESTIMATED_ERROR = METHOD_GET_LOCAL_FREQ + 1; - private static final int METHOD_GET_TIMELINE_ID = METHOD_GET_ESTIMATED_ERROR + 1; - private static final int METHOD_GET_STATE = METHOD_GET_TIMELINE_ID + 1; - private static final int METHOD_GET_MASTER_ADDRESS = METHOD_GET_STATE + 1; - private static final int METHOD_REGISTER_LISTENER = METHOD_GET_MASTER_ADDRESS + 1; - private static final int METHOD_UNREGISTER_LISTENER = METHOD_REGISTER_LISTENER + 1; - - private static final int METHOD_CBK_ON_TIMELINE_CHANGED = IBinder.FIRST_CALL_TRANSACTION; -} diff --git a/core/java/android/os/CommonTimeConfig.java b/core/java/android/os/CommonTimeConfig.java deleted file mode 100644 index 1f9fab5eb73d..000000000000 --- a/core/java/android/os/CommonTimeConfig.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (C) 2012 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.os; - -import java.net.InetSocketAddress; -import java.util.NoSuchElementException; - -import android.os.CommonTimeUtils; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; - -/** - * Used for configuring and controlling the status of the android common time service. - * @hide - */ -public class CommonTimeConfig { - /** - * Successful operation. - */ - public static final int SUCCESS = 0; - /** - * Unspecified error. - */ - public static final int ERROR = -1; - /** - * Operation failed due to bad parameter value. - */ - public static final int ERROR_BAD_VALUE = -4; - /** - * Operation failed due to dead remote object. - */ - public static final int ERROR_DEAD_OBJECT = -7; - - /** - * Sentinel value returned by {@link #getMasterElectionGroupId()} when an error occurs trying to - * fetch the master election group. - */ - public static final long INVALID_GROUP_ID = -1; - - /** - * Name of the underlying native binder service - */ - public static final String SERVICE_NAME = "common_time.config"; - - /** - * Class constructor. - * @throws android.os.RemoteException - */ - public CommonTimeConfig() - throws RemoteException { - mRemote = ServiceManager.getService(SERVICE_NAME); - if (null == mRemote) - throw new RemoteException(); - - mInterfaceDesc = mRemote.getInterfaceDescriptor(); - mUtils = new CommonTimeUtils(mRemote, mInterfaceDesc); - mRemote.linkToDeath(mDeathHandler, 0); - } - - /** - * Handy class factory method. - */ - static public CommonTimeConfig create() { - CommonTimeConfig retVal; - - try { - retVal = new CommonTimeConfig(); - } - catch (RemoteException e) { - retVal = null; - } - - return retVal; - } - - /** - * Release all native resources held by this {@link android.os.CommonTimeConfig} instance. Once - * resources have been released, the {@link android.os.CommonTimeConfig} instance is - * disconnected from the native service and will throw a {@link android.os.RemoteException} if - * any of its methods are called. Clients should always call release on their client instances - * before releasing their last Java reference to the instance. Failure to do this will cause - * non-deterministic native resource reclamation and may cause the common time service to remain - * active on the network for longer than it should. - */ - public void release() { - if (null != mRemote) { - try { - mRemote.unlinkToDeath(mDeathHandler, 0); - } - catch (NoSuchElementException e) { } - mRemote = null; - } - mUtils = null; - } - - /** - * Gets the current priority of the common time service used in the master election protocol. - * - * @return an 8 bit value indicating the priority of this common time service relative to other - * common time services operating in the same domain. - * @throws android.os.RemoteException - */ - public byte getMasterElectionPriority() - throws RemoteException { - throwOnDeadServer(); - return (byte)mUtils.transactGetInt(METHOD_GET_MASTER_ELECTION_PRIORITY, -1); - } - - /** - * Sets the current priority of the common time service used in the master election protocol. - * - * @param priority priority of the common time service used in the master election protocol. - * Lower numbers are lower priority. - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int setMasterElectionPriority(byte priority) { - if (checkDeadServer()) - return ERROR_DEAD_OBJECT; - return mUtils.transactSetInt(METHOD_SET_MASTER_ELECTION_PRIORITY, priority); - } - - /** - * Gets the IP endpoint used by the time service to participate in the master election protocol. - * - * @return an InetSocketAddress containing the IP address and UDP port being used by the - * system's common time service to participate in the master election protocol. - * @throws android.os.RemoteException - */ - public InetSocketAddress getMasterElectionEndpoint() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetSockaddr(METHOD_GET_MASTER_ELECTION_ENDPOINT); - } - - /** - * Sets the IP endpoint used by the common time service to participate in the master election - * protocol. - * - * @param ep The IP address and UDP port to be used by the common time service to participate in - * the master election protocol. The supplied IP address must be either the broadcast or - * multicast address, unicast addresses are considered to be illegal values. - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int setMasterElectionEndpoint(InetSocketAddress ep) { - if (checkDeadServer()) - return ERROR_DEAD_OBJECT; - return mUtils.transactSetSockaddr(METHOD_SET_MASTER_ELECTION_ENDPOINT, ep); - } - - /** - * Gets the current group ID used by the common time service in the master election protocol. - * - * @return The 64-bit group ID of the common time service. - * @throws android.os.RemoteException - */ - public long getMasterElectionGroupId() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetLong(METHOD_GET_MASTER_ELECTION_GROUP_ID, INVALID_GROUP_ID); - } - - /** - * Sets the current group ID used by the common time service in the master election protocol. - * - * @param id The 64-bit group ID of the common time service. - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int setMasterElectionGroupId(long id) { - if (checkDeadServer()) - return ERROR_DEAD_OBJECT; - return mUtils.transactSetLong(METHOD_SET_MASTER_ELECTION_GROUP_ID, id); - } - - /** - * Gets the name of the network interface which the common time service attempts to bind to. - * - * @return a string with the network interface name which the common time service is bound to, - * or null if the service is currently unbound. Examples of interface names are things like - * "eth0", or "wlan0". - * @throws android.os.RemoteException - */ - public String getInterfaceBinding() - throws RemoteException { - throwOnDeadServer(); - - String ifaceName = mUtils.transactGetString(METHOD_GET_INTERFACE_BINDING, null); - - if ((null != ifaceName) && (0 == ifaceName.length())) - return null; - - return ifaceName; - } - - /** - * Sets the name of the network interface which the common time service should attempt to bind - * to. - * - * @param ifaceName The name of the network interface ("eth0", "wlan0", etc...) wich the common - * time service should attempt to bind to, or null to force the common time service to unbind - * from the network and run in networkless mode. - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int setNetworkBinding(String ifaceName) { - if (checkDeadServer()) - return ERROR_DEAD_OBJECT; - - return mUtils.transactSetString(METHOD_SET_INTERFACE_BINDING, - (null == ifaceName) ? "" : ifaceName); - } - - /** - * Gets the amount of time the common time service will wait between master announcements when - * it is the timeline master. - * - * @return The time (in milliseconds) between master announcements. - * @throws android.os.RemoteException - */ - public int getMasterAnnounceInterval() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetInt(METHOD_GET_MASTER_ANNOUNCE_INTERVAL, -1); - } - - /** - * Sets the amount of time the common time service will wait between master announcements when - * it is the timeline master. - * - * @param interval The time (in milliseconds) between master announcements. - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int setMasterAnnounceInterval(int interval) { - if (checkDeadServer()) - return ERROR_DEAD_OBJECT; - return mUtils.transactSetInt(METHOD_SET_MASTER_ANNOUNCE_INTERVAL, interval); - } - - /** - * Gets the amount of time the common time service will wait between time synchronization - * requests when it is the client of another common time service on the network. - * - * @return The time (in milliseconds) between time sync requests. - * @throws android.os.RemoteException - */ - public int getClientSyncInterval() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetInt(METHOD_GET_CLIENT_SYNC_INTERVAL, -1); - } - - /** - * Sets the amount of time the common time service will wait between time synchronization - * requests when it is the client of another common time service on the network. - * - * @param interval The time (in milliseconds) between time sync requests. - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int setClientSyncInterval(int interval) { - if (checkDeadServer()) - return ERROR_DEAD_OBJECT; - return mUtils.transactSetInt(METHOD_SET_CLIENT_SYNC_INTERVAL, interval); - } - - /** - * Gets the panic threshold for the estimated error level of the common time service. When the - * common time service's estimated error rises above this level, the service will panic and - * reset, causing a discontinuity in the currently synchronized timeline. - * - * @return The threshold (in microseconds) past which the common time service will panic. - * @throws android.os.RemoteException - */ - public int getPanicThreshold() - throws RemoteException { - throwOnDeadServer(); - return mUtils.transactGetInt(METHOD_GET_PANIC_THRESHOLD, -1); - } - - /** - * Sets the panic threshold for the estimated error level of the common time service. When the - * common time service's estimated error rises above this level, the service will panic and - * reset, causing a discontinuity in the currently synchronized timeline. - * - * @param threshold The threshold (in microseconds) past which the common time service will - * panic. - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR}, {@link #ERROR_BAD_VALUE} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int setPanicThreshold(int threshold) { - if (checkDeadServer()) - return ERROR_DEAD_OBJECT; - return mUtils.transactSetInt(METHOD_SET_PANIC_THRESHOLD, threshold); - } - - /** - * Gets the current state of the common time service's auto disable flag. - * - * @return The current state of the common time service's auto disable flag. - * @throws android.os.RemoteException - */ - public boolean getAutoDisable() - throws RemoteException { - throwOnDeadServer(); - return (1 == mUtils.transactGetInt(METHOD_GET_AUTO_DISABLE, 1)); - } - - /** - * Sets the current state of the common time service's auto disable flag. When the time - * service's auto disable flag is set, it will automatically cease all network activity when - * it has no active local clients, resuming activity the next time the service has interested - * local clients. When the auto disabled flag is cleared, the common time service will continue - * to participate the time synchronization group even when it has no active local clients. - * - * @param autoDisable The desired state of the common time service's auto disable flag. - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int setAutoDisable(boolean autoDisable) { - if (checkDeadServer()) - return ERROR_DEAD_OBJECT; - - return mUtils.transactSetInt(METHOD_SET_AUTO_DISABLE, autoDisable ? 1 : 0); - } - - /** - * At startup, the time service enters the initial state and remains there until it is given a - * network interface to bind to. Common time will be unavailable to clients of the common time - * service until the service joins a network (even an empty network). Devices may use the - * {@link #forceNetworklessMasterMode()} method to force a time service in the INITIAL state - * with no network configuration to assume MASTER status for a brand new timeline in order to - * allow clients of the common time service to operate, even though the device is isolated and - * not on any network. When a networkless master does join a network, it will defer to any - * masters already on the network, or continue to maintain the timeline it made up during its - * networkless state if no other masters are detected. Attempting to force a client into master - * mode while it is actively bound to a network will fail with the status code {@link #ERROR} - * - * @return {@link #SUCCESS} in case of success, - * {@link #ERROR} or {@link #ERROR_DEAD_OBJECT} in case of failure. - */ - public int forceNetworklessMasterMode() { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - - try { - data.writeInterfaceToken(mInterfaceDesc); - mRemote.transact(METHOD_FORCE_NETWORKLESS_MASTER_MODE, data, reply, 0); - - return reply.readInt(); - } - catch (RemoteException e) { - return ERROR_DEAD_OBJECT; - } - finally { - reply.recycle(); - data.recycle(); - } - } - - /** - * The OnServerDiedListener interface defines a method called by the - * {@link android.os.CommonTimeConfig} instance to indicate that the connection to the native - * media server has been broken and that the {@link android.os.CommonTimeConfig} instance will - * need to be released and re-created. The client application can implement this interface and - * register the listener with the {@link #setServerDiedListener(OnServerDiedListener)} method. - */ - public interface OnServerDiedListener { - /** - * Method called when the native common time service has died. <p>If the native common time - * service encounters a fatal error and needs to restart, the binder connection from the - * {@link android.os.CommonTimeConfig} instance to the common time service will be broken. - */ - void onServerDied(); - } - - /** - * Registers an OnServerDiedListener interface. - * <p>Call this method with a null listener to stop receiving server death notifications. - */ - public void setServerDiedListener(OnServerDiedListener listener) { - synchronized (mListenerLock) { - mServerDiedListener = listener; - } - } - - protected void finalize() throws Throwable { release(); } - - private boolean checkDeadServer() { - return ((null == mRemote) || (null == mUtils)); - } - - private void throwOnDeadServer() throws RemoteException { - if (checkDeadServer()) - throw new RemoteException(); - } - - private final Object mListenerLock = new Object(); - private OnServerDiedListener mServerDiedListener = null; - - private IBinder mRemote = null; - private String mInterfaceDesc = ""; - private CommonTimeUtils mUtils; - - private IBinder.DeathRecipient mDeathHandler = new IBinder.DeathRecipient() { - public void binderDied() { - synchronized (mListenerLock) { - if (null != mServerDiedListener) - mServerDiedListener.onServerDied(); - } - } - }; - - private static final int METHOD_GET_MASTER_ELECTION_PRIORITY = IBinder.FIRST_CALL_TRANSACTION; - private static final int METHOD_SET_MASTER_ELECTION_PRIORITY = METHOD_GET_MASTER_ELECTION_PRIORITY + 1; - private static final int METHOD_GET_MASTER_ELECTION_ENDPOINT = METHOD_SET_MASTER_ELECTION_PRIORITY + 1; - private static final int METHOD_SET_MASTER_ELECTION_ENDPOINT = METHOD_GET_MASTER_ELECTION_ENDPOINT + 1; - private static final int METHOD_GET_MASTER_ELECTION_GROUP_ID = METHOD_SET_MASTER_ELECTION_ENDPOINT + 1; - private static final int METHOD_SET_MASTER_ELECTION_GROUP_ID = METHOD_GET_MASTER_ELECTION_GROUP_ID + 1; - private static final int METHOD_GET_INTERFACE_BINDING = METHOD_SET_MASTER_ELECTION_GROUP_ID + 1; - private static final int METHOD_SET_INTERFACE_BINDING = METHOD_GET_INTERFACE_BINDING + 1; - private static final int METHOD_GET_MASTER_ANNOUNCE_INTERVAL = METHOD_SET_INTERFACE_BINDING + 1; - private static final int METHOD_SET_MASTER_ANNOUNCE_INTERVAL = METHOD_GET_MASTER_ANNOUNCE_INTERVAL + 1; - private static final int METHOD_GET_CLIENT_SYNC_INTERVAL = METHOD_SET_MASTER_ANNOUNCE_INTERVAL + 1; - private static final int METHOD_SET_CLIENT_SYNC_INTERVAL = METHOD_GET_CLIENT_SYNC_INTERVAL + 1; - private static final int METHOD_GET_PANIC_THRESHOLD = METHOD_SET_CLIENT_SYNC_INTERVAL + 1; - private static final int METHOD_SET_PANIC_THRESHOLD = METHOD_GET_PANIC_THRESHOLD + 1; - private static final int METHOD_GET_AUTO_DISABLE = METHOD_SET_PANIC_THRESHOLD + 1; - private static final int METHOD_SET_AUTO_DISABLE = METHOD_GET_AUTO_DISABLE + 1; - private static final int METHOD_FORCE_NETWORKLESS_MASTER_MODE = METHOD_SET_AUTO_DISABLE + 1; -} diff --git a/core/java/android/os/CommonTimeUtils.java b/core/java/android/os/CommonTimeUtils.java deleted file mode 100644 index ba060b87567e..000000000000 --- a/core/java/android/os/CommonTimeUtils.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (C) 2012 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.os; - -import java.net.InetAddress; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetSocketAddress; -import java.util.Locale; -import static android.system.OsConstants.*; - -class CommonTimeUtils { - /** - * Successful operation. - */ - public static final int SUCCESS = 0; - /** - * Unspecified error. - */ - public static final int ERROR = -1; - /** - * Operation failed due to bad parameter value. - */ - public static final int ERROR_BAD_VALUE = -4; - /** - * Operation failed due to dead remote object. - */ - public static final int ERROR_DEAD_OBJECT = -7; - - public CommonTimeUtils(IBinder remote, String interfaceDesc) { - mRemote = remote; - mInterfaceDesc = interfaceDesc; - } - - public int transactGetInt(int method_code, int error_ret_val) - throws RemoteException { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - int ret_val; - - try { - int res; - data.writeInterfaceToken(mInterfaceDesc); - mRemote.transact(method_code, data, reply, 0); - - res = reply.readInt(); - ret_val = (0 == res) ? reply.readInt() : error_ret_val; - } - finally { - reply.recycle(); - data.recycle(); - } - - return ret_val; - } - - public int transactSetInt(int method_code, int val) { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - - try { - data.writeInterfaceToken(mInterfaceDesc); - data.writeInt(val); - mRemote.transact(method_code, data, reply, 0); - - return reply.readInt(); - } - catch (RemoteException e) { - return ERROR_DEAD_OBJECT; - } - finally { - reply.recycle(); - data.recycle(); - } - } - - public long transactGetLong(int method_code, long error_ret_val) - throws RemoteException { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - long ret_val; - - try { - int res; - data.writeInterfaceToken(mInterfaceDesc); - mRemote.transact(method_code, data, reply, 0); - - res = reply.readInt(); - ret_val = (0 == res) ? reply.readLong() : error_ret_val; - } - finally { - reply.recycle(); - data.recycle(); - } - - return ret_val; - } - - public int transactSetLong(int method_code, long val) { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - - try { - data.writeInterfaceToken(mInterfaceDesc); - data.writeLong(val); - mRemote.transact(method_code, data, reply, 0); - - return reply.readInt(); - } - catch (RemoteException e) { - return ERROR_DEAD_OBJECT; - } - finally { - reply.recycle(); - data.recycle(); - } - } - - public String transactGetString(int method_code, String error_ret_val) - throws RemoteException { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - String ret_val; - - try { - int res; - data.writeInterfaceToken(mInterfaceDesc); - mRemote.transact(method_code, data, reply, 0); - - res = reply.readInt(); - ret_val = (0 == res) ? reply.readString() : error_ret_val; - } - finally { - reply.recycle(); - data.recycle(); - } - - return ret_val; - } - - public int transactSetString(int method_code, String val) { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - - try { - data.writeInterfaceToken(mInterfaceDesc); - data.writeString(val); - mRemote.transact(method_code, data, reply, 0); - - return reply.readInt(); - } - catch (RemoteException e) { - return ERROR_DEAD_OBJECT; - } - finally { - reply.recycle(); - data.recycle(); - } - } - - public InetSocketAddress transactGetSockaddr(int method_code) - throws RemoteException { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - InetSocketAddress ret_val = null; - - try { - int res; - data.writeInterfaceToken(mInterfaceDesc); - mRemote.transact(method_code, data, reply, 0); - - res = reply.readInt(); - if (0 == res) { - int type; - int port = 0; - String addrStr = null; - - type = reply.readInt(); - - if (AF_INET == type) { - int addr = reply.readInt(); - port = reply.readInt(); - addrStr = String.format(Locale.US, "%d.%d.%d.%d", - (addr >> 24) & 0xFF, - (addr >> 16) & 0xFF, - (addr >> 8) & 0xFF, - addr & 0xFF); - } else if (AF_INET6 == type) { - int addr1 = reply.readInt(); - int addr2 = reply.readInt(); - int addr3 = reply.readInt(); - int addr4 = reply.readInt(); - - port = reply.readInt(); - - int flowinfo = reply.readInt(); - int scope_id = reply.readInt(); - - addrStr = String.format(Locale.US, "[%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X]", - (addr1 >> 16) & 0xFFFF, addr1 & 0xFFFF, - (addr2 >> 16) & 0xFFFF, addr2 & 0xFFFF, - (addr3 >> 16) & 0xFFFF, addr3 & 0xFFFF, - (addr4 >> 16) & 0xFFFF, addr4 & 0xFFFF); - } - - if (null != addrStr) { - ret_val = new InetSocketAddress(addrStr, port); - } - } - } - finally { - reply.recycle(); - data.recycle(); - } - - return ret_val; - } - - public int transactSetSockaddr(int method_code, InetSocketAddress addr) { - android.os.Parcel data = android.os.Parcel.obtain(); - android.os.Parcel reply = android.os.Parcel.obtain(); - int ret_val = ERROR; - - try { - data.writeInterfaceToken(mInterfaceDesc); - - if (null == addr) { - data.writeInt(0); - } else { - data.writeInt(1); - final InetAddress a = addr.getAddress(); - final byte[] b = a.getAddress(); - final int p = addr.getPort(); - - if (a instanceof Inet4Address) { - int v4addr = (((int)b[0] & 0xFF) << 24) | - (((int)b[1] & 0xFF) << 16) | - (((int)b[2] & 0xFF) << 8) | - ((int)b[3] & 0xFF); - - data.writeInt(AF_INET); - data.writeInt(v4addr); - data.writeInt(p); - } else - if (a instanceof Inet6Address) { - int i; - Inet6Address v6 = (Inet6Address)a; - data.writeInt(AF_INET6); - for (i = 0; i < 4; ++i) { - int aword = (((int)b[(i*4) + 0] & 0xFF) << 24) | - (((int)b[(i*4) + 1] & 0xFF) << 16) | - (((int)b[(i*4) + 2] & 0xFF) << 8) | - ((int)b[(i*4) + 3] & 0xFF); - data.writeInt(aword); - } - data.writeInt(p); - data.writeInt(0); // flow info - data.writeInt(v6.getScopeId()); - } else { - return ERROR_BAD_VALUE; - } - } - - mRemote.transact(method_code, data, reply, 0); - ret_val = reply.readInt(); - } - catch (RemoteException e) { - ret_val = ERROR_DEAD_OBJECT; - } - finally { - reply.recycle(); - data.recycle(); - } - - return ret_val; - } - - private IBinder mRemote; - private String mInterfaceDesc; -}; diff --git a/libs/common_time/Android.mk b/libs/common_time/Android.mk deleted file mode 100644 index 636f05752ee4..000000000000 --- a/libs/common_time/Android.mk +++ /dev/null @@ -1,39 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -# -# common_time_service -# - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - common_clock_service.cpp \ - common_time_config_service.cpp \ - common_time_server.cpp \ - common_time_server_api.cpp \ - common_time_server_packets.cpp \ - clock_recovery.cpp \ - common_clock.cpp \ - main.cpp \ - utils.cpp \ - LinearTransform.cpp - -# Uncomment to enable vesbose logging and debug service. -#TIME_SERVICE_DEBUG=true -ifeq ($(TIME_SERVICE_DEBUG), true) -LOCAL_SRC_FILES += diag_thread.cpp -LOCAL_CFLAGS += -DTIME_SERVICE_DEBUG -endif - -LOCAL_SHARED_LIBRARIES := \ - libbinder \ - libcommon_time_client \ - libutils \ - liblog - -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE := common_time - -LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code - -include $(BUILD_EXECUTABLE) diff --git a/libs/common_time/LinearTransform.cpp b/libs/common_time/LinearTransform.cpp deleted file mode 100644 index 67308550fa4b..000000000000 --- a/libs/common_time/LinearTransform.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#define __STDC_LIMIT_MACROS - -#include "LinearTransform.h" -#include <assert.h> - - -// disable sanitize as these functions may intentionally overflow (see comments below). -// the ifdef can be removed when host builds use clang. -#if defined(__clang__) -#define ATTRIBUTE_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer"))) -#else -#define ATTRIBUTE_NO_SANITIZE_INTEGER -#endif - -namespace android { - -// sanitize failure with T = int32_t and x = 0x80000000 -template<class T> -ATTRIBUTE_NO_SANITIZE_INTEGER -static inline T ABS(T x) { return (x < 0) ? -x : x; } - -// Static math methods involving linear transformations -// remote sanitize failure on overflow case. -ATTRIBUTE_NO_SANITIZE_INTEGER -static bool scale_u64_to_u64( - uint64_t val, - uint32_t N, - uint32_t D, - uint64_t* res, - bool round_up_not_down) { - uint64_t tmp1, tmp2; - uint32_t r; - - assert(res); - assert(D); - - // Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit - // integer X. - // Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit - // integer X. - // Let X[A, B] with A <= B denote bits A through B of the integer X. - // Let (A | B) denote the concatination of two 32 bit ints, A and B. - // IOW X = (A | B) => U32(X) == A && L32(X) == B - // - // compute M = val * N (a 96 bit int) - // --------------------------------- - // tmp2 = U32(val) * N (a 64 bit int) - // tmp1 = L32(val) * N (a 64 bit int) - // which means - // M = val * N = (tmp2 << 32) + tmp1 - tmp2 = (val >> 32) * N; - tmp1 = (val & UINT32_MAX) * N; - - // compute M[32, 95] - // tmp2 = tmp2 + U32(tmp1) - // = (U32(val) * N) + U32(L32(val) * N) - // = M[32, 95] - tmp2 += tmp1 >> 32; - - // if M[64, 95] >= D, then M/D has bits > 63 set and we have - // an overflow. - if ((tmp2 >> 32) >= D) { - *res = UINT64_MAX; - return false; - } - - // Divide. Going in we know - // tmp2 = M[32, 95] - // U32(tmp2) < D - r = tmp2 % D; - tmp2 /= D; - - // At this point - // tmp1 = L32(val) * N - // tmp2 = M[32, 95] / D - // = (M / D)[32, 95] - // r = M[32, 95] % D - // U32(tmp2) = 0 - // - // compute tmp1 = (r | M[0, 31]) - tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32); - - // Divide again. Keep the remainder around in order to round properly. - r = tmp1 % D; - tmp1 /= D; - - // At this point - // tmp2 = (M / D)[32, 95] - // tmp1 = (M / D)[ 0, 31] - // r = M % D - // U32(tmp1) = 0 - // U32(tmp2) = 0 - - // Pack the result and deal with the round-up case (As well as the - // remote possiblility over overflow in such a case). - *res = (tmp2 << 32) | tmp1; - if (r && round_up_not_down) { - ++(*res); - if (!(*res)) { - *res = UINT64_MAX; - return false; - } - } - - return true; -} - -// at least one known sanitize failure (see comment below) -ATTRIBUTE_NO_SANITIZE_INTEGER -static bool linear_transform_s64_to_s64( - int64_t val, - int64_t basis1, - int32_t N, - uint32_t D, - bool invert_frac, - int64_t basis2, - int64_t* out) { - uint64_t scaled, res; - uint64_t abs_val; - bool is_neg; - - if (!out) - return false; - - // Compute abs(val - basis_64). Keep track of whether or not this delta - // will be negative after the scale opertaion. - if (val < basis1) { - is_neg = true; - abs_val = basis1 - val; - } else { - is_neg = false; - abs_val = val - basis1; - } - - if (N < 0) - is_neg = !is_neg; - - if (!scale_u64_to_u64(abs_val, - invert_frac ? D : ABS(N), - invert_frac ? ABS(N) : D, - &scaled, - is_neg)) - return false; // overflow/undeflow - - // if scaled is >= 0x8000<etc>, then we are going to overflow or - // underflow unless ABS(basis2) is large enough to pull us back into the - // non-overflow/underflow region. - if (scaled & INT64_MIN) { - if (is_neg && (basis2 < 0)) - return false; // certain underflow - - if (!is_neg && (basis2 >= 0)) - return false; // certain overflow - - if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX)) - return false; // not enough - - // Looks like we are OK - *out = (is_neg ? (-scaled) : scaled) + basis2; - } else { - // Scaled fits within signed bounds, so we just need to check for - // over/underflow for two signed integers. Basically, if both scaled - // and basis2 have the same sign bit, and the result has a different - // sign bit, then we have under/overflow. An easy way to compute this - // is - // (scaled_signbit XNOR basis_signbit) && - // (scaled_signbit XOR res_signbit) - // == - // (scaled_signbit XOR basis_signbit XOR 1) && - // (scaled_signbit XOR res_signbit) - - if (is_neg) - scaled = -scaled; // known sanitize failure - res = scaled + basis2; - - if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN) - return false; - - *out = res; - } - - return true; -} - -bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const { - if (0 == a_to_b_denom) - return false; - - return linear_transform_s64_to_s64(a_in, - a_zero, - a_to_b_numer, - a_to_b_denom, - false, - b_zero, - b_out); -} - -bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const { - if (0 == a_to_b_numer) - return false; - - return linear_transform_s64_to_s64(b_in, - b_zero, - a_to_b_numer, - a_to_b_denom, - true, - a_zero, - a_out); -} - -template <class T> void LinearTransform::reduce(T* N, T* D) { - T a, b; - if (!N || !D || !(*D)) { - assert(false); - return; - } - - a = *N; - b = *D; - - if (a == 0) { - *D = 1; - return; - } - - // This implements Euclid's method to find GCD. - if (a < b) { - T tmp = a; - a = b; - b = tmp; - } - - while (1) { - // a is now the greater of the two. - const T remainder = a % b; - if (remainder == 0) { - *N /= b; - *D /= b; - return; - } - // by swapping remainder and b, we are guaranteeing that a is - // still the greater of the two upon entrance to the loop. - a = b; - b = remainder; - } -}; - -template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D); -template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D); - -// sanitize failure if *N = 0x80000000 -ATTRIBUTE_NO_SANITIZE_INTEGER -void LinearTransform::reduce(int32_t* N, uint32_t* D) { - if (N && D && *D) { - if (*N < 0) { - *N = -(*N); - reduce(reinterpret_cast<uint32_t*>(N), D); - *N = -(*N); - } else { - reduce(reinterpret_cast<uint32_t*>(N), D); - } - } -} - -} // namespace android diff --git a/libs/common_time/LinearTransform.h b/libs/common_time/LinearTransform.h deleted file mode 100644 index bf6ab8e78eb8..000000000000 --- a/libs/common_time/LinearTransform.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#ifndef _LINEAR_TRANSFORM_H -#define _LINEAR_TRANSFORM_H - -#include <stdint.h> - -namespace android { - -// LinearTransform defines a structure which hold the definition of a -// transformation from single dimensional coordinate system A into coordinate -// system B (and back again). Values in A and in B are 64 bit, the linear -// scale factor is expressed as a rational number using two 32 bit values. -// -// Specifically, let -// f(a) = b -// F(b) = f^-1(b) = a -// then -// -// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero; -// -// and -// -// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero; -// -struct LinearTransform { - int64_t a_zero; - int64_t b_zero; - int32_t a_to_b_numer; - uint32_t a_to_b_denom; - - // Transform from A->B - // Returns true on success, or false in the case of a singularity or an - // overflow. - bool doForwardTransform(int64_t a_in, int64_t* b_out) const; - - // Transform from B->A - // Returns true on success, or false in the case of a singularity or an - // overflow. - bool doReverseTransform(int64_t b_in, int64_t* a_out) const; - - // Helpers which will reduce the fraction N/D using Euclid's method. - template <class T> static void reduce(T* N, T* D); - static void reduce(int32_t* N, uint32_t* D); -}; - - -} - -#endif // _LINEAR_TRANSFORM_H diff --git a/libs/common_time/clock_recovery.cpp b/libs/common_time/clock_recovery.cpp deleted file mode 100644 index 392caa0ca16f..000000000000 --- a/libs/common_time/clock_recovery.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -/* - * A service that exchanges time synchronization information between - * a master that defines a timeline and clients that follow the timeline. - */ - -#define __STDC_LIMIT_MACROS -#define LOG_TAG "common_time" -#include <utils/Log.h> -#include <inttypes.h> -#include <stdint.h> - -#include <common_time/local_clock.h> -#include <assert.h> - -#include "clock_recovery.h" -#include "common_clock.h" -#ifdef TIME_SERVICE_DEBUG -#include "diag_thread.h" -#endif - -// Define log macro so we can make LOGV into LOGE when we are exclusively -// debugging this code. -#ifdef TIME_SERVICE_DEBUG -#define LOG_TS ALOGE -#else -#define LOG_TS ALOGV -#endif - -namespace android { - -ClockRecoveryLoop::ClockRecoveryLoop(LocalClock* local_clock, - CommonClock* common_clock) { - assert(NULL != local_clock); - assert(NULL != common_clock); - - local_clock_ = local_clock; - common_clock_ = common_clock; - - local_clock_can_slew_ = local_clock_->initCheck() && - (local_clock_->setLocalSlew(0) == OK); - tgt_correction_ = 0; - cur_correction_ = 0; - - // Precompute the max rate at which we are allowed to change the VCXO - // control. - uint64_t N = 0x10000ull * 1000ull; - uint64_t D = local_clock_->getLocalFreq() * kMinFullRangeSlewChange_mSec; - LinearTransform::reduce(&N, &D); - while ((N > INT32_MAX) || (D > UINT32_MAX)) { - N >>= 1; - D >>= 1; - LinearTransform::reduce(&N, &D); - } - time_to_cur_slew_.a_to_b_numer = static_cast<int32_t>(N); - time_to_cur_slew_.a_to_b_denom = static_cast<uint32_t>(D); - - reset(true, true); - -#ifdef TIME_SERVICE_DEBUG - diag_thread_ = new DiagThread(common_clock_, local_clock_); - if (diag_thread_ != NULL) { - status_t res = diag_thread_->startWorkThread(); - if (res != OK) - ALOGW("Failed to start A@H clock recovery diagnostic thread."); - } else - ALOGW("Failed to allocate diagnostic thread."); -#endif -} - -ClockRecoveryLoop::~ClockRecoveryLoop() { -#ifdef TIME_SERVICE_DEBUG - diag_thread_->stopWorkThread(); -#endif -} - -// Constants. -const float ClockRecoveryLoop::dT = 1.0; -const float ClockRecoveryLoop::Kc = 1.0f; -const float ClockRecoveryLoop::Ti = 15.0f; -const float ClockRecoveryLoop::Tf = 0.05; -const float ClockRecoveryLoop::bias_Fc = 0.01; -const float ClockRecoveryLoop::bias_RC = (dT / (2 * 3.14159f * bias_Fc)); -const float ClockRecoveryLoop::bias_Alpha = (dT / (bias_RC + dT)); -const int64_t ClockRecoveryLoop::panic_thresh_ = 50000; -const int64_t ClockRecoveryLoop::control_thresh_ = 10000; -const float ClockRecoveryLoop::COmin = -100.0f; -const float ClockRecoveryLoop::COmax = 100.0f; -const uint32_t ClockRecoveryLoop::kMinFullRangeSlewChange_mSec = 300; -const int ClockRecoveryLoop::kSlewChangeStepPeriod_mSec = 10; - - -void ClockRecoveryLoop::reset(bool position, bool frequency) { - Mutex::Autolock lock(&lock_); - reset_l(position, frequency); -} - -uint32_t ClockRecoveryLoop::findMinRTTNdx(DisciplineDataPoint* data, - uint32_t count) { - uint32_t min_rtt = 0; - for (uint32_t i = 1; i < count; ++i) - if (data[min_rtt].rtt > data[i].rtt) - min_rtt = i; - - return min_rtt; -} - -bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time, - int64_t nominal_common_time, - int64_t rtt) { - Mutex::Autolock lock(&lock_); - - int64_t local_common_time = 0; - common_clock_->localToCommon(local_time, &local_common_time); - int64_t raw_delta = nominal_common_time - local_common_time; - -#ifdef TIME_SERVICE_DEBUG - ALOGE("local=%lld, common=%lld, delta=%lld, rtt=%lld\n", - local_common_time, nominal_common_time, - raw_delta, rtt); -#endif - - // If we have not defined a basis for common time, then we need to use these - // initial points to do so. In order to avoid significant initial error - // from a particularly bad startup data point, we collect the first N data - // points and choose the best of them before moving on. - if (!common_clock_->isValid()) { - if (startup_filter_wr_ < kStartupFilterSize) { - DisciplineDataPoint& d = startup_filter_data_[startup_filter_wr_]; - d.local_time = local_time; - d.nominal_common_time = nominal_common_time; - d.rtt = rtt; - startup_filter_wr_++; - } - - if (startup_filter_wr_ == kStartupFilterSize) { - uint32_t min_rtt = findMinRTTNdx(startup_filter_data_, - kStartupFilterSize); - - common_clock_->setBasis( - startup_filter_data_[min_rtt].local_time, - startup_filter_data_[min_rtt].nominal_common_time); - } - - return true; - } - - int64_t observed_common; - int64_t delta; - float delta_f, dCO; - int32_t tgt_correction; - - if (OK != common_clock_->localToCommon(local_time, &observed_common)) { - // Since we just checked to make certain that this conversion was valid, - // and no one else in the system should be messing with it, if this - // conversion is suddenly invalid, it is a good reason to panic. - ALOGE("Failed to convert local time to common time in %s:%d", - __PRETTY_FUNCTION__, __LINE__); - return false; - } - - // Implement a filter which should match NTP filtering behavior when a - // client is associated with only one peer of lower stratum. Basically, - // always use the best of the N last data points, where best is defined as - // lowest round trip time. NTP uses an N of 8; we use a value of 6. - // - // TODO(johngro) : experiment with other filter strategies. The goal here - // is to mitigate the effects of high RTT data points which typically have - // large asymmetries in the TX/RX legs. Downside of the existing NTP - // approach (particularly because of the PID controller we are using to - // produce the control signal from the filtered data) are that the rate at - // which discipline events are actually acted upon becomes irregular and can - // become drawn out (the time between actionable event can go way up). If - // the system receives a strong high quality data point, the proportional - // component of the controller can produce a strong correction which is left - // in place for too long causing overshoot. In addition, the integral - // component of the system currently is an approximation based on the - // assumption of a more or less homogeneous sampling of the error. Its - // unclear what the effect of undermining this assumption would be right - // now. - - // Two ideas which come to mind immediately would be to... - // 1) Keep a history of more data points (32 or so) and ignore data points - // whose RTT is more than a certain number of standard deviations outside - // of the norm. - // 2) Eliminate the PID controller portion of this system entirely. - // Instead, move to a system which uses a very wide filter (128 data - // points or more) with a sum-of-least-squares line fitting approach to - // tracking the long term drift. This would take the place of the I - // component in the current PID controller. Also use a much more narrow - // outlier-rejector filter (as described in #1) to drive a short term - // correction factor similar to the P component of the PID controller. - assert(filter_wr_ < kFilterSize); - filter_data_[filter_wr_].local_time = local_time; - filter_data_[filter_wr_].observed_common_time = observed_common; - filter_data_[filter_wr_].nominal_common_time = nominal_common_time; - filter_data_[filter_wr_].rtt = rtt; - filter_data_[filter_wr_].point_used = false; - uint32_t current_point = filter_wr_; - filter_wr_ = (filter_wr_ + 1) % kFilterSize; - if (!filter_wr_) - filter_full_ = true; - - uint32_t scan_end = filter_full_ ? kFilterSize : filter_wr_; - uint32_t min_rtt = findMinRTTNdx(filter_data_, scan_end); - // We only use packets with low RTTs for control. If the packet RTT - // is less than the panic threshold, we can probably eat the jitter with the - // control loop. Otherwise, take the packet only if it better than all - // of the packets we have in the history. That way we try to track - // something, even if it is noisy. - if (current_point == min_rtt || rtt < control_thresh_) { - delta_f = delta = nominal_common_time - observed_common; - - last_error_est_valid_ = true; - last_error_est_usec_ = delta; - - // Compute the error then clamp to the panic threshold. If we ever - // exceed this amt of error, its time to panic and reset the system. - // Given that the error in the measurement of the error could be as - // high as the RTT of the data point, we don't actually panic until - // the implied error (delta) is greater than the absolute panic - // threashold plus the RTT. IOW - we don't panic until we are - // absoluely sure that our best case sync is worse than the absolute - // panic threshold. - int64_t effective_panic_thresh = panic_thresh_ + rtt; - if ((delta > effective_panic_thresh) || - (delta < -effective_panic_thresh)) { - // PANIC!!! - reset_l(false, true); - return false; - } - - } else { - // We do not have a good packet to look at, but we also do not want to - // free-run the clock at some crazy slew rate. So we guess the - // trajectory of the clock based on the last controller output and the - // estimated bias of our clock against the master. - // The net effect of this is that CO == CObias after some extended - // period of no feedback. - delta_f = last_delta_f_ - dT*(CO - CObias); - delta = delta_f; - } - - // Velocity form PI control equation. - dCO = Kc * (1.0f + dT/Ti) * delta_f - Kc * last_delta_f_; - CO += dCO * Tf; // Filter CO by applying gain <1 here. - - // Save error terms for later. - last_delta_f_ = delta_f; - - // Clamp CO to +/- 100ppm. - if (CO < COmin) - CO = COmin; - else if (CO > COmax) - CO = COmax; - - // Update the controller bias. - CObias = bias_Alpha * CO + (1.0f - bias_Alpha) * lastCObias; - lastCObias = CObias; - - // Convert PPM to 16-bit int range. Add some guard band (-0.01) so we - // don't get fp weirdness. - tgt_correction = CO * 327.66; - - // If there was a change in the amt of correction to use, update the - // system. - setTargetCorrection_l(tgt_correction); - - LOG_TS("clock_loop %" PRId64 " %f %f %f %d\n", raw_delta, delta_f, CO, CObias, tgt_correction); - -#ifdef TIME_SERVICE_DEBUG - diag_thread_->pushDisciplineEvent( - local_time, - observed_common, - nominal_common_time, - tgt_correction, - rtt); -#endif - - return true; -} - -int32_t ClockRecoveryLoop::getLastErrorEstimate() { - Mutex::Autolock lock(&lock_); - - if (last_error_est_valid_) - return last_error_est_usec_; - else - return ICommonClock::kErrorEstimateUnknown; -} - -void ClockRecoveryLoop::reset_l(bool position, bool frequency) { - assert(NULL != common_clock_); - - if (position) { - common_clock_->resetBasis(); - startup_filter_wr_ = 0; - } - - if (frequency) { - last_error_est_valid_ = false; - last_error_est_usec_ = 0; - last_delta_f_ = 0.0; - CO = 0.0f; - lastCObias = CObias = 0.0f; - setTargetCorrection_l(0); - applySlew_l(); - } - - filter_wr_ = 0; - filter_full_ = false; -} - -void ClockRecoveryLoop::setTargetCorrection_l(int32_t tgt) { - // When we make a change to the slew rate, we need to be careful to not - // change it too quickly as it can anger some HDMI sinks out there, notably - // some Sony panels from the 2010-2011 timeframe. From experimenting with - // some of these sinks, it seems like swinging from one end of the range to - // another in less that 190mSec or so can start to cause trouble. Adding in - // a hefty margin, we limit the system to a full range sweep in no less than - // 300mSec. - if (tgt_correction_ != tgt) { - int64_t now = local_clock_->getLocalTime(); - - tgt_correction_ = tgt; - - // Set up the transformation to figure out what the slew should be at - // any given point in time in the future. - time_to_cur_slew_.a_zero = now; - time_to_cur_slew_.b_zero = cur_correction_; - - // Make sure the sign of the slope is headed in the proper direction. - bool needs_increase = (cur_correction_ < tgt_correction_); - bool is_increasing = (time_to_cur_slew_.a_to_b_numer > 0); - if (( needs_increase && !is_increasing) || - (!needs_increase && is_increasing)) { - time_to_cur_slew_.a_to_b_numer = -time_to_cur_slew_.a_to_b_numer; - } - - // Finally, figure out when the change will be finished and start the - // slew operation. - time_to_cur_slew_.doReverseTransform(tgt_correction_, - &slew_change_end_time_); - - applySlew_l(); - } -} - -bool ClockRecoveryLoop::applySlew_l() { - bool ret = true; - - // If cur == tgt, there is no ongoing sleq rate change and we are already - // finished. - if (cur_correction_ == tgt_correction_) - goto bailout; - - if (local_clock_can_slew_) { - int64_t now = local_clock_->getLocalTime(); - int64_t tmp; - - if (now >= slew_change_end_time_) { - cur_correction_ = tgt_correction_; - next_slew_change_timeout_.setTimeout(-1); - } else { - time_to_cur_slew_.doForwardTransform(now, &tmp); - - if (tmp > INT16_MAX) - cur_correction_ = INT16_MAX; - else if (tmp < INT16_MIN) - cur_correction_ = INT16_MIN; - else - cur_correction_ = static_cast<int16_t>(tmp); - - next_slew_change_timeout_.setTimeout(kSlewChangeStepPeriod_mSec); - ret = false; - } - - local_clock_->setLocalSlew(cur_correction_); - } else { - // Since we are not actually changing the rate of a HW clock, we don't - // need to worry to much about changing the slew rate so fast that we - // anger any downstream HDMI devices. - cur_correction_ = tgt_correction_; - next_slew_change_timeout_.setTimeout(-1); - - // The SW clock recovery implemented by the common clock class expects - // values expressed in PPM. CO is in ppm. - common_clock_->setSlew(local_clock_->getLocalTime(), CO); - } - -bailout: - return ret; -} - -int ClockRecoveryLoop::applyRateLimitedSlew() { - Mutex::Autolock lock(&lock_); - - int ret = next_slew_change_timeout_.msecTillTimeout(); - if (!ret) { - if (applySlew_l()) - next_slew_change_timeout_.setTimeout(-1); - ret = next_slew_change_timeout_.msecTillTimeout(); - } - - return ret; -} - -} // namespace android diff --git a/libs/common_time/clock_recovery.h b/libs/common_time/clock_recovery.h deleted file mode 100644 index 8066a3968b59..000000000000 --- a/libs/common_time/clock_recovery.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#ifndef __CLOCK_RECOVERY_H__ -#define __CLOCK_RECOVERY_H__ - -#include <stdint.h> -#include <common_time/ICommonClock.h> -#include <utils/threads.h> - -#include "LinearTransform.h" - -#ifdef TIME_SERVICE_DEBUG -#include "diag_thread.h" -#endif - -#include "utils.h" - -namespace android { - -class CommonClock; -class LocalClock; - -class ClockRecoveryLoop { - public: - ClockRecoveryLoop(LocalClock* local_clock, CommonClock* common_clock); - ~ClockRecoveryLoop(); - - void reset(bool position, bool frequency); - bool pushDisciplineEvent(int64_t local_time, - int64_t nominal_common_time, - int64_t data_point_rtt); - int32_t getLastErrorEstimate(); - - // Applies the next step in any ongoing slew change operation. Returns a - // timeout suitable for use with poll/select indicating the number of mSec - // until the next change should be applied. - int applyRateLimitedSlew(); - - private: - - // Tuned using the "Good Gain" method. - // See: - // http://techteach.no/publications/books/dynamics_and_control/tuning_pid_controller.pdf - - // Controller period (1Hz for now). - static const float dT; - - // Controller gain, positive and unitless. Larger values converge faster, - // but can cause instability. - static const float Kc; - - // Integral reset time. Smaller values cause loop to track faster, but can - // also cause instability. - static const float Ti; - - // Controller output filter time constant. Range (0-1). Smaller values make - // output smoother, but slow convergence. - static const float Tf; - - // Low-pass filter for bias tracker. - static const float bias_Fc; // HZ - static const float bias_RC; // Computed in constructor. - static const float bias_Alpha; // Computed inconstructor. - - // The maximum allowed error (as indicated by a pushDisciplineEvent) before - // we panic. - static const int64_t panic_thresh_; - - // The maximum allowed error rtt time for packets to be used for control - // feedback, unless the packet is the best in recent memory. - static const int64_t control_thresh_; - - typedef struct { - int64_t local_time; - int64_t observed_common_time; - int64_t nominal_common_time; - int64_t rtt; - bool point_used; - } DisciplineDataPoint; - - static uint32_t findMinRTTNdx(DisciplineDataPoint* data, uint32_t count); - - void reset_l(bool position, bool frequency); - void setTargetCorrection_l(int32_t tgt); - bool applySlew_l(); - - // The local clock HW abstraction we use as the basis for common time. - LocalClock* local_clock_; - bool local_clock_can_slew_; - - // The common clock we end up controlling along with the lock used to - // serialize operations. - CommonClock* common_clock_; - Mutex lock_; - - // parameters maintained while running and reset during a reset - // of the frequency correction. - bool last_error_est_valid_; - int32_t last_error_est_usec_; - float last_delta_f_; - int32_t tgt_correction_; - int32_t cur_correction_; - LinearTransform time_to_cur_slew_; - int64_t slew_change_end_time_; - Timeout next_slew_change_timeout_; - - // Contoller Output. - float CO; - - // Bias tracking for trajectory estimation. - float CObias; - float lastCObias; - - // Controller output bounds. The controller will not try to - // slew faster that +/-100ppm offset from center per interation. - static const float COmin; - static const float COmax; - - // State kept for filtering the discipline data. - static const uint32_t kFilterSize = 16; - DisciplineDataPoint filter_data_[kFilterSize]; - uint32_t filter_wr_; - bool filter_full_; - - static const uint32_t kStartupFilterSize = 4; - DisciplineDataPoint startup_filter_data_[kStartupFilterSize]; - uint32_t startup_filter_wr_; - - // Minimum number of milliseconds over which we allow a full range change - // (from rail to rail) of the VCXO control signal. This is the rate - // limiting factor which keeps us from changing the clock rate so fast that - // we get in trouble with certain HDMI sinks. - static const uint32_t kMinFullRangeSlewChange_mSec; - - // How much time (in msec) to wait - static const int kSlewChangeStepPeriod_mSec; - -#ifdef TIME_SERVICE_DEBUG - sp<DiagThread> diag_thread_; -#endif -}; - -} // namespace android - -#endif // __CLOCK_RECOVERY_H__ diff --git a/libs/common_time/common_clock.cpp b/libs/common_time/common_clock.cpp deleted file mode 100644 index aed52f177c80..000000000000 --- a/libs/common_time/common_clock.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#define __STDC_LIMIT_MACROS - -#define LOG_TAG "common_time" -#include <utils/Log.h> - -#include <inttypes.h> -#include <stdint.h> - -#include <utils/Errors.h> - -#include "common_clock.h" - -namespace android { - -CommonClock::CommonClock() { - cur_slew_ = 0; - cur_trans_valid_ = false; - - cur_trans_.a_zero = 0; - cur_trans_.b_zero = 0; - cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = 1; - cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = 1; - duration_trans_ = cur_trans_; -} - -bool CommonClock::init(uint64_t local_freq) { - Mutex::Autolock lock(&lock_); - - if (!local_freq) - return false; - - uint64_t numer = kCommonFreq; - uint64_t denom = local_freq; - - LinearTransform::reduce(&numer, &denom); - if ((numer > UINT32_MAX) || (denom > UINT32_MAX)) { - ALOGE("Overflow in CommonClock::init while trying to reduce %" PRIu64 "/%" PRIu64, - kCommonFreq, local_freq); - return false; - } - - cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = - static_cast<uint32_t>(numer); - cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = - static_cast<uint32_t>(denom); - duration_trans_ = cur_trans_; - - return true; -} - -status_t CommonClock::localToCommon(int64_t local, int64_t *common_out) const { - Mutex::Autolock lock(&lock_); - - if (!cur_trans_valid_) - return INVALID_OPERATION; - - if (!cur_trans_.doForwardTransform(local, common_out)) - return INVALID_OPERATION; - - return OK; -} - -status_t CommonClock::commonToLocal(int64_t common, int64_t *local_out) const { - Mutex::Autolock lock(&lock_); - - if (!cur_trans_valid_) - return INVALID_OPERATION; - - if (!cur_trans_.doReverseTransform(common, local_out)) - return INVALID_OPERATION; - - return OK; -} - -int64_t CommonClock::localDurationToCommonDuration(int64_t localDur) const { - int64_t ret; - duration_trans_.doForwardTransform(localDur, &ret); - return ret; -} - -void CommonClock::setBasis(int64_t local, int64_t common) { - Mutex::Autolock lock(&lock_); - - cur_trans_.a_zero = local; - cur_trans_.b_zero = common; - cur_trans_valid_ = true; -} - -void CommonClock::resetBasis() { - Mutex::Autolock lock(&lock_); - - cur_trans_.a_zero = 0; - cur_trans_.b_zero = 0; - cur_trans_valid_ = false; -} - -status_t CommonClock::setSlew(int64_t change_time, int32_t ppm) { - Mutex::Autolock lock(&lock_); - - int64_t new_local_basis; - int64_t new_common_basis; - - if (cur_trans_valid_) { - new_local_basis = change_time; - if (!cur_trans_.doForwardTransform(change_time, &new_common_basis)) { - ALOGE("Overflow when attempting to set slew rate to %d", ppm); - return INVALID_OPERATION; - } - } else { - new_local_basis = 0; - new_common_basis = 0; - } - - cur_slew_ = ppm; - uint32_t n1 = local_to_common_freq_numer_; - uint32_t n2 = 1000000 + cur_slew_; - - uint32_t d1 = local_to_common_freq_denom_; - uint32_t d2 = 1000000; - - // n1/d1 has already been reduced, no need to do so here. - LinearTransform::reduce(&n1, &d2); - LinearTransform::reduce(&n2, &d1); - LinearTransform::reduce(&n2, &d2); - - cur_trans_.a_zero = new_local_basis; - cur_trans_.b_zero = new_common_basis; - cur_trans_.a_to_b_numer = n1 * n2; - cur_trans_.a_to_b_denom = d1 * d2; - - return OK; -} - -} // namespace android diff --git a/libs/common_time/common_clock.h b/libs/common_time/common_clock.h deleted file mode 100644 index 5e4e5f51b446..000000000000 --- a/libs/common_time/common_clock.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#ifndef __COMMON_CLOCK_H__ -#define __COMMON_CLOCK_H__ - -#include <stdint.h> - -#include <utils/Errors.h> -#include <utils/threads.h> - -#include "LinearTransform.h" - -namespace android { - -class CommonClock { - public: - CommonClock(); - - bool init(uint64_t local_freq); - - status_t localToCommon(int64_t local, int64_t *common_out) const; - status_t commonToLocal(int64_t common, int64_t *local_out) const; - int64_t localDurationToCommonDuration(int64_t localDur) const; - uint64_t getCommonFreq() const { return kCommonFreq; } - bool isValid() const { return cur_trans_valid_; } - status_t setSlew(int64_t change_time, int32_t ppm); - void setBasis(int64_t local, int64_t common); - void resetBasis(); - private: - mutable Mutex lock_; - - int32_t cur_slew_; - uint32_t local_to_common_freq_numer_; - uint32_t local_to_common_freq_denom_; - - LinearTransform duration_trans_; - LinearTransform cur_trans_; - bool cur_trans_valid_; - - static const uint64_t kCommonFreq = 1000000ull; -}; - -} // namespace android -#endif // __COMMON_CLOCK_H__ diff --git a/libs/common_time/common_clock_service.cpp b/libs/common_time/common_clock_service.cpp deleted file mode 100644 index 592ab1dceab8..000000000000 --- a/libs/common_time/common_clock_service.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#include <common_time/local_clock.h> -#include <utils/String8.h> - -#include "common_clock_service.h" -#include "common_clock.h" -#include "common_time_server.h" - -namespace android { - -sp<CommonClockService> CommonClockService::instantiate( - CommonTimeServer& timeServer) { - sp<CommonClockService> tcc = new CommonClockService(timeServer); - if (tcc == NULL) - return NULL; - - defaultServiceManager()->addService(ICommonClock::kServiceName, tcc); - return tcc; -} - -status_t CommonClockService::dump(int fd, const Vector<String16>& args) { - Mutex::Autolock lock(mRegistrationLock); - return mTimeServer.dumpClockInterface(fd, args, mListeners.size()); -} - -status_t CommonClockService::isCommonTimeValid(bool* valid, - uint32_t* timelineID) { - return mTimeServer.isCommonTimeValid(valid, timelineID); -} - -status_t CommonClockService::commonTimeToLocalTime(int64_t commonTime, - int64_t* localTime) { - return mTimeServer.getCommonClock().commonToLocal(commonTime, localTime); -} - -status_t CommonClockService::localTimeToCommonTime(int64_t localTime, - int64_t* commonTime) { - return mTimeServer.getCommonClock().localToCommon(localTime, commonTime); -} - -status_t CommonClockService::getCommonTime(int64_t* commonTime) { - return localTimeToCommonTime(mTimeServer.getLocalClock().getLocalTime(), commonTime); -} - -status_t CommonClockService::getCommonFreq(uint64_t* freq) { - *freq = mTimeServer.getCommonClock().getCommonFreq(); - return OK; -} - -status_t CommonClockService::getLocalTime(int64_t* localTime) { - *localTime = mTimeServer.getLocalClock().getLocalTime(); - return OK; -} - -status_t CommonClockService::getLocalFreq(uint64_t* freq) { - *freq = mTimeServer.getLocalClock().getLocalFreq(); - return OK; -} - -status_t CommonClockService::getEstimatedError(int32_t* estimate) { - *estimate = mTimeServer.getEstimatedError(); - return OK; -} - -status_t CommonClockService::getTimelineID(uint64_t* id) { - *id = mTimeServer.getTimelineID(); - return OK; -} - -status_t CommonClockService::getState(State* state) { - *state = mTimeServer.getState(); - return OK; -} - -status_t CommonClockService::getMasterAddr(struct sockaddr_storage* addr) { - return mTimeServer.getMasterAddr(addr); -} - -status_t CommonClockService::registerListener( - const sp<ICommonClockListener>& listener) { - Mutex::Autolock lock(mRegistrationLock); - - { // scoping for autolock pattern - Mutex::Autolock lock(mCallbackLock); - // check whether this is a duplicate - for (size_t i = 0; i < mListeners.size(); i++) { - if (IInterface::asBinder(mListeners[i]) == IInterface::asBinder(listener)) - return ALREADY_EXISTS; - } - } - - mListeners.add(listener); - mTimeServer.reevaluateAutoDisableState(0 != mListeners.size()); - return IInterface::asBinder(listener)->linkToDeath(this); -} - -status_t CommonClockService::unregisterListener( - const sp<ICommonClockListener>& listener) { - Mutex::Autolock lock(mRegistrationLock); - status_t ret_val = NAME_NOT_FOUND; - - { // scoping for autolock pattern - Mutex::Autolock lock(mCallbackLock); - for (size_t i = 0; i < mListeners.size(); i++) { - if (IInterface::asBinder(mListeners[i]) == IInterface::asBinder(listener)) { - IInterface::asBinder(mListeners[i])->unlinkToDeath(this); - mListeners.removeAt(i); - ret_val = OK; - break; - } - } - } - - mTimeServer.reevaluateAutoDisableState(0 != mListeners.size()); - return ret_val; -} - -void CommonClockService::binderDied(const wp<IBinder>& who) { - Mutex::Autolock lock(mRegistrationLock); - - { // scoping for autolock pattern - Mutex::Autolock lock(mCallbackLock); - for (size_t i = 0; i < mListeners.size(); i++) { - if (IInterface::asBinder(mListeners[i]) == who) { - mListeners.removeAt(i); - break; - } - } - } - - mTimeServer.reevaluateAutoDisableState(0 != mListeners.size()); -} - -void CommonClockService::notifyOnTimelineChanged(uint64_t timelineID) { - Mutex::Autolock lock(mCallbackLock); - - for (size_t i = 0; i < mListeners.size(); i++) { - mListeners[i]->onTimelineChanged(timelineID); - } -} - -}; // namespace android diff --git a/libs/common_time/common_clock_service.h b/libs/common_time/common_clock_service.h deleted file mode 100644 index aea507ec0f30..000000000000 --- a/libs/common_time/common_clock_service.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#ifndef ANDROID_COMMON_CLOCK_SERVICE_H -#define ANDROID_COMMON_CLOCK_SERVICE_H - -#include <sys/socket.h> -#include <common_time/ICommonClock.h> - -namespace android { - -class CommonTimeServer; - -class CommonClockService : public BnCommonClock, - public android::IBinder::DeathRecipient { - public: - static sp<CommonClockService> instantiate(CommonTimeServer& timeServer); - - virtual status_t dump(int fd, const Vector<String16>& args); - - virtual status_t isCommonTimeValid(bool* valid, uint32_t *timelineID); - virtual status_t commonTimeToLocalTime(int64_t common_time, - int64_t* local_time); - virtual status_t localTimeToCommonTime(int64_t local_time, - int64_t* common_time); - virtual status_t getCommonTime(int64_t* common_time); - virtual status_t getCommonFreq(uint64_t* freq); - virtual status_t getLocalTime(int64_t* local_time); - virtual status_t getLocalFreq(uint64_t* freq); - virtual status_t getEstimatedError(int32_t* estimate); - virtual status_t getTimelineID(uint64_t* id); - virtual status_t getState(ICommonClock::State* state); - virtual status_t getMasterAddr(struct sockaddr_storage* addr); - - virtual status_t registerListener( - const sp<ICommonClockListener>& listener); - virtual status_t unregisterListener( - const sp<ICommonClockListener>& listener); - - void notifyOnTimelineChanged(uint64_t timelineID); - - private: - explicit CommonClockService(CommonTimeServer& timeServer) - : mTimeServer(timeServer) { }; - - virtual void binderDied(const wp<IBinder>& who); - - CommonTimeServer& mTimeServer; - - // locks used to synchronize access to the list of registered listeners. - // The callback lock is held whenever the list is used to perform callbacks - // or while the list is being modified. The registration lock used to - // serialize access across registerListener, unregisterListener, and - // binderDied. - // - // The reason for two locks is that registerListener, unregisterListener, - // and binderDied each call into the core service and obtain the core - // service thread lock when they call reevaluateAutoDisableState. The core - // service thread obtains the main thread lock whenever its thread is - // running, and sometimes needs to call notifyOnTimelineChanged which then - // obtains the callback lock. If callers of registration functions were - // holding the callback lock when they called into the core service, we - // would have a classic A/B, B/A ordering deadlock. To avoid this, the - // registration functions hold the registration lock for the duration of - // their call, but hold the callback lock only while they mutate the list. - // This way, the list's size cannot change (because of the registration - // lock) during the call into reevaluateAutoDisableState, but the core work - // thread can still safely call notifyOnTimelineChanged while holding the - // main thread lock. - Mutex mCallbackLock; - Mutex mRegistrationLock; - - Vector<sp<ICommonClockListener> > mListeners; -}; - -}; // namespace android - -#endif // ANDROID_COMMON_CLOCK_SERVICE_H diff --git a/libs/common_time/common_time_config_service.cpp b/libs/common_time/common_time_config_service.cpp deleted file mode 100644 index 958561818423..000000000000 --- a/libs/common_time/common_time_config_service.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#include <utils/String8.h> - -#include "common_time_config_service.h" -#include "common_time_server.h" - -namespace android { - -sp<CommonTimeConfigService> CommonTimeConfigService::instantiate( - CommonTimeServer& timeServer) { - sp<CommonTimeConfigService> ctcs = new CommonTimeConfigService(timeServer); - if (ctcs == NULL) - return NULL; - - defaultServiceManager()->addService(ICommonTimeConfig::kServiceName, ctcs); - return ctcs; -} - -status_t CommonTimeConfigService::dump(int fd, const Vector<String16>& args) { - return mTimeServer.dumpConfigInterface(fd, args); -} - -status_t CommonTimeConfigService::getMasterElectionPriority(uint8_t *priority) { - return mTimeServer.getMasterElectionPriority(priority); -} - -status_t CommonTimeConfigService::setMasterElectionPriority(uint8_t priority) { - return mTimeServer.setMasterElectionPriority(priority); -} - -status_t CommonTimeConfigService::getMasterElectionEndpoint( - struct sockaddr_storage *addr) { - return mTimeServer.getMasterElectionEndpoint(addr); -} - -status_t CommonTimeConfigService::setMasterElectionEndpoint( - const struct sockaddr_storage *addr) { - return mTimeServer.setMasterElectionEndpoint(addr); -} - -status_t CommonTimeConfigService::getMasterElectionGroupId(uint64_t *id) { - return mTimeServer.getMasterElectionGroupId(id); -} - -status_t CommonTimeConfigService::setMasterElectionGroupId(uint64_t id) { - return mTimeServer.setMasterElectionGroupId(id); -} - -status_t CommonTimeConfigService::getInterfaceBinding(String16& ifaceName) { - String8 tmp; - status_t ret = mTimeServer.getInterfaceBinding(tmp); - ifaceName = String16(tmp); - return ret; -} - -status_t CommonTimeConfigService::setInterfaceBinding(const String16& ifaceName) { - String8 tmp(ifaceName); - return mTimeServer.setInterfaceBinding(tmp); -} - -status_t CommonTimeConfigService::getMasterAnnounceInterval(int *interval) { - return mTimeServer.getMasterAnnounceInterval(interval); -} - -status_t CommonTimeConfigService::setMasterAnnounceInterval(int interval) { - return mTimeServer.setMasterAnnounceInterval(interval); -} - -status_t CommonTimeConfigService::getClientSyncInterval(int *interval) { - return mTimeServer.getClientSyncInterval(interval); -} - -status_t CommonTimeConfigService::setClientSyncInterval(int interval) { - return mTimeServer.setClientSyncInterval(interval); -} - -status_t CommonTimeConfigService::getPanicThreshold(int *threshold) { - return mTimeServer.getPanicThreshold(threshold); -} - -status_t CommonTimeConfigService::setPanicThreshold(int threshold) { - return mTimeServer.setPanicThreshold(threshold); -} - -status_t CommonTimeConfigService::getAutoDisable(bool *autoDisable) { - return mTimeServer.getAutoDisable(autoDisable); -} - -status_t CommonTimeConfigService::setAutoDisable(bool autoDisable) { - return mTimeServer.setAutoDisable(autoDisable); -} - -status_t CommonTimeConfigService::forceNetworklessMasterMode() { - return mTimeServer.forceNetworklessMasterMode(); -} - -}; // namespace android diff --git a/libs/common_time/common_time_config_service.h b/libs/common_time/common_time_config_service.h deleted file mode 100644 index 23abb1a9e47e..000000000000 --- a/libs/common_time/common_time_config_service.h +++ /dev/null @@ -1,60 +0,0 @@ -/* * Copyright (C) 2012 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. - */ - -#ifndef ANDROID_COMMON_TIME_CONFIG_SERVICE_H -#define ANDROID_COMMON_TIME_CONFIG_SERVICE_H - -#include <sys/socket.h> -#include <common_time/ICommonTimeConfig.h> - -namespace android { - -class String16; -class CommonTimeServer; - -class CommonTimeConfigService : public BnCommonTimeConfig { - public: - static sp<CommonTimeConfigService> instantiate(CommonTimeServer& timeServer); - - virtual status_t dump(int fd, const Vector<String16>& args); - - virtual status_t getMasterElectionPriority(uint8_t *priority); - virtual status_t setMasterElectionPriority(uint8_t priority); - virtual status_t getMasterElectionEndpoint(struct sockaddr_storage *addr); - virtual status_t setMasterElectionEndpoint(const struct sockaddr_storage *addr); - virtual status_t getMasterElectionGroupId(uint64_t *id); - virtual status_t setMasterElectionGroupId(uint64_t id); - virtual status_t getInterfaceBinding(String16& ifaceName); - virtual status_t setInterfaceBinding(const String16& ifaceName); - virtual status_t getMasterAnnounceInterval(int *interval); - virtual status_t setMasterAnnounceInterval(int interval); - virtual status_t getClientSyncInterval(int *interval); - virtual status_t setClientSyncInterval(int interval); - virtual status_t getPanicThreshold(int *threshold); - virtual status_t setPanicThreshold(int threshold); - virtual status_t getAutoDisable(bool *autoDisable); - virtual status_t setAutoDisable(bool autoDisable); - virtual status_t forceNetworklessMasterMode(); - - private: - explicit CommonTimeConfigService(CommonTimeServer& timeServer) - : mTimeServer(timeServer) { } - CommonTimeServer& mTimeServer; - -}; - -}; // namespace android - -#endif // ANDROID_COMMON_TIME_CONFIG_SERVICE_H diff --git a/libs/common_time/common_time_server.cpp b/libs/common_time/common_time_server.cpp deleted file mode 100644 index b1495effbc81..000000000000 --- a/libs/common_time/common_time_server.cpp +++ /dev/null @@ -1,1507 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -/* - * A service that exchanges time synchronization information between - * a master that defines a timeline and clients that follow the timeline. - */ - -#define LOG_TAG "common_time" -#include <utils/Log.h> - -#include <arpa/inet.h> -#include <assert.h> -#include <fcntl.h> -#include <inttypes.h> -#include <linux/if_ether.h> -#include <net/if.h> -#include <net/if_arp.h> -#include <netinet/ip.h> -#include <poll.h> -#include <stdio.h> -#include <sys/eventfd.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/socket.h> - -#include <common_time/local_clock.h> -#include <binder/IPCThreadState.h> -#include <binder/ProcessState.h> -#include <utils/Timers.h> - -#include "common_clock_service.h" -#include "common_time_config_service.h" -#include "common_time_server.h" -#include "common_time_server_packets.h" -#include "clock_recovery.h" -#include "common_clock.h" - -#define MAX_INT ((int)0x7FFFFFFF) - -namespace android { - -const char* CommonTimeServer::kDefaultMasterElectionAddr = "255.255.255.255"; -const uint16_t CommonTimeServer::kDefaultMasterElectionPort = 8886; -const uint64_t CommonTimeServer::kDefaultSyncGroupID = 1; -const uint8_t CommonTimeServer::kDefaultMasterPriority = 1; -const uint32_t CommonTimeServer::kDefaultMasterAnnounceIntervalMs = 10000; -const uint32_t CommonTimeServer::kDefaultSyncRequestIntervalMs = 1000; -const uint32_t CommonTimeServer::kDefaultPanicThresholdUsec = 50000; -const bool CommonTimeServer::kDefaultAutoDisable = true; -const int CommonTimeServer::kSetupRetryTimeoutMs = 30000; -const int64_t CommonTimeServer::kNoGoodDataPanicThresholdUsec = 600000000ll; -const uint32_t CommonTimeServer::kRTTDiscardPanicThreshMultiplier = 5; - -// timeout value representing an infinite timeout -const int CommonTimeServer::kInfiniteTimeout = -1; - -/*** Initial state constants ***/ - -// number of WhoIsMaster attempts sent before giving up -const int CommonTimeServer::kInitial_NumWhoIsMasterRetries = 6; - -// timeout used when waiting for a response to a WhoIsMaster request -const int CommonTimeServer::kInitial_WhoIsMasterTimeoutMs = 500; - -/*** Client state constants ***/ - -// number of sync requests that can fail before a client assumes its master -// is dead -const int CommonTimeServer::kClient_NumSyncRequestRetries = 10; - -/*** Master state constants ***/ - -/*** Ronin state constants ***/ - -// number of WhoIsMaster attempts sent before declaring ourselves master -const int CommonTimeServer::kRonin_NumWhoIsMasterRetries = 20; - -// timeout used when waiting for a response to a WhoIsMaster request -const int CommonTimeServer::kRonin_WhoIsMasterTimeoutMs = 500; - -/*** WaitForElection state constants ***/ - -// how long do we wait for an announcement from a master before -// trying another election? -const int CommonTimeServer::kWaitForElection_TimeoutMs = 12500; - -CommonTimeServer::CommonTimeServer() - : Thread(false) - , mState(ICommonClock::STATE_INITIAL) - , mClockRecovery(&mLocalClock, &mCommonClock) - , mSocket(-1) - , mLastPacketRxLocalTime(0) - , mTimelineID(ICommonClock::kInvalidTimelineID) - , mClockSynced(false) - , mCommonClockHasClients(false) - , mStateChangeLog("Recent State Change Events", 30) - , mElectionLog("Recent Master Election Traffic", 30) - , mBadPktLog("Recent Bad Packet RX Info", 8) - , mInitial_WhoIsMasterRequestTimeouts(0) - , mClient_MasterDeviceID(0) - , mClient_MasterDevicePriority(0) - , mRonin_WhoIsMasterRequestTimeouts(0) { - // zero out sync stats - resetSyncStats(); - - // Setup the master election endpoint to use the default. - struct sockaddr_in* meep = - reinterpret_cast<struct sockaddr_in*>(&mMasterElectionEP); - memset(&mMasterElectionEP, 0, sizeof(mMasterElectionEP)); - inet_aton(kDefaultMasterElectionAddr, &meep->sin_addr); - meep->sin_family = AF_INET; - meep->sin_port = htons(kDefaultMasterElectionPort); - - // Zero out the master endpoint. - memset(&mMasterEP, 0, sizeof(mMasterEP)); - mMasterEPValid = false; - mBindIfaceValid = false; - setForceLowPriority(false); - - // Set all remaining configuration parameters to their defaults. - mDeviceID = 0; - mSyncGroupID = kDefaultSyncGroupID; - mMasterPriority = kDefaultMasterPriority; - mMasterAnnounceIntervalMs = kDefaultMasterAnnounceIntervalMs; - mSyncRequestIntervalMs = kDefaultSyncRequestIntervalMs; - mPanicThresholdUsec = kDefaultPanicThresholdUsec; - mAutoDisable = kDefaultAutoDisable; - - // Create the eventfd we will use to signal our thread to wake up when - // needed. - mWakeupThreadFD = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - - // seed the random number generator (used to generated timeline IDs) - srand48(static_cast<unsigned int>(systemTime())); -} - -CommonTimeServer::~CommonTimeServer() { - shutdownThread(); - - // No need to grab the lock here. We are in the destructor; if the the user - // has a thread in any of the APIs while the destructor is being called, - // there is a threading problem a the application level we cannot reasonably - // do anything about. - cleanupSocket_l(); - - if (mWakeupThreadFD >= 0) { - close(mWakeupThreadFD); - mWakeupThreadFD = -1; - } -} - -bool CommonTimeServer::startServices() { - // start the ICommonClock service - mICommonClock = CommonClockService::instantiate(*this); - if (mICommonClock == NULL) - return false; - - // start the ICommonTimeConfig service - mICommonTimeConfig = CommonTimeConfigService::instantiate(*this); - if (mICommonTimeConfig == NULL) - return false; - - return true; -} - -bool CommonTimeServer::threadLoop() { - // Register our service interfaces. - if (!startServices()) - return false; - - // Hold the lock while we are in the main thread loop. It will release the - // lock when it blocks, and hold the lock at all other times. - mLock.lock(); - runStateMachine_l(); - mLock.unlock(); - - IPCThreadState::self()->stopProcess(); - return false; -} - -bool CommonTimeServer::runStateMachine_l() { - if (!mLocalClock.initCheck()) - return false; - - if (!mCommonClock.init(mLocalClock.getLocalFreq())) - return false; - - // Enter the initial state. - becomeInitial("startup"); - - // run the state machine - while (!exitPending()) { - struct pollfd pfds[2]; - int rc, timeout; - int eventCnt = 0; - int64_t wakeupTime; - uint32_t t1, t2; - bool needHandleTimeout = false; - - // We are always interested in our wakeup FD. - pfds[eventCnt].fd = mWakeupThreadFD; - pfds[eventCnt].events = POLLIN; - pfds[eventCnt].revents = 0; - eventCnt++; - - // If we have a valid socket, then we are interested in what it has to - // say as well. - if (mSocket >= 0) { - pfds[eventCnt].fd = mSocket; - pfds[eventCnt].events = POLLIN; - pfds[eventCnt].revents = 0; - eventCnt++; - } - - t1 = static_cast<uint32_t>(mCurTimeout.msecTillTimeout()); - t2 = static_cast<uint32_t>(mClockRecovery.applyRateLimitedSlew()); - timeout = static_cast<int>(t1 < t2 ? t1 : t2); - - // Note, we were holding mLock when this function was called. We - // release it only while we are blocking and hold it at all other times. - mLock.unlock(); - rc = poll(pfds, eventCnt, timeout); - wakeupTime = mLocalClock.getLocalTime(); - mLock.lock(); - - // Is it time to shutdown? If so, don't hesitate... just do it. - if (exitPending()) - break; - - // Did the poll fail? This should never happen and is fatal if it does. - if (rc < 0) { - ALOGE("%s:%d poll failed", __PRETTY_FUNCTION__, __LINE__); - return false; - } - - if (rc == 0) { - needHandleTimeout = !mCurTimeout.msecTillTimeout(); - if (needHandleTimeout) - mCurTimeout.setTimeout(kInfiniteTimeout); - } - - // Were we woken up on purpose? If so, clear the eventfd with a read. - if (pfds[0].revents) - clearPendingWakeupEvents_l(); - - // Is out bind address dirty? If so, clean up our socket (if any). - // Alternatively, do we have an active socket but should be auto - // disabled? If so, release the socket and enter the proper sync state. - bool droppedSocket = false; - if (mBindIfaceDirty || ((mSocket >= 0) && shouldAutoDisable())) { - cleanupSocket_l(); - mBindIfaceDirty = false; - droppedSocket = true; - } - - // Do we not have a socket but should have one? If so, try to set one - // up. - if ((mSocket < 0) && mBindIfaceValid && !shouldAutoDisable()) { - if (setupSocket_l()) { - // Success! We are now joining a new network (either coming - // from no network, or coming from a potentially different - // network). Force our priority to be lower so that we defer to - // any other masters which may already be on the network we are - // joining. Later, when we enter either the client or the - // master state, we will clear this flag and go back to our - // normal election priority. - setForceLowPriority(true); - switch (mState) { - // If we were in initial (whether we had a immediately - // before this network or not) we want to simply reset the - // system and start again. Forcing a transition from - // INITIAL to INITIAL should do the job. - case CommonClockService::STATE_INITIAL: - becomeInitial("bound interface"); - break; - - // If we were in the master state, then either we were the - // master in a no-network situation, or we were the master - // of a different network and have moved to a new interface. - // In either case, immediately transition to Ronin at low - // priority. If there is no one in the network we just - // joined, we will become master soon enough. If there is, - // we want to be certain to defer master status to the - // existing timeline currently running on the network. - // - case CommonClockService::STATE_MASTER: - becomeRonin("leaving networkless mode"); - break; - - // If we were in any other state (CLIENT, RONIN, or - // WAIT_FOR_ELECTION) then we must be moving from one - // network to another. We have lost our old master; - // transition to RONIN in an attempt to find a new master. - // If there are none out there, we will just assume - // responsibility for the timeline we used to be a client - // of. - default: - becomeRonin("bound interface"); - break; - } - } else { - // That's odd... we failed to set up our socket. This could be - // due to some transient network change which will work itself - // out shortly; schedule a retry attempt in the near future. - mCurTimeout.setTimeout(kSetupRetryTimeoutMs); - } - - // One way or the other, we don't have any data to process at this - // point (since we just tried to bulid a new socket). Loop back - // around and wait for the next thing to do. - continue; - } else if (droppedSocket) { - // We just lost our socket, and for whatever reason (either no - // config, or auto disable engaged) we are not supposed to rebuild - // one at this time. We are not going to rebuild our socket until - // something about our config/auto-disabled status changes, so we - // are basically in network-less mode. If we are already in either - // INITIAL or MASTER, just stay there until something changes. If - // we are in any other state (CLIENT, RONIN or WAIT_FOR_ELECTION), - // then transition to either INITIAL or MASTER depending on whether - // or not our timeline is valid. - mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, - "Entering networkless mode interface is %s, " - "shouldAutoDisable = %s", - mBindIfaceValid ? "valid" : "invalid", - shouldAutoDisable() ? "true" : "false"); - if ((mState != ICommonClock::STATE_INITIAL) && - (mState != ICommonClock::STATE_MASTER)) { - if (mTimelineID == ICommonClock::kInvalidTimelineID) - becomeInitial("network-less mode"); - else - becomeMaster("network-less mode"); - } - - continue; - } - - // Time to handle the timeouts? - if (needHandleTimeout) { - if (!handleTimeout()) - ALOGE("handleTimeout failed"); - continue; - } - - // Does our socket have data for us (assuming we still have one, we - // may have RXed a packet at the same time as a config change telling us - // to shut our socket down)? If so, process its data. - if ((mSocket >= 0) && (eventCnt > 1) && (pfds[1].revents)) { - mLastPacketRxLocalTime = wakeupTime; - if (!handlePacket()) - ALOGE("handlePacket failed"); - } - } - - cleanupSocket_l(); - return true; -} - -void CommonTimeServer::clearPendingWakeupEvents_l() { - int64_t tmp; - read(mWakeupThreadFD, &tmp, sizeof(tmp)); -} - -void CommonTimeServer::wakeupThread_l() { - int64_t tmp = 1; - write(mWakeupThreadFD, &tmp, sizeof(tmp)); -} - -void CommonTimeServer::cleanupSocket_l() { - if (mSocket >= 0) { - close(mSocket); - mSocket = -1; - } -} - -void CommonTimeServer::shutdownThread() { - // Flag the work thread for shutdown. - this->requestExit(); - - // Signal the thread in case its sleeping. - mLock.lock(); - wakeupThread_l(); - mLock.unlock(); - - // Wait for the thread to exit. - this->join(); -} - -bool CommonTimeServer::setupSocket_l() { - int rc; - bool ret_val = false; - struct sockaddr_in* ipv4_addr = NULL; - char masterElectionEPStr[64]; - const int one = 1; - - // This should never be needed, but if we happened to have an old socket - // lying around, be sure to not leak it before proceeding. - cleanupSocket_l(); - - // If we don't have a valid endpoint to bind to, then how did we get here in - // the first place? Regardless, we know that we are going to fail to bind, - // so don't even try. - if (!mBindIfaceValid) - return false; - - sockaddrToString(mMasterElectionEP, true, masterElectionEPStr, - sizeof(masterElectionEPStr)); - mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, - "Building socket :: bind = %s master election = %s", - mBindIface.string(), masterElectionEPStr); - - // TODO: add proper support for IPv6. Right now, we block IPv6 addresses at - // the configuration interface level. - if (AF_INET != mMasterElectionEP.ss_family) { - mStateChangeLog.log(ANDROID_LOG_WARN, LOG_TAG, - "TODO: add proper IPv6 support"); - goto bailout; - } - - // open a UDP socket for the timeline serivce - mSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (mSocket < 0) { - mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, - "Failed to create socket (errno = %d)", errno); - goto bailout; - } - - // Bind to the selected interface using Linux's spiffy SO_BINDTODEVICE. - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", mBindIface.string()); - ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = 0; - rc = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, - (void *)&ifr, sizeof(ifr)); - if (rc) { - mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, - "Failed to bind socket at to interface %s " - "(errno = %d)", ifr.ifr_name, errno); - goto bailout; - } - - // Bind our socket to INADDR_ANY and the master election port. The - // interface binding we made using SO_BINDTODEVICE should limit us to - // traffic only on the interface we are interested in. We need to bind to - // INADDR_ANY and the specific master election port in order to be able to - // receive both unicast traffic and master election multicast traffic with - // just a single socket. - struct sockaddr_in bindAddr; - ipv4_addr = reinterpret_cast<struct sockaddr_in*>(&mMasterElectionEP); - memcpy(&bindAddr, ipv4_addr, sizeof(bindAddr)); - bindAddr.sin_addr.s_addr = INADDR_ANY; - rc = bind(mSocket, - reinterpret_cast<const sockaddr *>(&bindAddr), - sizeof(bindAddr)); - if (rc) { - mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, - "Failed to bind socket to port %hu (errno = %d)", - ntohs(bindAddr.sin_port), errno); - goto bailout; - } - - if (0xE0000000 == (ntohl(ipv4_addr->sin_addr.s_addr) & 0xF0000000)) { - // If our master election endpoint is a multicast address, be sure to join - // the multicast group. - struct ip_mreq mreq; - mreq.imr_multiaddr = ipv4_addr->sin_addr; - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - rc = setsockopt(mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, - &mreq, sizeof(mreq)); - if (rc == -1) { - ALOGE("Failed to join multicast group at %s. (errno = %d)", - masterElectionEPStr, errno); - goto bailout; - } - - // disable loopback of multicast packets - const int zero = 0; - rc = setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_LOOP, - &zero, sizeof(zero)); - if (rc == -1) { - mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, - "Failed to disable multicast loopback " - "(errno = %d)", errno); - goto bailout; - } - } else - if (ntohl(ipv4_addr->sin_addr.s_addr) == 0xFFFFFFFF) { - // If the master election address is the broadcast address, then enable - // the broadcast socket option - rc = setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)); - if (rc == -1) { - mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, - "Failed to enable broadcast (errno = %d)", - errno); - goto bailout; - } - } else { - // If the master election address is neither broadcast, nor multicast, - // then we are misconfigured. The config API layer should prevent this - // from ever happening. - goto bailout; - } - - // Set the TTL of sent packets to 1. (Time protocol sync should never leave - // the local subnet) - rc = setsockopt(mSocket, IPPROTO_IP, IP_TTL, &one, sizeof(one)); - if (rc == -1) { - mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG, - "Failed to set TTL to %d (errno = %d)", one, errno); - goto bailout; - } - - // get the device's unique ID - if (!assignDeviceID()) - goto bailout; - - ret_val = true; - -bailout: - if (!ret_val) - cleanupSocket_l(); - return ret_val; -} - -// generate a unique device ID that can be used for arbitration -bool CommonTimeServer::assignDeviceID() { - if (!mBindIfaceValid) - return false; - - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_addr.sa_family = AF_INET; - strlcpy(ifr.ifr_name, mBindIface.string(), IFNAMSIZ); - - int rc = ioctl(mSocket, SIOCGIFHWADDR, &ifr); - if (rc) { - ALOGE("%s:%d ioctl failed", __PRETTY_FUNCTION__, __LINE__); - return false; - } - - if (ifr.ifr_addr.sa_family != ARPHRD_ETHER) { - ALOGE("%s:%d got non-Ethernet address", __PRETTY_FUNCTION__, __LINE__); - return false; - } - - mDeviceID = 0; - for (int i = 0; i < ETH_ALEN; i++) { - mDeviceID = (mDeviceID << 8) | ifr.ifr_hwaddr.sa_data[i]; - } - - return true; -} - -// generate a new timeline ID -void CommonTimeServer::assignTimelineID() { - do { - mTimelineID = (static_cast<uint64_t>(lrand48()) << 32) - | static_cast<uint64_t>(lrand48()); - } while (mTimelineID == ICommonClock::kInvalidTimelineID); -} - -// Select a preference between the device IDs of two potential masters. -// Returns true if the first ID wins, or false if the second ID wins. -bool CommonTimeServer::arbitrateMaster( - uint64_t deviceID1, uint8_t devicePrio1, - uint64_t deviceID2, uint8_t devicePrio2) { - return ((devicePrio1 > devicePrio2) || - ((devicePrio1 == devicePrio2) && (deviceID1 > deviceID2))); -} - -static void hexDumpToString(const uint8_t* src, size_t src_len, - char* dst, size_t dst_len) { - size_t offset = 0; - size_t i; - - for (i = 0; (i < src_len) && (offset < dst_len); ++i) { - int res; - if (0 == (i % 16)) { - res = snprintf(dst + offset, dst_len - offset, "\n%04zx :", i); - if (res < 0) - break; - offset += res; - if (offset >= dst_len) - break; - } - - res = snprintf(dst + offset, dst_len - offset, " %02x", src[i]); - if (res < 0) - break; - offset += res; - } - - dst[dst_len - 1] = 0; -} - -bool CommonTimeServer::handlePacket() { - uint8_t buf[256]; - struct sockaddr_storage srcAddr; - socklen_t srcAddrLen = sizeof(srcAddr); - - ssize_t recvBytes = recvfrom( - mSocket, buf, sizeof(buf), 0, - reinterpret_cast<sockaddr *>(&srcAddr), &srcAddrLen); - - if (recvBytes < 0) { - mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG, "recvfrom failed (%s)", - strerror(errno)); - return false; - } - - UniversalTimeServicePacket pkt; - if (pkt.deserializePacket(buf, recvBytes, mSyncGroupID) < 0) { - char hex[256]; - char srcEPStr[64]; - - hexDumpToString(buf, static_cast<size_t>(recvBytes), hex, sizeof(hex)); - sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); - - mBadPktLog.log("Failed to parse %d byte packet from %s.%s", - recvBytes, srcEPStr, hex); - return false; - } - - bool result; - switch (pkt.packetType) { - case TIME_PACKET_WHO_IS_MASTER_REQUEST: - result = handleWhoIsMasterRequest(&pkt.p.who_is_master_request, - srcAddr); - break; - - case TIME_PACKET_WHO_IS_MASTER_RESPONSE: - result = handleWhoIsMasterResponse(&pkt.p.who_is_master_response, - srcAddr); - break; - - case TIME_PACKET_SYNC_REQUEST: - result = handleSyncRequest(&pkt.p.sync_request, srcAddr); - break; - - case TIME_PACKET_SYNC_RESPONSE: - result = handleSyncResponse(&pkt.p.sync_response, srcAddr); - break; - - case TIME_PACKET_MASTER_ANNOUNCEMENT: - result = handleMasterAnnouncement(&pkt.p.master_announcement, - srcAddr); - break; - - default: { - char srcEPStr[64]; - sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); - - mBadPktLog.log(ANDROID_LOG_WARN, LOG_TAG, - "unknown packet type (%d) from %s", - pkt.packetType, srcEPStr); - - result = false; - } break; - } - - return result; -} - -bool CommonTimeServer::handleTimeout() { - // If we have no socket, then this must be a timeout to retry socket setup. - if (mSocket < 0) - return true; - - switch (mState) { - case ICommonClock::STATE_INITIAL: - return handleTimeoutInitial(); - case ICommonClock::STATE_CLIENT: - return handleTimeoutClient(); - case ICommonClock::STATE_MASTER: - return handleTimeoutMaster(); - case ICommonClock::STATE_RONIN: - return handleTimeoutRonin(); - case ICommonClock::STATE_WAIT_FOR_ELECTION: - return handleTimeoutWaitForElection(); - } - - return false; -} - -bool CommonTimeServer::handleTimeoutInitial() { - if (++mInitial_WhoIsMasterRequestTimeouts == - kInitial_NumWhoIsMasterRetries) { - // none of our attempts to discover a master succeeded, so make - // this device the master - return becomeMaster("initial timeout"); - } else { - // retry the WhoIsMaster request - return sendWhoIsMasterRequest(); - } -} - -bool CommonTimeServer::handleTimeoutClient() { - if (shouldPanicNotGettingGoodData()) - return becomeInitial("timeout panic, no good data"); - - if (mClient_SyncRequestPending) { - mClient_SyncRequestPending = false; - - if (++mClient_SyncRequestTimeouts < kClient_NumSyncRequestRetries) { - // a sync request has timed out, so retry - return sendSyncRequest(); - } else { - // The master has failed to respond to a sync request for too many - // times in a row. Assume the master is dead and start electing - // a new master. - return becomeRonin("master not responding"); - } - } else { - // initiate the next sync request - return sendSyncRequest(); - } -} - -bool CommonTimeServer::handleTimeoutMaster() { - // send another announcement from the master - return sendMasterAnnouncement(); -} - -bool CommonTimeServer::handleTimeoutRonin() { - if (++mRonin_WhoIsMasterRequestTimeouts == kRonin_NumWhoIsMasterRetries) { - // no other master is out there, so we won the election - return becomeMaster("no better masters detected"); - } else { - return sendWhoIsMasterRequest(); - } -} - -bool CommonTimeServer::handleTimeoutWaitForElection() { - return becomeRonin("timeout waiting for election conclusion"); -} - -bool CommonTimeServer::handleWhoIsMasterRequest( - const WhoIsMasterRequestPacket* request, - const sockaddr_storage& srcAddr) { - // Skip our own messages which come back via broadcast loopback. - if (request->senderDeviceID == mDeviceID) - return true; - - char srcEPStr[64]; - sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); - mElectionLog.log("RXed WhoIs master request while in state %s. " - "src %s reqTID %016llx ourTID %016llx", - stateToString(mState), srcEPStr, - request->timelineID, mTimelineID); - - if (mState == ICommonClock::STATE_MASTER) { - // is this request related to this master's timeline? - if (request->timelineID != ICommonClock::kInvalidTimelineID && - request->timelineID != mTimelineID) - return true; - - WhoIsMasterResponsePacket pkt; - pkt.initHeader(mTimelineID, mSyncGroupID); - pkt.deviceID = mDeviceID; - pkt.devicePriority = effectivePriority(); - - mElectionLog.log("TXing WhoIs master resp to %s while in state %s. " - "ourTID %016llx ourGID %016llx ourDID %016llx " - "ourPrio %u", - srcEPStr, stateToString(mState), - mTimelineID, mSyncGroupID, - pkt.deviceID, pkt.devicePriority); - - uint8_t buf[256]; - ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf)); - if (bufSz < 0) - return false; - - ssize_t sendBytes = sendto( - mSocket, buf, bufSz, 0, - reinterpret_cast<const sockaddr *>(&srcAddr), - sizeof(srcAddr)); - if (sendBytes == -1) { - ALOGE("%s:%d sendto failed", __PRETTY_FUNCTION__, __LINE__); - return false; - } - } else if (mState == ICommonClock::STATE_RONIN) { - // if we hear a WhoIsMaster request from another device following - // the same timeline and that device wins arbitration, then we will stop - // trying to elect ourselves master and will instead wait for an - // announcement from the election winner - if (request->timelineID != mTimelineID) - return true; - - if (arbitrateMaster(request->senderDeviceID, - request->senderDevicePriority, - mDeviceID, - effectivePriority())) - return becomeWaitForElection("would lose election"); - - return true; - } else if (mState == ICommonClock::STATE_INITIAL) { - // If a group of devices booted simultaneously (e.g. after a power - // outage) and all of them are in the initial state and there is no - // master, then each device may time out and declare itself master at - // the same time. To avoid this, listen for - // WhoIsMaster(InvalidTimeline) requests from peers. If we would lose - // arbitration against that peer, reset our timeout count so that the - // peer has a chance to become master before we time out. - if (request->timelineID == ICommonClock::kInvalidTimelineID && - arbitrateMaster(request->senderDeviceID, - request->senderDevicePriority, - mDeviceID, - effectivePriority())) { - mInitial_WhoIsMasterRequestTimeouts = 0; - } - } - - return true; -} - -bool CommonTimeServer::handleWhoIsMasterResponse( - const WhoIsMasterResponsePacket* response, - const sockaddr_storage& srcAddr) { - // Skip our own messages which come back via broadcast loopback. - if (response->deviceID == mDeviceID) - return true; - - char srcEPStr[64]; - sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); - mElectionLog.log("RXed WhoIs master response while in state %s. " - "src %s respTID %016llx respDID %016llx respPrio %u " - "ourTID %016llx", - stateToString(mState), srcEPStr, - response->timelineID, - response->deviceID, - static_cast<uint32_t>(response->devicePriority), - mTimelineID); - - if (mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN) { - return becomeClient(srcAddr, - response->deviceID, - response->devicePriority, - response->timelineID, - "heard whois response"); - } else if (mState == ICommonClock::STATE_CLIENT) { - // if we get multiple responses because there are multiple devices - // who believe that they are master, then follow the master that - // wins arbitration - if (arbitrateMaster(response->deviceID, - response->devicePriority, - mClient_MasterDeviceID, - mClient_MasterDevicePriority)) { - return becomeClient(srcAddr, - response->deviceID, - response->devicePriority, - response->timelineID, - "heard whois response"); - } - } - - return true; -} - -bool CommonTimeServer::handleSyncRequest(const SyncRequestPacket* request, - const sockaddr_storage& srcAddr) { - SyncResponsePacket pkt; - pkt.initHeader(mTimelineID, mSyncGroupID); - - if ((mState == ICommonClock::STATE_MASTER) && - (mTimelineID == request->timelineID)) { - int64_t rxLocalTime = mLastPacketRxLocalTime; - int64_t rxCommonTime; - - // If we are master on an actual network and have actual clients, then - // we are no longer low priority. - setForceLowPriority(false); - - if (OK != mCommonClock.localToCommon(rxLocalTime, &rxCommonTime)) { - return false; - } - - int64_t txLocalTime = mLocalClock.getLocalTime();; - int64_t txCommonTime; - if (OK != mCommonClock.localToCommon(txLocalTime, &txCommonTime)) { - return false; - } - - pkt.nak = 0; - pkt.clientTxLocalTime = request->clientTxLocalTime; - pkt.masterRxCommonTime = rxCommonTime; - pkt.masterTxCommonTime = txCommonTime; - } else { - pkt.nak = 1; - pkt.clientTxLocalTime = 0; - pkt.masterRxCommonTime = 0; - pkt.masterTxCommonTime = 0; - } - - uint8_t buf[256]; - ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf)); - if (bufSz < 0) - return false; - - ssize_t sendBytes = sendto( - mSocket, &buf, bufSz, 0, - reinterpret_cast<const sockaddr *>(&srcAddr), - sizeof(srcAddr)); - if (sendBytes == -1) { - ALOGE("%s:%d sendto failed", __PRETTY_FUNCTION__, __LINE__); - return false; - } - - return true; -} - -bool CommonTimeServer::handleSyncResponse( - const SyncResponsePacket* response, - const sockaddr_storage& srcAddr) { - if (mState != ICommonClock::STATE_CLIENT) - return true; - - assert(mMasterEPValid); - if (!sockaddrMatch(srcAddr, mMasterEP, true)) { - char srcEP[64], expectedEP[64]; - sockaddrToString(srcAddr, true, srcEP, sizeof(srcEP)); - sockaddrToString(mMasterEP, true, expectedEP, sizeof(expectedEP)); - ALOGI("Dropping sync response from unexpected address." - " Expected %s Got %s", expectedEP, srcEP); - return true; - } - - if (response->nak) { - // if our master is no longer accepting requests, then we need to find - // a new master - return becomeRonin("master NAK'ed"); - } - - mClient_SyncRequestPending = 0; - mClient_SyncRequestTimeouts = 0; - mClient_PacketRTTLog.logRX(response->clientTxLocalTime, - mLastPacketRxLocalTime); - - bool result; - if (!(mClient_SyncRespsRXedFromCurMaster++)) { - // the first request/response exchange between a client and a master - // may take unusually long due to ARP, so discard it. - result = true; - } else { - int64_t clientTxLocalTime = response->clientTxLocalTime; - int64_t clientRxLocalTime = mLastPacketRxLocalTime; - int64_t masterTxCommonTime = response->masterTxCommonTime; - int64_t masterRxCommonTime = response->masterRxCommonTime; - - int64_t rtt = (clientRxLocalTime - clientTxLocalTime); - int64_t avgLocal = (clientTxLocalTime + clientRxLocalTime) >> 1; - int64_t avgCommon = (masterTxCommonTime + masterRxCommonTime) >> 1; - - // if the RTT of the packet is significantly larger than the panic - // threshold, we should simply discard it. Its better to do nothing - // than to take cues from a packet like that. - int64_t rttCommon = mCommonClock.localDurationToCommonDuration(rtt); - if (rttCommon > (static_cast<int64_t>(mPanicThresholdUsec) * - kRTTDiscardPanicThreshMultiplier)) { - ALOGV("Dropping sync response with RTT of %" PRId64 " uSec", rttCommon); - mClient_ExpiredSyncRespsRXedFromCurMaster++; - if (shouldPanicNotGettingGoodData()) - return becomeInitial("RX panic, no good data"); - return true; - } else { - result = mClockRecovery.pushDisciplineEvent(avgLocal, avgCommon, rttCommon); - mClient_LastGoodSyncRX = clientRxLocalTime; - - if (result) { - // indicate to listeners that we've synced to the common timeline - notifyClockSync(); - } else { - ALOGE("Panic! Observed clock sync error is too high to tolerate," - " resetting state machine and starting over."); - notifyClockSyncLoss(); - return becomeInitial("panic"); - } - } - } - - mCurTimeout.setTimeout(mSyncRequestIntervalMs); - return result; -} - -bool CommonTimeServer::handleMasterAnnouncement( - const MasterAnnouncementPacket* packet, - const sockaddr_storage& srcAddr) { - uint64_t newDeviceID = packet->deviceID; - uint8_t newDevicePrio = packet->devicePriority; - uint64_t newTimelineID = packet->timelineID; - - // Skip our own messages which come back via broadcast loopback. - if (newDeviceID == mDeviceID) - return true; - - char srcEPStr[64]; - sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr)); - mElectionLog.log("RXed master announcement while in state %s. " - "src %s srcDevID %lld srcPrio %u srcTID %016llx", - stateToString(mState), srcEPStr, - newDeviceID, static_cast<uint32_t>(newDevicePrio), - newTimelineID); - - if (mState == ICommonClock::STATE_INITIAL || - mState == ICommonClock::STATE_RONIN || - mState == ICommonClock::STATE_WAIT_FOR_ELECTION) { - // if we aren't currently following a master, then start following - // this new master - return becomeClient(srcAddr, - newDeviceID, - newDevicePrio, - newTimelineID, - "heard master announcement"); - } else if (mState == ICommonClock::STATE_CLIENT) { - // if the new master wins arbitration against our current master, - // then become a client of the new master - if (arbitrateMaster(newDeviceID, - newDevicePrio, - mClient_MasterDeviceID, - mClient_MasterDevicePriority)) - return becomeClient(srcAddr, - newDeviceID, - newDevicePrio, - newTimelineID, - "heard master announcement"); - } else if (mState == ICommonClock::STATE_MASTER) { - // two masters are competing - if the new one wins arbitration, then - // cease acting as master - if (arbitrateMaster(newDeviceID, newDevicePrio, - mDeviceID, effectivePriority())) - return becomeClient(srcAddr, newDeviceID, - newDevicePrio, newTimelineID, - "heard master announcement"); - } - - return true; -} - -bool CommonTimeServer::sendWhoIsMasterRequest() { - assert(mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN); - - // If we have no socket, then we must be in the unconfigured initial state. - // Don't report any errors, just don't try to send the initial who-is-master - // query. Eventually, our network will either become configured, or we will - // be forced into network-less master mode by higher level code. - if (mSocket < 0) { - assert(mState == ICommonClock::STATE_INITIAL); - return true; - } - - bool ret = false; - WhoIsMasterRequestPacket pkt; - pkt.initHeader(mSyncGroupID); - pkt.senderDeviceID = mDeviceID; - pkt.senderDevicePriority = effectivePriority(); - - uint8_t buf[256]; - ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf)); - if (bufSz >= 0) { - char dstEPStr[64]; - sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr)); - mElectionLog.log("TXing WhoIs master request to %s while in state %s. " - "ourTID %016llx ourGID %016llx ourDID %016llx " - "ourPrio %u", - dstEPStr, stateToString(mState), - mTimelineID, mSyncGroupID, - pkt.senderDeviceID, pkt.senderDevicePriority); - - ssize_t sendBytes = sendto( - mSocket, buf, bufSz, 0, - reinterpret_cast<const sockaddr *>(&mMasterElectionEP), - sizeof(mMasterElectionEP)); - if (sendBytes < 0) - ALOGE("WhoIsMaster sendto failed (errno %d)", errno); - ret = true; - } - - if (mState == ICommonClock::STATE_INITIAL) { - mCurTimeout.setTimeout(kInitial_WhoIsMasterTimeoutMs); - } else { - mCurTimeout.setTimeout(kRonin_WhoIsMasterTimeoutMs); - } - - return ret; -} - -bool CommonTimeServer::sendSyncRequest() { - // If we are sending sync requests, then we must be in the client state and - // we must have a socket (when we have no network, we are only supposed to - // be in INITIAL or MASTER) - assert(mState == ICommonClock::STATE_CLIENT); - assert(mSocket >= 0); - - bool ret = false; - SyncRequestPacket pkt; - pkt.initHeader(mTimelineID, mSyncGroupID); - pkt.clientTxLocalTime = mLocalClock.getLocalTime(); - - if (!mClient_FirstSyncTX) - mClient_FirstSyncTX = pkt.clientTxLocalTime; - - mClient_PacketRTTLog.logTX(pkt.clientTxLocalTime); - - uint8_t buf[256]; - ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf)); - if (bufSz >= 0) { - ssize_t sendBytes = sendto( - mSocket, buf, bufSz, 0, - reinterpret_cast<const sockaddr *>(&mMasterEP), - sizeof(mMasterEP)); - if (sendBytes < 0) - ALOGE("SyncRequest sendto failed (errno %d)", errno); - ret = true; - } - - mClient_SyncsSentToCurMaster++; - mCurTimeout.setTimeout(mSyncRequestIntervalMs); - mClient_SyncRequestPending = true; - - return ret; -} - -bool CommonTimeServer::sendMasterAnnouncement() { - bool ret = false; - assert(mState == ICommonClock::STATE_MASTER); - - // If we are being asked to send a master announcement, but we have no - // socket, we must be in network-less master mode. Don't bother to send the - // announcement, and don't bother to schedule a timeout. When the network - // comes up, the work thread will get poked and start the process of - // figuring out who the current master should be. - if (mSocket < 0) { - mCurTimeout.setTimeout(kInfiniteTimeout); - return true; - } - - MasterAnnouncementPacket pkt; - pkt.initHeader(mTimelineID, mSyncGroupID); - pkt.deviceID = mDeviceID; - pkt.devicePriority = effectivePriority(); - - uint8_t buf[256]; - ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf)); - if (bufSz >= 0) { - char dstEPStr[64]; - sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr)); - mElectionLog.log("TXing Master announcement to %s while in state %s. " - "ourTID %016llx ourGID %016llx ourDID %016llx " - "ourPrio %u", - dstEPStr, stateToString(mState), - mTimelineID, mSyncGroupID, - pkt.deviceID, pkt.devicePriority); - - ssize_t sendBytes = sendto( - mSocket, buf, bufSz, 0, - reinterpret_cast<const sockaddr *>(&mMasterElectionEP), - sizeof(mMasterElectionEP)); - if (sendBytes < 0) - ALOGE("MasterAnnouncement sendto failed (errno %d)", errno); - ret = true; - } - - mCurTimeout.setTimeout(mMasterAnnounceIntervalMs); - return ret; -} - -bool CommonTimeServer::becomeClient(const sockaddr_storage& masterEP, - uint64_t masterDeviceID, - uint8_t masterDevicePriority, - uint64_t timelineID, - const char* cause) { - char newEPStr[64], oldEPStr[64]; - sockaddrToString(masterEP, true, newEPStr, sizeof(newEPStr)); - sockaddrToString(mMasterEP, mMasterEPValid, oldEPStr, sizeof(oldEPStr)); - - mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, - "%s --> CLIENT (%s) :%s" - " OldMaster: %02x-%014llx::%016llx::%s" - " NewMaster: %02x-%014llx::%016llx::%s", - stateToString(mState), cause, - (mTimelineID != timelineID) ? " (new timeline)" : "", - mClient_MasterDevicePriority, mClient_MasterDeviceID, - mTimelineID, oldEPStr, - masterDevicePriority, masterDeviceID, - timelineID, newEPStr); - - if (mTimelineID != timelineID) { - // start following a new timeline - mTimelineID = timelineID; - mClockRecovery.reset(true, true); - notifyClockSyncLoss(); - } else { - // start following a new master on the existing timeline - mClockRecovery.reset(false, true); - } - - mMasterEP = masterEP; - mMasterEPValid = true; - - // If we are on a real network as a client of a real master, then we should - // no longer force low priority. If our master disappears, we should have - // the high priority bit set during the election to replace the master - // because this group was a real group and not a singleton created in - // networkless mode. - setForceLowPriority(false); - - mClient_MasterDeviceID = masterDeviceID; - mClient_MasterDevicePriority = masterDevicePriority; - resetSyncStats(); - - setState(ICommonClock::STATE_CLIENT); - - // add some jitter to when the various clients send their requests - // in order to reduce the likelihood that a group of clients overload - // the master after receiving a master announcement - usleep((lrand48() % 100) * 1000); - - return sendSyncRequest(); -} - -bool CommonTimeServer::becomeMaster(const char* cause) { - uint64_t oldTimelineID = mTimelineID; - if (mTimelineID == ICommonClock::kInvalidTimelineID) { - // this device has not been following any existing timeline, - // so it will create a new timeline and declare itself master - assert(!mCommonClock.isValid()); - - // set the common time basis - mCommonClock.setBasis(mLocalClock.getLocalTime(), 0); - - // assign an arbitrary timeline iD - assignTimelineID(); - - // notify listeners that we've created a common timeline - notifyClockSync(); - } - - mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, - "%s --> MASTER (%s) : %s timeline %016llx", - stateToString(mState), cause, - (oldTimelineID == mTimelineID) ? "taking ownership of" - : "creating new", - mTimelineID); - - memset(&mMasterEP, 0, sizeof(mMasterEP)); - mMasterEPValid = false; - mClient_MasterDevicePriority = effectivePriority(); - mClient_MasterDeviceID = mDeviceID; - mClockRecovery.reset(false, true); - resetSyncStats(); - - setState(ICommonClock::STATE_MASTER); - return sendMasterAnnouncement(); -} - -bool CommonTimeServer::becomeRonin(const char* cause) { - // If we were the client of a given timeline, but had never received even a - // single time sync packet, then we transition back to Initial instead of - // Ronin. If we transition to Ronin and end up becoming the new Master, we - // will be unable to service requests for other clients because we never - // actually knew what time it was. By going to initial, we ensure that - // other clients who know what time it is, but would lose master arbitration - // in the Ronin case, will step up and become the proper new master of the - // old timeline. - - char oldEPStr[64]; - sockaddrToString(mMasterEP, mMasterEPValid, oldEPStr, sizeof(oldEPStr)); - memset(&mMasterEP, 0, sizeof(mMasterEP)); - mMasterEPValid = false; - - if (mCommonClock.isValid()) { - mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, - "%s --> RONIN (%s) : lost track of previously valid timeline " - "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)", - stateToString(mState), cause, - mClient_MasterDevicePriority, mClient_MasterDeviceID, - mTimelineID, oldEPStr, - mClient_SyncsSentToCurMaster, - mClient_SyncRespsRXedFromCurMaster, - mClient_ExpiredSyncRespsRXedFromCurMaster); - - mRonin_WhoIsMasterRequestTimeouts = 0; - setState(ICommonClock::STATE_RONIN); - return sendWhoIsMasterRequest(); - } else { - mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, - "%s --> INITIAL (%s) : never synced timeline " - "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)", - stateToString(mState), cause, - mClient_MasterDevicePriority, mClient_MasterDeviceID, - mTimelineID, oldEPStr, - mClient_SyncsSentToCurMaster, - mClient_SyncRespsRXedFromCurMaster, - mClient_ExpiredSyncRespsRXedFromCurMaster); - - return becomeInitial("ronin, no timeline"); - } -} - -bool CommonTimeServer::becomeWaitForElection(const char* cause) { - mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, - "%s --> WAIT_FOR_ELECTION (%s) : dropping out of election," - " waiting %d mSec for completion.", - stateToString(mState), cause, kWaitForElection_TimeoutMs); - - setState(ICommonClock::STATE_WAIT_FOR_ELECTION); - mCurTimeout.setTimeout(kWaitForElection_TimeoutMs); - return true; -} - -bool CommonTimeServer::becomeInitial(const char* cause) { - mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG, - "Entering INITIAL (%s), total reset.", - cause); - - setState(ICommonClock::STATE_INITIAL); - - // reset clock recovery - mClockRecovery.reset(true, true); - - // reset internal state bookkeeping. - mCurTimeout.setTimeout(kInfiniteTimeout); - memset(&mMasterEP, 0, sizeof(mMasterEP)); - mMasterEPValid = false; - mLastPacketRxLocalTime = 0; - mTimelineID = ICommonClock::kInvalidTimelineID; - mClockSynced = false; - mInitial_WhoIsMasterRequestTimeouts = 0; - mClient_MasterDeviceID = 0; - mClient_MasterDevicePriority = 0; - mRonin_WhoIsMasterRequestTimeouts = 0; - resetSyncStats(); - - // send the first request to discover the master - return sendWhoIsMasterRequest(); -} - -void CommonTimeServer::notifyClockSync() { - if (!mClockSynced) { - mClockSynced = true; - mICommonClock->notifyOnTimelineChanged(mTimelineID); - } -} - -void CommonTimeServer::notifyClockSyncLoss() { - if (mClockSynced) { - mClockSynced = false; - mICommonClock->notifyOnTimelineChanged( - ICommonClock::kInvalidTimelineID); - } -} - -void CommonTimeServer::setState(ICommonClock::State s) { - mState = s; -} - -const char* CommonTimeServer::stateToString(ICommonClock::State s) { - switch(s) { - case ICommonClock::STATE_INITIAL: - return "INITIAL"; - case ICommonClock::STATE_CLIENT: - return "CLIENT"; - case ICommonClock::STATE_MASTER: - return "MASTER"; - case ICommonClock::STATE_RONIN: - return "RONIN"; - case ICommonClock::STATE_WAIT_FOR_ELECTION: - return "WAIT_FOR_ELECTION"; - default: - return "unknown"; - } -} - -void CommonTimeServer::sockaddrToString(const sockaddr_storage& addr, - bool addrValid, - char* buf, size_t bufLen) { - if (!bufLen || !buf) - return; - - if (addrValid) { - switch (addr.ss_family) { - case AF_INET: { - const struct sockaddr_in* sa = - reinterpret_cast<const struct sockaddr_in*>(&addr); - unsigned long a = ntohl(sa->sin_addr.s_addr); - uint16_t p = ntohs(sa->sin_port); - snprintf(buf, bufLen, "%lu.%lu.%lu.%lu:%hu", - ((a >> 24) & 0xFF), ((a >> 16) & 0xFF), - ((a >> 8) & 0xFF), (a & 0xFF), p); - } break; - - case AF_INET6: { - const struct sockaddr_in6* sa = - reinterpret_cast<const struct sockaddr_in6*>(&addr); - const uint8_t* a = sa->sin6_addr.s6_addr; - uint16_t p = ntohs(sa->sin6_port); - snprintf(buf, bufLen, - "%02X%02X:%02X%02X:%02X%02X:%02X%02X:" - "%02X%02X:%02X%02X:%02X%02X:%02X%02X port %hd", - a[0], a[1], a[ 2], a[ 3], a[ 4], a[ 5], a[ 6], a[ 7], - a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - p); - } break; - - default: - snprintf(buf, bufLen, - "<unknown sockaddr family %d>", addr.ss_family); - break; - } - } else { - snprintf(buf, bufLen, "<none>"); - } - - buf[bufLen - 1] = 0; -} - -bool CommonTimeServer::sockaddrMatch(const sockaddr_storage& a1, - const sockaddr_storage& a2, - bool matchAddressOnly) { - if (a1.ss_family != a2.ss_family) - return false; - - switch (a1.ss_family) { - case AF_INET: { - const struct sockaddr_in* sa1 = - reinterpret_cast<const struct sockaddr_in*>(&a1); - const struct sockaddr_in* sa2 = - reinterpret_cast<const struct sockaddr_in*>(&a2); - - if (sa1->sin_addr.s_addr != sa2->sin_addr.s_addr) - return false; - - return (matchAddressOnly || (sa1->sin_port == sa2->sin_port)); - } break; - - case AF_INET6: { - const struct sockaddr_in6* sa1 = - reinterpret_cast<const struct sockaddr_in6*>(&a1); - const struct sockaddr_in6* sa2 = - reinterpret_cast<const struct sockaddr_in6*>(&a2); - - if (memcmp(&sa1->sin6_addr, &sa2->sin6_addr, sizeof(sa2->sin6_addr))) - return false; - - return (matchAddressOnly || (sa1->sin6_port == sa2->sin6_port)); - } break; - - // Huh? We don't deal in non-IPv[46] addresses. Not sure how we got - // here, but we don't know how to comapre these addresses and simply - // default to a no-match decision. - default: return false; - } -} - -bool CommonTimeServer::shouldPanicNotGettingGoodData() { - if (mClient_FirstSyncTX) { - int64_t now = mLocalClock.getLocalTime(); - int64_t delta = now - (mClient_LastGoodSyncRX - ? mClient_LastGoodSyncRX - : mClient_FirstSyncTX); - int64_t deltaUsec = mCommonClock.localDurationToCommonDuration(delta); - - if (deltaUsec >= kNoGoodDataPanicThresholdUsec) - return true; - } - - return false; -} - -void CommonTimeServer::PacketRTTLog::logTX(int64_t txTime) { - txTimes[wrPtr] = txTime; - rxTimes[wrPtr] = 0; - wrPtr = (wrPtr + 1) % RTT_LOG_SIZE; - if (!wrPtr) - logFull = true; -} - -void CommonTimeServer::PacketRTTLog::logRX(int64_t txTime, int64_t rxTime) { - if (!logFull && !wrPtr) - return; - - uint32_t i = logFull ? wrPtr : 0; - do { - if (txTimes[i] == txTime) { - rxTimes[i] = rxTime; - break; - } - i = (i + 1) % RTT_LOG_SIZE; - } while (i != wrPtr); -} - -} // namespace android diff --git a/libs/common_time/common_time_server.h b/libs/common_time/common_time_server.h deleted file mode 100644 index 6e1805086978..000000000000 --- a/libs/common_time/common_time_server.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#ifndef ANDROID_COMMON_TIME_SERVER_H -#define ANDROID_COMMON_TIME_SERVER_H - -#include <arpa/inet.h> -#include <stdint.h> -#include <sys/socket.h> - -#include <common_time/ICommonClock.h> -#include <common_time/local_clock.h> -#include <utils/String8.h> - -#include "clock_recovery.h" -#include "common_clock.h" -#include "common_time_server_packets.h" -#include "utils.h" - -#define RTT_LOG_SIZE 30 - -namespace android { - -class CommonClockService; -class CommonTimeConfigService; - -/***** time service implementation *****/ - -class CommonTimeServer : public Thread { - public: - CommonTimeServer(); - ~CommonTimeServer(); - - bool startServices(); - - // Common Clock API methods - CommonClock& getCommonClock() { return mCommonClock; } - LocalClock& getLocalClock() { return mLocalClock; } - uint64_t getTimelineID(); - int32_t getEstimatedError(); - ICommonClock::State getState(); - status_t getMasterAddr(struct sockaddr_storage* addr); - status_t isCommonTimeValid(bool* valid, uint32_t* timelineID); - - // Config API methods - status_t getMasterElectionPriority(uint8_t *priority); - status_t setMasterElectionPriority(uint8_t priority); - status_t getMasterElectionEndpoint(struct sockaddr_storage *addr); - status_t setMasterElectionEndpoint(const struct sockaddr_storage *addr); - status_t getMasterElectionGroupId(uint64_t *id); - status_t setMasterElectionGroupId(uint64_t id); - status_t getInterfaceBinding(String8& ifaceName); - status_t setInterfaceBinding(const String8& ifaceName); - status_t getMasterAnnounceInterval(int *interval); - status_t setMasterAnnounceInterval(int interval); - status_t getClientSyncInterval(int *interval); - status_t setClientSyncInterval(int interval); - status_t getPanicThreshold(int *threshold); - status_t setPanicThreshold(int threshold); - status_t getAutoDisable(bool *autoDisable); - status_t setAutoDisable(bool autoDisable); - status_t forceNetworklessMasterMode(); - - // Method used by the CommonClockService to notify the core service about - // changes in the number of active common clock clients. - void reevaluateAutoDisableState(bool commonClockHasClients); - - status_t dumpClockInterface(int fd, const Vector<String16>& args, - size_t activeClients); - status_t dumpConfigInterface(int fd, const Vector<String16>& args); - - private: - class PacketRTTLog { - public: - PacketRTTLog() { - resetLog(); - } - - void resetLog() { - wrPtr = 0; - logFull = 0; - } - - void logTX(int64_t txTime); - void logRX(int64_t txTime, int64_t rxTime); - void dumpLog(int fd, const CommonClock& cclk); - - private: - uint32_t wrPtr; - bool logFull; - int64_t txTimes[RTT_LOG_SIZE]; - int64_t rxTimes[RTT_LOG_SIZE]; - }; - - bool threadLoop(); - - bool runStateMachine_l(); - bool setupSocket_l(); - - void assignTimelineID(); - bool assignDeviceID(); - - static bool arbitrateMaster(uint64_t deviceID1, uint8_t devicePrio1, - uint64_t deviceID2, uint8_t devicePrio2); - - bool handlePacket(); - bool handleWhoIsMasterRequest (const WhoIsMasterRequestPacket* request, - const sockaddr_storage& srcAddr); - bool handleWhoIsMasterResponse(const WhoIsMasterResponsePacket* response, - const sockaddr_storage& srcAddr); - bool handleSyncRequest (const SyncRequestPacket* request, - const sockaddr_storage& srcAddr); - bool handleSyncResponse (const SyncResponsePacket* response, - const sockaddr_storage& srcAddr); - bool handleMasterAnnouncement (const MasterAnnouncementPacket* packet, - const sockaddr_storage& srcAddr); - - bool handleTimeout(); - bool handleTimeoutInitial(); - bool handleTimeoutClient(); - bool handleTimeoutMaster(); - bool handleTimeoutRonin(); - bool handleTimeoutWaitForElection(); - - bool sendWhoIsMasterRequest(); - bool sendSyncRequest(); - bool sendMasterAnnouncement(); - - bool becomeClient(const sockaddr_storage& masterAddr, - uint64_t masterDeviceID, - uint8_t masterDevicePriority, - uint64_t timelineID, - const char* cause); - bool becomeMaster(const char* cause); - bool becomeRonin(const char* cause); - bool becomeWaitForElection(const char* cause); - bool becomeInitial(const char* cause); - - void notifyClockSync(); - void notifyClockSyncLoss(); - - ICommonClock::State mState; - void setState(ICommonClock::State s); - - void clearPendingWakeupEvents_l(); - void wakeupThread_l(); - void cleanupSocket_l(); - void shutdownThread(); - - inline uint8_t effectivePriority() const { - return (mMasterPriority & 0x7F) | - (mForceLowPriority ? 0x00 : 0x80); - } - - inline bool shouldAutoDisable() const { - return (mAutoDisable && !mCommonClockHasClients); - } - - inline void resetSyncStats() { - mClient_SyncRequestPending = false; - mClient_SyncRequestTimeouts = 0; - mClient_SyncsSentToCurMaster = 0; - mClient_SyncRespsRXedFromCurMaster = 0; - mClient_ExpiredSyncRespsRXedFromCurMaster = 0; - mClient_FirstSyncTX = 0; - mClient_LastGoodSyncRX = 0; - mClient_PacketRTTLog.resetLog(); - } - - bool shouldPanicNotGettingGoodData(); - - // Helper to keep track of the state machine's current timeout - Timeout mCurTimeout; - - // common clock, local clock abstraction, and clock recovery loop - CommonClock mCommonClock; - LocalClock mLocalClock; - ClockRecoveryLoop mClockRecovery; - - // implementation of ICommonClock - sp<CommonClockService> mICommonClock; - - // implementation of ICommonTimeConfig - sp<CommonTimeConfigService> mICommonTimeConfig; - - // UDP socket for the time sync protocol - int mSocket; - - // eventfd used to wakeup the work thread in response to configuration - // changes. - int mWakeupThreadFD; - - // timestamp captured when a packet is received - int64_t mLastPacketRxLocalTime; - - // ID of the timeline that this device is following - uint64_t mTimelineID; - - // flag for whether the clock has been synced to a timeline - bool mClockSynced; - - // flag used to indicate that clients should be considered to be lower - // priority than all of their peers during elections. This flag is set and - // cleared by the state machine. It is set when the client joins a new - // network. If the client had been a master in the old network (or an - // isolated master with no network connectivity) it should defer to any - // masters which may already be on the network. It will be cleared whenever - // the state machine transitions to the master state. - bool mForceLowPriority; - inline void setForceLowPriority(bool val) { - mForceLowPriority = val; - if (mState == ICommonClock::STATE_MASTER) - mClient_MasterDevicePriority = effectivePriority(); - } - - // Lock to synchronize access to internal state and configuration. - Mutex mLock; - - // Flag updated by the common clock service to indicate that it does or does - // not currently have registered clients. When the the auto disable flag is - // cleared on the common time service, the service will participate in - // network synchronization whenever it has a valid network interface to bind - // to. When the auto disable flag is set on the common time service, it - // will only participate in network synchronization when it has both a valid - // interface AND currently active common clock clients. - bool mCommonClockHasClients; - - // Internal logs used for dumpsys. - LogRing mStateChangeLog; - LogRing mElectionLog; - LogRing mBadPktLog; - - // Configuration info - struct sockaddr_storage mMasterElectionEP; // Endpoint over which we conduct master election - String8 mBindIface; // Endpoint for the service to bind to. - bool mBindIfaceValid; // whether or not the bind Iface is valid. - bool mBindIfaceDirty; // whether or not the bind Iface is valid. - struct sockaddr_storage mMasterEP; // Endpoint of our current master (if any) - bool mMasterEPValid; - uint64_t mDeviceID; // unique ID of this device - uint64_t mSyncGroupID; // synchronization group ID of this device. - uint8_t mMasterPriority; // Priority of this device in master election. - uint32_t mMasterAnnounceIntervalMs; - uint32_t mSyncRequestIntervalMs; - uint32_t mPanicThresholdUsec; - bool mAutoDisable; - - // Config defaults. - static const char* kDefaultMasterElectionAddr; - static const uint16_t kDefaultMasterElectionPort; - static const uint64_t kDefaultSyncGroupID; - static const uint8_t kDefaultMasterPriority; - static const uint32_t kDefaultMasterAnnounceIntervalMs; - static const uint32_t kDefaultSyncRequestIntervalMs; - static const uint32_t kDefaultPanicThresholdUsec; - static const bool kDefaultAutoDisable; - - // Priority mask and shift fields. - static const uint64_t kDeviceIDMask; - static const uint8_t kDevicePriorityMask; - static const uint8_t kDevicePriorityHiLowBit; - static const uint32_t kDevicePriorityShift; - - // Unconfgurable constants - static const int kSetupRetryTimeoutMs; - static const int64_t kNoGoodDataPanicThresholdUsec; - static const uint32_t kRTTDiscardPanicThreshMultiplier; - - /*** status while in the Initial state ***/ - int mInitial_WhoIsMasterRequestTimeouts; - static const int kInitial_NumWhoIsMasterRetries; - static const int kInitial_WhoIsMasterTimeoutMs; - - /*** status while in the Client state ***/ - uint64_t mClient_MasterDeviceID; - uint8_t mClient_MasterDevicePriority; - bool mClient_SyncRequestPending; - int mClient_SyncRequestTimeouts; - uint32_t mClient_SyncsSentToCurMaster; - uint32_t mClient_SyncRespsRXedFromCurMaster; - uint32_t mClient_ExpiredSyncRespsRXedFromCurMaster; - int64_t mClient_FirstSyncTX; - int64_t mClient_LastGoodSyncRX; - PacketRTTLog mClient_PacketRTTLog; - static const int kClient_NumSyncRequestRetries; - - - /*** status while in the Master state ***/ - static const uint32_t kDefaultMaster_AnnouncementIntervalMs; - - /*** status while in the Ronin state ***/ - int mRonin_WhoIsMasterRequestTimeouts; - static const int kRonin_NumWhoIsMasterRetries; - static const int kRonin_WhoIsMasterTimeoutMs; - - /*** status while in the WaitForElection state ***/ - static const int kWaitForElection_TimeoutMs; - - static const int kInfiniteTimeout; - - static const char* stateToString(ICommonClock::State s); - static void sockaddrToString(const sockaddr_storage& addr, bool addrValid, - char* buf, size_t bufLen); - static bool sockaddrMatch(const sockaddr_storage& a1, - const sockaddr_storage& a2, - bool matchAddressOnly); -}; - -} // namespace android - -#endif // ANDROID_COMMON_TIME_SERVER_H diff --git a/libs/common_time/common_time_server_api.cpp b/libs/common_time/common_time_server_api.cpp deleted file mode 100644 index 60e65677b2f9..000000000000 --- a/libs/common_time/common_time_server_api.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -/* - * A service that exchanges time synchronization information between - * a master that defines a timeline and clients that follow the timeline. - */ - -#define LOG_TAG "common_time" -#include <utils/Log.h> - -#include <binder/IServiceManager.h> -#include <binder/IPCThreadState.h> - -#include "common_time_server.h" - -#include <inttypes.h> - -namespace android { - -// -// Clock API -// -uint64_t CommonTimeServer::getTimelineID() { - AutoMutex _lock(&mLock); - return mTimelineID; -} - -ICommonClock::State CommonTimeServer::getState() { - AutoMutex _lock(&mLock); - return mState; -} - -status_t CommonTimeServer::getMasterAddr(struct sockaddr_storage* addr) { - AutoMutex _lock(&mLock); - if (mMasterEPValid) { - memcpy(addr, &mMasterEP, sizeof(*addr)); - return OK; - } - - return UNKNOWN_ERROR; -} - -int32_t CommonTimeServer::getEstimatedError() { - AutoMutex _lock(&mLock); - - if (ICommonClock::STATE_MASTER == mState) - return 0; - - if (!mClockSynced) - return ICommonClock::kErrorEstimateUnknown; - - return mClockRecovery.getLastErrorEstimate(); -} - -status_t CommonTimeServer::isCommonTimeValid(bool* valid, - uint32_t* timelineID) { - AutoMutex _lock(&mLock); - *valid = mCommonClock.isValid(); - *timelineID = mTimelineID; - return OK; -} - -// -// Config API -// -status_t CommonTimeServer::getMasterElectionPriority(uint8_t *priority) { - AutoMutex _lock(&mLock); - *priority = mMasterPriority; - return OK; -} - -status_t CommonTimeServer::setMasterElectionPriority(uint8_t priority) { - AutoMutex _lock(&mLock); - - if (priority > 0x7F) - return BAD_VALUE; - - mMasterPriority = priority; - return OK; -} - -status_t CommonTimeServer::getMasterElectionEndpoint( - struct sockaddr_storage *addr) { - AutoMutex _lock(&mLock); - memcpy(addr, &mMasterElectionEP, sizeof(*addr)); - return OK; -} - -status_t CommonTimeServer::setMasterElectionEndpoint( - const struct sockaddr_storage *addr) { - AutoMutex _lock(&mLock); - - if (!addr) - return BAD_VALUE; - - // TODO: add proper support for IPv6 - if (addr->ss_family != AF_INET) - return BAD_VALUE; - - // Only multicast and broadcast endpoints with explicit ports are allowed. - uint16_t ipv4Port = ntohs( - reinterpret_cast<const struct sockaddr_in*>(addr)->sin_port); - if (!ipv4Port) - return BAD_VALUE; - - uint32_t ipv4Addr = ntohl( - reinterpret_cast<const struct sockaddr_in*>(addr)->sin_addr.s_addr); - if ((ipv4Addr != 0xFFFFFFFF) && (0xE0000000 != (ipv4Addr & 0xF0000000))) - return BAD_VALUE; - - memcpy(&mMasterElectionEP, addr, sizeof(mMasterElectionEP)); - - // Force a rebind in order to change election enpoints. - mBindIfaceDirty = true; - wakeupThread_l(); - return OK; -} - -status_t CommonTimeServer::getMasterElectionGroupId(uint64_t *id) { - AutoMutex _lock(&mLock); - *id = mSyncGroupID; - return OK; -} - -status_t CommonTimeServer::setMasterElectionGroupId(uint64_t id) { - AutoMutex _lock(&mLock); - mSyncGroupID = id; - return OK; -} - -status_t CommonTimeServer::getInterfaceBinding(String8& ifaceName) { - AutoMutex _lock(&mLock); - if (!mBindIfaceValid) - return INVALID_OPERATION; - ifaceName = mBindIface; - return OK; -} - -status_t CommonTimeServer::setInterfaceBinding(const String8& ifaceName) { - AutoMutex _lock(&mLock); - - mBindIfaceDirty = true; - if (ifaceName.size()) { - mBindIfaceValid = true; - mBindIface = ifaceName; - } else { - mBindIfaceValid = false; - mBindIface.clear(); - } - - wakeupThread_l(); - return OK; -} - -status_t CommonTimeServer::getMasterAnnounceInterval(int *interval) { - AutoMutex _lock(&mLock); - *interval = mMasterAnnounceIntervalMs; - return OK; -} - -status_t CommonTimeServer::setMasterAnnounceInterval(int interval) { - AutoMutex _lock(&mLock); - - if (interval > (6 *3600000)) // Max interval is once every 6 hrs - return BAD_VALUE; - - if (interval < 500) // Min interval is once per 0.5 seconds - return BAD_VALUE; - - mMasterAnnounceIntervalMs = interval; - if (ICommonClock::STATE_MASTER == mState) { - int pendingTimeout = mCurTimeout.msecTillTimeout(); - if ((kInfiniteTimeout == pendingTimeout) || - (pendingTimeout > interval)) { - mCurTimeout.setTimeout(mMasterAnnounceIntervalMs); - wakeupThread_l(); - } - } - - return OK; -} - -status_t CommonTimeServer::getClientSyncInterval(int *interval) { - AutoMutex _lock(&mLock); - *interval = mSyncRequestIntervalMs; - return OK; -} - -status_t CommonTimeServer::setClientSyncInterval(int interval) { - AutoMutex _lock(&mLock); - - if (interval > (3600000)) // Max interval is once every 60 min - return BAD_VALUE; - - if (interval < 250) // Min interval is once per 0.25 seconds - return BAD_VALUE; - - mSyncRequestIntervalMs = interval; - if (ICommonClock::STATE_CLIENT == mState) { - int pendingTimeout = mCurTimeout.msecTillTimeout(); - if ((kInfiniteTimeout == pendingTimeout) || - (pendingTimeout > interval)) { - mCurTimeout.setTimeout(mSyncRequestIntervalMs); - wakeupThread_l(); - } - } - - return OK; -} - -status_t CommonTimeServer::getPanicThreshold(int *threshold) { - AutoMutex _lock(&mLock); - *threshold = mPanicThresholdUsec; - return OK; -} - -status_t CommonTimeServer::setPanicThreshold(int threshold) { - AutoMutex _lock(&mLock); - - if (threshold < 1000) // Min threshold is 1mSec - return BAD_VALUE; - - mPanicThresholdUsec = threshold; - return OK; -} - -status_t CommonTimeServer::getAutoDisable(bool *autoDisable) { - AutoMutex _lock(&mLock); - *autoDisable = mAutoDisable; - return OK; -} - -status_t CommonTimeServer::setAutoDisable(bool autoDisable) { - AutoMutex _lock(&mLock); - mAutoDisable = autoDisable; - wakeupThread_l(); - return OK; -} - -status_t CommonTimeServer::forceNetworklessMasterMode() { - AutoMutex _lock(&mLock); - - // Can't force networkless master mode if we are currently bound to a - // network. - if (mSocket >= 0) - return INVALID_OPERATION; - - becomeMaster("force networkless"); - - return OK; -} - -void CommonTimeServer::reevaluateAutoDisableState(bool commonClockHasClients) { - AutoMutex _lock(&mLock); - bool needWakeup = (mAutoDisable && mMasterEPValid && - (commonClockHasClients != mCommonClockHasClients)); - - mCommonClockHasClients = commonClockHasClients; - - if (needWakeup) { - ALOGI("Waking up service, auto-disable is engaged and service now has%s" - " clients", mCommonClockHasClients ? "" : " no"); - wakeupThread_l(); - } -} - -#define dump_printf(a, b...) do { \ - int res; \ - res = snprintf(buffer, sizeof(buffer), a, b); \ - buffer[sizeof(buffer) - 1] = 0; \ - if (res > 0) \ - write(fd, buffer, res); \ -} while (0) -#define checked_percentage(a, b) ((0 == (b)) ? 0.0f : ((100.0f * (a)) / (b))) - -status_t CommonTimeServer::dumpClockInterface(int fd, - const Vector<String16>& /* args */, - size_t activeClients) { - AutoMutex _lock(&mLock); - const size_t SIZE = 256; - char buffer[SIZE]; - - if (checkCallingPermission(String16("android.permission.DUMP")) == false) { - snprintf(buffer, SIZE, "Permission Denial: " - "can't dump CommonClockService from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - write(fd, buffer, strlen(buffer)); - } else { - int64_t commonTime; - int64_t localTime; - bool synced; - char maStr[64]; - - localTime = mLocalClock.getLocalTime(); - synced = (OK == mCommonClock.localToCommon(localTime, &commonTime)); - sockaddrToString(mMasterEP, mMasterEPValid, maStr, sizeof(maStr)); - - dump_printf("Common Clock Service Status\nLocal time : %" PRId64 "\n", - localTime); - - if (synced) - dump_printf("Common time : %" PRId64 "\n", commonTime); - else - dump_printf("Common time : %s\n", "not synced"); - - dump_printf("Timeline ID : %016" PRIu64 "\n", mTimelineID); - dump_printf("State : %s\n", stateToString(mState)); - dump_printf("Master Addr : %s\n", maStr); - - - if (synced) { - int32_t est = (ICommonClock::STATE_MASTER != mState) - ? mClockRecovery.getLastErrorEstimate() - : 0; - dump_printf("Error Est. : %.3f msec\n", - static_cast<float>(est) / 1000.0); - } else { - dump_printf("Error Est. : %s\n", "unknown"); - } - - dump_printf("Syncs TXes : %u\n", mClient_SyncsSentToCurMaster); - dump_printf("Syncs RXes : %u (%.2f%%)\n", - mClient_SyncRespsRXedFromCurMaster, - checked_percentage( - mClient_SyncRespsRXedFromCurMaster, - mClient_SyncsSentToCurMaster)); - dump_printf("RXs Expired : %u (%.2f%%)\n", - mClient_ExpiredSyncRespsRXedFromCurMaster, - checked_percentage( - mClient_ExpiredSyncRespsRXedFromCurMaster, - mClient_SyncsSentToCurMaster)); - - if (!mClient_LastGoodSyncRX) { - dump_printf("Last Good RX : %s\n", "unknown"); - } else { - int64_t localDelta, usecDelta; - localDelta = localTime - mClient_LastGoodSyncRX; - usecDelta = mCommonClock.localDurationToCommonDuration(localDelta); - dump_printf("Last Good RX : %" PRId64 " uSec ago\n", usecDelta); - } - - dump_printf("Active Clients : %zu\n", activeClients); - mClient_PacketRTTLog.dumpLog(fd, mCommonClock); - mStateChangeLog.dumpLog(fd); - mElectionLog.dumpLog(fd); - mBadPktLog.dumpLog(fd); - } - - return NO_ERROR; -} - -status_t CommonTimeServer::dumpConfigInterface(int fd, - const Vector<String16>& /* args */) { - AutoMutex _lock(&mLock); - const size_t SIZE = 256; - char buffer[SIZE]; - - if (checkCallingPermission(String16("android.permission.DUMP")) == false) { - snprintf(buffer, SIZE, "Permission Denial: " - "can't dump CommonTimeConfigService from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - write(fd, buffer, strlen(buffer)); - } else { - char meStr[64]; - - sockaddrToString(mMasterElectionEP, true, meStr, sizeof(meStr)); - - dump_printf("Common Time Config Service Status\n" - "Bound Interface : %s\n", - mBindIfaceValid ? mBindIface.string() : "<unbound>"); - dump_printf("Master Election Endpoint : %s\n", meStr); - dump_printf("Master Election Group ID : %016" PRIu64 "\n", mSyncGroupID); - dump_printf("Master Announce Interval : %d mSec\n", - mMasterAnnounceIntervalMs); - dump_printf("Client Sync Interval : %d mSec\n", - mSyncRequestIntervalMs); - dump_printf("Panic Threshold : %d uSec\n", - mPanicThresholdUsec); - dump_printf("Base ME Prio : 0x%02x\n", - static_cast<uint32_t>(mMasterPriority)); - dump_printf("Effective ME Prio : 0x%02x\n", - static_cast<uint32_t>(effectivePriority())); - dump_printf("Auto Disable Allowed : %s\n", - mAutoDisable ? "yes" : "no"); - dump_printf("Auto Disable Engaged : %s\n", - shouldAutoDisable() ? "yes" : "no"); - } - - return NO_ERROR; -} - -void CommonTimeServer::PacketRTTLog::dumpLog(int fd, const CommonClock& cclk) { - const size_t SIZE = 256; - char buffer[SIZE]; - uint32_t avail = !logFull ? wrPtr : RTT_LOG_SIZE; - - if (!avail) - return; - - dump_printf("\nPacket Log (%d entries)\n", avail); - - uint32_t ndx = 0; - uint32_t i = logFull ? wrPtr : 0; - do { - if (rxTimes[i]) { - int64_t delta = rxTimes[i] - txTimes[i]; - int64_t deltaUsec = cclk.localDurationToCommonDuration(delta); - dump_printf("pkt[%2d] : localTX %12" PRId64 " localRX %12" PRId64 " " - "(%.3f msec RTT)\n", - ndx, txTimes[i], rxTimes[i], - static_cast<float>(deltaUsec) / 1000.0); - } else { - dump_printf("pkt[%2d] : localTX %12" PRId64 " localRX never\n", - ndx, txTimes[i]); - } - i = (i + 1) % RTT_LOG_SIZE; - ndx++; - } while (i != wrPtr); -} - -#undef dump_printf -#undef checked_percentage - -} // namespace android diff --git a/libs/common_time/common_time_server_packets.cpp b/libs/common_time/common_time_server_packets.cpp deleted file mode 100644 index c7c893d34499..000000000000 --- a/libs/common_time/common_time_server_packets.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -/* - * A service that exchanges time synchronization information between - * a master that defines a timeline and clients that follow the timeline. - */ - -#define LOG_TAG "common_time" -#include <utils/Log.h> - -#include <arpa/inet.h> -#include <stdint.h> - -#include "common_time_server_packets.h" - -namespace android { - -const uint32_t TimeServicePacketHeader::kMagic = - (static_cast<uint32_t>('c') << 24) | - (static_cast<uint32_t>('c') << 16) | - (static_cast<uint32_t>('l') << 8) | - static_cast<uint32_t>('k'); - -const uint16_t TimeServicePacketHeader::kCurVersion = 1; - -#define SERIALIZE_FIELD(field_name, type, converter) \ - do { \ - if ((offset + sizeof(field_name)) > length) \ - return -1; \ - *((type*)(data + offset)) = converter(field_name); \ - offset += sizeof(field_name); \ - } while (0) -#define SERIALIZE_INT16(field_name) SERIALIZE_FIELD(field_name, int16_t, htons) -#define SERIALIZE_INT32(field_name) SERIALIZE_FIELD(field_name, int32_t, htonl) -#define SERIALIZE_INT64(field_name) SERIALIZE_FIELD(field_name, int64_t, htonq) - -#define DESERIALIZE_FIELD(field_name, type, converter) \ - do { \ - if ((offset + sizeof(field_name)) > length) \ - return -1; \ - (field_name) = converter(*((type*)(data + offset))); \ - offset += sizeof(field_name); \ - } while (0) -#define DESERIALIZE_INT16(field_name) DESERIALIZE_FIELD(field_name, int16_t, ntohs) -#define DESERIALIZE_INT32(field_name) DESERIALIZE_FIELD(field_name, int32_t, ntohl) -#define DESERIALIZE_INT64(field_name) DESERIALIZE_FIELD(field_name, int64_t, ntohq) - -#define kDevicePriorityShift 56 -#define kDeviceIDMask ((static_cast<uint64_t>(1) << kDevicePriorityShift) - 1) - -inline uint64_t packDeviceID(uint64_t devID, uint8_t prio) { - return (devID & kDeviceIDMask) | - (static_cast<uint64_t>(prio) << kDevicePriorityShift); -} - -inline uint64_t unpackDeviceID(uint64_t packed) { - return (packed & kDeviceIDMask); -} - -inline uint8_t unpackDevicePriority(uint64_t packed) { - return static_cast<uint8_t>(packed >> kDevicePriorityShift); -} - -ssize_t TimeServicePacketHeader::serializeHeader(uint8_t* data, - uint32_t length) { - ssize_t offset = 0; - int16_t pktType = static_cast<int16_t>(packetType); - SERIALIZE_INT32(magic); - SERIALIZE_INT16(version); - SERIALIZE_INT16(pktType); - SERIALIZE_INT64(timelineID); - SERIALIZE_INT64(syncGroupID); - return offset; -} - -ssize_t TimeServicePacketHeader::deserializeHeader(const uint8_t* data, - uint32_t length) { - ssize_t offset = 0; - int16_t tmp; - DESERIALIZE_INT32(magic); - DESERIALIZE_INT16(version); - DESERIALIZE_INT16(tmp); - DESERIALIZE_INT64(timelineID); - DESERIALIZE_INT64(syncGroupID); - packetType = static_cast<TimeServicePacketType>(tmp); - return offset; -} - -ssize_t TimeServicePacketHeader::serializePacket(uint8_t* data, - uint32_t length) { - ssize_t ret, tmp; - - ret = serializeHeader(data, length); - if (ret < 0) - return ret; - - data += ret; - length -= ret; - - switch (packetType) { - case TIME_PACKET_WHO_IS_MASTER_REQUEST: - tmp =((WhoIsMasterRequestPacket*)(this))->serializePacket(data, - length); - break; - case TIME_PACKET_WHO_IS_MASTER_RESPONSE: - tmp =((WhoIsMasterResponsePacket*)(this))->serializePacket(data, - length); - break; - case TIME_PACKET_SYNC_REQUEST: - tmp =((SyncRequestPacket*)(this))->serializePacket(data, length); - break; - case TIME_PACKET_SYNC_RESPONSE: - tmp =((SyncResponsePacket*)(this))->serializePacket(data, length); - break; - case TIME_PACKET_MASTER_ANNOUNCEMENT: - tmp =((MasterAnnouncementPacket*)(this))->serializePacket(data, - length); - break; - default: - return -1; - } - - if (tmp < 0) - return tmp; - - return ret + tmp; -} - -ssize_t UniversalTimeServicePacket::deserializePacket( - const uint8_t* data, - uint32_t length, - uint64_t expectedSyncGroupID) { - ssize_t ret; - TimeServicePacketHeader* header; - if (length < 8) - return -1; - - packetType = ntohs(*((uint16_t*)(data + 6))); - switch (packetType) { - case TIME_PACKET_WHO_IS_MASTER_REQUEST: - ret = p.who_is_master_request.deserializePacket(data, length); - header = &p.who_is_master_request; - break; - case TIME_PACKET_WHO_IS_MASTER_RESPONSE: - ret = p.who_is_master_response.deserializePacket(data, length); - header = &p.who_is_master_response; - break; - case TIME_PACKET_SYNC_REQUEST: - ret = p.sync_request.deserializePacket(data, length); - header = &p.sync_request; - break; - case TIME_PACKET_SYNC_RESPONSE: - ret = p.sync_response.deserializePacket(data, length); - header = &p.sync_response; - break; - case TIME_PACKET_MASTER_ANNOUNCEMENT: - ret = p.master_announcement.deserializePacket(data, length); - header = &p.master_announcement; - break; - default: - return -1; - } - - if ((ret >= 0) && !header->checkPacket(expectedSyncGroupID)) - ret = -1; - - return ret; -} - -ssize_t WhoIsMasterRequestPacket::serializePacket(uint8_t* data, - uint32_t length) { - ssize_t offset = serializeHeader(data, length); - if (offset > 0) { - uint64_t packed = packDeviceID(senderDeviceID, senderDevicePriority); - SERIALIZE_INT64(packed); - } - return offset; -} - -ssize_t WhoIsMasterRequestPacket::deserializePacket(const uint8_t* data, - uint32_t length) { - ssize_t offset = deserializeHeader(data, length); - if (offset > 0) { - uint64_t packed; - DESERIALIZE_INT64(packed); - senderDeviceID = unpackDeviceID(packed); - senderDevicePriority = unpackDevicePriority(packed); - } - return offset; -} - -ssize_t WhoIsMasterResponsePacket::serializePacket(uint8_t* data, - uint32_t length) { - ssize_t offset = serializeHeader(data, length); - if (offset > 0) { - uint64_t packed = packDeviceID(deviceID, devicePriority); - SERIALIZE_INT64(packed); - } - return offset; -} - -ssize_t WhoIsMasterResponsePacket::deserializePacket(const uint8_t* data, - uint32_t length) { - ssize_t offset = deserializeHeader(data, length); - if (offset > 0) { - uint64_t packed; - DESERIALIZE_INT64(packed); - deviceID = unpackDeviceID(packed); - devicePriority = unpackDevicePriority(packed); - } - return offset; -} - -ssize_t SyncRequestPacket::serializePacket(uint8_t* data, - uint32_t length) { - ssize_t offset = serializeHeader(data, length); - if (offset > 0) { - SERIALIZE_INT64(clientTxLocalTime); - } - return offset; -} - -ssize_t SyncRequestPacket::deserializePacket(const uint8_t* data, - uint32_t length) { - ssize_t offset = deserializeHeader(data, length); - if (offset > 0) { - DESERIALIZE_INT64(clientTxLocalTime); - } - return offset; -} - -ssize_t SyncResponsePacket::serializePacket(uint8_t* data, - uint32_t length) { - ssize_t offset = serializeHeader(data, length); - if (offset > 0) { - SERIALIZE_INT64(clientTxLocalTime); - SERIALIZE_INT64(masterRxCommonTime); - SERIALIZE_INT64(masterTxCommonTime); - SERIALIZE_INT32(nak); - } - return offset; -} - -ssize_t SyncResponsePacket::deserializePacket(const uint8_t* data, - uint32_t length) { - ssize_t offset = deserializeHeader(data, length); - if (offset > 0) { - DESERIALIZE_INT64(clientTxLocalTime); - DESERIALIZE_INT64(masterRxCommonTime); - DESERIALIZE_INT64(masterTxCommonTime); - DESERIALIZE_INT32(nak); - } - return offset; -} - -ssize_t MasterAnnouncementPacket::serializePacket(uint8_t* data, - uint32_t length) { - ssize_t offset = serializeHeader(data, length); - if (offset > 0) { - uint64_t packed = packDeviceID(deviceID, devicePriority); - SERIALIZE_INT64(packed); - } - return offset; -} - -ssize_t MasterAnnouncementPacket::deserializePacket(const uint8_t* data, - uint32_t length) { - ssize_t offset = deserializeHeader(data, length); - if (offset > 0) { - uint64_t packed; - DESERIALIZE_INT64(packed); - deviceID = unpackDeviceID(packed); - devicePriority = unpackDevicePriority(packed); - } - return offset; -} - -} // namespace android - diff --git a/libs/common_time/common_time_server_packets.h b/libs/common_time/common_time_server_packets.h deleted file mode 100644 index 57ba8a256308..000000000000 --- a/libs/common_time/common_time_server_packets.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#ifndef ANDROID_COMMON_TIME_SERVER_PACKETS_H -#define ANDROID_COMMON_TIME_SERVER_PACKETS_H - -#include <stdint.h> -#include <common_time/ICommonClock.h> - -namespace android { - -/***** time sync protocol packets *****/ - -enum TimeServicePacketType { - TIME_PACKET_WHO_IS_MASTER_REQUEST = 1, - TIME_PACKET_WHO_IS_MASTER_RESPONSE, - TIME_PACKET_SYNC_REQUEST, - TIME_PACKET_SYNC_RESPONSE, - TIME_PACKET_MASTER_ANNOUNCEMENT, -}; - -class TimeServicePacketHeader { - public: - friend class UniversalTimeServicePacket; - // magic number identifying the protocol - uint32_t magic; - - // protocol version of the packet - uint16_t version; - - // type of the packet - TimeServicePacketType packetType; - - // the timeline ID - uint64_t timelineID; - - // synchronization group this packet belongs to (used to operate multiple - // synchronization domains which all use the same master election endpoint) - uint64_t syncGroupID; - - ssize_t serializePacket(uint8_t* data, uint32_t length); - - protected: - void initHeader(TimeServicePacketType type, - const uint64_t tlID, - const uint64_t groupID) { - magic = kMagic; - version = kCurVersion; - packetType = type; - timelineID = tlID; - syncGroupID = groupID; - } - - bool checkPacket(uint64_t expectedSyncGroupID) const { - return ((magic == kMagic) && - (version == kCurVersion) && - (!expectedSyncGroupID || (syncGroupID == expectedSyncGroupID))); - } - - ssize_t serializeHeader(uint8_t* data, uint32_t length); - ssize_t deserializeHeader(const uint8_t* data, uint32_t length); - - private: - static const uint32_t kMagic; - static const uint16_t kCurVersion; -}; - -// packet querying for a suitable master -class WhoIsMasterRequestPacket : public TimeServicePacketHeader { - public: - uint64_t senderDeviceID; - uint8_t senderDevicePriority; - - void initHeader(const uint64_t groupID) { - TimeServicePacketHeader::initHeader(TIME_PACKET_WHO_IS_MASTER_REQUEST, - ICommonClock::kInvalidTimelineID, - groupID); - } - - ssize_t serializePacket(uint8_t* data, uint32_t length); - ssize_t deserializePacket(const uint8_t* data, uint32_t length); -}; - -// response to a WhoIsMaster request -class WhoIsMasterResponsePacket : public TimeServicePacketHeader { - public: - uint64_t deviceID; - uint8_t devicePriority; - - void initHeader(const uint64_t tlID, const uint64_t groupID) { - TimeServicePacketHeader::initHeader(TIME_PACKET_WHO_IS_MASTER_RESPONSE, - tlID, groupID); - } - - ssize_t serializePacket(uint8_t* data, uint32_t length); - ssize_t deserializePacket(const uint8_t* data, uint32_t length); -}; - -// packet sent by a client requesting correspondence between local -// and common time -class SyncRequestPacket : public TimeServicePacketHeader { - public: - // local time when this request was transmitted - int64_t clientTxLocalTime; - - void initHeader(const uint64_t tlID, const uint64_t groupID) { - TimeServicePacketHeader::initHeader(TIME_PACKET_SYNC_REQUEST, - tlID, groupID); - } - - ssize_t serializePacket(uint8_t* data, uint32_t length); - ssize_t deserializePacket(const uint8_t* data, uint32_t length); -}; - -// response to a sync request sent by the master -class SyncResponsePacket : public TimeServicePacketHeader { - public: - // local time when this request was transmitted by the client - int64_t clientTxLocalTime; - - // common time when the master received the request - int64_t masterRxCommonTime; - - // common time when the master transmitted the response - int64_t masterTxCommonTime; - - // flag that is set if the recipient of the sync request is not acting - // as a master for the requested timeline - uint32_t nak; - - void initHeader(const uint64_t tlID, const uint64_t groupID) { - TimeServicePacketHeader::initHeader(TIME_PACKET_SYNC_RESPONSE, - tlID, groupID); - } - - ssize_t serializePacket(uint8_t* data, uint32_t length); - ssize_t deserializePacket(const uint8_t* data, uint32_t length); -}; - -// announcement of the master's presence -class MasterAnnouncementPacket : public TimeServicePacketHeader { - public: - // the master's device ID - uint64_t deviceID; - uint8_t devicePriority; - - void initHeader(const uint64_t tlID, const uint64_t groupID) { - TimeServicePacketHeader::initHeader(TIME_PACKET_MASTER_ANNOUNCEMENT, - tlID, groupID); - } - - ssize_t serializePacket(uint8_t* data, uint32_t length); - ssize_t deserializePacket(const uint8_t* data, uint32_t length); -}; - -class UniversalTimeServicePacket { - public: - uint16_t packetType; - union { - WhoIsMasterRequestPacket who_is_master_request; - WhoIsMasterResponsePacket who_is_master_response; - SyncRequestPacket sync_request; - SyncResponsePacket sync_response; - MasterAnnouncementPacket master_announcement; - } p; - - ssize_t deserializePacket(const uint8_t* data, - uint32_t length, - uint64_t expectedSyncGroupID); -}; - -}; // namespace android - -#endif // ANDROID_COMMON_TIME_SERVER_PACKETS_H - - diff --git a/libs/common_time/diag_thread.cpp b/libs/common_time/diag_thread.cpp deleted file mode 100644 index 4cb955131099..000000000000 --- a/libs/common_time/diag_thread.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#define LOG_TAG "common_time" -#include <utils/Log.h> - -#include <fcntl.h> -#include <linux/in.h> -#include <linux/tcp.h> -#include <poll.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> -#include <utils/Errors.h> -#include <utils/misc.h> - -#include <common_time/local_clock.h> - -#include "common_clock.h" -#include "diag_thread.h" - -#define kMaxEvents 16 -#define kListenPort 9876 - -static bool setNonblocking(int fd) { - int flags = fcntl(fd, F_GETFL); - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { - ALOGE("Failed to set socket (%d) to non-blocking mode (errno %d)", - fd, errno); - return false; - } - - return true; -} - -static bool setNodelay(int fd) { - int tmp = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &tmp, sizeof(tmp)) < 0) { - ALOGE("Failed to set socket (%d) to no-delay mode (errno %d)", - fd, errno); - return false; - } - - return true; -} - -namespace android { - -DiagThread::DiagThread(CommonClock* common_clock, LocalClock* local_clock) { - common_clock_ = common_clock; - local_clock_ = local_clock; - listen_fd_ = -1; - data_fd_ = -1; - kernel_logID_basis_known_ = false; - discipline_log_ID_ = 0; -} - -DiagThread::~DiagThread() { -} - -status_t DiagThread::startWorkThread() { - status_t res; - stopWorkThread(); - res = run("Diag"); - - if (res != OK) - ALOGE("Failed to start work thread (res = %d)", res); - - return res; -} - -void DiagThread::stopWorkThread() { - status_t res; - res = requestExitAndWait(); // block until thread exit. - if (res != OK) - ALOGE("Failed to stop work thread (res = %d)", res); -} - -bool DiagThread::openListenSocket() { - bool ret = false; - int flags; - cleanupListenSocket(); - - if ((listen_fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { - ALOGE("Socket failed."); - goto bailout; - } - - // Set non-blocking operation - if (!setNonblocking(listen_fd_)) - goto bailout; - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(kListenPort); - - if (bind(listen_fd_, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - ALOGE("Bind failed."); - goto bailout; - } - - if (listen(listen_fd_, 1) < 0) { - ALOGE("Listen failed."); - goto bailout; - } - - ret = true; -bailout: - if (!ret) - cleanupListenSocket(); - - return ret; -} - -void DiagThread::cleanupListenSocket() { - if (listen_fd_ >= 0) { - int res; - - struct linger l; - l.l_onoff = 1; - l.l_linger = 0; - - setsockopt(listen_fd_, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); - shutdown(listen_fd_, SHUT_RDWR); - close(listen_fd_); - listen_fd_ = -1; - } -} - -void DiagThread::cleanupDataSocket() { - if (data_fd_ >= 0) { - int res; - - struct linger l; - l.l_onoff = 1; - l.l_linger = 0; - - setsockopt(data_fd_, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); - shutdown(data_fd_, SHUT_RDWR); - close(data_fd_); - data_fd_ = -1; - } -} - -void DiagThread::resetLogIDs() { - // Drain and discard all of the events from the kernel - struct local_time_debug_event events[kMaxEvents]; - while(local_clock_->getDebugLog(events, kMaxEvents) > 0) - ; - - { - Mutex::Autolock lock(&discipline_log_lock_); - discipline_log_.clear(); - discipline_log_ID_ = 0; - } - - kernel_logID_basis_known_ = false; -} - -void DiagThread::pushDisciplineEvent(int64_t observed_local_time, - int64_t observed_common_time, - int64_t nominal_common_time, - int32_t total_correction, - int32_t rtt) { - Mutex::Autolock lock(&discipline_log_lock_); - - DisciplineEventRecord evt; - - evt.event_id = discipline_log_ID_++; - - evt.action_local_time = local_clock_->getLocalTime(); - common_clock_->localToCommon(evt.action_local_time, - &evt.action_common_time); - - evt.observed_local_time = observed_local_time; - evt.observed_common_time = observed_common_time; - evt.nominal_common_time = nominal_common_time; - evt.total_correction = total_correction; - evt.rtt = rtt; - - discipline_log_.push_back(evt); - while (discipline_log_.size() > kMaxDisciplineLogSize) - discipline_log_.erase(discipline_log_.begin()); -} - -bool DiagThread::threadLoop() { - struct pollfd poll_fds[1]; - - if (!openListenSocket()) { - ALOGE("Failed to open listen socket"); - goto bailout; - } - - while (!exitPending()) { - memset(&poll_fds, 0, sizeof(poll_fds)); - - if (data_fd_ < 0) { - poll_fds[0].fd = listen_fd_; - poll_fds[0].events = POLLIN; - } else { - poll_fds[0].fd = data_fd_; - poll_fds[0].events = POLLRDHUP | POLLIN; - } - - int poll_res = poll(poll_fds, NELEM(poll_fds), 50); - if (poll_res < 0) { - ALOGE("Fatal error (%d,%d) while waiting on events", - poll_res, errno); - goto bailout; - } - - if (exitPending()) - break; - - if (poll_fds[0].revents) { - if (poll_fds[0].fd == listen_fd_) { - data_fd_ = accept(listen_fd_, NULL, NULL); - - if (data_fd_ < 0) { - ALOGW("Failed accept on socket %d with err %d", - listen_fd_, errno); - } else { - if (!setNonblocking(data_fd_)) - cleanupDataSocket(); - if (!setNodelay(data_fd_)) - cleanupDataSocket(); - } - } else - if (poll_fds[0].fd == data_fd_) { - if (poll_fds[0].revents & POLLRDHUP) { - // Connection hung up; time to clean up. - cleanupDataSocket(); - } else - if (poll_fds[0].revents & POLLIN) { - uint8_t cmd; - if (read(data_fd_, &cmd, sizeof(cmd)) > 0) { - switch(cmd) { - case 'r': - case 'R': - resetLogIDs(); - break; - } - } - } - } - } - - struct local_time_debug_event events[kMaxEvents]; - int amt = local_clock_->getDebugLog(events, kMaxEvents); - - if (amt > 0) { - for (int i = 0; i < amt; i++) { - struct local_time_debug_event& e = events[i]; - - if (!kernel_logID_basis_known_) { - kernel_logID_basis_ = e.local_timesync_event_id; - kernel_logID_basis_known_ = true; - } - - char buf[1024]; - int64_t common_time; - status_t res = common_clock_->localToCommon(e.local_time, - &common_time); - snprintf(buf, sizeof(buf), "E,%lld,%lld,%lld,%d\n", - e.local_timesync_event_id - kernel_logID_basis_, - e.local_time, - common_time, - (OK == res) ? 1 : 0); - buf[sizeof(buf) - 1] = 0; - - if (data_fd_ >= 0) - write(data_fd_, buf, strlen(buf)); - } - } - - { // scope for autolock pattern - Mutex::Autolock lock(&discipline_log_lock_); - - while (discipline_log_.size() > 0) { - char buf[1024]; - DisciplineEventRecord& e = *discipline_log_.begin(); - snprintf(buf, sizeof(buf), - "D,%lld,%lld,%lld,%lld,%lld,%lld,%d,%d\n", - e.event_id, - e.action_local_time, - e.action_common_time, - e.observed_local_time, - e.observed_common_time, - e.nominal_common_time, - e.total_correction, - e.rtt); - buf[sizeof(buf) - 1] = 0; - - if (data_fd_ >= 0) - write(data_fd_, buf, strlen(buf)); - - discipline_log_.erase(discipline_log_.begin()); - } - } - } - -bailout: - cleanupDataSocket(); - cleanupListenSocket(); - return false; -} - -} // namespace android diff --git a/libs/common_time/diag_thread.h b/libs/common_time/diag_thread.h deleted file mode 100644 index c630e0d9b525..000000000000 --- a/libs/common_time/diag_thread.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -#ifndef __DIAG_THREAD_H__ -#define __DIAG_THREAD_H__ - -#include <utils/List.h> -#include <utils/threads.h> - -namespace android { - -class CommonClock; -class LocalClock; - -class DiagThread : public Thread { - public: - DiagThread(CommonClock* common_clock, LocalClock* local_clock); - ~DiagThread(); - - status_t startWorkThread(); - void stopWorkThread(); - virtual bool threadLoop(); - - void pushDisciplineEvent(int64_t observed_local_time, - int64_t observed_common_time, - int64_t nominal_common_time, - int32_t total_correction, - int32_t rtt); - - private: - typedef struct { - int64_t event_id; - int64_t action_local_time; - int64_t action_common_time; - int64_t observed_local_time; - int64_t observed_common_time; - int64_t nominal_common_time; - int32_t total_correction; - int32_t rtt; - } DisciplineEventRecord; - - bool openListenSocket(); - void cleanupListenSocket(); - void cleanupDataSocket(); - void resetLogIDs(); - - CommonClock* common_clock_; - LocalClock* local_clock_; - int listen_fd_; - int data_fd_; - - int64_t kernel_logID_basis_; - bool kernel_logID_basis_known_; - - static const size_t kMaxDisciplineLogSize = 16; - Mutex discipline_log_lock_; - List<DisciplineEventRecord> discipline_log_; - int64_t discipline_log_ID_; -}; - -} // namespace android - -#endif //__ DIAG_THREAD_H__ diff --git a/libs/common_time/main.cpp b/libs/common_time/main.cpp deleted file mode 100644 index ac52c851daa3..000000000000 --- a/libs/common_time/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -/* - * A service that exchanges time synchronization information between - * a master that defines a timeline and clients that follow the timeline. - */ - -#define LOG_TAG "common_time" -#include <utils/Log.h> - -#include <binder/IPCThreadState.h> -#include <binder/ProcessState.h> - -#include "common_time_server.h" - -int main() { - using namespace android; - - sp<CommonTimeServer> service = new CommonTimeServer(); - if (service == NULL) - return 1; - - ProcessState::self()->startThreadPool(); - service->run("CommonTimeServer", ANDROID_PRIORITY_NORMAL); - - IPCThreadState::self()->joinThreadPool(); - return 0; -} - diff --git a/libs/common_time/utils.cpp b/libs/common_time/utils.cpp deleted file mode 100644 index ddcdfe7f211b..000000000000 --- a/libs/common_time/utils.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#define LOG_TAG "common_time" -#include <utils/Log.h> - -#include "utils.h" - -namespace android { - -void Timeout::setTimeout(int msec) { - if (msec < 0) { - mSystemEndTime = 0; - return; - } - - mSystemEndTime = systemTime() + (static_cast<nsecs_t>(msec) * 1000000); -} - -int Timeout::msecTillTimeout(nsecs_t nowTime) { - if (!mSystemEndTime) { - return -1; - } - - if (mSystemEndTime < nowTime) { - return 0; - } - - nsecs_t delta = mSystemEndTime - nowTime; - delta += 999999; - delta /= 1000000; - if (delta > 0x7FFFFFFF) { - return 0x7FFFFFFF; - } - - return static_cast<int>(delta); -} - -LogRing::LogRing(const char* header, size_t entries) - : mSize(entries) - , mWr(0) - , mIsFull(false) - , mHeader(header) { - mRingBuffer = new Entry[mSize]; - if (NULL == mRingBuffer) - ALOGE("Failed to allocate log ring with %zu entries.", mSize); -} - -LogRing::~LogRing() { - if (NULL != mRingBuffer) - delete[] mRingBuffer; -} - -void LogRing::log(int prio, const char* tag, const char* fmt, ...) { - va_list argp; - va_start(argp, fmt); - internalLog(prio, tag, fmt, argp); - va_end(argp); -} - -void LogRing::log(const char* fmt, ...) { - va_list argp; - va_start(argp, fmt); - internalLog(0, NULL, fmt, argp); - va_end(argp); -} - -void LogRing::internalLog(int prio, - const char* tag, - const char* fmt, - va_list argp) { - if (NULL != mRingBuffer) { - Mutex::Autolock lock(&mLock); - String8 s(String8::formatV(fmt, argp)); - Entry* last = NULL; - - if (mIsFull || mWr) - last = &(mRingBuffer[(mWr + mSize - 1) % mSize]); - - - if ((NULL != last) && !last->s.compare(s)) { - gettimeofday(&(last->last_ts), NULL); - ++last->count; - } else { - gettimeofday(&mRingBuffer[mWr].first_ts, NULL); - mRingBuffer[mWr].last_ts = mRingBuffer[mWr].first_ts; - mRingBuffer[mWr].count = 1; - mRingBuffer[mWr].s.setTo(s); - - mWr = (mWr + 1) % mSize; - if (!mWr) - mIsFull = true; - } - } - - if (NULL != tag) - LOG_PRI_VA(prio, tag, fmt, argp); -} - -void LogRing::dumpLog(int fd) { - if (NULL == mRingBuffer) - return; - - Mutex::Autolock lock(&mLock); - - if (!mWr && !mIsFull) - return; - - char buf[1024]; - int res; - size_t start = mIsFull ? mWr : 0; - size_t count = mIsFull ? mSize : mWr; - static const char* kTimeFmt = "%a %b %d %Y %H:%M:%S"; - - res = snprintf(buf, sizeof(buf), "\n%s\n", mHeader); - if (res > 0) - write(fd, buf, res); - - for (size_t i = 0; i < count; ++i) { - struct tm t; - char timebuf[64]; - char repbuf[96]; - size_t ndx = (start + i) % mSize; - - if (1 != mRingBuffer[ndx].count) { - localtime_r(&mRingBuffer[ndx].last_ts.tv_sec, &t); - strftime(timebuf, sizeof(timebuf), kTimeFmt, &t); - snprintf(repbuf, sizeof(repbuf), - " (repeated %d times, last was %s.%03ld)", - mRingBuffer[ndx].count, - timebuf, - mRingBuffer[ndx].last_ts.tv_usec / 1000); - repbuf[sizeof(repbuf) - 1] = 0; - } else { - repbuf[0] = 0; - } - - localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t); - strftime(timebuf, sizeof(timebuf), kTimeFmt, &t); - res = snprintf(buf, sizeof(buf), "[%2zu] %s.%03ld :: %s%s\n", - i, timebuf, - mRingBuffer[ndx].first_ts.tv_usec / 1000, - mRingBuffer[ndx].s.string(), - repbuf); - - if (res > 0) - write(fd, buf, res); - } -} - -} // namespace android diff --git a/libs/common_time/utils.h b/libs/common_time/utils.h deleted file mode 100644 index c28cf0ac33d7..000000000000 --- a/libs/common_time/utils.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#ifndef __UTILS_H__ -#define __UTILS_H__ - -#include <stdint.h> -#include <unistd.h> - -#include <utils/String8.h> -#include <utils/threads.h> -#include <utils/Timers.h> - -namespace android { - -class Timeout { - public: - Timeout() : mSystemEndTime(0) { } - - // Set a timeout which should occur msec milliseconds from now. - // Negative values will cancel any current timeout; - void setTimeout(int msec); - - // Return the number of milliseconds until the timeout occurs, or -1 if - // no timeout is scheduled. - int msecTillTimeout(nsecs_t nowTime); - int msecTillTimeout() { return msecTillTimeout(systemTime()); } - - private: - // The systemTime() at which the timeout will be complete, or 0 if no - // timeout is currently scheduled. - nsecs_t mSystemEndTime; -}; - -class LogRing { - public: - LogRing(const char* header, size_t entries); - ~LogRing(); - - // Send a log message to logcat as well as storing it in the ring buffer. - void log(int prio, const char* tag, const char* fmt, ...); - - // Add a log message the ring buffer, do not send the message to logcat. - void log(const char* fmt, ...); - - // Dump the log to an fd (dumpsys style) - void dumpLog(int fd); - - private: - class Entry { - public: - uint32_t count; - struct timeval first_ts; - struct timeval last_ts; - String8 s; - }; - - Mutex mLock; - Entry* mRingBuffer; - size_t mSize; - size_t mWr; - bool mIsFull; - const char* mHeader; - - void internalLog(int prio, const char* tag, const char* fmt, va_list va); -}; - -} // namespace android - -#endif // __UTILS_H__ diff --git a/services/core/java/com/android/server/CommonTimeManagementService.java b/services/core/java/com/android/server/CommonTimeManagementService.java deleted file mode 100644 index 5cebfa5a6edf..000000000000 --- a/services/core/java/com/android/server/CommonTimeManagementService.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (C) 2012 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 com.android.server; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.INetworkManagementEventObserver; -import android.net.InterfaceConfiguration; -import android.os.Binder; -import android.os.CommonTimeConfig; -import android.os.Handler; -import android.os.IBinder; -import android.os.INetworkManagementService; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemProperties; -import android.util.Log; - -import com.android.internal.util.DumpUtils; -import com.android.server.net.BaseNetworkObserver; - -/** - * @hide - * <p>CommonTimeManagementService manages the configuration of the native Common Time service, - * reconfiguring the native service as appropriate in response to changes in network configuration. - */ -class CommonTimeManagementService extends Binder { - /* - * Constants and globals. - */ - private static final String TAG = CommonTimeManagementService.class.getSimpleName(); - private static final int NATIVE_SERVICE_RECONNECT_TIMEOUT = 5000; - private static final String AUTO_DISABLE_PROP = "ro.common_time.auto_disable"; - private static final String ALLOW_WIFI_PROP = "ro.common_time.allow_wifi"; - private static final String SERVER_PRIO_PROP = "ro.common_time.server_prio"; - private static final String NO_INTERFACE_TIMEOUT_PROP = "ro.common_time.no_iface_timeout"; - private static final boolean AUTO_DISABLE; - private static final boolean ALLOW_WIFI; - private static final byte BASE_SERVER_PRIO; - private static final int NO_INTERFACE_TIMEOUT; - private static final InterfaceScoreRule[] IFACE_SCORE_RULES; - - static { - int tmp; - AUTO_DISABLE = (0 != SystemProperties.getInt(AUTO_DISABLE_PROP, 1)); - ALLOW_WIFI = (0 != SystemProperties.getInt(ALLOW_WIFI_PROP, 0)); - tmp = SystemProperties.getInt(SERVER_PRIO_PROP, 1); - NO_INTERFACE_TIMEOUT = SystemProperties.getInt(NO_INTERFACE_TIMEOUT_PROP, 60000); - - if (tmp < 1) - BASE_SERVER_PRIO = 1; - else - if (tmp > 30) - BASE_SERVER_PRIO = 30; - else - BASE_SERVER_PRIO = (byte)tmp; - - if (ALLOW_WIFI) { - IFACE_SCORE_RULES = new InterfaceScoreRule[] { - new InterfaceScoreRule("wlan", (byte)1), - new InterfaceScoreRule("eth", (byte)2), - }; - } else { - IFACE_SCORE_RULES = new InterfaceScoreRule[] { - new InterfaceScoreRule("eth", (byte)2), - }; - } - }; - - /* - * Internal state - */ - private final Context mContext; - private final Object mLock = new Object(); - private INetworkManagementService mNetMgr; - private CommonTimeConfig mCTConfig; - private String mCurIface; - private Handler mReconnectHandler = new Handler(); - private Handler mNoInterfaceHandler = new Handler(); - private boolean mDetectedAtStartup = false; - private byte mEffectivePrio = BASE_SERVER_PRIO; - - /* - * Callback handler implementations. - */ - private INetworkManagementEventObserver mIfaceObserver = new BaseNetworkObserver() { - @Override - public void interfaceStatusChanged(String iface, boolean up) { - reevaluateServiceState(); - } - @Override - public void interfaceLinkStateChanged(String iface, boolean up) { - reevaluateServiceState(); - } - @Override - public void interfaceAdded(String iface) { - reevaluateServiceState(); - } - @Override - public void interfaceRemoved(String iface) { - reevaluateServiceState(); - } - }; - - private BroadcastReceiver mConnectivityMangerObserver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - reevaluateServiceState(); - } - }; - - private CommonTimeConfig.OnServerDiedListener mCTServerDiedListener = - () -> scheduleTimeConfigReconnect(); - - private Runnable mReconnectRunnable = () -> connectToTimeConfig(); - - private Runnable mNoInterfaceRunnable = () -> handleNoInterfaceTimeout(); - - /* - * Public interface (constructor, systemReady and dump) - */ - public CommonTimeManagementService(Context context) { - mContext = context; - } - - void systemRunning() { - if (ServiceManager.checkService(CommonTimeConfig.SERVICE_NAME) == null) { - Log.i(TAG, "No common time service detected on this platform. " + - "Common time services will be unavailable."); - return; - } - - mDetectedAtStartup = true; - - IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - mNetMgr = INetworkManagementService.Stub.asInterface(b); - - // Network manager is running along-side us, so we should never receiver a remote exception - // while trying to register this observer. - try { - mNetMgr.registerObserver(mIfaceObserver); - } - catch (RemoteException e) { } - - // Register with the connectivity manager for connectivity changed intents. - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - mContext.registerReceiver(mConnectivityMangerObserver, filter); - - // Connect to the common time config service and apply the initial configuration. - connectToTimeConfig(); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - - if (!mDetectedAtStartup) { - pw.println("Native Common Time service was not detected at startup. " + - "Service is unavailable"); - return; - } - - synchronized (mLock) { - pw.println("Current Common Time Management Service Config:"); - pw.println(String.format(" Native service : %s", - (null == mCTConfig) ? "reconnecting" - : "alive")); - pw.println(String.format(" Bound interface : %s", - (null == mCurIface ? "unbound" : mCurIface))); - pw.println(String.format(" Allow WiFi : %s", ALLOW_WIFI ? "yes" : "no")); - pw.println(String.format(" Allow Auto Disable : %s", AUTO_DISABLE ? "yes" : "no")); - pw.println(String.format(" Server Priority : %d", mEffectivePrio)); - pw.println(String.format(" No iface timeout : %d", NO_INTERFACE_TIMEOUT)); - } - } - - /* - * Inner helper classes - */ - private static class InterfaceScoreRule { - public final String mPrefix; - public final byte mScore; - public InterfaceScoreRule(String prefix, byte score) { - mPrefix = prefix; - mScore = score; - } - }; - - /* - * Internal implementation - */ - private void cleanupTimeConfig() { - mReconnectHandler.removeCallbacks(mReconnectRunnable); - mNoInterfaceHandler.removeCallbacks(mNoInterfaceRunnable); - if (null != mCTConfig) { - mCTConfig.release(); - mCTConfig = null; - } - } - - private void connectToTimeConfig() { - // Get access to the common time service configuration interface. If we catch a remote - // exception in the process (service crashed or no running for w/e reason), schedule an - // attempt to reconnect in the future. - cleanupTimeConfig(); - try { - synchronized (mLock) { - mCTConfig = new CommonTimeConfig(); - mCTConfig.setServerDiedListener(mCTServerDiedListener); - mCurIface = mCTConfig.getInterfaceBinding(); - mCTConfig.setAutoDisable(AUTO_DISABLE); - mCTConfig.setMasterElectionPriority(mEffectivePrio); - } - - if (NO_INTERFACE_TIMEOUT >= 0) - mNoInterfaceHandler.postDelayed(mNoInterfaceRunnable, NO_INTERFACE_TIMEOUT); - - reevaluateServiceState(); - } - catch (RemoteException e) { - scheduleTimeConfigReconnect(); - } - } - - private void scheduleTimeConfigReconnect() { - cleanupTimeConfig(); - Log.w(TAG, String.format("Native service died, will reconnect in %d mSec", - NATIVE_SERVICE_RECONNECT_TIMEOUT)); - mReconnectHandler.postDelayed(mReconnectRunnable, - NATIVE_SERVICE_RECONNECT_TIMEOUT); - } - - private void handleNoInterfaceTimeout() { - if (null != mCTConfig) { - Log.i(TAG, "Timeout waiting for interface to come up. " + - "Forcing networkless master mode."); - if (CommonTimeConfig.ERROR_DEAD_OBJECT == mCTConfig.forceNetworklessMasterMode()) - scheduleTimeConfigReconnect(); - } - } - - private void reevaluateServiceState() { - String bindIface = null; - byte bestScore = -1; - try { - // Check to see if this interface is suitable to use for time synchronization. - // - // TODO : This selection algorithm needs to be enhanced for use with mobile devices. In - // particular, the choice of whether to a wireless interface or not should not be an all - // or nothing thing controlled by properties. It would probably be better if the - // platform had some concept of public wireless networks vs. home or friendly wireless - // networks (something a user would configure in settings or when a new interface is - // added). Then this algorithm could pick only wireless interfaces which were flagged - // as friendly, and be dormant when on public wireless networks. - // - // Another issue which needs to be dealt with is the use of driver supplied interface - // name to determine the network type. The fact that the wireless interface on a device - // is named "wlan0" is just a matter of convention; its not a 100% rule. For example, - // there are devices out there where the wireless is name "tiwlan0", not "wlan0". The - // internal network management interfaces in Android have all of the information needed - // to make a proper classification, there is just no way (currently) to fetch an - // interface's type (available from the ConnectionManager) as well as its address - // (available from either the java.net interfaces or from the NetworkManagment service). - // Both can enumerate interfaces, but that is no way to correlate their results (no - // common shared key; although using the interface name in the connection manager would - // be a good start). Until this gets resolved, we resort to substring searching for - // tags like wlan and eth. - // - String ifaceList[] = mNetMgr.listInterfaces(); - if (null != ifaceList) { - for (String iface : ifaceList) { - - byte thisScore = -1; - for (InterfaceScoreRule r : IFACE_SCORE_RULES) { - if (iface.contains(r.mPrefix)) { - thisScore = r.mScore; - break; - } - } - - if (thisScore <= bestScore) - continue; - - InterfaceConfiguration config = mNetMgr.getInterfaceConfig(iface); - if (null == config) - continue; - - if (config.isActive()) { - bindIface = iface; - bestScore = thisScore; - } - } - } - } - catch (RemoteException e) { - // Bad news; we should not be getting remote exceptions from the connectivity manager - // since it is running in SystemServer along side of us. It probably does not matter - // what we do here, but go ahead and unbind the common time service in this case, just - // so we have some defined behavior. - bindIface = null; - } - - boolean doRebind = true; - synchronized (mLock) { - if ((null != bindIface) && (null == mCurIface)) { - Log.e(TAG, String.format("Binding common time service to %s.", bindIface)); - mCurIface = bindIface; - } else - if ((null == bindIface) && (null != mCurIface)) { - Log.e(TAG, "Unbinding common time service."); - mCurIface = null; - } else - if ((null != bindIface) && (null != mCurIface) && !bindIface.equals(mCurIface)) { - Log.e(TAG, String.format("Switching common time service binding from %s to %s.", - mCurIface, bindIface)); - mCurIface = bindIface; - } else { - doRebind = false; - } - } - - if (doRebind && (null != mCTConfig)) { - byte newPrio = (bestScore > 0) - ? (byte)(bestScore * BASE_SERVER_PRIO) - : BASE_SERVER_PRIO; - if (newPrio != mEffectivePrio) { - mEffectivePrio = newPrio; - mCTConfig.setMasterElectionPriority(mEffectivePrio); - } - - int res = mCTConfig.setNetworkBinding(mCurIface); - if (res != CommonTimeConfig.SUCCESS) - scheduleTimeConfigReconnect(); - - else if (NO_INTERFACE_TIMEOUT >= 0) { - mNoInterfaceHandler.removeCallbacks(mNoInterfaceRunnable); - if (null == mCurIface) - mNoInterfaceHandler.postDelayed(mNoInterfaceRunnable, NO_INTERFACE_TIMEOUT); - } - } - } -} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 60f201ff4aac..7caa4d7c4149 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -690,7 +690,6 @@ public final class SystemServer { WindowManagerService wm = null; SerialService serial = null; NetworkTimeUpdateService networkTimeUpdater = null; - CommonTimeManagementService commonTimeMgmtService = null; InputManagerService inputManager = null; TelephonyRegistry telephonyRegistry = null; ConsumerIrService consumerIr = null; @@ -1383,15 +1382,6 @@ public final class SystemServer { traceEnd(); } - traceBeginAndSlog("StartCommonTimeManagementService"); - try { - commonTimeMgmtService = new CommonTimeManagementService(context); - ServiceManager.addService("commontime_management", commonTimeMgmtService); - } catch (Throwable e) { - reportWtf("starting CommonTimeManagementService service", e); - } - traceEnd(); - if (!disableNetwork) { traceBeginAndSlog("CertBlacklister"); try { @@ -1667,7 +1657,6 @@ public final class SystemServer { final LocationManagerService locationF = location; final CountryDetectorService countryDetectorF = countryDetector; final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater; - final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService; final InputManagerService inputManagerF = inputManager; final TelephonyRegistry telephonyRegistryF = telephonyRegistry; final MediaRouterService mediaRouterF = mediaRouter; @@ -1813,15 +1802,6 @@ public final class SystemServer { reportWtf("Notifying NetworkTimeService running", e); } traceEnd(); - traceBeginAndSlog("MakeCommonTimeManagementServiceReady"); - try { - if (commonTimeMgmtServiceF != null) { - commonTimeMgmtServiceF.systemRunning(); - } - } catch (Throwable e) { - reportWtf("Notifying CommonTimeManagementService running", e); - } - traceEnd(); traceBeginAndSlog("MakeInputManagerServiceReady"); try { // TODO(BT) Pass parameter to input manager |