近期,在调试自己的Android2.3.4系统(三星s5pv210平台)时,发现自己的light sensor不仅仅是光传感器,还有靠近/接近传感器功能(Proximity),而自己的平台也没有通话功能,故将其利用起来,模仿ipad2做个盖子关屏功能,我这边实现的是靠近让系统待机,相当于我们平台上的短按电源键待机操作。对于我们的Proximity Sensor,可以获取到8位精度的值,而我们在Linux驱动上报时只传两个状态:远和近,故在Android HAL上也只传两个状态:0和100cm,这已足够我们功能实现了,下面是功能实现的两个步骤:
1、前台开关
在Settings/Display里添加一项Auto-close screen,这里实现是一个复选框,相应的操作如下:
1)、修改packages/apps/Settings/res/xml/display_settings.xml文件,添加:
android:key="proximity"
android:title="@string/proximity_title"/>
2)、修改packages/apps/Settings/res/values/strings.xml文件,添加:
Auto-close screen
由于此处是实验用,故不实现多国语言,暂不修改其他values-*目录下的strings.xml文件。
3)、修改packages/apps/Settings/src/com/android/settings/DisplaySettings.java文件,在public class DisplaySettings extends PreferenceActivity implementsPreference.OnPreferenceChangeListener类里添加如下内容:
private static final String KEY_PROXIMITY = "proximity";
private static final String PROXIMITY_CLOSE = "proximity_close";
private CheckBoxPreference mProximity;
在protected void onCreate(Bundle savedInstanceState)函数里添加如下内容:
mProximity = (CheckBoxPreference) findPreference(KEY_PROXIMITY);
mProximity.setPersistent(false);
在private void updateState(boolean force)函数里添加如下内容:
mProximity.setChecked(Settings.System.getInt(getContentResolver(),PROXIMITY_
CLOSE,0) != 0);
在public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)函数里添加如下内容:
if (preference == mProximity) {
Settings.System.putInt(getContentResolver(),PROXIMITY_CLOSE,mProximity.isChecked() ? 1 : 0);
}
至此,整个用户控制界面实现好了,即我们的前台开关控制界面实现好了,接下来要实现后台数据控制了。
2、后台实现
后台相对简单点,因为不用修改太多文件,只需修改frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java文件即可。
在文件中添加如下包含:
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.SensorEvent;
import android.hardware.Sensor;
接下来在public class PhoneWindowManager implements WindowManagerPolicy类中添加如下内容:
static final int DEFAULT_PROXIMITY_SCREEN_CLOSE = 0;
int mProximityDefault = DEFAULT_PROXIMITY_SCREEN_CLOSE;
private static final String PROXIMITY_CLOSE = "proximity_close";
SensorManager mSensorManager;
Sensor mProximitySensor;
接下来在void observe()函数中添加如下内容:
resolver.registerContentObserver(Settings.System.getUriFor(PROXIMITY_CLOSE),false,this);
接下来在上面的函数后添加如下定义内容:
private SensorEventListener proximityListener = new SensorEventListener(){
@Override
public void onSensorChanged(SensorEvent event){
//Log.v(TAG,"onSensorChanged");
switch (event.sensor.getType()){
case Sensor.TYPE_PROXIMITY:
if (event.values[0] == 0){//near
//Log.v(TAG,"near");
PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
pm.goToSleep(SystemClock.uptimeMillis());
}
else {//far
//Log.v(TAG,"far");
}
break;
}
//Log.v(TAG,"type="+event.sensor.getType());
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//Log.v(TAG,"onAccuracyChanged");
}
};
void updateScreenCloseListerner() {
if (mProximityDefault == 1)
{//allow proximity sensor to close screen
mSensorManager =(SensorManager)mContext.getSystemService(Context.SENSOR_SERVICE);
mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
mSensorManager.registerListener(proximityListener,mProximitySensor,SensorManager.SENSOR_DELAY_FASTEST);
Log.v(TAG,"proximity control screen allowed");
}
else if (mProximityDefault == 0)
{//not allow
mSensorManager.unregisterListener(proximityListener);
Log.v(TAG,"proximity control screen not allowed");
}
}
接下来在public void updateSettings()函数中添加如下内容:
int proximityDefault = Settings.System.getInt(resolver,PROXIMITY_CLOSE,DEFAULT_PROXIMITY_SCREEN_CLOSE);
if (mProximityDefault != proximityDefault) {
mProximityDefault = proximityDefault;
updateScreenCloseListerner();
}
至此,整个后台的控制也实现好了,接下来要看你的Proximity Sensor发力了。