有宏控的测试项只需要改成true就行了,路径在override/vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/config/TestConfig.java
比如public static final boolean TEST_EN_SENSOR_GYRO = true; //FeatureOption.FREEME_FACTORYMODE_GYROSCOPE ,这个就是陀螺仪。
TEST_ITEM_INFRARED 红外。 TEST_ITEM_STROBE_BACK 后闪光灯。TEST_ITEM_GYROSCOPE 陀螺仪。TEST_ITEM_LIGHT_ATTENTION 信号指示灯。
TEST_ITEM_LED 按键指示灯。
调取的值有宏控,
FeatureOption.FREEME_FACTORYMODE_GYROSCOPE
device/common/device.factory.mk
灯,如果里面没有测试项,需要新加,比如说手电筒。
那就自己建一个Java文件,如override/vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/light/Flashlight.java,
这里面的逻辑是写节点亮灯,所以需要加权限
device/droi/pl2281_zrk/init.project.rc
chmod 666 /sys/kernel/flash_cur/flash_cur
chown system system /sys/kernel/flash_cur/flash_cur
也可以不用写节点的方式,可以做到与状态栏快捷按钮同步,推荐!
public class FlashLight extends BaseTest implements View.OnClickListener {
private static String TAG = "FlashLight";
private Button light;
boolean lightEnable = false;
private int torch = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.strobe);
//yantao
torch = Settings.Secure.getInt(getContentResolver(),"qs_torch",0);
Log.i("yantao","flashlight test torch init ="+torch);
lightEnable = torch == 1;
light = (Button) findViewById(R.id.strobe_switcher);
light.setText(getString(R.string.flashlight_switcher_arg,
getText(lightEnable ? R.string.flashlight_state_on : R.string.flashlight_state_off)));
light.setOnClickListener(this);
testActionCompleted(false);
}
@Override
public void onClick(View v) {
torch = Settings.Secure.getInt(getContentResolver(),"qs_torch",0);
lightEnable = torch == 1;
light.setText(getString(R.string.flashlight_switcher_arg,
getText(lightEnable ? R.string.flashlight_state_on : R.string.flashlight_state_off)));
if(lightEnable){
Settings.Secure.putInt(getContentResolver(),"qs_torch",0);
}else{
Settings.Secure.putInt(getContentResolver(),"qs_torch",1);
}
testActionCompleted(true);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Settings.Secure.putInt(getContentResolver(),"qs_torch",0);
}
}
然后需要在清单文件里注册activity,路径override/vendor/freeme/packages/apps/FreemeFactoryTest/AndroidManifest.xml 加上<activity
android:name=".light.Flashlight"
android:label="@string/flashlight_name"
android:screenOrientation="portrait" />
也要在工厂模式的activity加入跳转的逻辑override/vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/FactoryTest.java
case TestConfig.TEST_ITEM_FLASH_LIGHT:
intent.setClass(this, Flashlight.class);
startActivityForResult(intent, item);
break;
src/com/freeme/factory/config/TestConfig.java加入
public static final int TEST_ITEM_FLASHLIGHT = 47;
int[] kTestItems_Full方法中加入
TEST_ITEM_FLASHLIGHT,
getNameByItemId(方法中加入
case TEST_ITEM_FLASHLIGHT:
resid = R.string.flashlight;
break;
字符串也要加一下override/vendor/freeme/packages/apps/FreemeFactoryTest/res/values/strings.xml
还有中文的
<string name="flashlight">手电筒</string>
<string name="flashlight_switcher_arg">手电筒 开/关\n(%s)</string>
<string name="flashlight_state_on">打开</string>
<string name="flashlight_state_off">关闭</string>
移除测试项,上面布尔值没有定义的直接往下找,比如移除听筒:
src/com/freeme/factory/config/TestConfig.java
getNameByItemId方法里可以找到听筒
case TestConfig.TEST_ITEM_RECEIVER:
resid = R.string.earphone_name;
break;
直接注掉,然后上面的int[] kTestItems_Full方法内也注掉TEST_ITEM_RECEIVER,
更改手电筒快捷方式逻辑,改写属性值打开或关闭手电筒
O版本肯定可以,q版本有这个@Inject注解之后,总会编译报错。
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+import android.util.Slog;
+import android.os.Handler;
+import android.os.Looper;
+import android.net.Uri;
+import android.provider.Settings;
+import android.database.ContentObserver;
全局变量
+ private static final String QS_TORCH = "qs_torch";
+ private final SettingObserver mObserver = new SettingObserver();
@Inject
注意!!!!高版本是有这个注解的@Inject,切记一定要在这个注解前面写全局变量,不然编译会报错,也不可以直接删掉!cannot be provided without an @Inject constructor or an @Provides-annotated method.
这个SettingObserver是自定义的类,作用是作为系统属性保存的数据库,关键在于当值变化时刷新
+ private final class SettingObserver extends ContentObserver {
+ public SettingObserver() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ refreshState();
+ }
+ }
构造方法下
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(QS_TORCH), false,
mObserver);
创建系统属性值QS_TORCH,这里第三个参数只是为了刷新,其他自定义的话可以直接new ContentObserver();
如果
第一个参数:需要监听的 uri。
第二个参数:为 false 表示精确匹配,即只匹配该 Uri。为 true 表示可以同时匹配其派生的 Uri,如:
content://com.qin.cb/student(精确匹配)
content://com.qin.cb/student/# (派生,false 才能匹配到)
content://com.qin.cb/student/schoolchild(派生,false 才能匹配到)
第三个参数:ContentObserver 的实例。
源码的处理更新状态的方法handleUpdateState
+ state.value = getIntValue() == 1;
+ mFlashlightController.setFlashlight(state.value);
+ /*/
if (arg instanceof Boolean) {
boolean value = (Boolean) arg;
if (value == state.value) {
return;
}
state.value = value;
} else {
state.value = mFlashlightController.isEnabled();
}*/
把源码判断状态的逻辑去掉,就由当前属性值得到
注意后面还要加上亮灯操作,原本只有点击快捷方式才会亮灯,现在更新状态就要亮灯
+ mFlashlightController.setFlashlight(state.value);
在点击方法中handleClick
boolean newState = !mState.value;
refreshState(newState);
mFlashlightController.setFlashlight(newState);
+ putIntValue(newState ? 1:0);
最后在销毁后handleDestroy
解绑数据库
@Override
protected void handleDestroy() {
super.handleDestroy();
+ unRegisterOB();
用到的方法如下:
public int getIntValue() {
+ int newValue = Settings.Secure.getInt(mContext.getContentResolver(),QS_TORCH,0);
+ Slog.v(TAG, " getString = " + newValue);
+ return newValue;
+ }
+
+ public void putIntValue(int value) {
+ Settings.Secure.putInt(mContext.getContentResolver(), QS_TORCH, value);
+ Slog.v(TAG, " putIntValue " + value);
+ }
+
+ public void unRegisterOB() {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ }
别的地方使用打开或关闭手电筒就可以:
int torchState = Settings.Secure.getInt(mContext.getContentResolver(),"qs_torch",0);
if(torchState ==0){
Settings.Secure.putInt(mContext.getContentResolver(),"qs_torch",1);
}else{
Settings.Secure.putInt(mContext.getContentResolver(),"qs_torch",0);
}
注意导包import android.provider.Settings;
注意!!!此方法需要把手电筒快捷图标放到default里面不要放到stock,需要初始化一下,不然不起作用