标签归档:MTK

【MT8382/8121】为MTK的工厂测试添加测试项

Published / by sickworm / Leave a Comment

摘要:

本文介绍添加MTK工厂测试项的步骤及调试技巧。

纲要:

1. 描述添加MTK工厂测试项的步骤

2.调试小技巧

1. 描述添加MTK工厂测试项的步骤

以添加红外测试为例:

 

1. mediatek/factory/inc/common.h

enum枚举添加ITEM_IR_TEST到最下面的ITEM_MAX_IDS上面,即倒数第2个;

 

2. mediatek/factory/inc/uistrings_chn.h

添加 #define uistr_ir_test “红外”;

这个字符串用于匹配factory.ini配置文件的测试项,只有两者一致的时候才会添加。注意这个文件是gbk编码。

unistrings.h是选择了英文才会使用,我们现在都使用的是中文,所以会匹配uistring_chn.h

 

3. mediatek/factory/src/factory.c

ftm_test_items[]添加item(ITEM_IR_TEST, uistr_ir_test);(在手动测试和单项测试中显示,必添加)

ftm_auto_test_items[]添加item(ITEM_IR_TEST, uistr_ir_test);(在自动测试中显示,尚不清楚机制,可选)

这两个参数就是步骤1 2添加的项目,名字要一致。

这里一般都会使用宏来控制是否添加,除非是都测的项目,以免运行出错。

 

4. mediatek/factory/src/test/ftm_irtest.c

添加ftm_irtest.c文件。实现ir_test_init(),  ir_test_entry()两个函数。函数名没有要求。具体实现参考ftm_rftest.c。(rftest是通过代码判断是否测试通过的,如果需要手动确认是否通过,参考ftm_otg.c。主要区别在entry函数)

ir_test_init()中需要调用ftm_alloc,这个会注册一个ITEM_IR_TEST相关的结构体。然后调用ftm_register,把ir_test_entry和这个结构体绑定。

ir_test_init()在factory初始化过程中会调用。

ir_test_entry()在项目被点击的时候调用。需要实现一些UI相关的绑定,以及具体的验证方法。通常会启动一个线程如ir_update_thread来测试,entry通过全局变量ir_factory检测测试结果。

 

5. mediatek/factory/src/test/ftm_mods.c

添加extern int ir_test_init();

在ftm_init_funcs[]的倒数第二个(NULL上面)添加ir_test_init。这样在factory启动的时候就会自动调用ir_test_init,从而将ITEM_IR_TEST测试项与ir_test_entry绑定起来。

至此,所有添加项都关联起来了。

 

6.mediatek/factory/Android.mk

将ftm_ir_test.c加进TEST_SRC_FILES中。

同样用宏控制是否添加,这里用到CVTE_IRREMOTE_APP_SUPPORT的宏来控制。

 

7.factory.ini

添加MenuItem=红外;需要和uistr_ir_test 名字一致,否则无法匹配。

这个文件会先去/sdcard目录寻找,再去/etc目录寻找,我们调试的时候直接放进sdcard目录就可以了。

 

8.mediatek/custom/active_1051j/factory/factory.ini

把修改的ini文件放入custom目录下,使用mk文件将其拷贝至/etc目录下。

custom的factory目录会存在factory.ini和factory_chn.ini两个文件。如果是中文,则把factory_chn.ini拷进去,并重命名为factory.ini;英文则直接拷贝。也可以只留一个factory.ini文件,里面是中文。factory程序只会解析名为factory.ini的文件

 

调试小技巧:

1. 烧录eng版本软件,打开USB调试。

2. 重启进入MTK工厂测试。

3. 需要烧录新factory程序的时候,push进/system/bin并chmod 777 /system/bin/factory。

4. 执行ps factory查询当前正在运行的测试程序,kill掉。

5. 在shell中输入factory重新启动MTK工厂测试程序。

6. 再次需要烧录新的factory程序的时候,ctrl+C即可停掉当前的factory程序,然后重新执行步骤3,5。 无需重启。

 

版权所有,转载请注明出处:

http://sickworm.com/?p=30 

Settings点击Location(位置)后右上角的开关button不会消失

Published / by sickworm / Leave a Comment

MT8121/8382平台:

 

前几天又遇到一个源码的bug。在10寸平板上,进入设置界面,点击Location(位置)项,右上角Title处会显示一个开关button,用来开关定位服务。但点完Location项再点其他项的时候,button并不会消失。直到你点到Developer(开发者选项),再点击其他项那个button才会消失。Developer项本身右上角也有一个开关button。

于是很自然地想到,在切换设置项时,Location页面在退出时没有把button去掉。

结果一看果然是。

 

--- a/packages/apps/Settings/src/com/android/settings/location/LocationSettings.java +++ b/packages/apps/Settings/src/com/android/settings/location/LocationSettings.java @@ -100,6 +100,9 @@ public class LocationSettings extends LocationSettingsBase super.onPause(); mValidListener = false; mSwitch.setOnCheckedChangeListener(null); +        getActivity().getActionBar().setCustomView(null);

 

版权所有,转载请注明出处:

http://sickworm.com/?p=19

Launcher3自定义壁纸旋转后拉伸无法恢复

Published / by sickworm / Leave a Comment

MTK8382/8121平台。

 

描述:将自定义图片设置成壁纸后,横屏显示时,旋转为竖屏,图片由于分辨率过小,会拉伸;再旋转为横屏,拉伸不恢复。

这两天正在解这个问题,研究了很久,走了不少弯路,最后发现是Launcher读取SharePreferences时的一个bug。

 

bug是这样产生的:

Launcher3设置完自定义壁纸(系统自带壁纸不会记录)的时候,会在com.android.launcher3.WallpaperCropActivity.xml中记录被设置壁纸的分辨率,并提交分辨率给WallpaperManager(通过suggestWallpaperDimension())。具体函数是:WallpaperCropActivity.java中的updateWallpaperDimensions(),它被WallpaperCropActivity.java的setWallpaper()调用;

Launcher3每次旋转后会重新执行onCreate(),同时会提交当前壁纸的分辨率给WallpaperManager,提交分辨率的函数在Workspace.java中的setWallpaperDimension()中。问题在这里:setWallpaperDimension()无法获取之前updateWallpaperDimensions()修改的SharedPreferences,导致它提交的是默认的壁纸分辨率1920×1080,从而导致低分辨率的壁纸拉伸。

解决此问题的方法是:修改Workspace.java中的setWallpaperDimension()中的getSharedPreferences()的flag,把MODE_PRIVATE改为MODE_MULTI_PROCESS。修改后成功访问。

 

我的问题是:

根据Android Developer的解释:

MODE_PRIVATE:

File creation mode: the default mode, where the created file can only be accessed by the calling application (or all applications sharing the same user ID).

即MODEL_PRIVATE只能被同一个application或者同一个userID的application调用。按这个说法,这两个Activity应该是可以共同访问的。(Workspace.java使用的是Launcher.java的context,两个Activity pid不一样,uid一样)

同时我还看了MODE_MULTI_PROCESS的解释:

MODE_MULTI_PROCESS:

SharedPreference loading flag: when set, the file on disk will be checked for modification even if the shared preferences instance is already loaded in this process. This behavior is sometimes desired in cases where the application has multiple processes, all writing to the same SharedPreferences file. Generally there are better forms of communication between processes, though.

This was the legacy (but undocumented) behavior in and before Gingerbread (Android 2.3) and this flag is implied when targetting such releases. For applications targetting SDK versions greater than Android 2.3, this flag must be explicitly set if desired.

意思是这个flag用于给拥有多个进程的application共同访问同一个SharedPreferences使用的。按照这个说法,似乎又确实应该使用MODEL_MULTI_PROCESS。

 

于是我想找到getSharedPreference实现代码,看看它怎么处理这几个flag。可恶的是,从Activity父类一级一级往上找,都找不到实现的方法,直到找到这篇文章:

http://blog.csdn.net/qinjuning/article/details/7310620

才知道ContextImpl实现了Context的具体方法,进而找到了答案:

ContextImpl类中有getSharedPreferences的实现。里面说明了在MODE_MULTI_PROCESS标志中,getSharedPreferences会进行reload。换言之MODE_PRIVATE不会重新读取SharedPreferences。

这里终于搞懂他的意思:在之前的bug,并不是SharedPreferences获取失败,而是因为没有reload所以没有获取到新写入的分辨率信息。因为之前没有注意到这个问题,所以走了弯路。

不过还有问题:每次Launcher旋转的时候都会重新启动Activity调用onCreate,为什么我getSharePreferences还是旧的呢?继续观察android.app.ContextImpl的getSharedPreferences:

@Override public SharedPreferences getSharedPreferences(String name, int mode) { Log.w("Launcher", "contextImpl: " + this, new RuntimeException("getSp").fillInStackTrace()); SharedPreferencesImpl sp; synchronized (ContextImpl.class) { if (sSharedPrefs == null) { Log.e("Launcher", "all init"); sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>(); } final String packageName = getPackageName(); ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName); if (packagePrefs == null) { Log.e("Launcher", "package init"); packagePrefs = new ArrayMap<String, SharedPreferencesImpl>(); sSharedPrefs.put(packageName, packagePrefs); } // At least one application in the world actually passes in a null // name. This happened to work because when we generated the file name // we would stringify it to "null.xml". Nice.
if (mPackageInfo.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.KITKAT) { if (name == null) { name = "null"; } } sp = packagePrefs.get(name); if (sp == null) { File prefsFile = getSharedPrefsFile(name); sp = new SharedPreferencesImpl(prefsFile, mode); packagePrefs.put(name, sp); Log.e("Launcher", "new sp"); return sp; } Log.e("Launcher", "old sp"); } if ((mode & Context.MODE_MULTI_PROCESS) != 0 || getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) { // If somebody else (some other process) changed the prefs // file behind our back, we reload it. This has been the // historical (if undocumented) behavior.
sp.startReloadIfChangedUnexpectedly(); Log.e("Launcher", "reload"); } return sp; }

里面Log.e(“Launcher”, …);是我自己加的调试信息。首先会判断sSharedPrefs是否有内容,然后从中获取对应package的prefsFile。如果sSharedPrefs找不到,才从xml文件中重新读取。最后加了一个判断,如果设置了MODE_MULTI_PROCESS变量,或者Android 2.2以下的系统,会默认从xml文件中重新reload,以保持最新的SharedPreferences数据。

注意这里的sSharedPrefs变量,它只在getSharedPreferences中有赋值,也就是说SharedPreferences的数据一直跟随着ContextImpl实例走,只从getSharedPreferences()方法中获取数据。也就是说,当旋转屏幕的时候,我们调用getSharedPreferences()获取的数据都是从这个sSharedPrefs变量中取出来的。实际从下面Log信息也可以看到,旋转并不会有”new sp”的Log打印,只有对Launcher3在设置中force stop和clear data的时候才会出现”new sp”。

旋转的Log提示:

09-11 08:47:19.599: E/Launcher(4628): launcher:com.android.launcher3.Launcher@42392ac8 09-11 08:47:19.599: E/Launcher(4628): mBase:android.app.ContextImpl@424c1898 09-11 08:47:19.608: E/Launcher(4628): old sp 09-11 08:47:19.727: E/Launcher(4628): old sp 09-11 08:47:19.731: E/Launcher(4628): reload 09-11 08:47:19.932: E/Launcher(4628): old sp

force stop的提示:

09-11 08:48:29.456: E/Launcher(5271): launcher:com.android.launcher3.Launcher@4238f220 09-11 08:48:29.456: E/Launcher(5271): mBase:android.app.ContextImpl@42391ab8 09-11 08:48:29.489: E/Launcher(5271): all init 09-11 08:48:29.489: E/Launcher(5271): package init 09-11 08:48:29.493: E/Launcher(5271): new sp 09-11 08:48:29.679: E/Launcher(5271): new sp 09-11 08:48:29.766: E/Launcher(5271): old sp 09-11 08:48:29.767: E/Launcher(5271): old sp 09-11 08:48:29.790: E/Launcher(5271): old sp

里面三个连着的old sp,只有第二个是读取分辨率的,其他两个分辨是LauncherAppState的SharedPreferences。因为此时Launcher3代码已经被我修改为MODE_MULTI_PROCESS,所以旋转会打出”reload”信息。

 

也就是说,旋转的时候sSharedPrefs的值是一直保存着的。可是通过Log打印信息,我们发现,每一次的getSharedPreferences()的contextImpl都是不一样的!

这里要注意的是,执行方法的context是Activity的父类ContextThemeWrapper的mBase私有成员执行的,获取mBase可以在getSharedPreferences()中打印this出来,也可以在Activity中进行反射,这里用的是反射方法:

try { Log.e("Launcher", "launcher:" + this); java.lang.reflect.Field f = Activity.class.getSuperclass().getDeclaredField("mBase"); f.setAccessible(true); Context s = (Context) f.get(this); Log.e("Launcher", "mBase:" + s); } catch(Exception e) { e.printStackTrace(); }

contextImpl不一样了,但是sSharedPrefs数据还保存着,且sSharedPrefs不能通过其他方法赋值,只能猜测在旋转的时候通过原型模式把原来的context传进去了。Launcher3的旋转处理,我只找到ACTION_CONFIGURATION_CHANGE这个广播,但是我把里面的代码注释了,依然可以正常工作。估计是更底层的代码控制的。

 

具体代码还没找到,因为还要搬砖。有空再研究吧!

版权所有,转载请注明出处:

http://sickworm.com/?p=17

Launcher3无图标问题

Published / by sickworm / Leave a Comment

 

MTK8382/8121平台。

 

机器(8寸,默认竖屏)第一次烧录完成后,以横放姿势启动,发现Launcher没有图标,而竖屏启动是没有这个问题的。在测试过程中发现,在设置中clear data后也会有这样的问题。因此可以初步判断是database初始化的问题,因为database存储着favorite icon和workspace的数据。

对比database,发现workspaces字段没有写入。查看输出的log,发现最大的不同在于,在step1的初始化过程中,出现了

setApplicationContext called twice!old=com.android.launcher3.LauncherApplication@41c76888 new=com.android.launcher3.LauncherApplication@41c76888

的warning。查找warning输出的位置,发现在onCreate中。也就是说在初始化过程中,Launcher3 onCreate了两次。

 

我们知道,为了重新布局,Launcher每次转屏都会重新onCreate的。而以横屏摆放启动,会导致在默认竖屏的状态下,很短时间内又进行了一次转屏。

看了一下AndroidManifest.xml,发现android:screenOrientation属性是nosensor,所以每次启动都是默认(竖屏)。改为sensor后,第一次初始化方向和实际方向一致,则不会出现执行两次onCreate()的情况。

 

在LauncherModel.java中,搜索“step 1”,可以找到初始化workspace的过程。而恰恰这个workspace初始化没有被synchronized保护起来。导致初始化database的过程中产生冲突,从而导致写入失败。

版权所有,转载请注明出处:

http://sickworm.com/?p=15

【MT8382/8121】使用绝对路径编译模块会导致recourse_overlay无法应用的问题

Published / by sickworm / Leave a Comment

 

之前为了方便mm模块编译,写了个脚本,实现了在任意模块其子目录下执行脚本即可编译的功能。

其实原理就是一层一层目录地往上寻找Android.mk文件,找到存放Android.mk目录后,就把该目录当作./mk mm 的目录参数。

(脚本现在还有点bug,等改好再放上来,以免误人子弟)

这里我犯了一个错误,我获取目录参数的使用的是pwd,也就是绝对路径。大家使用mm命令都是用相对路径,不会无聊打绝对路径上去的。这导致了一个问题,我编译出来的Launcher3.apk没有添加recourse_overlay中的壁纸,只有1.4M左右。由于mm.log中是没有相关信息的,导致发现的过程比较曲折。

后来发现overlay记录是在AppAssets_Overlay.log中,但是里面记录的东西都是重复的,没什么价值。

版权所有,转载请注明出处:

http://sickworm.com/?p=13

Android源码的BUG

Published / by sickworm / Leave a Comment

 

在Android系统移植过程中,遇到很多源码上的BUG。但是我们看到市面上都是没有这些问题的。难道这些BUG在每个开发商都要经历一次解BUG的过程吗?Android释放的源码是否是最新的?暂时没有想法。仅在此记录我遇到的Android源码上的BUG。

 

MTK8382/8121:

1、Launcher3无图标问题

 

2、Launcher3自定义壁纸旋转后拉伸无法恢复

 

3、Settings点击Location(位置)后右上角的开关button不会消失

 

 

版权所有,转载请注明出处:

http://sickworm.com/?p=11