下面列出了android.os.Message#setAsynchronous ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@SuppressLint("NewApi")
AsyncHandler(Looper looper) {
super(looper);
if (Build.VERSION.SDK_INT < 16) {
async = false;
} else if (async && Build.VERSION.SDK_INT < 22) {
// Confirm that the method is available on this API level despite being @hide.
Message message = Message.obtain();
try {
message.setAsynchronous(true);
} catch (NoSuchMethodError e) {
async = false;
}
message.recycle();
}
}
private void updateScreenBrightnessBoostLocked(int dirty) {
if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {
if (mScreenBrightnessBoostInProgress) {
final long now = SystemClock.uptimeMillis();
mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
final long boostTimeout = mLastScreenBrightnessBoostTime +
SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
if (boostTimeout > now) {
Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, boostTimeout);
return;
}
}
mScreenBrightnessBoostInProgress = false;
mNotifier.onScreenBrightnessBoostChanged();
userActivityNoUpdateLocked(now,
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
}
}
private void startDetectionLocked() {
if (!mDetectionInProgress && mGravitySensor != null) {
if (mSensorManager.registerListener(mListener, mGravitySensor,
SAMPLING_INTERVAL_MILLIS * 1000)) {
mSuspendBlocker.acquire();
mDetectionInProgress = true;
mDetectionStartTime = SystemClock.uptimeMillis();
mTotalSamples = 0;
mMovingSamples = 0;
Message msg = Message.obtain(mHandler, mSensorTimeout);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, SETTLE_TIME_MILLIS);
}
}
}
/**
* Called when there has been user activity.
*/
public void onUserActivity(int event, int uid) {
if (DEBUG) {
Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
}
try {
mBatteryStats.noteUserActivity(uid, event);
} catch (RemoteException ex) {
// Ignore
}
synchronized (mLock) {
if (!mUserActivityPending) {
mUserActivityPending = true;
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
}
private void requestUpdate() {
if (mFrameDrawScheduled) {
return;
}
final Message request = Message.obtain(mHandler, mMagnifierUpdater);
request.setAsynchronous(true);
request.sendToTarget();
mFrameDrawScheduled = true;
}
private void scheduleSandmanLocked() {
if (!mSandmanScheduled) {
mSandmanScheduled = true;
Message msg = mHandler.obtainMessage(MSG_SANDMAN);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
/**
* Called when screen brightness boost begins or ends.
*/
public void onScreenBrightnessBoostChanged() {
if (DEBUG) {
Slog.d(TAG, "onScreenBrightnessBoostChanged");
}
mSuspendBlocker.acquire();
Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
/**
* mAsynchronous=trueでAPI>=22の場合にMessage#setAsynchronousで非同期設定フラグをつける。
* 今のHandlerの実装だと#sendMessageAtTimeと#sendMessageAtFrontOfQueueから
* #enqueueMessage(private)を呼び出していてその中でsetAsynchronousが呼び出されている。
*
* sendMessageAtFrontOfQueueもoverrideしたいけどfinalなのでoverrideできない
* @param msg
* @param uptimeMillis
* @return
*/
@SuppressLint("NewApi")
@Override
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
if (mAsynchronous
&& (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1)) {
msg.setAsynchronous(true);
}
return super.sendMessageAtTime(msg, uptimeMillis);
}
/**
* Called when wireless charging has started so as to provide user feedback (sound and visual).
*/
public void onWirelessChargingStarted(int batteryLevel) {
if (DEBUG) {
Slog.d(TAG, "onWirelessChargingStarted");
}
mSuspendBlocker.acquire();
Message msg = mHandler.obtainMessage(MSG_WIRELESS_CHARGING_STARTED);
msg.setAsynchronous(true);
msg.arg1 = batteryLevel;
mHandler.sendMessage(msg);
}
/**
* Called when wired charging has started so as to provide user feedback
*/
public void onWiredChargingStarted() {
if (DEBUG) {
Slog.d(TAG, "onWiredChargingStarted");
}
mSuspendBlocker.acquire();
Message msg = mHandler.obtainMessage(MSG_WIRED_CHARGING_STARTED);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
private void updatePendingBroadcastLocked() {
if (!mBroadcastInProgress
&& mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
&& (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
|| mPendingInteractiveState != mBroadcastedInteractiveState)) {
mBroadcastInProgress = true;
mSuspendBlocker.acquire();
Message msg = mHandler.obtainMessage(MSG_BROADCAST);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
/**
* Dispatches an input event to the IME.
*
* Returns {@link #DISPATCH_HANDLED} if the event was handled.
* Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
* Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
* callback will be invoked later.
*
* @hide
*/
public int dispatchInputEvent(InputEvent event, Object token,
FinishedInputEventCallback callback, Handler handler) {
synchronized (mH) {
if (mCurMethod != null) {
if (event instanceof KeyEvent) {
KeyEvent keyEvent = (KeyEvent)event;
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
&& keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
&& keyEvent.getRepeatCount() == 0) {
showInputMethodPickerLocked();
return DISPATCH_HANDLED;
}
}
if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
PendingEvent p = obtainPendingEventLocked(
event, token, mCurId, callback, handler);
if (mMainLooper.isCurrentThread()) {
// Already running on the IMM thread so we can send the event immediately.
return sendInputEventOnMainLooperLocked(p);
}
// Post the event to the IMM thread.
Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
msg.setAsynchronous(true);
mH.sendMessage(msg);
return DISPATCH_IN_PROGRESS;
}
}
return DISPATCH_NOT_HANDLED;
}
private void flushPendingEventsLocked() {
mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
final int count = mPendingEvents.size();
for (int i = 0; i < count; i++) {
int seq = mPendingEvents.keyAt(i);
Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
msg.setAsynchronous(true);
msg.sendToTarget();
}
}
@Override
public void execute(@NonNull Runnable command) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
mHandler.post(command);
} else {
Message message = Message.obtain(mHandler, command);
message.setAsynchronous(true);
mHandler.sendMessage(message);
}
}
@SuppressLint("NewApi")
@Override
public void setAsynchronous(Message msg, boolean async) {
msg.setAsynchronous(async);
}
private void performPendingShutdown() {
final String shutdownAction = SystemProperties.get(
ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
if (shutdownAction != null && shutdownAction.length() > 0) {
boolean reboot = (shutdownAction.charAt(0) == '1');
final String reason;
if (shutdownAction.length() > 1) {
reason = shutdownAction.substring(1, shutdownAction.length());
} else {
reason = null;
}
// If it's a pending reboot into recovery to apply an update,
// always make sure uncrypt gets executed properly when needed.
// If '/cache/recovery/block.map' hasn't been created, stop the
// reboot which will fail for sure, and get a chance to capture a
// bugreport when that's still feasible. (Bug: 26444951)
if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
File packageFile = new File(UNCRYPT_PACKAGE_FILE);
if (packageFile.exists()) {
String filename = null;
try {
filename = FileUtils.readTextFile(packageFile, 0, null);
} catch (IOException e) {
Slog.e(TAG, "Error reading uncrypt package file", e);
}
if (filename != null && filename.startsWith("/data")) {
if (!new File(BLOCK_MAP_FILE).exists()) {
Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
"unexpected runtime restart?");
return;
}
}
}
}
Runnable runnable = new Runnable() {
@Override
public void run() {
synchronized (this) {
ShutdownThread.rebootOrShutdown(null, reboot, reason);
}
}
};
// ShutdownThread must run on a looper capable of displaying the UI.
Message msg = Message.obtain(UiThread.getHandler(), runnable);
msg.setAsynchronous(true);
UiThread.getHandler().sendMessage(msg);
}
}
private void scheduleUserInactivityTimeout(long timeMs) {
final Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timeMs);
}
private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,
final String reason, boolean wait) {
if (mHandler == null || !mSystemReady) {
if (RescueParty.isAttemptingFactoryReset()) {
// If we're stuck in a really low-level reboot loop, and a
// rescue party is trying to prompt the user for a factory data
// reset, we must GET TO DA CHOPPA!
PowerManagerService.lowLevelReboot(reason);
} else {
throw new IllegalStateException("Too early to call shutdown() or reboot()");
}
}
Runnable runnable = new Runnable() {
@Override
public void run() {
synchronized (this) {
if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
ShutdownThread.rebootSafeMode(getUiContext(), confirm);
} else if (haltMode == HALT_MODE_REBOOT) {
ShutdownThread.reboot(getUiContext(), reason, confirm);
} else {
ShutdownThread.shutdown(getUiContext(), reason, confirm);
}
}
}
};
// ShutdownThread must run on a looper capable of displaying the UI.
Message msg = Message.obtain(UiThread.getHandler(), runnable);
msg.setAsynchronous(true);
UiThread.getHandler().sendMessage(msg);
// PowerManager.reboot() is documented not to return so just wait for the inevitable.
if (wait) {
synchronized (runnable) {
while (true) {
try {
runnable.wait();
} catch (InterruptedException e) {
}
}
}
}
}
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
// Ignore vsync from secondary display.
// This can be problematic because the call to scheduleVsync() is a one-shot.
// We need to ensure that we will still receive the vsync from the primary
// display which is the one we really care about. Ideally we should schedule
// vsync for a particular display.
// At this time Surface Flinger won't send us vsyncs for secondary displays
// but that could change in the future so let's log a message to help us remember
// that we need to fix this.
if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
Log.d(TAG, "Received vsync from secondary display, but we don't support "
+ "this case yet. Choreographer needs a way to explicitly request "
+ "vsync for a specific display to ensure it doesn't lose track "
+ "of its scheduled vsync.");
scheduleVsync();
return;
}
// Post the vsync event to the Handler.
// The idea is to prevent incoming vsync events from completely starving
// the message queue. If there are no messages in the queue with timestamps
// earlier than the frame time, then the vsync event will be processed immediately.
// Otherwise, messages that predate the vsync event will be handled first.
long now = System.nanoTime();
if (timestampNanos > now) {
Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
+ " ms in the future! Check that graphics HAL is generating vsync "
+ "timestamps using the correct timebase.");
timestampNanos = now;
}
if (mHavePendingVsync) {
Log.w(TAG, "Already have a pending vsync event. There should only be "
+ "one at a time.");
} else {
mHavePendingVsync = true;
}
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
public void postAsynchronous(Runnable r) {
Message renderMsg = Message.obtain(mHandler, r);
renderMsg.setAsynchronous(true);
mHandler.sendMessage(renderMsg);
}