ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2011年12月7日 星期三

property_set/get in android

android 的 property 系統也是一種 IPC 的方法 (用在跟 system 溝通上).
一般 c program 可以用 property_set, property_get 來設定/取得 property 值。

property related function 實做在 system/core/libcutils/propertied.c
基本上就是用 local socket 跟 PROP_SERVICE_NAME 溝通。

property service 好像是在 init 就啟動了.. void start_property_service(void) { int fd; load_properties_from_file(PROP_PATH_SYSTEM_BUILD); load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT); load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); /* Read persistent properties after all default values have been loaded. */ load_persistent_properties(); fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0); if(fd < 0) return; fcntl(fd, F_SETFD, FD_CLOEXEC); fcntl(fd, F_SETFL, O_NONBLOCK); listen(fd, 8); property_set_fd = fd; } core/init 這個 process 最後,好像就是在做 property_service.. main() 的最後: for(;;) { ... ... nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; for (i = 0; i < fd_count; i++) { if (ufds[i].revents == POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) handle_keychord(); else if (ufds[i].fd == get_signal_fd()) handle_signal(); } } } ufds 就是剛剛 create_socket(PROP_SERVICE_NAME...) 的 fd

這個 source file : core/init/property_service.c 有所有 property 的操作。

像:
persistant property value (以 persistant. 開頭的 property)存放方式,位置: #define PERSISTENT_PROPERTY_DIR "/data/property"

2011年12月5日 星期一

"adb server is out of date. killing"

啟動 adb 時,會出現:"adb server is out of date. killing"。
因為 adb server 被重啟動,所以沒有辦法建立兩個連線。

查這段 message "adb server is out of date. killing",是在 ./system/core/adb/adb_client.c:251: printf("adb server is out of date. killing...\n"); 是 compare version: int adb_connect(const char *service) { // first query the adb server's version int fd = _adb_connect("host:version"); .... char buf[100]; int n; int version = ADB_SERVER_VERSION - 1; // if we have a file descriptor, then parse version result if(readx(fd, buf, 4)) goto error; buf[4] = 0; n = strtoul(buf, 0, 16); if(readx(fd, buf, n)) goto error; adb_close(fd); if (sscanf(buf, "%04x", &version) != 1) goto error; } else { ........ } .... if(version != ADB_SERVER_VERSION) { printf("adb server is out of date. killing...\n"); 就是去詢問 host adb server 的版本,然後和自己比較。
不一樣就 print msg & restart



就在我加上 debug message (print out version),重新 run 後,就 OK 了
===> 所以說,我 pc 上的 adb 版本太舊了...

2011年11月28日 星期一

libusb-1.0.0.8 for android

就 這篇 http://android.serverbox.ch/?p=151http://my0613.blogspot.com/2010/11/porting-lsusb-libusb-on-android.html 分別是 libusb 和 lsusb。

porting lib 還是和以前一樣,要先run ./configure. 產生 config.h,然後再自己改成 for android 的配置。

然後加入 Android.mk (兩個)

再修改一下 build error 的 file



我的 config.h: /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* Default visibility */ #define API_EXPORTED __attribute__((visibility("default"))) /* Debug message logging */ /* #undef ENABLE_DEBUG_LOGGING */ /* Message logging */ #define ENABLE_LOGGING 1 /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `rt' library (-lrt). */ #define HAVE_LIBRT 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* Darwin backend */ /* #undef OS_DARWIN */ /* Linux backend */ #define OS_LINUX /**/ /* Name of package */ #define PACKAGE "libusb" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "libusb" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "libusb 1.0.8" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "libusb" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "1.0.8" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Backend handles timeout */ /* #undef USBI_OS_HANDLES_TIMEOUT */ /* timerfd headers available */ /* #undef USBI_TIMERFD_AVAILABLE */ /* Version number of package */ #define VERSION "1.0.8" /* Use GNU extensions */ #define _GNU_SOURCE /**/ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif
我的 external/libusb-1.0.0.8/Android.mk: LOCAL_PATH := $(call my-dir) subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ libusb \ examples \ )) include $(subdirs)
我的 external/libusb-1.0.0.8/libusb/Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS:= tests LOCAL_PRELINK_MODULE:= false LOCAL_SRC_FILES:= \ core.c \ descriptor.c \ io.c \ sync.c \ os/linux_usbfs.c LOCAL_C_INCLUDES += \ external/libusb-1.0.8/ \ external/libusb-1.0.8/libusb/ \ external/libusb-1.0.8/libusb/os LOCAL_MODULE:= libusb include $(BUILD_SHARED_LIBRARY)
我的 external/libusb-1.0.0.8/example/Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := lsusb.c LOCAL_MODULE := lsusb LOCAL_C_INCLUDES += external/libusb-1.0.8/ LOCAL_SHARED_LIBRARIES := libc libusb include $(BUILD_EXECUTABLE)



  1. download libusb-1.0.0.8, unzip to external (result in a external/libusb-1.0.0.8)
  2. run ./configure -disable-timerfd
  3. modify libusb/io.c
    加上#define TIMESPEC_TO_TIMEVAL(tv, ts) \ do { \ (tv)->tv_sec = (ts)->tv_sec; \ (tv)->tv_usec = (ts)->tv_nsec / 1000; \ } while (0)
  4. add 3 Android.mk files
OK to build, mm
sync to target, run bash-3.2# lsusb 1d6b:0002 (bus 1, device 1) 1d6b:0002 (bus 2, device 1) 0424:2517 (bus 2, device 2) 0a12:0001 (bus 2, device 3) 13fe:1d00 (bus 2, device 4)
不用 mount usbfs /proc/bus/usbfs 就可以動作(?)

查 libusb/os/linux_usbfs.c : static const char *find_usbfs_path(void) { const char *path = "/dev/bus/usb"; const char *ret = NULL; if (check_usb_vfs(path)) { ret = path; } else { path = "/proc/bus/usb"; if (check_usb_vfs(path)) ret = path; } usbi_dbg("found usbfs at %s", ret); return ret; } 用的是 /dev/bus/usb



2008 這篇 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=483392 有說不要再 mount /proc/bus/usbfs,請直接用 /dev/bus/usb..

但是到現在好像還很多人在用...

2011年11月24日 星期四

Keyboard shortcut (Hotkey) in Android

Android 有 keyboard shortcut 功能,就是自己定義按著 Search 時,同時按下某個 key 就 啟動 XX app (可以自訂)。

但是要在有 keyboard 的 機器 上那個設定畫面才會出現。

這個功能一樣做在 PhoneWindowManager.java 的 interceptKeyBeforeDispatching
在 HOME, MENU, CALL,, 等等 KEYCODE 的判斷後面...
// Shortcuts are invoked through Search+key, so intercept those here if (mSearchKeyPressed) { if (down && repeatCount == 0 && !keyguardOn) { Intent shortcutIntent = mShortcutManager.getIntent(keyCode, metaState); if (shortcutIntent != null) { shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(shortcutIntent); /* * We launched an app, so the up-event of the search key * should be consumed */ mConsumeSearchKeyUp = true; return true; } } } 一樣用 startActivity( ) 叫起 app (intent),那個 對應哪個 key,都在ShorcutManager 的 database (bookmark) 中紀錄。



Setting 部份的 source code 在 src/com/android/settings/ApplicationSettings.java
如果沒有 physical keyboard,就移除這個 Setting: if (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_NOKEYS) { // No hard keyboard, remove the setting for quick launch Preference quickLaunchSetting = findPreference(KEY_QUICK_LAUNCH); getPreferenceScreen().removePreference(quickLaunchSetting); }
實際設定的 class 是 quicklaunch


如果要作假...
以叫起 browser (S-B) 為例..,
  1. 送出一個 SEARCH KEY Down : 217, down
  2. 送出一個 b Key down, up : 48, down,up
  3. 這時候就可以看到 browser 已經被叫起來了
  4. 送出一個 SEARCH KEY Up : 217 up
keycode 定義可以看 ./include/linux/input.h
-- 新版 (3.0.X) 在 /include/uapi/linux/input.h



自己紀錄一下,就是:
  1. cd /sys/devices/platform/virkeyboard/
  2. echo D217 > vmevent
  3. echo 48 > vmevent -- 可以看到 browser 起來了
  4. echo U217 > vmevent

HOTKEY to launch HOME launcher

收到 KEYCODE_HOME 後: launchHomeFromHotKey();
launchHomeFromHotKey 中 laucn Home 的 code: try { ActivityManagerNative.getDefault().stopAppSwitches(); } catch (RemoteException e) { } sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); startDockOrHome();
  1. stopAppSwitches()
  2. sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY)
  3. startDockOrHome()



stopAppSwitches():

好像是停止 app switch 5 sec.


sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY):

是 call : ActivityManagerNative.getDefault().closeSystemDialogs(reason); 就是把 windws map 叫出來,一個一個 send message: Message msg = Message.obtain(); msg.what = CLOSE_SYSTEM_DIALOGS; msg.obj = reason; sendMessage(msg);

startDockOrHome:
mHomeIntent = new Intent(Intent.ACTION_MAIN, null); mHomeIntent.addCategory(Intent.CATEGORY_HOME); mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); ........ startActivity(mHomeIntent)

... framework 自己也用 startActivity...

Add app project in android build system

google 的說明文件有 如何用 android 的 build 系統 build apk:
http://www.kandroid.org/online-pdk/guide/build_cookbook.html

copy 一些過來:

Android system 用 Android.mk,簡單的 apk 可以用: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # Build all java files in the java subdirectory LOCAL_SRC_FILES := $(call all-subdir-java-files) # Name of the APK to build LOCAL_PACKAGE_NAME := LocalPackage # Tell it to build an APK include $(BUILD_PACKAGE) 把這個 Android.mk 放在 app 的 folder 中就可以。
... LocalPackage 就是最後 apk 的 filename


這一篇是說明把 Eclipse create 的 project folder 搬到 Android root 中 build 的方法:
http://owenhuangtw.pixnet.net/blog/post/23935524-using-android-bluetoothdevice-class-to-control-blue-deivce

.. 好像就是把 Android.mk 放進去就可以了 (?)

用 eclipse create 的 project 如果有 build 過,搬到 android root 後,要把 gen, bin 清掉,不然 build 會有 R.jar 的 error。

其實 developement/sample 下每一個 project 都是 用這個方法。
可以參考


很奇怪,給 file path 就不行,可以的是用 MediaScanner scan 過後,再傳 uri 過去。
所以可能要自己 scan,
example 在 development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java:

scan 單檔的 方法:
            File path = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES);
            File file = new File(path, "DemoPicture.jpg");
            .....
            .....
            // Tell the media scanner about the new file so that it is
            // immediately available to the user.
            MediaScannerConnection.scanFile(this,
                    new String[] { file.toString() }, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) {
                    Log.i("ExternalStorage", "Scanned " + path + ":");
                    Log.i("ExternalStorage", "-> uri=" + uri);
                }
            });

2011年11月23日 星期三

forceStopPackage

ActivityManager.java: public void forceStopPackage(String packageName) { try { ActivityManagerNative.getDefault().forceStopPackage(packageName); } catch (RemoteException e) { } }
call 的是ActivivityManagerProxy Implement IActivityManager: public void forceStopPackage(String packageName) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeString(packageName); mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); }
mRemote transact 經由 IBinder 傳送 FORCE_STO_PACKAGE_TRANSACTION 需求。
收到並執行的是
在 ActivityManagerNative 的 onTransact(): case FORCE_STOP_PACKAGE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String packageName = data.readString(); forceStopPackage(packageName); reply.writeNoException(); return true; }
onTransact 的 case handler
呼叫的是ActivityManagerService 的 forceStopPackage(?): IPackageManager pm = AppGlobals.getPackageManager(); int pkgUid = pm.getPackageUid(packageName); forceStopPackageLocked(packageName, pkgUid);
就是從 package manager 找出 packageName 的 pid,然後 call forceStopPackageLocked( ) 結束他。


其中的 forceStopPackageLocked 是: private void forceStopPackageLocked(final String packageName, int uid) { forceStopPackageLocked(packageName, uid, false, false, true); Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED, Uri.fromParts("package", packageName, null)); if (!mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } intent.putExtra(Intent.EXTRA_UID, uid); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, false, false, MY_PID, Process.SYSTEM_UID); } 就是call forceStopPackageLocked( ) 結束他,然後再 broadcast ACTION_PACKAGE_RESTARTED.. (叫他再起來?)

Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator(); while (badApps.hasNext()) { SparseArray ba = badApps.next(); if (ba.get(uid) != null) { badApps.remove(); } } 把 mProcessCrashTime (上次system crash 時的 proces map) 中,同 uid 的 process data 從 record map 中移除。


boolean didSomething = killPackageProcessesLocked(name, uid, -100, callerWillRestart, doit); 然後 killPackageProcessLocked( ).


for (i=mMainStack.mHistory.size()-1; i>=0; i--) { ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); if (r.packageName.equals(name)) { if (!doit) { return true; } didSomething = true; Slog.i(TAG, " Force finishing activity " + r); if (r.app != null) { r.app.removed = true; } r.app = null; r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall"); } } 然後再從 目前系統 activiry stack (所有執行過的 activity) 中,找出符合name 的package,作 RESULT_CANCELED 的 finishActivityLocked( )。



後面看起來會把 activity stack 中 下一個 activity resume 回來 (到 top)。

如果 stack 是空的,就 launch home launcher
trace code 的其中一點,最後是用 kill 把 process 殺掉。

標籤

網誌存檔