編輯:關於Android編程
平時通過一個slider調節改變屏幕亮度,其實這個slider是systemui的東西,叫做BrightnessDialog
public class BrightnessDialog extends Activity { .... private BrightnessController mBrightnessController; @Override protected void onStart() { super.onStart(); // mBrightnessController是BrightnessController類型的 mBrightnessController.registerCallbacks(); } .... }
進一步會通過BrightnessController
public class BrightnessController implements ToggleSlider.Listener { .... public void registerCallbacks() { .... // mControl.setOnChangedListener(this); } .... @Override public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value, boolean stopTracking) { mTracking = tracking; updateIcon(mAutomatic); if (mExternalChange) return; // 如果不是自動亮度,即用戶手動設置的亮度 if (!mAutomatic) { final int val = value + mMinimumBacklight; if (stopTracking) { MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS, val); } // 設置當前手機屏幕亮度 setBrightness(val); // 存儲當前手機屏幕亮度的值到數據庫中 if (!tracking) { AsyncTask.execute(new Runnable() { public void run() { Settings.System.putIntForUser(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, val, UserHandle.USER_CURRENT); } }); } } else { // 自動亮度,計算出自動亮度值,然後通過setBrightnessAdj進行設置 final float adj = value / ((mMaximumBacklight - mMinimumBacklight) / 2f) - 1; if (stopTracking) { MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS_AUTO, value); } setBrightnessAdj(adj); if (!tracking) { AsyncTask.execute(new Runnable() { public void run() { Settings.System.putFloatForUser(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj, UserHandle.USER_CURRENT); } }); } } // 回調所有實現BrightnessStateChangeCallback接口的監聽 for (BrightnessStateChangeCallback cb : mChangeCallbacks) { cb.onBrightnessLevelChanged(); } } private void setBrightness(int brightness) { try { // mPower是一個IPowerManager接口,最終實現是在PowerManagerService mPower.setTemporaryScreenBrightnessSettingOverride(brightness); } catch (RemoteException ex) { } } }
可以看到,在BrightnessController#onChanged 回調中,調用了自己的setBrightness方法,並且最終通過PowerManagerService#setTemporaryScreenBrightnessSettingOverride實現
PowerManagerService#setTemporaryScreenBrightnessSettingOverride
@Override // Binder call public void setTemporaryScreenBrightnessSettingOverride(int brightness) { // 檢查當前調用是否有android.Manifest.permission.DEVICE_POWER權限,如果沒有,則拋出SecurityException mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DEVICE_POWER, null); final long ident = Binder.clearCallingIdentity(); try { // 通過setTemporaryScreenBrightnessSettingOverrideInternal方法設置屏幕亮度 setTemporaryScreenBrightnessSettingOverrideInternal(brightness); } finally { Binder.restoreCallingIdentity(ident); } } private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) { synchronized (mLock) { // 屏幕亮度發生改變的時候調用 if (mTemporaryScreenBrightnessSettingOverride != brightness) { // 設置新的屏幕亮度,後面在更新屏幕亮度中會用到 mTemporaryScreenBrightnessSettingOverride = brightness; mDirty |= DIRTY_SETTINGS; // 改變當前屏幕亮度 updatePowerStateLocked(); } } } private void updatePowerStateLocked() { .... try { // 設置屏幕顯示 boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2); } finally { } .... } private boolean updateDisplayPowerStateLocked(int dirty) { final boolean oldDisplayReady = mDisplayReady; if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) { .... boolean autoBrightness = (mScreenBrightnessModeSetting == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) { screenBrightness = mScreenBrightnessOverrideFromWindowManager; autoBrightness = false; brightnessSetByUser = false; } else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) { // 用戶自己設置的屏幕亮度值 screenBrightness = mTemporaryScreenBrightnessSettingOverride; } else if (isValidBrightness(mScreenBrightnessSetting)) { screenBrightness = mScreenBrightnessSetting; } if (autoBrightness) { //如果是自動亮度 .... } screenBrightness = Math.max(Math.min(screenBrightness, mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum); // 將新的屏幕亮度值賦值給mDisplayPowerRequest.screenBrightness mDisplayPowerRequest.screenBrightness = screenBrightness; // 進一步通過mDisplayManagerInternal請求改變當前的power狀態 mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest, mRequestWaitForNegativeProximity); } return mDisplayReady && !oldDisplayReady; }
這裡的mDisplayManagerInternal是什麼呢,可以看到它是DisplayManagerInternal類,是一個抽象類
public abstract class DisplayManagerInternal { }
那麼它的實現在哪裡?還記得我們手機開機的時候所有的系統服務都是由SystemServer來啟動的,其中在startBootstrapServices中啟動了DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
接著DisplayManagerService#onStart會被執行
@Override public void onStart() { mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER); publishBinderService(Context.DISPLAY_SERVICE, new BinderService(), true /*allowIsolated*/); // DisplayManagerInternal對應的是LocalService服務 publishLocalService(DisplayManagerInternal.class, new LocalService()); }
從上面代碼可以看出DisplayManagerInternal對應的是LocalService服務,LocalService是DisplayManagerService的一個內部類,繼承自DisplayManagerInternal
private final class LocalService extends DisplayManagerInternal { @Override public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager) { synchronized (mSyncRoot) { DisplayBlanker blanker = new DisplayBlanker() { @Override public void requestDisplayState(int state, int brightness, int brightnessMode) { // The order of operations is important for legacy reasons. if (state == Display.STATE_OFF) { requestGlobalDisplayStateInternal(state, brightness, brightnessMode); } callbacks.onDisplayStateChange(state); if (state != Display.STATE_OFF) { requestGlobalDisplayStateInternal(state, brightness, brightnessMode); } } }; mDisplayPowerController = new DisplayPowerController( mContext, callbacks, handler, sensorManager, blanker); } } .... @Override public boolean requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity) { // mDisplayPowerController是DisplayPowerController類型 return mDisplayPowerController.requestPowerState(request, waitForNegativeProximity); } .... }
接著看下DisplayPowerController#requestPowerState方法:
public boolean requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity) { synchronized (mLock) { boolean changed = false; .... if (changed && !mPendingRequestChangedLocked) { mPendingRequestChangedLocked = true; sendUpdatePowerStateLocked(); } return mDisplayReadyLocked; } } private void sendUpdatePowerStateLocked() { if (!mPendingUpdatePowerStateLocked) { mPendingUpdatePowerStateLocked = true; Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE); msg.setAsynchronous(true); mHandler.sendMessage(msg); } }
發送”MSG_UPDATE_POWER_STATE”消息,DisplayControllerHandler是DisplayPowerController的一個內部handler
private final class DisplayControllerHandler extends Handler { public DisplayControllerHandler(Looper looper) { super(looper, null, true /*async*/); } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_UPDATE_POWER_STATE: updatePowerState(); break; .... } } } private void updatePowerState() { .... // If need to set the screen brightness immediately, // set the brightness and the brightness mode here. if (mSetBrightnessImmediatelyAtNextRequest) { if (DEBUG) { Slog.d(TAG, "Setting the screen brightness immediately:" + brightness); } mPowerState.setScreenBrightnessAndBrightnessMode( brightness, hardwareAutoBrightnessEnabled ? Light.BRIGHTNESS_MODE_SENSOR : Light.BRIGHTNESS_MODE_USER); } .... if (!mPendingScreenOff) { if (!mSetBrightnessImmediatelyAtNextRequest && (state == Display.STATE_ON || state == Display.STATE_DOZE)) { // 動態調整屏幕亮度 animateScreenBrightness(brightness, slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST); } else { animateScreenBrightness(brightness, 0); mSetBrightnessImmediatelyAtNextRequest = false; } } } public void setScreenBrightnessAndBrightnessMode(int brightness, int brightnessMode) { if (mScreenBrightness != brightness || mBrightnessMode != brightnessMode) { mScreenBrightness = brightness; mBrightnessMode = brightnessMode; if (mScreenState != Display.STATE_OFF) { mScreenReady = false; scheduleScreenUpdate(); } } } private void scheduleScreenUpdate() { if (!mScreenUpdatePending) { mScreenUpdatePending = true; postScreenUpdateThreadSafe(); } } private void postScreenUpdateThreadSafe() { mHandler.removeCallbacks(mScreenUpdateRunnable); mHandler.post(mScreenUpdateRunnable); } private final Runnable mScreenUpdateRunnable = new Runnable() { @Override public void run() { mScreenUpdatePending = false; int brightness = mScreenState != Display.STATE_OFF && mColorFadeLevel > 0f ? mScreenBrightness : 0; // 調用了setState方法,mPhotonicModulator是PhotonicModulator類型,是一個線程 if (mPhotonicModulator.setState(mScreenState, brightness, mBrightnessMode)) { mScreenReady = true; invokeCleanListenerIfNeeded(); } else { } } };
看下PhotonicModulator線程
private final class PhotonicModulator extends Thread { private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off private final Object mLock = new Object(); private boolean mChangeInProgress; public PhotonicModulator() { super("PhotonicModulator"); } public boolean setState(int state, int backlight, int brightnessMode) { synchronized (mLock) { if (state != mPendingState || backlight != mPendingBacklight || brightnessMode != mPendingBrightnessMode) { mPendingState = state; mPendingBacklight = backlight; mPendingBrightnessMode = brightnessMode; if (!mChangeInProgress) { mChangeInProgress = true; // 當亮度發生改變完成以後,通過notifyAll喚醒處於等待的所有線程,包括自己, // 此時就會繼續走之前"mLock.wait();"下面的代碼,通過mBlanker.requestDisplayState實現屏幕亮度變化 mLock.notifyAll(); } } return !mChangeInProgress; } } @Override public void run() { for (;;) { // Get pending change. final int state; final boolean stateChanged; final int backlight; final boolean backlightChanged; final int brightnessMode; final boolean brightnessModeChanged; synchronized (mLock) { state = mPendingState; stateChanged = (state != mActualState); backlight = mPendingBacklight; backlightChanged = (backlight != mActualBacklight); brightnessMode = mPendingBrightnessMode; brightnessModeChanged = (brightnessMode != mActualBrightnessMode); if (!stateChanged && !backlightChanged && !brightnessModeChanged) { // All changed applied, notify outer class and wait for more. mChangeInProgress = false; postScreenUpdateThreadSafe(); // 如果沒有發生改變,則當前線程處於等待狀態,下面的代碼也是不會執行的 try { mLock.wait(); } catch (InterruptedException ex) { } continue; } mActualState = state; mActualBacklight = backlight; mActualBrightnessMode = brightnessMode; } // 通過mBlanker.requestDisplayState來實現頁面亮度改變 mBlanker.requestDisplayState(state, backlight, brightnessMode); } } }
這裡,可以看到,在mScreenUpdateRunnable線程中調用了PhotonicModulator#setState來喚醒所有處於等待狀態的線程,包括它自己,PhotonicModulator是在DisplayPowerState的構造方法中就已經啟動了,
好了現在看下mBlanker.requestDisplayState,可是發現mBlanker對應的DisplayBlanker是一個接口,那麼肯定有它的實現類:
public interface DisplayBlanker { void requestDisplayState(int state, int brightness, int brightnessMode); }
DisplayBlanker是在DisplayManagerService#onStart中綁定LocalService時候構造的
private final class LocalService extends DisplayManagerInternal { @Override public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager) { synchronized (mSyncRoot) { DisplayBlanker blanker = new DisplayBlanker() { @Override public void requestDisplayState(int state, int brightness, int brightnessMode) { // The order of operations is important for legacy reasons. if (state == Display.STATE_OFF) { requestGlobalDisplayStateInternal(state, brightness, brightnessMode); } // 調用了PowerManagerService中的onDisplayStateChange callbacks.onDisplayStateChange(state); if (state != Display.STATE_OFF) { requestGlobalDisplayStateInternal(state, brightness, brightnessMode); } } }; mDisplayPowerController = new DisplayPowerController( mContext, callbacks, handler, sensorManager, blanker); } } } @Override public void onDisplayStateChange(int state) { // This method is only needed to support legacy display blanking behavior // where the display's power state is coupled to suspend or to the power HAL. // The order of operations matters here. synchronized (mLock) { if (mDisplayState != state) { mDisplayState = state; if (state == Display.STATE_OFF) { if (!mDecoupleHalInteractiveModeFromDisplayConfig) { setHalInteractiveModeLocked(false); } if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) { setHalAutoSuspendModeLocked(true); } } else { if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) { setHalAutoSuspendModeLocked(false); } if (!mDecoupleHalInteractiveModeFromDisplayConfig) { setHalInteractiveModeLocked(true); } } } } }
其中setHalInteractiveModeLocked是一個native函數,設置屏幕是否亮。
接著繼續看下updatePowerState中animateScreenBrightness動態調整屏幕亮度的過程
private void animateScreenBrightness(int target, float rate) { if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {//泛型技術,最後調用了DisplayPowerState的setScreenBrightness函數 try { mBatteryStats.noteScreenBrightness(target); } catch (RemoteException ex) { // same process } } }
最終程序會走到LightsService$LightImpl類中
public class LightsService extends SystemService { private final class LightImpl extends Light { @Override public void setBrightnessForce(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, true); } } .... private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode, boolean force) { if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS || brightnessMode != mBrightnessMode || force) { mColor = color; mMode = mode; mOnMS = onMS; mOffMS = offMS; Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x" + Integer.toHexString(color) + ")"); mBrightnessMode = brightnessMode; try { if (mAllowSetLight) { // 設置當前屏幕亮度 setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode); } } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } } .... } }
(一)帶陰影的TextView涉及到的幾個屬性:運行效果如下:實現代碼: (二)帶邊框的TextView:簡單說下shapeDrawable資源文件的幾個節點及其屬性:運
java虛擬機基本結構:JVM是一個內存中的虛擬機,那它的存儲就是內存了,我們寫的所有類、常量、變量、方法都在內存中,因此明白java虛擬機的內存分配非常重要,本部分主要
1.概念 Adapter是連接後端數據和前端顯示的適配器接口,是數據和UI(View)之間一個重要的紐帶。在常見的View(ListView,Grid
一個Android項目包含了Android app代碼在內的所有文件。Android SDK工具提供默認的項目目錄和文件讓創建一個項目變得很簡單。 這篇課程會向大家展