Android系统设置通用接口的编写
作为一个Android系统和系统级应开发工程师,我不得不吐槽每次换到一个新平台就不得花大量的时间来修改我们开发的公版Android系统设置中的代码,为什么不能开发一套所有平台都通用的公版Android系统设置呢。这其中的原因吗,主要是因为不同平台对底层硬件的操作接口不相同有关,这其中主要是对分辨率和OSD层的设置的接口不同,像对于WIFI和语言的相关设置由于Android统一了接口就不必那么的麻烦了。
很不幸的,编写Android系统设置通用接口的任务落在了我的头上。经过几天的思考我这里想到了一个方法就是定义一套通用的服务将底层对于系统分辨率和OSD的操作封装在该服务中,上层系统应用的开发就不必关心Android底层怎么操作的了,只要调用我们注册的服务就可以了,下面就是我编写的系统设置中修改分辨率和OSD层的代码,这里并没有将底层对于分辨率和OSD层的修改编写出来,因为每个平台不同吗。同时应用开发工程师也不需要关注这些细节。
如果对于我上树的描述还不清楚的话,用一句话总结就是在Android系统中添加一个系统级服务统一相关的接口(对分辨率和OSD层等的设置),以后应用开发人员无论是什么平台的情况下都可以调用该服务的相关方法,至于是在什么平台下面应用开发人员就不需要关心了(就将这些方法看成Android SDK相关的API就可以了)。接下来我以设置分辨率作为实例来描写。
详细步骤如下:
1在frameworks/base/core/java/android/app/添加一个aidl的接口定义文件ICoshipManager.aidl,该文件主要是定义了设置和获取分辨率的接口
package android.app;
interface ICoshipManager {
void setHDMIResolution(in int index);//设置分辨率
int getHdmiResolution(); //获取当前系统分辨率
}
2.在frameworks/base/core/java/android/app/添加一个CoshipManager.java,该文件的作用是提供Android系统层服务接口给应用开发工程师调用用来实现Android系统设置得共功能,其代码如下所示:
package android.app;
import android.content.Context;
import android.content.res.Configuration;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.app.ICoshipManager;
import android.hardware.display.WifiDisplayStatus;
import android.hardware.display.DisplayManager;
import android.net.wifi.p2p.WifiP2pManager;
import android.view.Surface;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
/** @hide */
public class CoshipManager {
private static final String TAG = "CoshipManager";
private ICoshipManager mService;
/** @hide */
public CoshipManager() {
mService = ICoshipManager.Stub.asInterface(ServiceManager.getService("coshipcfg"));
if (mService != null) {
Log.e(TAG, "get coship manager service OK");
} else {
Log.e(TAG, "get coship manager service NG");
}
}
public void setHDMIResolution(int res) {
if (mService != null) {
try {
mService.setHDMIResolution(res);
} catch (RemoteException e) {
Log.e(TAG, "setResolution: RemoteException", e);
}
}
}
public int getHdmiResolution(){
int mResolution = 0;
if (mService != null) {
try {
mResolution = mService.getHdmiResolution();
} catch (RemoteException e) {
Log.e(TAG, "getResolution: RemoteException", e);
}
}
return mResolution;
}
}
3.在framew//base/services/java/com/android/server/下添加文件CoshipManagerService.java,该文件才是Android中真正的实现系统分辨率设置得地方,其代码如下所示:
package com.android.server;
import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Slog;
import android.util.Log;
import android.provider.Settings.SettingNotFoundException;
import android.provider.Settings;
import android.app.CoshipManager;
import android.app.ICoshipManager;
import android.view.SurfaceControl;
import android.view.SurfaceView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;
import com.mediatek.common.hdmi.IMtkHdmiManager;
import android.content.ContentResolver;
import android.os.UserHandle;
import android.hardware.display.DisplayManager;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.view.Surface;
import android.hardware.display.WifiDisplayStatus;
class CoshipManagerService extends ICoshipManager.Stub {
private static final String TAG = "<CoshipManagerService>";
private final Context mContext;
final Object mLock = new Object();
private static final int HDMI_RESOLUTION_AUTO = 100;
private static final int HDMI_VIDEO_RESOLUTION_DEFAULT = 100;
private IMtkHdmiManager mHdmiManager;
private final ContentResolver mContentResolver;
private int[] supportedResolutions = { HDMI_RESOLUTION_AUTO };
public CoshipManagerService(Context context) {
mContext = context;
ServiceManager.addService("coshipcfg", this);
mHdmiManager = IMtkHdmiManager.Stub.asInterface(ServiceManager.getService(Context.MTK_HDMI_SERVICE));
if (null == mHdmiManager) {
Slog.e(TAG, "get Hdmi Manager failure");
}
mContentResolver = mContext.getContentResolver();
try {
supportedResolutions = mHdmiManager.getSupportedResolutions();
} catch (RemoteException e) {
Slog.w(TAG, "hdmi manager RemoteException: " + e.getMessage());
}
}
public void init(){
}
public void setHDMIResolution(int res) {
Slog.e("wangshengjie", "setHDMIResolution " + res);
int scaleValue = transUIHdmiIndex2System(res);
if(scaleValue == -1 || scaleValue > supportedResolutions.length)
{
Slog.e(TAG, "Hdmi Resolutions error ");
return;
}
Slog.e(TAG, "mHdmiManager.setVideoScale " + scaleValue);
try {
mHdmiManager.setVideoResolution(supportedResolutions[scaleValue]);
} catch (RemoteException e) {
Slog.w(TAG, "hdmi manager RemoteException: " + e.getMessage());
}
}
public int getHdmiResolution() throws RemoteException {
int mHdmiVideoResolution = -1;
int mHdmiVideoResolutionLast = Settings.System.getIntForUser(mContentResolver,
Settings.System.HDMI_VIDEO_RESOLUTION,
HDMI_VIDEO_RESOLUTION_DEFAULT, UserHandle.USER_CURRENT);
for(int i = 0; i < supportedResolutions.length; ++i) {
if(supportedResolutions[i] == mHdmiVideoResolutionLast) {
mHdmiVideoResolution = i;
break;
}
}
Slog.i(TAG, "getHdmiResolution " + mHdmiVideoResolution);
int uiHdmiIndex = transSystemHdmiIndex2UI(mHdmiVideoResolution);
Slog.i(TAG, "getHdmiResolution " + uiHdmiIndex);
return uiHdmiIndex;
}
private int transUIHdmiIndex2System(int uiHdmiIndex)
{
int systemIndex = -1;
if(uiHdmiIndex > 6 || uiHdmiIndex < 0)
{
Slog.e(TAG, "not support Hdmi Resolutions");
return systemIndex;
}
switch(uiHdmiIndex)
{
case 0: systemIndex = 6; break;
case 1: systemIndex = 9; break;
case 2: systemIndex = 4; break;
case 3: systemIndex = 5; break;
case 4: systemIndex = 2; break;
case 5: systemIndex = 3; break;
case 6: systemIndex = 0; break;
}
return systemIndex;
}
private int transSystemHdmiIndex2UI(int systemHdmiIndex)
{
//System 1080p_60hz, 1080p_50hz, 1080i_60hz, 1080i_50hz, 720p_60hz, 720p_50hz, 480p, 576p
//UI 480p, 576i, 720p_60hz, 720p_50hz, 1080i_60hz, 1080i_50hz, 1080p_60hz
int uiHdmiIndex = -1;
//Slog.i(TAG, "supportedResolutions " + supportedResolutions);
if(systemHdmiIndex > 7 || systemHdmiIndex < 0)
{
Slog.e(TAG, "not support Hdmi Resolutions");
return uiHdmiIndex;
}
switch(systemHdmiIndex)
{
case 6: uiHdmiIndex = 0; break;
case 9: uiHdmiIndex = 1; break;
case 4: uiHdmiIndex = 2; break;
case 5: uiHdmiIndex = 3; break;
case 2: uiHdmiIndex = 4; break;
case 3: uiHdmiIndex = 5; break;
case 0: uiHdmiIndex = 6; break;
}
return uiHdmiIndex;
}
void systemReady() {
synchronized (mLock) {
}
}
}
总结:
上述的代码只是以设置分辨率举例,至于其它的相关通用的系统设置得接口也可以按照相同的方式来定义,这样以后应用开发的工程师就不必关心不同平台的相关情况了,这样就能做到一套系统设置能适应多个平台了。以后应用开发工程师就只需像使用普通的API一样调用相关的函数来进行系统相关设置了。