XMLの読み込み
設定値を扱うためにXMLを利用したい場合、
どのように扱うのだろうか。
- Parserを利用する。
- DOM
- XmlPullParser
androidにおけるリソースファイルの読み込み
リソースファイルは、XMLで記述されており、これを読み込むためのフレームワークが存在するはず。
これを流用することはできないか。
以下の手順でAttributeSetが取れる。これをどうやって使うのか分からない、、、。
AttributeSet attrs = Xml.asAttributeSet(parser);
androidのアプリがXMLデータを読み込む処理
/data/system以下には、以下のXMLデータがあるので、これらを読み込む処理について調べてみる。
appwidges.xml
AppWidgetService::void readStateFromFileLocked(File file); で読み出し処理
// XmlPullParserを生成 stream = new FileInputStream(file); XmlPullParser parser = Xml.newPullParser(); parser.setInput(stream, null); int type; int providerIndex = 0; HashMap<Integer,Provider> loadedProviders = new HashMap<Integer, Provider>(); do { type = parser.next(); if (type == XmlPullParser.START_TAG) { // START_TAGならば、タグ名を取得 String tag = parser.getName(); if ("p".equals(tag)) { // 目的のタグが見つかれば、getAttributeValue()で属性値を取得する。 // TODO: do we need to check that this package has the same signature // as before? String pkg = parser.getAttributeValue(null, "pkg"); String cl = parser.getAttributeValue(null, "cl");
wallpaper_info.xml
WallpaperManagerService::loadSettingsLocked()で読み出し。
手順的には上記と同様
packages.xml
PackageManagerService::readLP()で読み出し。
手順は同上
XMLからのデータ読み出し
どうやら、XmlPullParserを利用するのが一般的なのかしら。
楽な方法があれば知りたい。
蛇足
アプリケーションのAndroidManifest.xml にユーザの独自定義のパラメータを追加したい事がある。
(※frameworkをいじっている人たち?)
以下の方法でアクティビティに定義したメタデータを取得可能なので、
このパーサを解析する処理をかけば、独自定義を得られるっぽい?(未確認)
XmlResourceParser parser = null;
parser = activityInfo.loadXmlMetaData(mPackageManager,
AppWidgetManager.META_DATA_APPWIDGET_PROVIDER);
アプリケーション独自定義データの取得
AndroidManifest.xml に定義した値を取得する方法
AndroidManifest.xmlに、
ApplicationInfo/ActivityInfoなりの metaData(Bundleクラス)から getString(hogehoge)として取得するだけ。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.misetu.test.metadata" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <meta-data android:name="com.misetu.test.metadata.collabo_app_name" android:value="test_app" /> </application> </manifest>
MainActivity.java
package com.misetu.test.metadata; import android.app.Activity; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.util.Log; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { ApplicationInfo info = this.getPackageManager().getApplicationInfo(this.getPackageName(), PackageManager.GET_META_DATA ); String appname = info.metaData.getString("com.misetu.test.metadata.collabo_app_name"); Log.d("TestMetaData", appname); } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
雑多なメモ
Debug手法?
http://omappedia.org/wiki/Android_Debugging
パンダボード
http://pandaboard.org/
http://blog.sola-dolphin-1.net/archives/3173852.html
メモリマップ
http://home1.catvmics.ne.jp/~kanemoto/linux/nr-linux.html
http://www-06.ibm.com/jp/domino01/mkt/cnpages7.nsf/ec7481a5abd4ed3149256f9400478d7d/4925722f004efe92492570b2002463e2/$FILE/Linux_Memory_Management_v1_3.pdf
http://armadillo.atmark-techno.com/articles/sd-a500-embedded-course-ch2
http://coin.nikkeibp.co.jp/coin/ncc/semi/0812/Android_20081211_Tsuji.pdf
http://home1.catvmics.ne.jp/~kanemoto/linux/nr-linux.html
ARMポーティング
http://blog.kmckk.com/archives/2042775.html
http://armputer.pbworks.com/f/porting_to_arm.pdf
ポーティング
http://groups.google.com/group/android-embedded-japan/browse_thread/thread/e445ecce882a8bda
android OOM
http://micketoh.web.fc2.com/PDF/lecture2010/l1-3.pdf
http://techbooster.jpn.org/application/1517/
http://springpadit.com/crybaby.sumire.springpad/bookmark/androidkillhappymylife
android 勉強会
http://www.yokohama.android-pf.org/study/dai-san-kai-benkyou-kai
Low Memory Killer の ソースコード
という訳で、lowmem_shrink() の詳細をチェックする。
static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask) { struct task_struct *p; struct task_struct *selected = NULL; int rem = 0; int tasksize; int i; int min_adj = OOM_ADJUST_MAX + 1;
include/linux/oom.h にて、以下のように定義
#define OOM_ADJUST_MAX 15
int selected_tasksize = 0; int array_size = ARRAY_SIZE(lowmem_adj); int other_free = global_page_state(NR_FREE_PAGES); int other_file = global_page_state(NR_FILE_PAGES); if(lowmem_adj_size < array_size) array_size = lowmem_adj_size; if(lowmem_minfree_size < array_size) array_size = lowmem_minfree_size; for(i = 0; i < array_size; i++) { if (other_free < lowmem_minfree[i] && other_file < lowmem_minfree[i]) { min_adj = lowmem_adj[i];
FREE_PAGES は、空きページ数。FILE_PAGES は、/proc/meminfo の Buffers/Cached/SwapCachedの総計。
other_file < lowmem_minfree[i] の意図が分からない。
おそらく、空きページ数が少なくても、キャッシュされているページが多ければ、問題がないと判断している。
そして、lowmem_minfree[i] より小さい場合、adj (priority)を取得する
break; } } if(nr_to_scan > 0) lowmem_print(3, "lowmem_shrink %d, %x, ofree %d %d, ma %d\n", nr_to_scan, gfp_mask, other_free, other_file, min_adj); rem = global_page_state(NR_ACTIVE) + global_page_state(NR_INACTIVE); if (nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) { lowmem_print(5, "lowmem_shrink %d, %x, return %d\n", nr_to_scan, gfp_mask, rem);
0以外が指定されているか、もしくは、minfreeの最大値よりメモリが十分にあり、min_adjが変更されていない。
return rem; } read_lock(&tasklist_lock); for_each_process(p) { if (p->oomkilladj < min_adj || !p->mm) continue;
min_adjよりプロセスのoom_adjより小さい、もしくは、!p->mm ならば、
このプロセスはkillしない。
tasksize = get_mm_rss(p->mm);
使用している物理メモリのサイズを取得する
if (tasksize <= 0) continue; if (selected) { if (p->oomkilladj < selected->oomkilladj) continue; if (p->oomkilladj == selected->oomkilladj && tasksize <= selected_tasksize) continue;
選択したプロセスより、今回のプロセスが小さい、もしくは、
選択したプロセスと今回のプロセスが同じで、タスクサイズが小さいならば、
プロセスの変更は行わない。
} selected = p; selected_tasksize = tasksize; lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n", p->pid, p->comm, p->oomkilladj, tasksize); } if(selected != NULL) { lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n", selected->pid, selected->comm, selected->oomkilladj, selected_tasksize); force_sig(SIGKILL, selected); rem -= selected_tasksize;
ここでプロセスをkillして、削減できる物理メモリ量を引いておく。
} lowmem_print(4, "lowmem_shrink %d, %x, return %d\n", nr_to_scan, gfp_mask, rem); read_unlock(&tasklist_lock); return rem; }
LowMemory Killer
いまさらながら、androidさんには、プロセスが殺される要因として、
OOM Killerとは別に、LowMemoryKiller が存在していることに気づいた。
そして、OOM Killerによって殺されていると考えていたのが間違いだった。
http://blog.kmckk.com/archives/2795577.html#more
LowMemory関連の情報は、ActivityManager.MemoryInfo で取得できるようだ。
http://techbooster.jpn.org/application/1517/
LowMemory Killer の起動
こいつのソースコードは、これのようです。
http://www.google.co.jp/codesearch/p?hl=ja#iCXnLOj7beI/drivers/misc/lowmemorykiller.c&q=android.git%20common%20lowmemorykiller.c&d=0
lowmem_shrink()によって、プロセスは、killされる様子である。
では、lowmem_shrink()は、どこから呼ばれるか?
static struct shrinker lowmem_shrinker = { .shrink = lowmem_shrink, .seeks = DEFAULT_SEEKS * 16 };
この構造体に設定されているので、どこかでこの構造体を参照しているはず。
static int __init lowmem_init(void) { register_shrinker(&lowmem_shrinker); return 0; }
register_shrinker()の引数に与えられている。
このregister_shrinker()は、あちこちでコールされている。
何をするものなのだろうか。最近追加されたもの?
/* * Add a shrinker callback to be called from the vm */ void register_shrinker(struct shrinker *shrinker) { shrinker->nr = 0; down_write(&shrinker_rwsem); list_add_tail(&shrinker->list, &shrinker_list); up_write(&shrinker_rwsem); } EXPORT_SYMBOL(register_shrinker);
http://www.google.co.jp/codesearch/p?hl=ja#iCXnLOj7beI/mm/vmscan.c&q=android.git%20common%20register_shrinker&sa=N&cd=1&ct=rc
shrinker_listに追加しているだけ。
このshrinker_listが使用されるのはどこか?
unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, unsigned long lru_pages) ・・・略
shrink_slab()でコールされている。
ここまで、整理すると。
Linuxには、shrinker という機構があるようで、
必要に応じてコールされるようです。
このあたりは、よく分からないので、誰かが説明を書いてくれることを期待する。
ともかく、lowmem_shrink()によって、プロセスがkillされているのは確実である。