Android7.0 PowerManagerService亮滅屏分析(三)
在前面兩部分已經對繪製windows與設定裝置狀態進行了詳細講解. 之後接著就該對亮度值進行設定, 實現亮屏動作了.
在DisplayPowerController中的animateScreenBrightness函式通過亮度漸變動畫來將亮度設定到目標亮度.
在animateScreenBrightness函式中呼叫動畫mScreenBrightnessRampAnimator對亮度值處理, 而mScreenBrightnessRampAnimator是在initialize()函式中進行初始化的, 在建構函式中將DisplayPowerState和DisplayPowerState.SCREEN_BRIGHTNESS傳輸過去.// Brightness animation ramp rate in brightness units per second. private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40; //亮度漸變動畫較慢的速率, 每秒變化40個亮度單位 mBrightnessRampRateFast = resources.getInteger( com.android.internal.R.integer.config_brightness_ramp_rate_fast); //從配置檔案中獲取較快的亮度速率 // Animate the screen brightness when the screen is on or dozing. // Skip the animation when the screen is off or suspended. if (!mPendingScreenOff) { if (state == Display.STATE_ON || state == Display.STATE_DOZE) { animateScreenBrightness(brightness, //當亮屏或doze狀態時有亮度漸變動畫 slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast); } else { animateScreenBrightness(brightness, 0); //滅屏時沒有亮度漸變動畫,直接將亮度設定為0 } }
private void initialize() { //.... mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>( //泛型為DisplayPowerState mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS); mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener); //... } private void animateScreenBrightness(int target, int rate) { if (DEBUG) { Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate); } if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { //動畫處理亮度值 try { mBatteryStats.noteScreenBrightness(target); } catch (RemoteException ex) { // same process } } }
在RampAnimator的建構函式中將DisplayPowerState賦值給mObject, DisplayPowerState.SCREEN_BRIGHTNESS賦值給mProperty, 並且建立mChoreographer例項.
public RampAnimator(T object, IntProperty<T> property) { mObject = object; mProperty = property; mChoreographer = Choreographer.getInstance(); }
下面重點講解animateTo函式.
public boolean animateTo(int target, int rate) {
// Immediately jump to the target the first time.
if (mFirstTime || rate <= 0) { //當第一次呼叫animateTo, 或者rate小於等於0時直接設定目標亮度.
if (mFirstTime || target != mCurrentValue) {
mFirstTime = false; //之後就不是第一次呼叫該函式
mRate = 0; //設定mRate為0
mTargetValue = target; //設定目標亮度為target
mCurrentValue = target;
mProperty.setValue(mObject, target); //呼叫DisplayPowerState.SCREEN_BRIGHTNESS設定亮度值
if (mAnimating) {
mAnimating = false;
cancelAnimationCallback();
}
if (mListener != null) {
mListener.onAnimationEnd(); //動畫結束
}
return true;
}
return false;
}
// Adjust the rate based on the closest target.
// If a faster rate is specified, then use the new rate so that we converge
// more rapidly based on the new request.
// If a slower rate is specified, then use the new rate only if the current
// value is somewhere in between the new and the old target meaning that
// we will be ramping in a different direction to get there.
// Otherwise, continue at the previous rate.
if (!mAnimating
|| rate > mRate
|| (target <= mCurrentValue && mCurrentValue <= mTargetValue)
|| (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
mRate = rate; //重新調節亮度速率
}
final boolean changed = (mTargetValue != target); //如果當前亮度值不等於目標亮度值,說明亮度改變了
mTargetValue = target; //重新設定mTargetValue
// Start animating. 開始動畫
if (!mAnimating && target != mCurrentValue) {
mAnimating = true;
mAnimatedValue = mCurrentValue;
mLastFrameTimeNanos = System.nanoTime();
postAnimationCallback();
}
return changed;
}
在postAnimationCallback中呼叫Choreographer的postCallback函式處理, 呼叫完成後回調回mAnimationCallback的run函式 private void postAnimationCallback() {
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
}
private final Runnable mAnimationCallback = new Runnable() {
@Override // Choreographer callback
public void run() {
final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
* 0.000000001f;
mLastFrameTimeNanos = frameTimeNanos; //記錄最後一次的frameTimeNanos
// Advance the animated value towards the target at the specified rate
// and clamp to the target. This gives us the new current value but
// we keep the animated value around to allow for fractional increments
// towards the target.
final float scale = ValueAnimator.getDurationScale();
if (scale == 0) {
// Animation off.
mAnimatedValue = mTargetValue; //讓scale為0時, 表示動畫停止了, 將mAnimatedValue設定為目標亮度
} else {
final float amount = timeDelta * mRate / scale; //計算每一次需要變化的亮度值
if (mTargetValue > mCurrentValue) {
mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue); //亮屏,每次增加亮度amount,不超過目標亮度
} else {
mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue); //暗屏, 每次減少amount個亮度, 不超過目標亮度
}
}
final int oldCurrentValue = mCurrentValue;
mCurrentValue = Math.round(mAnimatedValue); //獲取當前要達到的亮度值
if (oldCurrentValue != mCurrentValue) {
mProperty.setValue(mObject, mCurrentValue); //呼叫DisplayPowerState.SCREEN_BRIGHTNESS設定亮度值
}
if (mTargetValue != mCurrentValue) {
postAnimationCallback(); //如果還沒有達到目標亮度,就會繼續呼叫postAnimationCallback迴圈設定亮度值
} else {
mAnimating = false;
if (mListener != null) {
mListener.onAnimationEnd(); //否則,亮度動畫結束
}
}
}
};
DisplayPowerState.SCREEN_BRIGHTNESS的setValue函式是在DisplayPowerState中實現的. public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =
new IntProperty<DisplayPowerState>("screenBrightness") {
@Override
public void setValue(DisplayPowerState object, int value) {
object.setScreenBrightness(value); //呼叫DisplayPowerState的setScreenBrightness函式,設定亮度值
}
@Override
public Integer get(DisplayPowerState object) {
return object.getScreenBrightness();
}
};
public void setScreenBrightness(int brightness) {
if (mScreenBrightness != brightness) {
if (DEBUG) {
Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
}
mScreenBrightness = brightness; //設定全域性的亮度值
if (mScreenState != Display.STATE_OFF) {
mScreenReady = false;
scheduleScreenUpdate(); //如果不是滅屏狀態,更新螢幕狀態
}
}
}
scheduleScreenUpdate函式最終通過Handler傳送mScreenUpdateRunnable物件來更新亮度值. 從run函式中可以看出只有當mColorFadeLevel > 0f時才能給brightness設定亮度值, 所以說當windows沒有繪製完成時就算mScreenBrightness有值不為0, 但是brightness仍然為0不能點亮螢幕. private final Runnable mScreenUpdateRunnable = new Runnable() {
@Override
public void run() {
mScreenUpdatePending = false;
int brightness = mScreenState != Display.STATE_OFF
&& mColorFadeLevel > 0f ? mScreenBrightness : 0; //判斷設定亮度值
if (mPhotonicModulator.setState(mScreenState, brightness)) {
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
mScreenReady = true;
invokeCleanListenerIfNeeded();
} else {
if (DEBUG) {
Slog.d(TAG, "Screen not ready");
}
}
}
};
之後的流程就與設定設定狀態的流程相同了, 呼叫DisplayManagerService中DisplayBlanker的requestDisplayState函式. DisplayBlanker blanker = new DisplayBlanker() {
@Override
public void requestDisplayState(int state, int brightness) {
// The order of operations is important for legacy reasons.
if (state == Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
callbacks.onDisplayStateChange(state);
if (state != Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness); //亮屏呼叫設定狀態,亮度
}
}
};
private void requestGlobalDisplayStateInternal(int state, int brightness) {
if (state == Display.STATE_UNKNOWN) {
state = Display.STATE_ON;
}
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF; //滅屏設定螢幕亮度為0
} else if (brightness < 0) {
brightness = PowerManager.BRIGHTNESS_DEFAULT; //螢幕亮度小於0,設定為預設亮度
} else if (brightness > PowerManager.BRIGHTNESS_ON) {
brightness = PowerManager.BRIGHTNESS_ON; //螢幕亮度大於255設定最大亮度值255
}
synchronized (mTempDisplayStateWorkQueue) {
try {
// Update the display state within the lock.
// Note that we do not need to schedule traversals here although it
// may happen as a side-effect of displays changing state.
synchronized (mSyncRoot) {
if (mGlobalDisplayState == state
&& mGlobalDisplayBrightness == brightness) {
return; // no change 亮度與狀態都沒有改變就return
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
+ Display.stateToString(state)
+ ", brightness=" + brightness + ")");
mGlobalDisplayState = state;
mGlobalDisplayBrightness = brightness;
applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue); //應用全域性狀態
}
// Setting the display power state can take hundreds of milliseconds
// to complete so we defer the most expensive part of the work until
// after we have exited the critical section to avoid blocking other
// threads for a long time.
for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
mTempDisplayStateWorkQueue.get(i).run(); //執行mTempDisplayStateWorkQueue佇列中的runnable
}
Trace.traceEnd(Trace.TRACE_TAG_POWER);
} finally {
mTempDisplayStateWorkQueue.clear();
}
}
}
在applyGlobalDisplayStateLocked函式中獲取所有的devices, 呼叫對應裝置的requestDisplayStateLocked函式更新請求狀態. 啟動devices為LocalDisplayAdapter, 就會呼叫到該類的requestDisplayStateLocked獲得runnable. private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
final int count = mDisplayDevices.size();
for (int i = 0; i < count; i++) { //遍歷devices
DisplayDevice device = mDisplayDevices.get(i);
Runnable runnable = updateDisplayStateLocked(device); //獲得devices中的runnable
if (runnable != null) {
workQueue.add(runnable); //將runnable加入workQueue佇列, 即mTempDisplayStateWorkQueue佇列
}
}
}
private Runnable updateDisplayStateLocked(DisplayDevice device) {
// Blank or unblank the display immediately to match the state requested
// by the display power controller (if known).
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); //獲取devices資訊
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness); //呼叫requestDisplayStateLocked函式
}
return null;
}
在requestDisplayStateLocked中主要的任務就是建立一個runnable返回到DisplayManagerService中,並且等待回撥run函式.
@Override
public Runnable requestDisplayStateLocked(final int state, final int brightness) {
// Assume that the brightness is off if the display is being turned off.
assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
final boolean stateChanged = (mState != state); //狀態是否改變
final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null; //亮度值是否改變
if (stateChanged || brightnessChanged) { //如果亮度值或者亮度狀態發生改變就重新設定對應值
final int displayId = mBuiltInDisplayId;
final IBinder token = getDisplayTokenLocked();
final int oldState = mState;
if (stateChanged) { //設定亮度時.狀態已經設定好,無變化
mState = state;
updateDeviceInfoLocked();
}
if (brightnessChanged) {
mBrightness = brightness; //設定mBrightness
}
// Defer actually setting the display state until after we have exited
// the critical section since it can take hundreds of milliseconds
// to complete.
return new Runnable() { //新建一個runnable返回
@Override
public void run() { //在DisplayManagerService中呼叫run函式
// Exit a suspended state before making any changes.
int currentState = oldState;
if (Display.isSuspendedState(oldState) //判斷設定是否還是在suspend狀態
|| oldState == Display.STATE_UNKNOWN) {
if (!Display.isSuspendedState(state)) {
setDisplayState(state);
currentState = state;
} else if (state == Display.STATE_DOZE_SUSPEND
|| oldState == Display.STATE_DOZE_SUSPEND) {
setDisplayState(Display.STATE_DOZE);
currentState = Display.STATE_DOZE;
} else {
return; // old state and new state is off
}
}
// Apply brightness changes given that we are in a non-suspended state.
if (brightnessChanged) {
if (isPowerDebug()) {
Slog.d(TAG, "set display brightness=" + brightness);
}
setDisplayBrightness(brightness); //設定螢幕亮度
}
// Enter the final desired state, possibly suspended.
if (state != currentState) {
if(isPowerDebug()) {
Slog.d(TAG, "set display state=" + state);
}
setDisplayState(state);
}
}
private void setDisplayBrightness(int brightness) {
if (DEBUG) {
Slog.d(TAG, "setDisplayBrightness("
+ "id=" + displayId + ", brightness=" + brightness + ")");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
+ "id=" + displayId + ", brightness=" + brightness + ")");
try {
mBacklight.setBrightness(brightness); //呼叫LightService設定亮度
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
};
}
return null;
}
@Override
public void setBrightness(int brightness) {
setBrightness(brightness, BRIGHTNESS_MODE_USER); //亮度模式預設為BRIGHTNESS_MODE_USER
}
@Override
public void setBrightness(int brightness, int brightnessMode) {
synchronized (this) {
int color = brightness & 0x000000ff;
color = 0xff000000 | (color << 16) | (color << 8) | color; //設定光顏色
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
}
}
private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
if (!LightsUtilsFactory.getInstance().isBatteryOpenWhenNotificationCome(mId, color)){
if (!mLocked && (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
mBrightnessMode != brightnessMode)) {
if (DEBUG || isDebugNotifyLight()) Slog.v(TAG, "setLight #" + mId + ": color=#"
+ Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
mLastColor = mColor;
mColor = color;
mMode = mode;
mOnMS = onMS;
mOffMS = offMS;
mLastBrightnessMode = mBrightnessMode;
mBrightnessMode = brightnessMode;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
+ Integer.toHexString(color) + ")");
try {
setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode); //呼叫jni層設定亮度
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
}
}
通過JNI呼叫com_android_server_lights_LightsService.cpp的setLight_native函式static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
{
Devices* devices = (Devices*)ptr;
light_state_t state;
if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
return ;
}
uint32_t version = devices->lights[light]->common.version;
memset(&state, 0, sizeof(light_state_t));
if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
if (light != LIGHT_INDEX_BACKLIGHT) {
ALOGE("Cannot set low-persistence mode for non-backlight device.");
return;
}
if (version < LIGHTS_DEVICE_API_VERSION_2_0) {
// HAL impl has not been upgraded to support this.
return;
}
} else {
// Only set non-brightness settings when not in low-persistence mode
state.color = colorARGB;
state.flashMode = flashMode;
state.flashOnMS = onMS;
state.flashOffMS = offMS;
}
state.brightnessMode = brightnessMode;
{
ALOGD_IF_SLOW(50, "Excessive delay setting light"); //當設定亮度耗時大於50ms,就會輸出該行log.
devices->lights[light]->set_light(devices->lights[light], &state);
}
}
之後呼叫BSP向亮度節點寫入亮度值. 從而點亮螢幕.滅屏流程分析
滅屏總覽
在點選power鍵滅屏過程中,主要流程就是input對按鍵事件的傳輸,傳送到上層處理。在PhoneWindowManager中判斷是否為滅屏事件, 之後就是在power中進行對亮屏狀態的處理,計算一系列的數值,並且與AMS,WMS等模組進行互動,最後呼叫底層LCD進行最終的裝置狀態與亮度的設定。滅屏流程與亮屏流程有很多共同流程,在這裡只講解滅屏的獨特流程。
當wakefulness狀態發生改變,AMS收到通知。如果亮屏操作,AMS就會通過函式comeOutOfSleepIfNeedLocked呼叫到ActivityStackSupervisor中,將sleep超時訊息移除,如果抓的有partial鎖,就將其釋放,最後將在棧頂的activity顯示出來。
當亮屏時通過InputManagerService將當前螢幕狀態傳入JNI中進行記錄,當再次發生power鍵事件可以方便確認該事件是需要亮屏還是滅屏。
滅屏時首先在Notifier中通過PhoneWindowManager來通知keyguard系統開始滅屏。
滅屏動畫
在PowerManagerService中獲得螢幕的請求狀態為OFF,即設定state為Display.STATE_OFF,在這裡將performScreenOffTransition為true。
case DisplayPowerRequest.POLICY_OFF:
state = Display.STATE_OFF;
performScreenOffTransition = true;
break;
呼叫animateScreenStateChange進行處理螢幕狀態。 // Animate the screen state change unless already animating.
// The transition may be deferred, so after this point we will use the
// actual state instead of the desired one.
animateScreenStateChange(state, performScreenOffTransition);
state = mPowerState.getScreenState();
如果目標亮度不為STATE_ON,STATE_DOZE,STATE_DOZE_SUSPEND螢幕就要去睡眠了。 // Want screen off.
mPendingScreenOff = true;
if (mPowerState.getColorFadeLevel() == 0.0f) {
// Turn the screen off.
// A black surface is already hiding the contents of the screen.
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
mPowerState.dismissColorFadeResources();
} else if (performScreenOffTransition
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
&& mPowerState.getScreenState() != Display.STATE_OFF) {
// Perform the screen off animation.
mColorFadeOffAnimator.start();
} else {
// Skip the screen off animation and add a black surface to hide the
// contents of the screen.
mColorFadeOffAnimator.end();
}
在這裡就要判斷ColorFadeLevel是不是0.0,由於亮屏時將ColorFadeLevel設定為1.0所以走else語句,如果performScreenOffTransition為true並且將ColorFade準備好了就開始滅屏動畫將ColorFadeLevel從1.0漸變為0.0。但是前面知道將performScreenOffTransition設定為了false,所以就沒有了滅屏動畫,直接將ColorFadeLevel設定為0.0。之後就呼叫setScreenState設定狀態。傳送滅屏廣播
power是通過WindowManagerPolicy與PhoneWindowManager進行互動,當螢幕在finishedGoingToSleep時需要通知window進行更新手勢監聽,更新方向監聽,更新鎖屏超時時間。之後傳送滅屏廣播通知關心滅屏事件的模組。
到此為止亮滅屏流程講解完畢.
相關推薦
Android7.0 PowerManagerService亮滅屏分析(三)
在前面兩部分已經對繪製windows與設定裝置狀態進行了詳細講解. 之後接著就該對亮度值進行設定, 實現亮屏動作了.在DisplayPowerController中的animateScreenBrightness函式通過亮度漸變動畫來將亮度設定到目標亮度. // Bri
Android7.0 PowerManagerService亮滅屏分析(一)
緒論可以導致手機亮滅屏的因素有多種,而在本文中主要講解按power鍵亮滅屏過程以及來電亮屏。在亮滅屏過程power中主要的實現類與功能如下所述:PowerManagerService.java:以下簡稱PMS或者PowerMS,主要處理系統中與power相關的計算,然後決策系
Android7.0 PowerManagerService亮滅屏分析(二)
在PowerManagerService中對各種狀態進行判斷後,將其數值封裝進DisplayPowerRequest中傳入DisplayPowerController中進一步處理。在亮屏過程中DisplayPowerController會根據傳過來的數值來設定新的電源
Android7.1 Kyguard介面滅屏時間分析
概述 在Android系統中,當用戶沒有操作手機一段時間後,系統會自動滅屏進入休眠狀態,從而降低手機功耗。一般情況下系統滅屏的時間由使用者在手機設定中自己進行定義是10s,30s還是1min等等。但是如果現在系統當前顯示的是鎖屏介面,不論使用者在設定中定義的螢幕超時
popupWindow在android7.0以上顯示全屏的問題
在Android7.0以上版本呼叫popupWindow的showAsDropDown()方法,始終顯示全屏,今天記錄下解決這個問題的方法 自定義popupwindow複寫showAsDropDown
Android7.0去電流程原始碼分析(一)
2.去電從撥號盤介面有關撥號的部分由DialpadFragment.java實現,無論是單卡還是雙卡,當點選撥號按鍵時,最後都會呼叫handleDialButtonPressed方法進行處理,DialogFragmentCall_Action的活動Call_Ac
Android7.0 PowerManagerService(4) Power按鍵流程
按鍵的處理主要由InputManagerService負責,屬於Android輸入系統的流程。在這篇部落格裡,我們只關注與Power鍵相關的內容。InputManagerService處理的按鍵事件,最終將會傳遞到PhoneWindowManager的inter
android PowerManager亮滅屏(實現篇)
網上查了好多資料 不是講原理就是講原理呀! 你Tm到是實現呀!!!墨跡一大篇文章,都是看的官文件然後加上自己的理解一頓墨跡。 具體講下我要實現的功能: Android 6.0實現自動亮滅螢幕,按下電源鍵螢幕滅屏5s後自動亮屏,時間可以自己設定 用到的知識有 1:powe
android 監聽Home鍵和亮滅屏
1.註冊廣播 IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOS
Android6.0 亮屏滅屏流程(DisplayPowerControler、WMS)(二)亮度設定
上一篇部落格我們主要分析了在setScreenState中呼叫PhoneWindowManager的一些流程,在setScreenState中先是呼叫了DisplayPowerState的setScreenState函式。上篇部落格我們沒有分析,這篇部落格我們先從這個函式開
橫屏小遊戲--蘿莉快跑源代碼分析三
mark 無限 分享 idt alt popu odr tracking dispatch 主角出場: 初始化主角 hero = new GameObjH
Android7.0 MediaRecorder源碼分析
錄像 stage sdn ice ren oop 新建 n) edi 最近在做Camera的方案(雙進程打開一個Camera),涉及到使用MediaRecorder 進行錄像,還是自己新建一套錄像系統。接下來我將記錄下本次源碼分析的流程。 有關於Client和Server
popupwindow在android7.0出現全屏解決方案
在android7.0的版本測出popupwindow使用showAsDropDown方法之後,並不能顯示在指定view的下方,而是全屏顯示,只要重寫showAsDropDown判斷一下版本就好了.建議不要使用popupwindow了,使用DialogFragment代替 publi
Android 螢幕滅屏亮屏廣播,螢幕滅屏亮屏監聽
service 類註冊廣播進行監聽 /** * 作者:created by meixi * 郵箱:[email protected] * 日期:2018/9/27 09 */ public class Serview extends Service { /**
Android7.0原始碼分析之Binder——Client分析
Binder Client分析,咋一看,就那麼四個關鍵方法:getService()、addService()、checkService()、listServices()。四個方法原理都差不多,以下僅
android4.4 車載滅屏 按任意鍵及觸控式螢幕幕恢復亮屏
車載上的android4.4系統,基本上常亮。但最近需要一個新功能可以在launcher新增一個按鈕,點選的時候。螢幕亮度為0,但實際上不等於按power鍵,不會睡眠。 然後可以按任意鍵恢復亮度,包括觸屏事件。 一、PowerManagerService原先螢幕亮度流程
android 電容屏(三):驅動除錯之驅動程式分析篇
關鍵詞:android 電容屏 tp 工作佇列 中斷 坐點計算 電容屏主要引數 平臺資訊: 核心:linux2.6/linux3.0 系統:android/android4.0 平臺:S5PV310(samsung exynos 4210) 作者:xubin3417
[Android7.0]NFC初始化的流程分析
1、NFC初始化的時序圖: 2、程式碼分析: 初始化分兩部分,第一供應framework使用的服務端初始化,並將服務新增到ServiceManager中,第二是初始化NFC介面卡NfcAdapter,其中就包含何種對應NFC協議的服務。 * 服務端的初
Android7.0 分屏多視窗
如果您使用 N Preview SDK 構建應用,則可以配置應用處理多視窗顯示的方法。 例如,您可以指定 Activity 的最小允許尺寸。 您還可以禁用應用的多視窗顯示,確保系統僅以全屏模式顯示應用。 概覽 Android N 允許多個應用同時共享螢幕。例如,使用者可以分屏顯示應用,在左邊檢視網頁,
Android6.0系統啟動流程分析三:SystemServer程序
在上一篇部落格 Android6.0系統啟動流程分析二:zygote程序一文中,我們隊Zygote程序的有了一定的瞭解。我們知道Zygote程序會啟動SystemServer程序,但我們並沒有在上篇文章中分析SystemServer程序的相關內容。這篇部落格,我