編輯:關於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機制
四大組件之ContentProvider(一)-使用系統提供的ContentProvider
第1節 ContentProvider介紹ContentProvider是安卓系統的四大組件之一,可以向其他組件提供數據訪問的能力。它就像是一個網站,其他組件(或者其他應
android項目 之 記事本(9) ----- 畫板功能之橡皮擦、畫筆大小和畫筆顏色
上節已實現了畫板中的繪制,刪除,恢復入清空的功能,還有橡皮擦,設置畫筆大小和畫筆顏色沒有實現,這節就將這幾個功能逐一實現。 先看效果圖:
android:Activity啟動模式之singleTask(一)
先看一下standard啟動模式的說明:只有一個實例,在同一個應用程序中啟動他的時候,若不存在此Activity實例,則會在當前棧頂創建一個新的實例,若存在,則會把棧中在
Android 存儲學習之使用SharedPreference保存文件
上兩節我們都是使用文本文件保存用戶的信息,這明顯是存在漏洞的。同時對文件中的內容不好管理。今天我們學習用SharedPreference保存。sharedPreferen