編輯:關於Android編程
在android中,進程這個概念被淡化了,我們知道Android的每一個應用都是運行在一個獨立的DVM中,他們之間互不影響;應用退出之後,並沒有立馬殺死進程,進程依然停留在內存中,這麼做的目的是為了提高下次啟動時的速度。而在Android中管理進程的模塊是AMS,主要有LRU weight,OOM adj,Low Memory Killer共同來完成進程的管理。
final void updateLruProcessLocked(ProcessRecord app, boolean oomAdj, boolean updateActivityTime) { mLruSeq++;//lru序號加一 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0); }先將LRU序號加一,用於標記一次更新LRU的操作,然後調用updateLruProcessInternalLocked:
private final void updateLruProcessInternalLocked(ProcessRecord app, boolean oomAdj, boolean updateActivityTime, int bestPos) { // put it on the LRU to keep track of when it should be exited. int lrui = mLruProcesses.indexOf(app); if (lrui >= 0) mLruProcesses.remove(lrui); int i = mLruProcesses.size()-1; int skipTop = 0; app.lruSeq = mLruSeq; // compute the new weight for this process. if (updateActivityTime) { app.lastActivityTime = SystemClock.uptimeMillis(); } if (app.activities.size() > 0) { // If this process has activities, we more strongly want to keep // it around. app.lruWeight = app.lastActivityTime; } else if (app.pubProviders.size() > 0) { // If this process contains content providers, we want to keep // it a little more strongly. app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET; // Also don't let it kick out the first few real hidden processes. skipTop = ProcessList.MIN_HIDDEN_APPS; } else { // If this process doesn't have activities, we less strongly // want to keep it around, and generally want to avoid getting // in front of any very recently used activities. app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET; // Also don't let it kick out the first few real hidden processes. skipTop = ProcessList.MIN_HIDDEN_APPS; } while (i >= 0) { ProcessRecord p = mLruProcesses.get(i); // If this app shouldn't be in front of the first N background // apps, then skip over that many that are currently hidden. if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) { skipTop--; } if (p.lruWeight <= app.lruWeight || i < bestPos) { mLruProcesses.add(i+1, app);//添加到mLruProcesses合適的位置 break; } i--; } if (i < 0) { mLruProcesses.add(0, app); } // 如果這個進程之後總有cotent provider或者Service,重新計算 // If the app is currently using a content provider or service, // bump those processes as well. if (app.connections.size() > 0) { for (ConnectionRecord cr : app.connections) { if (cr.binding != null && cr.binding.service != null && cr.binding.service.app != null && cr.binding.service.app.lruSeq != mLruSeq) { updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,updateActivityTime, i+1); } } } if (app.conProviders.size() > 0) { for (ContentProviderRecord cpr : app.conProviders.keySet()) { if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) { updateLruProcessInternalLocked(cpr.proc, oomAdj, updateActivityTime, i+1); } } } if (oomAdj) { updateOomAdjLocked();調用updateOomAdjLocked 更新oom adj值 } }這個函數主要作用 1.為該進程計算LRU序列號和LRU weight 2.根據計算出來的LRU weight,將該進程信息插入到mLRUProcesses合適的位置之中 3.如果該進程之中有content provider或者service,重新計算LRU weight 4.判斷是否需要調用updateOomAdjLocked函數來更新oom adj的值
class ProcessList { // OOM adjustments for processes in various states: // This is a process without anything currently running in it. Definitely // the first to go! Value set in system/rootdir/init.rc on startup. // This value is initalized in the constructor, careful when refering to // this static variable externally. static final int EMPTY_APP_ADJ = 15; // This is a process only hosting activities that are not visible, // so it can be killed without any disruption. Value set in // system/rootdir/init.rc on startup. static final int HIDDEN_APP_MAX_ADJ = 15; static int HIDDEN_APP_MIN_ADJ = 7; // This is a process holding the home application -- we want to try // avoiding killing it, even if it would normally be in the background, // because the user interacts with it so much. static final int HOME_APP_ADJ = 6; // This is a process holding a secondary server -- killing it will not // have much of an impact as far as the user is concerned. Value set in // system/rootdir/init.rc on startup. static final int SECONDARY_SERVER_ADJ = 5; // This is a process currently hosting a backup operation. Killing it // is not entirely fatal but is generally a bad idea. static final int BACKUP_APP_ADJ = 4; // This is a process with a heavy-weight application. It is in the // background, but we want to try to avoid killing it. Value set in // system/rootdir/init.rc on startup. static final int HEAVY_WEIGHT_APP_ADJ = 3; // This is a process only hosting components that are perceptible to the // user, and we really want to avoid killing them, but they are not // immediately visible. An example is background music playback. Value set in // system/rootdir/init.rc on startup. static final int PERCEPTIBLE_APP_ADJ = 2; // This is a process only hosting activities that are visible to the // user, so we'd prefer they don't disappear. Value set in // system/rootdir/init.rc on startup. static final int VISIBLE_APP_ADJ = 1; // This is the process running the current foreground app. We'd really // rather not kill it! Value set in system/rootdir/init.rc on startup. static final int FOREGROUND_APP_ADJ = 0; // This is a process running a core server, such as telephony. Definitely // don't want to kill it, but doing so is not completely fatal. static final int CORE_SERVER_ADJ = -12; // The system process runs at the default adjustment. static final int SYSTEM_ADJ = -16; ..... }AMS提供了函數來改變這個值:updateOomAdjLocked
final void updateOomAdjLocked() { final ActivityRecord TOP_ACT = resumedAppLocked(); final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null; if (false) { RuntimeException e = new RuntimeException(); e.fillInStackTrace(); Slog.i(TAG, updateOomAdj: top= + TOP_ACT, e); } mAdjSeq++; // Let's determine how many processes we have running vs. // how many slots we have for background processes; we may want // to put multiple processes in a slot of there are enough of // them. int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1; int factor = (mLruProcesses.size()-4)/numSlots; if (factor < 1) factor = 1; int step = 0; int numHidden = 0; // First update the OOM adjustment for each of the // application processes based on their current state. int i = mLruProcesses.size(); int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ; int numBg = 0; while (i > 0) { i--; ProcessRecord app = mLruProcesses.get(i); //Slog.i(TAG, OOM + app + : cur hidden= + curHiddenAdj); //調用重載函數updateOomAdjLocked,更新OOM adj的值 updateOomAdjLocked(app, curHiddenAdj, TOP_APP); if (curHiddenAdj < ProcessList.EMPTY_APP_ADJ && app.curAdj == curHiddenAdj) { step++; if (step >= factor) { step = 0; curHiddenAdj++; } } if (!app.killedBackground) { // 如果adj的值大於等於ProcessList.HIDDEN_APP_MIN_ADJ if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) { numHidden++; if (numHidden > mProcessLimit) { Slog.i(TAG, No longer want + app.processName + (pid + app.pid + ): hidden # + numHidden); EventLog.writeEvent(EventLogTags.AM_KILL, app.pid, app.processName, app.setAdj, too many background); app.killedBackground = true; Process.killProcessQuiet(app.pid);//殺死進程 } else { numBg++; } } else if (app.curAdj >= ProcessList.HOME_APP_ADJ) { numBg++; } } } ...... }其中調用了重載函數updateOomAdjLocked,具體代碼如下:
private final boolean updateOomAdjLocked(ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) { app.hiddenAdj = hiddenAdj; if (app.thread == null) { return false; } final boolean wasKeeping = app.keeping; boolean success = true; // 1調用computeOomAdjLocked方法計算oom adj的值 computeOomAdjLocked(app, hiddenAdj, TOP_APP, false); if (app.curRawAdj != app.setRawAdj) { if (false) { // Removing for now. Forcing GCs is not so useful anymore // with Dalvik, and the new memory level hint facility is // better for what we need to do these days. if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) { // If this app is transitioning from foreground to // non-foreground, have it do a gc. scheduleAppGcLocked(app); } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) { // Likewise do a gc when an app is moving in to the // background (such as a service stopping). scheduleAppGcLocked(app); } } if (wasKeeping && !app.keeping) { // This app is no longer something we want to keep. Note // its current wake lock time to later know to kill it if // it is not behaving well. BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); synchronized (stats) { app.lastWakeTime = stats.getProcessWakeTime(app.info.uid, app.pid, SystemClock.elapsedRealtime()); } app.lastCpuTime = app.curCpuTime; } app.setRawAdj = app.curRawAdj; } if (app.curAdj != app.setAdj) { // 2 調用setOomAdj來修改進程的oom adj的值 if (Process.setOomAdj(app.pid, app.curAdj)) { if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v( TAG, Set app + app.processName + oom adj to + app.curAdj + because + app.adjType); app.setAdj = app.curAdj; } else { success = false; Slog.w(TAG, Failed setting oom adj of + app + to + app.curAdj); } } if (app.setSchedGroup != app.curSchedGroup) { app.setSchedGroup = app.curSchedGroup; if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG, Setting process group of + app.processName + to + app.curSchedGroup); if (app.waitingToKill != null && app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) { Slog.i(TAG, Killing + app.toShortString() + : + app.waitingToKill); EventLog.writeEvent(EventLogTags.AM_KILL, app.pid, app.processName, app.setAdj, app.waitingToKill); // 3 調用killProcessQuiet殺死進程 Process.killProcessQuiet(app.pid); success = false; } else { if (true) { long oldId = Binder.clearCallingIdentity(); try { // 4調用setProcessGroup修改進程的調度組 Process.setProcessGroup(app.pid, app.curSchedGroup); } catch (Exception e) { Slog.w(TAG, Failed setting process group of + app.pid + to + app.curSchedGroup); e.printStackTrace(); } finally { Binder.restoreCallingIdentity(oldId); } } else { if (app.thread != null) { try { app.thread.setSchedulingGroup(app.curSchedGroup); } catch (RemoteException e) { } } } } } return success; }函數updateOomAdjLocked,更新OOM adj的值,這一部分的主要工作有: 1.調用computeOomAdjLocked方法計算oom adj的值,這個函數比較復雜,通過一系列的運算,計算出oom adj的值 2.調用setOomAdj來修改進程的oom adj的值,這個函數就是向進程的/proc/
public static final void killProcessQuiet(int pid) { sendSignalQuiet(pid, SIGNAL_KILL); }調用了 sendSignalQuiet函數,這是一個native函數:
public static final native void sendSignalQuiet(int pid, int signal);對應的實現在android_util_Process.cpp文件中:
void android_os_Process_sendSignalQuiet(JNIEnv* env, jobject clazz, jint pid, jint sig) { if (pid > 0) { kill(pid, sig);//殺死進程 } }到此為止進程殺死了,這種方式是直接殺死進程的方式,同樣android還提供了一個被動殺死進程的機制 Low Memory Killer機制
第1節 ContentProvider介紹ContentProvider是安卓系統的四大組件之一,可以向其他組件提供數據訪問的能力。它就像是一個網站,其他組件(或者其他應
上節已實現了畫板中的繪制,刪除,恢復入清空的功能,還有橡皮擦,設置畫筆大小和畫筆顏色沒有實現,這節就將這幾個功能逐一實現。 先看效果圖:
先看一下standard啟動模式的說明:只有一個實例,在同一個應用程序中啟動他的時候,若不存在此Activity實例,則會在當前棧頂創建一個新的實例,若存在,則會把棧中在
上兩節我們都是使用文本文件保存用戶的信息,這明顯是存在漏洞的。同時對文件中的內容不好管理。今天我們學習用SharedPreference保存。sharedPreferen