[android原始碼日記]當系統時間小於1970年
阿新 • • 發佈:2018-12-14
我們知道,計算機的時間是從1970年開始的,而java獲取時間的方法System.currentTimeMillis()的返回值也是從0開始的,0就代表1970年一月一日。
那麼這個如果值為負數會怎麼樣?1969年?
今天在讀SystemServer原始碼的時候看到其中run方法修復時間的一段。它是這麼處理的。
// If a device's clock is before 1970 (before 0), a lot of // APIs crash dealing with negative numbers, notably // java.io.File#setLastModified, so instead we fake it and // hope that time from cell towers or NTP fixes it shortly. if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); }
也就是手機的時鐘可能是小於1970年的,但如果小於這個值的話java.io.File#setLastModified則會引起崩潰,因此android原始碼在這裡加了個判斷,如果時間小於1970,則把時間設定為1970年。。(註釋是說1970年,但實際上拿EARLIEST_SUPPORTED_TIME
這個時間戳計算是1972/9/27 8:0:0,不知道為什麼是這個時間,難道這就是口是心非??)
具體就是:
// The earliest supported time. We pick one day into 1970, to // give any timezone code room without going into negative time. private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
實現設定CurrentTimeMillis的程式碼:
/** * Sets the current wall time, in milliseconds. Requires the calling * process to have appropriate permissions. * * @return if the clock was successfully set to the specified time. */ public static boolean setCurrentTimeMillis(long millis) { IBinder b = ServiceManager.getService(Context.ALARM_SERVICE); IAlarmManager mgr = IAlarmManager.Stub.asInterface(b); if (mgr == null) { return false; } try { return mgr.setTime(millis); } catch (RemoteException e) { Slog.e(TAG, "Unable to set RTC", e); } catch (SecurityException e) { Slog.e(TAG, "Unable to set RTC", e); } return false; }
關鍵的就是mgr.setTime(millis);
設定了時間
public boolean setTime(long millis) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken("android.app.IAlarmManager");
_data.writeLong(millis);
this.mRemote.transact(2, _data, _reply, 0);
_reply.readException();
_result = 0 != _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}