androidfd
『壹』 android下視頻文件從解碼到播放需要哪幾步,請簡述
Android通過軟解碼播放視頻
1, 一般情況下Android的平台都是硬解碼視頻的,尤其是在Arm平台這種成熟的硬體平台上面(硬解碼代碼由晶元廠商提供)。但是Android移植到
2, MIPS平台時間還不長,還不成熟,還需要自己實現硬體解碼的工作。為了早日讓Android在MIPS平台運行起來,我選擇了先用軟解碼播放視頻。
3,Android代碼是從Android on MIPS社區獲得的代碼。發現軟解碼視頻播放過程中會發生崩潰。經過分析好像是內存分配的問題。
4, 經過研究OpenCore庫(Android框架是通過OpenCore來播放視頻的,網上有很多關於OpenCore的介紹,這里就不多說了),並參考Android平台——Surfaceflinger機制。發現問題出在源文件:
frameworks/base/libs/surfaceflinger/LayerBuffer.cpp的LayerBuffer::BufferSource::postBuffer方法中:
............
buffer = new LayerBuffer::Buffer(buffers, offset);
............類LayerBuffer::Buffer的構造函數代碼如下:
LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
: mBufferHeap(buffers)
{
NativeBuffer& src(mNativeBuffer);
g.handle = 0;
gralloc_mole_t const * mole = LayerBuffer::getGrallocMole();
if (mole && mole->perform) {
int err = mole->perform(mole,
GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,
buffers.heap->heapID(), buffers.heap->getSize(),
offset, buffers.heap->base(),
& g.handle);
if (err == NO_ERROR) {
op.l = 0;
op.t = 0;
op.r = buffers.w;
op.b = buffers.h;
g.w = buffers.hor_stride ?: buffers.w;
g.h = r_stride ?: buffers.h;
rmat = rmat;
se = (void*)(intptr_t(buffers.heap->base()) + offset);
}
}
}LayerBuffer::getGrallocMole方法的調用到的Gralloc為:
hardware/libhardware/moles/gralloc/gralloc.cpp因為的沒有實現在自己的硬體只能用通用的Gralloc,經過分析發現通用的Gralloc沒有實現
5, mole->perform函數指針,mole->perform為NULL,所以不會對Buffer進行必要的初始化(我覺得應該是一個疏忽,只是不知道是谷歌的疏忽,還是MIPS移植人員的疏忽,最起碼應該能夠讓通用硬體能跑起來)。參考其他的硬體實現一個perform函數指針到通用Gralloc中。
在源文件:
hardware/libhardware/moles/gralloc/mapper.cpp增加如下的函數定義:
int gralloc_perform(struct gralloc_mole_t const* mole,
int operation, ... )
{
int res = -EINVAL;
va_list args;
va_start(args, operation);
switch (operation) {
case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
int fd = va_arg(args, int);
size_t size = va_arg(args, size_t);
size_t offset = va_arg(args, size_t);
void* base = va_arg(args, void*);
native_handle_t** handle = va_arg(args, native_handle_t**);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
private_handle_t::sNumFds, private_handle_t::sNumInts);
hnd->magic = private_handle_t::sMagic;
hnd->fd = fd;
hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
hnd->size = size;
hnd->offset = offset;
hnd->base = intptr_t(base) + offset;
hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
*handle = (native_handle_t *)hnd;
res = 0;
break;
}
}
va_end(args);
return res;
}然後在gralloc.cpp中增加,gralloc_perform的聲明:
extern int gralloc_perform(struct gralloc_mole_t const* mole,
int operation, ... );並修改HAL_MODULE_INFO_SYM的定義,增加perform欄位的定義:
struct private_mole_t HAL_MODULE_INFO_SYM = {
base: {
.......
perform: gralloc_perform,
},
......
}; 重新編譯gralloc模塊,再次用Gallary應用程序通過軟解碼播放視頻,就可以流暢的播放了,軟解碼的效率挺高的,沒有卡的感覺!
『貳』 android 初始化公共資源什麼地方
android系統的初始化過程是從那裡開始呢?它在載入linux基本內核後,就開始運行一個初始化進程,叫做init進程,那麼怎麼樣知道它是載入init進程的呢?難道上天就註定的嗎?呵呵,不是的,原來是從android載入linux內核時,就設置了下面的參數:
Kernel command line: noinitrd root=/dev/nfs console=ttySAC0 init=/init nfsroot=192.168.1.103:/nfsboot ip=192.168.1.20:192.168.1.103:192.168.1.1:255.255.255.0::eth0:on
在這行命令里,就是告訴linux內核初始化完成後開始運行init進程,由於init進程就是放在系統根目錄下面。而這個進程的代碼,就是位於源碼的目錄system/core/init下面,現在就來仔細地分析這個進程到底做了什麼事情,以便理解整個系統運行情況。在分析過程中,會學習很多有用知識,甚至linux編程知識。這么有用,還等什麼呢?現在就開始,找到目錄system/core/init/init.c代碼,先從main函數開始,如下:
#001 int main(int argc, char **argv)
#002 {
#003 int device_fd = -1;
#004 int property_set_fd = -1;
#005 int signal_recv_fd = -1;
#006 int keychord_fd = -1;
#007 int fd_count;
#008 int s[2];
#009 int fd;
#010 struct sigaction act;
#011 char tmp[PROP_VALUE_MAX];
#012 struct pollfd ufds[4];
#013 char *tmpdev;
#014 char* debuggable;
#015
#016
#017 act.sa_handler = sigchld_handler;
#018 act.sa_flags = SA_NOCLDSTOP;
#019 act.sa_mask = 0;
#020 act.sa_restorer = NULL;
#021 sigaction(SIGCHLD, &act, 0);
在上面這段代碼里,調用函數sigaction來設置處理子進程發送回來的關閉信號,其中SIGCHLD是設置子進程信號處理,SA_NOCLDSTOP是表示子進程結束時不要向父進程發送SIGCHLD,sigchld_handler是信號SIGCHLD的處理函數。這樣做的作用,就是如果父進程不等待子進程結束,子進程將成為僵屍進程(zombie)從而佔用系統資源。因此需要對SIGCHLD信號做出處理,回收僵屍進程的資源,避免造成不必要的資源浪費。
#022
#023 /* clear the umask */
#024 umask(0);
在上面這段代碼里,調用函數umask來設置屏蔽位為0值。這樣的意思是什麼呢?是告訴系統做了那些工作呢?要了解這個,就得深入查看一下linux函數大全了,因為它的作用就一目瞭然了,它的解釋如下:
linux中的 umask 函數主要用於:在創建新文件或目錄時 屏蔽掉新文件或目錄不應有的訪問允許許可權。文件的訪問允許許可權共有9種,分別是:r w x r w x r w x(它們分別代表:用戶讀 用戶寫 用戶執行 組讀 組寫 組執行 其它讀 其它寫 其它執行)。
『叄』 關於android的錯誤信息
或許困擾很多Android開發者最大的問題莫過於Bug的修改了,調Bug 改Bug,想想都頭疼,以下就是一位對Bug很有經驗的開發者總結出來的有關Android錯誤的解決方法。
1 android java.net.UnknownHostException: Unable to resolve host "...": No address associated 錯誤
在android開發的時候經常會遇到這個錯誤,一般來說,造成這種錯誤的最普遍情況有兩種:
1.android設備網路連接沒打開,例如3G網路和WIFI網路
所以,如果遇到這種錯誤時,請先查看網路是否已正常連接.
2.Manifest文件沒有標明網路訪問許可權
如果確認網路已經正常連接並且還是出這種錯誤的話,那麼請看下你的Manifest文件是否標明應用需要網路訪問許可權,如果沒標明的話,也訪問不了網路,也會造成這種情況的.
//網路訪問許可權
2 Failed to install *.apk on device 'emulator-5554': timeout
錯誤提示:
Failed to install helloworld.apk on device 'emulator-5554': timeout
或者
the user data image is used
原因:
由於模擬器已經開啟而沒有關閉或者非法關閉引起的。
解決方法:
刪除 C:Documents and SettingsAdministrator.androidavd對應版本.avd
下所有以.lock結尾的文件夾。
或者
Failed to install *.apk on device *:
timeout Launch canceled!
還有一種辦法:
在window->preferences->Android->DDMS->ADB connection time out (ms):
將這個值設置的大一些,默認為5000,設置成500000,然後就OK了。
3 This Android SDK requires Andriod Developer Toolkit version 20.0.0 or above
打開Eclipse(Android 開發環境),發現以下報錯:
圖片顯示信息為:Android SDK要求ADT(Android Developer Toolkit)版本在20.0.0或以上版本,檢測到當前版本為18.0.0,請更新最新的ADT。
出現這樣的提示,根本原因是Eclipse啟動時檢測E:Program Filesandroid-sdk-windowstoolslibplugin.prop文件 文件內容為:
begin plugin.prop
plugin.version=20.0.0
# end plugin.prop
這就很容易理解了,需求插件版本為20.0.0,這時候我們只需要改成:
begin plugin.prop
plugin.version=18.0.0
# end plugin.prop
OK了,重新啟動下Eclipse,看看是不是解決了這個問題
4 [Accessibility] Missing contentDescription attribute on image
今天使用了下ADT 16.0 在定義一個ImageVIew的時候 總是提示這個[Accessibility] Missing contentDescription attribute on image警告,雖說可以不理 但總是感覺怪怪的,在網上一搜 發現原來這是ADT 16.0的新特性,在一些沒有文本顯示的控制項里,如imageView和imageButton等,ADT會提示你定義一個android:contentDescription屬性,用來描述這個控制項的作用。英文原文如下,如有翻譯的不對的地方,敬請批評指正。
Resolved this warning by setting attribute android:contentDescription for my ImageView
android:contentDescription="@string/desc"
Android Lint support in ADT 16 throws this warning to ensure that image widgets provide a contentDescription
This defines text that briefly describes content of the view. This property is used primarily for accessibility. Since some views do not have textual representation this attribute can be used for providing such.
Non-textual widgets like ImageViews and ImageButtons should use the contentDescription attribute to specify a textual description of the widget such that screen readers and other accessibility tools can adequately describe the user interface.
5 java.lang.NoClassDefFoundError: com..mapapi.BMapManager解決辦法
『肆』 android如何讀取串口數據
樓主問題解決了沒?我用串口調試助手調試,安卓端能發送數據到pc端接收,但反過來pc端發數據過來安卓無法接收,求大神指導啊
『伍』 android 屏幕顯示 怎麼刷新 framebuffer 詳解
Android屏幕繪制基本與linux相同,都是使用Framebuffer來繪制屏幕,設備為/dev/graphic/fb0.Framebuffer 存儲在內存或者顯存中,比如一個800 ×600的屏幕,每個像素點為16位色,那麼Framebuffer的大小就為(800 × 600 × 16/8) byte
手機的LCD屏幕通過顯存中當前的Framebffer和緩存的framebuffer來繪制屏幕上的每一個像素點.
具體順序為:
1打開framebuffer設備;
2通過ioctl取得fixed screen information;(ioctl(fd,FBIOGET_FSCREENINFO, &finfo))
3通過ioctl取得variable screen information;(ioctl(fd,FBIOGET_VSCREENINFO, &vinfo))
4通過mmap映射設備內存到進程空間;(記得區分內核空間和用戶空間,用戶空間是無法對物理內存直接讀寫的)
5寫framebuffer;
6終止。(記得終止時一定要取消映射,並close掉句柄)
『陸』 android源碼里有哪些比較好的演算法或框架推薦
Android中對於圖形界面以及多媒體的相關操作比較容易實現。而且對於大多數
手機
用戶來說,他們主要也就是根據這些方面的功能來對系統那個進行修改。我們可以通過本文介紹的Android多媒體框架的源碼解讀,來具體分析一下這方面的基本知識。
Android多媒體框架的代碼在以下目錄中:external/opencore/。這個目錄是Android多媒體框架的根目錄,其中包含的子目錄如下所示:
* android:這裡面是一個上層的庫,它基於PVPlayer和PVAuthor的SDK實現了一個為Android使用的Player和Author。
* baselibs:包含數據結構和線程安全等內容的底層庫
* codecs_v2:這是一個內容較多的庫,主要包含編解碼的實現,以及一個OpenMAX的實現
* engines:包含PVPlayer和PVAuthor引擎的實現
* extern_libs_v2:包含了khronos的OpenMAX的頭文件
* fileformats:文件格式的據具體解析(parser)類
* nodes:編解碼和文件解析的各個node類。
* oscl:操作系統兼容庫
* pvmi: 輸入輸出控制的抽象介面
* protocols:主要是與網路相關的RTSP、RTP、HTTP等協議的相關內容
* pvcommon:pvcommon庫文件的Android.mk文件,沒有源文件。
* pvplayer:pvplayer庫文件的Android.mk文件,沒有源文件。
* pvauthor:pvauthor庫文件的Android.mk文件,沒有源文件。
* tools_v2:編譯工具以及一些可注冊的模塊。
Splitter的定義與初始化
以wav的splitter為例,在fileformats目錄下有解析wav文件格式的pvwavfileparser.cpp文件,在nodes目錄下有pvmf_wavffparser_factory.cpp,pvmf_wavffparser_node.h, pvmf_wavffparser_port.h等文件。
我們由底往上看,vwavfileparser.cpp中的PV_Wav_Parser類有InitWavParser(),GetPCMData(),RetrieveFileInfo()等解析wav格式的成員函數,此類應該就是最終的解析類。我們搜索PV_Wav_Parser類被用到的地方可知,在PVMFWAVFFParserNode類中有PV_Wav_Parser的一個指針成員變數。
再搜索可知,PVMFWAVFFParserNode類是通過PVMFWAVFFParserNodeFactory的CreatePVMFWAVFFParserNode()成員函數生成的。而CreatePVMFWAVFFParserNode()函數是在PVPlayerNodeRegistry::PVPlayerNodeRegistry()類構造函數中通過PVPlayerNodeInfo類被注冊到Oscl_Vector<PVPlayerNodeInfo, OsclMemAllocator> 的vector中,在這個構造函數中,AMR,mp3等node也是同樣被注冊的。
由上可知,Android多媒體框架中對splitter的管理也是與ffmpeg等類似,都是在框架的初始化時注冊的,只不過Opencore注冊的是每個splitter的factory函數。
綜述一下splitter的定義與初始化過程:
每個splitter都在fileformats目錄下有個對應的子目錄,其下有各自的解析類。
每個splitter都在nodes目錄下有關對應的子目錄,其下有各自的統一介面的node類和node factory類。
播放引擎PVPlayerEngine類中有PVPlayerNodeRegistry iPlayerNodeRegistry成員變數。
在PVPlayerNodeRegistry的構造函數中,將 AMR, AAC, MP3等splitter的輸入與輸出類型標示和node factory類中的create node與release delete介面通過PVPlayerNodeInfo類push到Oscl_Vector<PVPlayerNodeInfo, OsclMemAllocator> iType成員變數中。
當前Splitter的匹配過程
PVMFStatus PVPlayerNodeRegistry::QueryRegistry(PVMFFormatType& aInputType, PVMFFormatType& aOutputType, Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids)函數的功能是根據輸入類型和輸出類型,在已注冊的node vector中尋找是否有匹配的node,有的話傳回其唯一識別標識PVUuid。
從QueryRegistry這個函數至底向上搜索可得到,在android中splitter的匹配過程如下:
android_media_MediaPlayer.cpp之中定義了一個JNINativeMethod(JAVA本地調用方法)類型的數組gMethods,供java代碼中調用MultiPlayer類的setDataSource成員函數時找到對應的c++函數
1.{"setDataSource", "(Ljava/lang/String;)V", (void *)
android_media_MediaPlayer_setDataSource},
2.static void android_media_MediaPlayer_setDataSource
(JNIEnv *env, jobject thiz, jstring path)
此函數中先得到當前的MediaPlayer實例,然後調用其setDataSource函數,傳入路徑
3.status_t MediaPlayer::setDataSource(const char *url)
此函數通過調getMediaPlayerService()先得到當前的MediaPlayerService, const sp<IMediaPlayerService>& service(getMediaPlayerService());
然後新建一個IMediaPlayer變數, sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length));
在sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)中
調status_t MediaPlayerService::Client::setDataSource(const char *url)函數,Client是MediaPlayerService的一個內部類。
在MediaPlayerService::Client::setDataSource中,調sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
生成一個繼承自MediaPlayerBase的PVPlayer實例。
『柒』 android中如何確認使用的是什麼平台簽名
一、判斷Apk是否簽名 用命令:jarsigner -verify -verbose -certs <apk文件> 1、如果有Android Debug字樣就是debug 2、如果已經簽名: [證書的有效期為13-8-31 下午2:31至41-1-16 下午2:31] 二、判斷Apk簽名是否一致 jdk 需要安裝;想查demo.apk所使用的簽名的fingerprint,可以這樣做: 1、查找apk里的rsa文件 Windows 平台: > jar tf demo .apk findstr RSA Linux 平台: $ jar tf demo .apk grep RSA META-INF/CERT.RSA 2、 從apk中解壓rsa文件 jar xf demo .apk META-INF/CERT.RSA 3、獲取簽名的fingerprints keytool -printcert -file META-INF/CERT.RSA 證書指紋: MD5: 5A:5A:96:63:8E:EF:FC:66:9E:BC:1C:2A:A9:1E:E5:95 SHA1: 44:BD:33:2D:C5:21:AE:78:D5:04:92:1A:39:FD:AC:01:E2:32:3C:AB SHA256: 2F:C0:A3:8C:0D:42:84:70:48:78:44:A4:2E:64:5B:50:B3:B3:1E:33:94:62:A3:9F:2F:10:DD:EF:D7:CF:02:0B 簽名演算法名稱: SHA1withRSA 版本: 3 兩個apk是否同簽名,比較簽名的MD5碼或SHA1碼 ,一樣就是相同的,反之,不是。
『捌』 Android怎麼生成設備節點
Android如何生成設備節點
在Android中,由於沒有mdev和udev,所以它沒有辦法動態的生成設備節點,那麼它是如何做的呢?
我們可以在system/core/init/下的init.c和devices.c中找到答案:
init.c中
int main(int argc, char **argv)
{
...
/* Get the basic filesystem setup we need put
* together in the initramdisk on / and then we'll
* let the rc file figure out the rest.
*/
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
for(;;) {
...
if (ufds[0].revents == POLLIN)
handle_device_fd(device_fd);
if (ufds[1].revents == POLLIN)
handle_property_set_fd(property_set_fd);
if (ufds[3].revents == POLLIN)
handle_keychord(keychord_fd);
}
return 0;
}
我們再來看看handle_device_fd(),該函數定義在devices.c中
void handle_device_fd(int fd)
{
...
handle_device_event(&uevent);
handle_firmware_event(&uevent);
}
}
而handle_device_event定義如下:
static void handle_device_event(struct uevent *uevent)
{
...
if(!strcmp(uevent->action, "add")) {
make_device(devpath, block, uevent->major, uevent->minor);
return;
}
...
}
make_device定義如下:
static void make_device(const char *path, int block, int major, int minor)
{
...
mode = get_device_perm(path, &uid, &gid) | (block S_IFBLK : S_IFCHR);
dev = (major $amp; ...
setegid(gid);
mknod(path, mode, dev);
chown(path, uid, -1);
setegid(AID_ROOT);
}
我們看看get_device_perm如下實現:
static mode_t get_device_perm(const char *path, unsigned *uid, unsigned *gid)
{
mode_t perm;
if (get_device_perm_inner(qemu_perms, path, uid, gid, &perm) == 0) {
return perm;
} else if (get_device_perm_inner(devperms, path, uid, gid, &perm) == 0) {
return perm;
} else {
struct listnode *node;
struct perm_node *perm_node;
struct perms_ *dp;
/* Check partners list. */
list_for_each(node, &devperms_partners) {
perm_node = node_to_item(node, struct perm_node, plist);
dp = &perm_node->dp;
if (dp->prefix) {
if (strncmp(path, dp->name, strlen(dp->name)))
continue;
} else {
if (strcmp(path, dp->name))
continue;
}
/* Found perm in partner list. */
*uid = dp->uid;
*gid = dp->gid;
return dp->perm;
}
/* Default if nothing found. */
*uid = 0;
*gid = 0;
return 0600;
}
}
我們最後可以看到在devperms中定義了要生成的設備節點:
static struct perms_ devperms[] = {
{ "/dev/null", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/zero", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/full", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/ptmx", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/tty", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/random", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/urandom", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/ashmem", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/binder", 0666, AID_ROOT, AID_ROOT, 0 },
/* logger should be world writable (for logging) but not readable */
{ "/dev/log/", 0662, AID_ROOT, AID_LOG, 1 },
/* the msm hw3d client device node is world writable/readable. */
{ "/dev/msm_hw3dc", 0666, AID_ROOT, AID_ROOT, 0 },
/* gpu driver for adreno200 is globally accessible */
{ "/dev/kgsl", 0666, AID_ROOT, AID_ROOT, 0 },
/* these should not be world writable */
{ "/dev/diag", 0660, AID_RADIO, AID_RADIO, 0 },
{ "/dev/diag_arm9", 0660, AID_RADIO, AID_RADIO, 0 },
{ "/dev/android_adb", 0660, AID_ADB, AID_ADB, 0 },
{ "/dev/android_adb_enable", 0660, AID_ADB, AID_ADB, 0 },
{ "/dev/ttyMSM0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
{ "/dev/ttyHS0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
{ "/dev/uinput", 0660, AID_SYSTEM, AID_BLUETOOTH, 0 },
{ "/dev/alarm", 0664, AID_SYSTEM, AID_RADIO, 0 },
{ "/dev/tty0", 0660, AID_ROOT, AID_SYSTEM, 0 },
{ "/dev/graphics/", 0660, AID_ROOT, AID_GRAPHICS, 1 },
{ "/dev/msm_hw3dm", 0660, AID_SYSTEM, AID_GRAPHICS, 0 },
{ "/dev/input/", 0660, AID_ROOT, AID_INPUT, 1 },
{ "/dev/eac", 0660, AID_ROOT, AID_AUDIO, 0 },
{ "/dev/cam", 0660, AID_ROOT, AID_CAMERA, 0 },
{ "/dev/pmem", 0660, AID_SYSTEM, AID_GRAPHICS, 0 },
{ "/dev/pmem_adsp", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/pmem_camera", 0660, AID_SYSTEM, AID_CAMERA, 1 },
{ "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 },
{ "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/snd/", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 },
{ "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 },
{ "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/akm8973_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/akm8973_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/bma150", 0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/cm3602", 0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 },
{ "/dev/lightsensor", 0640, AID_SYSTEM, AID_SYSTEM, 0 },
{ "/dev/msm_pcm_out", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_pcm_in", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_snd", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/audience_a1026", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/tpa2018d1", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_audpre", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/msm_audio_ctl", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/htc-acoustic", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/vdec", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/q6venc", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/snd/dsp", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/snd/dsp1", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/snd/mixer", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qemu_trace", 0666, AID_SYSTEM, AID_SYSTEM, 0 },
{ "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 },
/* CDMA radio interface MUX */
{ "/dev/ts0710mux", 0640, AID_RADIO, AID_RADIO, 1 },
{ "/dev/ppp", 0660, AID_RADIO, AID_VPN, 0 },
{ "/dev/tun", 0640, AID_VPN, AID_VPN, 0 },
{ NULL, 0, 0, 0, 0 },
};
『玖』 如何讓Android系統或Android應用執行shell腳本
一、Android應用啟動服務執行腳本
1 如何寫服務和腳本
在android源碼根目錄下有/device/tegatech/tegav2/init.rc文件相信大家對這個文件都不陌生(如果不明白就仔細研讀下android啟動流程)。如果在該腳本文件中添加諸如以下服務:
service usblp_test /data/setip/init.usblpmod.sh
oneshot
disabled
註解:每個設備下都會有自己對應的init.rc,init.設備名.rc腳本文件。oneshot disabled向我們說明了在系統啟動的時候這個服務是不會自動啟動的。並且該服務的目的是執行/data/setip/init.usblpmod.sh腳本。腳本的內容你可以隨便寫,只要符合shell語法就可以了,比如腳本可以是簡單的設置eth0:
# ! /system/bin/sh //腳本的開頭必須這樣寫。
Ifconfig eth0 172.16.100.206 netmask 255.255.0.0 up//設置ip的命令
2、如何在應用中啟動服務
1)首先了解下在服務啟動的流程
1. 在你的應用中讓init.rc中添加的服務啟動起來。
首先了解下在服務啟動的流程:
在設備目錄下的init.c(切記並不是system/core/init/init.rc)
Main函數的for(;;)循環中有一個handle_property_set_fd(),函數:
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();
}
}
這個函數的實現也在system/core/init目錄下,該函數中的check_control_perms(msg.value, cr.uid, cr.gid)函數就是檢查該uid是否有許可權啟動服務(msg.value就是你服務的名字),如果應用為root或system用戶則直接返回1.之後就是調用handle_control_message((char*) msg.name + 4, (char*) msg.value),該函數的參數就是去掉1.ctl.後的start和2.你服務的名字。這個函數的詳細內容:
void handle_control_message(const char *msg, const char *arg)
{
if (!strcmp(msg,"start")) {
msg_start(arg);
} else if (!strcmp(msg,"stop")) {
msg_stop(arg);
} else if (!strcmp(msg,"restart")) {
msg_stop(arg);
msg_start(arg);
} else {
ERROR("unknown control msg '%s'\n", msg);
}
}
匹配start後調用msg_start.服務就這樣起來了,我們的解決方案就是在檢查許可權的地方「下點功夫」,因為我們不確定uid,所以就讓check_control_perms這個函數不要檢查我們的uid,直接檢查我們服務的名字,看看這個函數:
static int check_control_perms(const char *name, unsigned int uid, unsigned int gid) {
int i;
if (uid == AID_SYSTEM || uid == AID_ROOT)
return 1;
/* Search the ACL */
for (i = 0; control_perms[i].service; i++) {
if (strcmp(control_perms[i].service, name) == 0) {
if ((uid && control_perms[i].uid == uid) ||
(gid && control_perms[i].gid == gid)) {
return 1;
}
}
}
return 0;
}
這個函數裡面是必須要檢查uid的,我們只要在for循環上寫上。
if(strcmp(「usblp_test」,name)==0) //usblp_test就是我們服務的名字。
return 1;
這樣做不會破壞android原本的結構,不會有什麼副作用。
init.c和init.rc都改好了,現在就可以編譯源碼了,編譯好了裝到機子開發板上就可以了。
『拾』 android匿名共享內存兩個進程間必須知道文件描述符嗎
在Android 匿名共享內存驅動源碼分析中詳細分析了匿名共享內存在Linux內核空間的實現,雖然內核空間實現了匿名共享內存,但仍然需要在用戶空間為用戶使用匿名共享內存提供訪問介面。Android系統在用戶空間,C++應用程序框架層,Java層分別提供了訪問介面
本文首先介紹匿名共享內存在用戶空間提供的C語言介面,在後續文章中在介紹Android匿名共享內存的C++及Java介面,從而全面理解並掌握Android匿名共享內存的使用。
1)匿名共享內存的創建
system\core\libcutils\ashmem-dev.c
Java代碼 收藏代碼
int ashmem_create_region(const char *name, size_t size)
{
int fd, ret;
//打開"/dev/ashmem"設備文件
fd = open(ASHMEM_DEVICE, O_RDWR);
if (fd < 0)
return fd;
//根據Java空間傳過來的名稱修改設備文件名
if (name) {
char buf[ASHMEM_NAME_LEN];
strlcpy(buf, name, sizeof(buf));
//進入匿名共享內存驅動修改匿名共享內存名稱
ret = ioctl(fd, ASHMEM_SET_NAME, buf);
if (ret < 0)
goto error;
}
////進入匿名共享內存驅動修改匿名共享內存大小
ret = ioctl(fd, ASHMEM_SET_SIZE, size);
if (ret < 0)
goto error;
return fd;
error:
close(fd);
return ret;
}
ASHMEM_DEVICE的宏定義如下:
Java代碼 收藏代碼
#define ASHMEM_DEVICE "/dev/ashmem"
函數ashmem_create_region首先通過open函數進入匿名共享內存驅動打開/dev/ashmem設備文件,打開過程在Android 匿名共享內存驅動源碼分析中已經詳細分析了,就是在匿名共享內存初始化過程創建的slab緩沖區ashmem_area_cachep中創建並初始化一個ashmem_area結構體了,接著通過IO命令來修改該ashmem_area結構體的成員name和size,具體設置過程請查看Android 匿名共享內存驅動源碼分析。匿名共享內存的創建過程可以歸納為以下三個步驟:
1.打開/dev/ashmem設備文件;
2. 修改匿名共享內存名稱
3. 修改匿名共享內存大小
2)設置匿名共享內存屬性
通過Ioctl命令控制系統調用進入內核空間的匿名共享內存驅動來設置匿名共享內存塊的屬性值,比如設置匿名共享內存塊的鎖定與解鎖,設置匿名共享內存塊的大小,名稱,保護位等屬性信息。Android對匿名共享內存的這些屬性訪問也提供了相應的C語言介面:
1. 設置匿名共享內存的保護位
Java代碼 收藏代碼
int ashmem_set_prot_region(int fd, int prot)
{
return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
}
2.鎖定匿名共享內存塊
Java代碼 收藏代碼
int ashmem_pin_region(int fd, size_t offset, size_t len)
{
struct ashmem_pin pin = { offset, len };
return ioctl(fd, ASHMEM_PIN, &pin);
}
3.解鎖指定匿名共享內存塊
Java代碼 收藏代碼
int ashmem_unpin_region(int fd, size_t offset, size_t len)
{
struct ashmem_pin pin = { offset, len };
return ioctl(fd, ASHMEM_UNPIN, &pin);
}
4.獲取創建的匿名共享內存大小
Java代碼 收藏代碼
int ashmem_get_size_region(int fd)
{
return ioctl(fd, ASHMEM_GET_SIZE, NULL);
}
無論是匿名共享內存的屬性設置還是獲取,都是直接使用ioctl系統調用進入匿名共享內存驅動中實現的,關於匿名共享內存驅動是如何實現這些功能的,在Android 匿名共享內存驅動源碼分析中有詳細的介紹,這里就不重復介紹了。這里我們知道Android提供的匿名共享內存C語言介面比較簡單。了解了匿名共享內存的C語言介面之後也為以後學習匿名共享內存的C++介面提供基礎。