顯示具有 Android 標籤的文章。 顯示所有文章
顯示具有 Android 標籤的文章。 顯示所有文章

2018年9月3日 星期一

mkfs.ubifs: Fix build with gcc 5.1


Android開發中,

遇到以下兩個問題:

error: redefinition of ‘hashtable_iterator_key’
error: redefinition of ‘hashtable_iterator_value’

這是由於gcc 5.1 對於編譯C文件已由gnu89改為gnu11,

這改變了對extern inline的定義,





在mkfs.ubifs中,

這導致了hashtable_iterator_key 與 hashtable_iterator_value 產生多重定義,(redefine),

最快速的解決方法是以extern inline 取代 static inline.


也就是在hashtable_itr.c 與 hashtable_itr.h 中
改為下列所示:


diff --git a/mkfs.ubifs/hashtable/hashtable_itr.c b/mkfs.ubifs/hashtable/hashtable_itr.c
index 24f4dde..d102453 100644
--- a/mkfs.ubifs/hashtable/hashtable_itr.c
+++ b/mkfs.ubifs/hashtable/hashtable_itr.c
@@ -35,18 +35,6 @@ hashtable_iterator(struct hashtable *h)
 }
 
 /*****************************************************************************/
-/* key      - return the key of the (key,value) pair at the current position */
-/* value    - return the value of the (key,value) pair at the current position */
-
-void *
-hashtable_iterator_key(struct hashtable_itr *i)
-{ return i->e->k; }
-
-void *
-hashtable_iterator_value(struct hashtable_itr *i)
-{ return i->e->v; }
-
-/*****************************************************************************/
 /* advance - advance the iterator to the next element
  *           returns zero if advanced to end of table */
 
diff --git a/mkfs.ubifs/hashtable/hashtable_itr.h b/mkfs.ubifs/hashtable/hashtable_itr.h
index 87a97eb..5c94a04 100644
--- a/mkfs.ubifs/hashtable/hashtable_itr.h
+++ b/mkfs.ubifs/hashtable/hashtable_itr.h
@@ -28,7 +28,7 @@ hashtable_iterator(struct hashtable *h);
 /* hashtable_iterator_key
  * - return the value of the (key,value) pair at the current position */
 
-extern inline void *
+static inline void *
 hashtable_iterator_key(struct hashtable_itr *i)
 {
     return i->e->k;
@@ -37,7 +37,7 @@ hashtable_iterator_key(struct hashtable_itr *i)
 /*****************************************************************************/
 /* value - return the value of the (key,value) pair at the current position */
 
-extern inline void *
+static inline void *
 hashtable_iterator_value(struct hashtable_itr *i)
 {
     return i->e->v;
}





2018年9月1日 星期六

Adnroid 專案的文件結構

在Android   左側的窗格中,

各個文件以樹狀結構展現,

從下圖可看到最上層兩者為

app   :    包含各種APP所需的檔案

Gradle   Scripts :   包含與build APP有關的各個Gradle檔案


開發者編輯的檔案都放在app層中,

manifests :   所有的App設定檔以XML方式存在

java :   用於存放程式檔案

res :   存放程式會用到的各類資源檔案 ,
                例如 :  圖形檔, 選單,  設定值

 


從下圖可看出

針對不同螢幕提供了不同的版本,

分別為 mdpi   ,   hdpi,   xdpi ,   xxdpi,   xxxdpi五種版本,

Android 會根據目前螢幕選擇適當的圖檔使用



除了以   Android studio預設的   Android模式檢視檔案之外,

也可以選擇以   project   模式檢視專案結構,

此方式則是以資料實際儲存的結構來顯示專案內容

如下圖,

可看到這個樹狀結構就呈現了專案在硬碟中實際的存放情形





2017年7月28日 星期五

從驅動程式原始碼認識USB OTG

USB OTG,

是USB-On-The-Go 的縮寫,

為USB 規格中的一個延伸,

擁有USB OTG功能的系統,(例如: 手機)

可以根據ID pin狀態的不同,

自行切換為host端或者client端,

已達到不同的目的使用.

例如:

a. 以手機接電腦,

手機會切換為client端,

這時可以把手機當隨身碟使用

b. 以手機接隨身碟,

手機會轉為host端,

讓手機能夠不透過電腦直接存取隨身碟裡面資料,





Google Git 上面可找到otg.c

可以讓我們

從驅動程式原始碼認識USB OTG


/**
* ci_otg_work - perform otg (vbus/id) event handle
* @work: work struct
*/
static void ci_otg_work(struct work_struct *work)
{
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
if (ci_otg_is_fsm_mode(ci) && !ci_otg_fsm_work(ci)) {
enable_irq(ci->irq);
return;
}
if (ci->id_event) {
ci->id_event = false;
ci_handle_id_switch(ci);
} else if (ci->b_sess_valid_event) {
ci->b_sess_valid_event = false;
ci_handle_vbus_change(ci);
} else
dev_err(ci->dev, "unexpected event occurs at %s\n", __func__);
enable_irq(ci->irq);
}
當ID pin產生變化,

系統偵測到事件觸發,

執行ci_handle_id_switch(ci);

#define CI_VBUS_STABLE_TIMEOUT_MS 5000
static void ci_handle_id_switch(struct ci_hdrc *ci)
{
enum ci_role role = ci_otg_role(ci);
if (role != ci->role) {
dev_dbg(ci->dev, "switching from %s to %s\n",
ci_role(ci)->name, ci->roles[role]->name);
ci_role_stop(ci);
/* wait vbus lower than OTGSC_BSV */
hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
CI_VBUS_STABLE_TIMEOUT_MS);
ci_role_start(ci, role);
}
}
ci_otg_role(ci);

根據ID pin 腳位的不同

會選擇USB功能為:

CI_ROLE_GADGET (client)

CI_ROLE_HOST (host)

/**
* ci_otg_role - pick role based on ID pin state
* @ci: the controller
*/
enum ci_role ci_otg_role(struct ci_hdrc *ci)
{
enum ci_role role = hw_read_otgsc(ci, OTGSC_ID)
? CI_ROLE_GADGET
: CI_ROLE_HOST;
return role;
}

接著driver 會將此變化傳到應用層,

如果是Android 系統,

USB功能的變化就會傳給Android 做相對應的處理



2017年7月20日 星期四

android開發基礎(五)- avc: denied解決範例


之前提到過 SELINUX for Android,

Android 5 之後引入了selinux機制,

在遇到權限問題時候,

系統都會有log 描述問題,

基本上就是缺什麼補什麼,

直到沒有avc denied為止,

當然,

系統預設的never allow建議不要修改,

底下列了幾個

avc: denied解決範例

1.
type=1400 audit(4.840:7): avc: denied { getattr } for pid=204 comm="cameraserver" path="/vendor" dev="rootfs" ino=7096 scontext=u:r:cameraserver:s0 tcontext=u:object_r:rootfs:s0 tclass=lnk_file permissive=0

重點在於紅字,

這個範例簡單的講,

cameraserver 對 rootfs  的 lnk_file 缺少了 { getattr } 的權限 ,

只需要在cameraserver.te中

新增


allow cameraserver rootfs:lnk_file { getattr };


即可

2.
type=1400 audit(28.360:14): avc: denied { execute } for pid=704 comm="sh" name="toybox" dev="mmcblk3p5" ino=368 scontext=u:r:demo:s0 tcontext=u:object_r:toolbox_exec:s0 tclass=file permissive=0

#type=1400 audit(28.130:14): avc: denied { read open } for pid=718 comm="sh" path="/system/bin/toybox" dev="mmcblk3p5" ino=368 scontext=u:r:demo:s0 tcontext=u:object_r:toolbox_exec:s0 tclass=file permissive=0

在這個範例中

demo 對 toolbox_exec  的 file 缺少了 { execute read open } 的權限 ,
(多個權限設定,

只需要以大括號框住 ,

空格隔開即可)

找到demo.te

加入


allow demo toolbox_exec:file { execute read open  };

權限問題不會一次全部顯示出來,

出現一個加一個直到沒有為止.





2017年7月13日 星期四

android 編譯錯誤 : Try increasing heap size with java option '-Xmx'

在開發過程中,

有時候會遇到

android 編譯錯誤 : Try increasing heap size with java option '-Xmx'

這是android使用新的編譯器Jack 常見的問題,

JACK( 全名 JAVA Android Compiler Kit)

在此網址 也有提到

當遇到這個問題的時候,

使需要手動停止jack server,

1.
進入  BSP/prebuilts/sdk/tools 資料夾
執行:

jack-admin stop-server

2.
利用文字編輯器打開 jack-admin

找到

JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -cp $LAUNCHER_JAR $LAUNCHER_NAME"

加上-Xmx4g , 也就是改為

 JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -Xmx4g -cp $LAUNCHER_JAR $LAUNCHER_NAME"

3. 再次執行android 編譯命令即可


如果出現同樣問題,

或者遇到系統在編譯過程中完全無回應,

就必須執行
1.
進入  BSP/prebuilts/sdk/tools 資料夾

執行:

jack-admin stop-server

2.

sudo gedit ~/.jack-server/config.properties

(或者:  sudo gedit ~/.jack )

3.
找到

SERVER_NB_COMPILE=N

N:預設為4

將這個值降低

4.
重新執行android編譯指令











2017年1月7日 星期六

app上傳google play

日前曾經介紹 部落格免費轉換app ,
若有試驗過應該手上有專屬的apk檔案,
此apk經過sign之後,可直接上傳Google Play .

1.新增應用程式之後,會出現對話框要輸入應用程式標題,接著會前往輸入應用程式資料

 2.上傳sign過的apk之後,畫面會如下方會有綠色打勾,表示此項設定已完成
 3.必須擷取應用程式實際的畫面提供給使用者參考,有打*號的圖片欄位是一定要上傳的,不然不會顯示已完成的綠色打勾符號
 4.每個應用程式都應該要有適合的分級,適用於各個年齡層
 5.接著設定收費標準,在此範例使用免費(做公益的,所以請大家多多支持)
6.底下是手機收到新文章發布的通知訊息
 7.程式執行之後可以看到部落格中的文章


2016年11月27日 星期日

[android] 透過android studio sign apk

為了在google 商店上架apk, 必須使用簽署過的apk,
在Android Studio 上面有提到過如何build出簽署過的apk,
但似乎沒有提到如何簽署現有的apk.
方法很簡單 ,只有兩個步驟
1. 在windows執行cmd進入控制台模式,執行以下命令
keytool -genkey -alias guangyawli -keyalg RSA -validity 40000 -keystore mykey.keystore
這支程式通常放在Android Studio安裝目錄底下的 \jre\bin,
如果還是找不到,就必須要安裝JDK了.
執行將依序詢問以下問題:
================================================================
輸入金鑰儲存庫密碼:
您的名字與姓氏為何?
  [Unknown]:  guangyaw li
您的組織單位名稱為何?
  [Unknown]:  personal
您的組織名稱為何?
  [Unknown]:  personal
您所在的城市或地區名稱為何?
  [Unknown]:  Taiwan
您所在的州及省份名稱為何?
  [Unknown]:  Taiwan
此單位的兩個字母國別代碼為何?
  [Unknown]:  TW
CN=guangyaw li, OU=personal, O=personal, L=Taiwan, ST=Taiwan, C=TW 正確嗎?
  [否]:  y

輸入 的金鑰密碼
        (RETURN 如果和金鑰儲存庫密碼相同):
===============================================================
填寫完之後就會產生個人的簽署用的key

參數說明:
-genkey: 產生key
-alias: 別名,在範例中使用guangyawli
-keyalg RSA: 生成文件使用RSA演算法
-validity 40000: 表示有效期限4000天
-keystore : 後面接著就是檔案名稱,沒有指定路徑,就是產生在執行目錄中

2. 接著執行
jarsigner -verbose -keystore mykey.keystore -signedjar sign_target.apk target.apk guangyawli
-verbose: 簽署過程的資訊都會顯示在控制台視窗中
-keystore: 指定使用的簽署文件
-signedjar: 在此範例中就是簽署target.apk後產生sign_target.apk,
guangyawli: 最後面填寫的是此文件的別名,對應到產生key時-alias參數

經過簽署之後的apk就能夠正式在google商店上架了





2016年7月6日 星期三

Android開發環境設定:變更JAVA 版本

在Android開發環境設定中,有時會遇到如下問題:

============================================
Checking build tools versions...

************************************************************
You are attempting to build with the incorrect version
of javac.

Your version is: javac 1.7.0_101.
The correct version is: 1.6.

Please follow the machine setup instructions at
https://source.android.com/source/download.html
************************************************************

build/core/main.mk:184: *** stop. Stop.

這問題是因為JAVA 版本與BSP不相容, 透過

Android開發環境設定:變更JAVA 版本


安裝相對應的版本即可.


在Linux可透過command查詢現在的版本:

$ java -version

java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)

$ javac -version

javac 1.7.0_101


為了編譯Android ,就必須變更JAVA版號:(當然執行變更之前,要安裝不同版本的JAVA)

1.變更javac:

$ sudo update-alternatives --config javac

替代項目 javac(提供 /usr/bin/javac)有 3 個選擇。



選項 路徑 優先權 狀態

------------------------------------------------------------
* 0 /usr/lib/jvm/java-7-openjdk-amd64/bin/javac 1071 自動模式

1 /usr/lib/jvm/java-7-openjdk-amd64/bin/javac 1071 手動模式

2 /usr/lib/jvm/java-7-oracle/bin/javac 301 手動模式

3 /usr/local/jdk1.6.0_45/bin/javac 300 手動模式

按 [enter] 保留目前選項 [*],或輸入選項編號:3

update-alternatives: 以 /usr/local/jdk1.6.0_45/bin/javac 提供 手動模式 中的 /usr/bin/javac (javac)

2.變更java:

$ sudo update-alternatives --config java

替代項目 java(提供 /usr/bin/java)有 3 個選擇。

選項 路徑 優先權 狀態

------------------------------------------------------------
0 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1071 自動模式

1 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1071 手動模式

2 /usr/lib/jvm/java-7-oracle/jre/bin/java 301 手動模式

* 3 /usr/local/jdk1.6.0_45/bin/java 300 手動模式

按 [enter] 保留目前選項 [*],或輸入選項編號:3

3. 變更javadoc

$ sudo update-alternatives --config javadoc

替代項目 javadoc(提供 /usr/bin/javadoc)有 3 個選擇。

選項 路徑 優先權 狀態
------------------------------------------------------------
0 /usr/lib/jvm/java-7-openjdk-amd64/bin/javadoc 1071 自動模式

1 /usr/lib/jvm/java-7-openjdk-amd64/bin/javadoc 1071 手動模式

2 /usr/lib/jvm/java-7-oracle/bin/javadoc 301 手動模式

* 3 /usr/local/jdk1.6.0_45/bin/javadoc 300 手動模式

按 [enter] 保留目前選項 [*],或輸入選項編號:3
-----------------------------------------------------------------

在這個範例需要java jdk6所以必須選擇: 3

更改完就能正常編譯Android了

2015年5月27日 星期三

[Android]Linux kernel 開發基礎 (六)- Interrupt

系統運作,有時要停下處理event,
這時候,可利用interrupt中斷去處理event之後再繼續運作,
尤其是輸入裝置通知有資料要送給系統時候,interrupt是一個好方法.

1.設定interrupt pin,以及觸發條件(
IRQF_TRIGGER_RISING ,    上升緣觸發
IRQF_TRIGGER_FALLING ,下降緣觸發
IRQF_TRIGGER_HIGH,         高準位觸發
IRQF_TRIGGER_LOW           低準位觸發)

  hello_irq_gpio = gpio_to_irq(/*put the interrupt pin here .*/);
    ret = request_threaded_irq(hello_irq_gpio, NULL, hello_interrupt,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"hello", hello_data);
if (ret < 0) {
printk("[hello.c]Failed to register interrupt\n");
}

2.設定觸發條件之後的處理:
static irqreturn_t hello_interrupt(int irq, void *dev_id)
{
printk("interrupt enter and define the behavior here \n");

return IRQ_HANDLED;
}


範例程式下載

2015年5月23日 星期六

[Android]Linux kernel 開發基礎 (五)- driver attribute

透過driver attribute的讀寫,

可以讓使用者用讀寫檔案方式,直接跟driver溝通,

這在debug與其他driver之間互動提供了簡便的方法,

要在driver定義attribute只需要兩個步驟

1. 定義attribute本身:


static ssize_t hello_show(struct device *dev,struct device_attribute *attr, char *buf)
{


printk("hello_show \n");

return 0;
}
static ssize_t hello_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t size)
{
printk("hello_store \n");
return -1;
}

static struct device_attribute hello_adv_setting = {
.attr = {
.name = "hello_adv",
.mode = 0664,
},
.show = hello_show,
.store = hello_store,
};

static struct device_attribute *hello_adv_group[] = {
&hello_adv_setting,
// &hello_adv_setting2,

};

2. 在driver建立attribute檔案

for (i = 0; i < ARRAY_SIZE(hello_adv_group); i++) { ret = device_create_file(&pdev->dev,hello_adv_group[i]);
if (ret) {
dev_err(&pdev->dev, "failed: sysfs file %s\n",hello_adv_group[i]->attr.name);
}
}

如果還不是很明白,

可以下載範例程式來觀看

2015年4月22日 星期三

Android studio - morphing

在Android studio 中如果要change layout的類型,要換成tablelayout,relativelayout....等,
可以到Component tree透過morphing來達成.
但是很可惜的預設建立的project找不到這個選項,似乎是官方IDE的一個bug.
如果堅持要在圖形化界面中使用這個功能,可能就必須先到"TEXT"模式下更改.
在"TEXT"模式改過一次之後,該選項就可以使用了

2015年4月20日 星期一

[Android]Linux kernel 開發基礎 (四)- 新增I2C device 範例

新增platform device 範例 是直接向platform bus註冊一個裝置
其他較常見的裝置要註冊也是大同小異,
makefile 與 kconfig 寫法是相同的,差異在於在哪個Bus下註冊裝置
底下為新增I2C device 範例:
1. makefile
根據kconfig的設定,定義要build的檔案
例如範例中的
obj-$(CONFIG_HELLO_DRIVER) += hello.o
這裡定義了:當CONFIG_HELLO_DRIVER為y
就將hello這個檔案build進kernel

2. kconfig
定義了driver 簡易描述以及預設值,與makefile一起,為kernel建立tree管理之用,
在make menuconfig時,可將該driver相關訊息顯示在視窗界面
config HELLO_DRIVER
    default y
    tristate "Hello Driver"
help
  Say Y here if you want to enable hello driver.
這裡定義了一個新的driver HELLO_DRIVER,,
預設值為y

3.如果要向I2C bus註冊新裝置,必須先找到I2C bus initial 的檔案(根據每個BSP設計不同,這個位置與名稱也不同,通常位於kernel/arch/arm/"cpu_name"),透過i2c_register_board_info來註冊新裝置,
(參考自: https://www.kernel.org/doc/htmldocs/device-drivers/API-i2c-register-board-info.html)

Name

i2c_register_board_info — statically declare I2C devices

Synopsis

int i2c_register_board_info (int busnum,
struct i2c_board_info const * info,
unsigned len);

Arguments


busnum
identifies the bus to which these devices belong
info
vector of i2c device descriptors
len
how many descriptors in the vector; may be zero to reserve the specified bus number.
例如:
i2c_register_board_info(i2c_bus_num, i2c_devs_define, ARRAY_SIZE(i2c_devs_define));

而i2c_devs_define 必須明確指出i2c device address 與i2c_bus_num才能根據設定將資料送到該裝置 ,定義範例如下:

static struct i2c_board_info i2c_devs_define[] __initdata = {
{
I2C_BOARD_INFO(i2c_device_name, i2c_address >> 1),
.irq = IRQ_EINT(IRQ_num),
},
};

4.最後調用i2c_add_driver(&i2c_driver);即可完成I2C device 新增

static const unsigned short normal_i2c[2] = {i2c_address,I2C_CLIENT_END};
static struct i2c_driver i2c_driver = {
.driver = {
.name = i2c_device_name,
.owner = THIS_MODULE,
},
.class = I2C_CLASS_HWMON,
.address_list = normal_i2c,
.id_table = id,
.probe = probe,
.remove = __exit_p(remove),
.suspend = suspend,
    .resume = resume,

};
i2c_add_driver(&i2c_driver);

Linux kernel 開發基礎 (三)- 新增platform device

新增platform device


並不複雜,

只需要更改三個地方

1. makefile

根據kconfig的設定,

定義要build的檔案

例如範例中的

obj-$(CONFIG_HELLO_DRIVER) += hello.o

這裡定義了:

當CONFIG_HELLO_DRIVER為y

就將hello這個檔案build進kernel



2. kconfig

定義了driver 簡易描述以及預設值,

與makefile一起,

為kernel建立tree管理之用,

在make menuconfig時,

可將該driver相關訊息顯示在視窗界面

config HELLO_DRIVER
    default y
    tristate "Hello Driver"
help
 Say Y here if you want to enable hello driver.

這裡定義了一個新的driver HELLO_DRIVER,,

預設值為y

3. driver本身

static struct platform_driver hello_driver = {
.probe = hello_probe,
.remove = __devexit_p(hello_remove),
.driver = {
.name = "hello",
.owner = THIS_MODULE,
},
.suspend = hello_suspend,
.resume = hello_resume,
};

driver定義著platform device的功能,

如果還是不是很了解,

可以下載範例程式去build 看看