《深入理解Android 5 源代码》——第2章,第2.3节Android源代码提供的接口

本节书摘来自异步社区《深入理解Android 5 源代码》一书中的第2章,第2.3节Android源代码提供的接口,作者 李骏,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.3 Android源代码提供的接口
我们知道,Android源代码当中提供了很多资源、工具或者文档供开发者使用,当然,其中也包括应用程序开发接口的实现,也就是我们开发应用程序所使用的SDK的API。正是由于有了这些种类丰富、功能强大、抽象程度高的接口,才让我们开发应用程序变得简单方便。在本节的内容中,将详细讲解Android系统中这些接口的基本知识。

2.3.1 暴露接口和隐藏接口
我们可以将Android源代码编译生成一个SDK,这个SDK的功能等同于官方网站上单独下载的SDK开发包。这说明在Android源代码中存在SDK的实现代码,不仅可以提供与独立SDK相同的API接口,而且会有一些SDK开发包中不具备的API接口。当然,这部分隐藏的接口在基于SDK开发的时候是看不到的,只有在基于源代码开发或者往独立的SDK中“增加”隐藏接口的时候才能调用到。

究竟源代码中的哪些接口是暴露接口,哪些接口是隐藏接口呢?比如要做一个统计电量消耗信息的应用程序,以及WiFi或者蓝牙的打开时间,在SDK中是没有直接相关的接口来调用的。当然通过其他途径可以找到很多种方法来满足这个需求,这里我们讲解怎么用源代码中的隐藏接口来实现这些功能。

在源代码路径/frameworks/base/core/java/android/os目录下,存在两个电池相关的文件:BatteryStats.java和BatteryStatsImpl.java,其中前者声明了一个与电池相关的抽象类BatteryStats,后者继承了BatteryStats,并实现了里面的方法。下面来看文件BatteryStats.java中的抽象类,在这个类中定义了很多变量来记录系统功能的状态变化,例如:
WiFi开关;
蓝牙开关;
音频打开;
视频打开;
上次充电时刻。
上述信息用来计算各个模块的电量消耗情况,同时在里面也定义了其他的抽象类,里面的抽象接口都可以用来计算电量消耗,文件BatteryStats.java的代码如下所示:

public abstract class BatteryStats implements Parcelable {
    /*省略部分代码*/
    //WIFI开启时间
    public static final int WIFI_RUNNING = 4;
    //WIFI完全锁定时间
    public static final int FULL_WIFI_LOCK = 5;
    //WIFI扫描时间
    public static final int WIFI_SCAN = 6;
    //WIFI其他功能开启时间
    public static final int WIFI_MULTICAST_ENABLED = 7;
    //音频开启时间
    public static final int AUDIO_TURNED_ON = 7;
     //视频开启时间
    public static final int VIDEO_TURNED_ON = 8;
    //系统状态自从上次变化到现在
    public static final int STATS_SINCE_CHARGED = 0;
    //上一次的系统状态
    public static final int STATS_LAST = 1;
    //现在的系统状态
    public static final int STATS_CURRENT = 2;
        //从上次拔下设备到现在的状态
    public static final int STATS_SINCE_UNPLUGGED = 3;
    /*省略部分代码*/
    public static abstract class Uid {
        //得到相关联UID锁屏状态
        public abstract Map<String, ? extends Wakelock> getWakelockStats();
        public static abstract class Wakelock {
            public abstract Timer getWakeTime(int type);
        }
        //得到相关联UID的传感器状态
        public abstract Map<Integer, ? extends Sensor> getSensorStats();
        //得到Pid状态
        public abstract SparseArray<? extends Pid> getPidStats();
        //得到进程状态
        public abstract Map<String, ? extends Proc> getProcessStats();
        //得到包状态
        public abstract Map<String, ? extends Pkg> getPackageStats();
        /**
* 得到Uid
         * {@hide}
         */
        public abstract int getUid();
        /**
* 得到Tcp接收到的字节数
         * {@hide}
         */
        public abstract long getTcpBytesReceived(int which);
        /**
* 得到Tcp发出的字节数
         * {@hide}
         */
        public abstract long getTcpBytesSent(int which);
        //记录WiFi运行时刻
        public abstract void noteWifiRunningLocked();
        //记录WiFi停止时刻
        public abstract void noteWifiStoppedLocked();
        public abstract void noteFullWifiLockAcquiredLocked();
        public abstract void noteFullWifiLockReleasedLocked();
        public abstract void noteWifiScanStartedLocked();
        public abstract void noteWifiScanStoppedLocked();
        public abstract void noteWifiMulticastEnabledLocked();
        public abstract void noteWifiMulticastDisabledLocked();
        public abstract void noteAudioTurnedOnLocked();
        public abstract void noteAudioTurnedOffLocked();
        public abstract void noteVideoTurnedOnLocked();
        public abstract void noteVideoTurnedOffLocked();
        //得到WiFi运行时间
        public abstract long getWifiRunningTime(long batteryRealtime, int which);
        //得到WiFi锁定时间
        public abstract long getFullWifiLockTime(long batteryRealtime, int which);
        //得到WiFi扫描时间
        public abstract long getWifiScanTime(long batteryRealtime, int which);
        //得到WiFi其他功能开启时间
        public abstract long getWifiMulticastTime(long batteryRealtime,
                                                  int which);
        //得到音频开启时间
        public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
              //得到视频开启时间 
        public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
        static final String[] USER_ACTIVITY_TYPES = {
            "other", "button", "touch"
        };
        public static final int NUM_USER_ACTIVITY_TYPES = 3;
        public abstract void noteUserActivityLocked(int type);
        public abstract boolean hasUserActivity();
        public abstract int getUserActivityCount(int type, int which);
        //传感器抽象类
        public static abstract class Sensor {
        public static final int GPS = -10000;
            public abstract int getHandle();
            public abstract Timer getSensorTime();
        }
        //Pid类
        public class Pid {
            public long mWakeSum;
            public long mWakeStart;
        }
        //进程相关类
        public static abstract class Proc {
            public static class ExcessivePower {
                //唤醒方式
                public static final int TYPE_WAKE = 1;
                //CPU类型
                public static final int TYPE_CPU = 2;
                public int type;
                public long overTime;
                public long usedTime;
            }
            //得到用户时间
            public abstract long getUserTime(int which);
            //得到系统时间
            public abstract long getSystemTime(int which);
                //得到状态
            public abstract int getStarts(int which);
            //得到CPU在前台运行的时间
            public abstract long getForegroundTime(int which);
            //得到CPU的速度等级
            public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
            //得到剩余的电量
            public abstract int countExcessivePowers();
            public abstract ExcessivePower getExcessivePower(int i);
        }
    }
/*省略部分代码*/
/** 得到屏幕点亮的时间
     * {@hide} 
     */
    public abstract long getScreenOnTime(long batteryRealtime, int which);
/** 根据屏幕点亮的等级,得到相应时间
     * {@hide}
     */
    public abstract long getScreenBrightnessTime(int brightnessBin,
                                               long batteryRealtime, int which);
/**
     * 得到用电池的时候电话运行时的时间
     * {@hide}
     */
    public abstract long getPhoneOnTime(long batteryRealtime, int which);
/**
* 得到手机处于不同信号强度的时间
     * {@hide}
     */
    public abstract long getPhoneSignalStrengthTime(int strengthBin,
            long batteryRealtime, int which);
/**
     * 得到手机扫描信号用掉的时间
     * {@hide}
     */
    public abstract long getPhoneSignalScanningTime(
            long batteryRealtime, int which);
/**
     * 得到手机扫描到不同信号强度用掉的时间
     * {@hide}
     */
    public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
    /**
     * 得到手机不同数据连接消耗的时间
     * {@hide}
     */
    public abstract long getPhoneDataConnectionTime(int dataType,
            long batteryRealtime, int which);
/**
     * 得到手机进入到不同数据连接所消耗的时间
     * {@hide}
     */
    public abstract int getPhoneDataConnectionCount(int dataType, int which);
     /**
     * 得到手机处于WiFi打开的状态的时间
     * {@hide}
     */
    public abstract long getWifiOnTime(long batteryRealtime, int which);
    /**
     * 得到手机处于WiFi打开的状态并且驱动层的WiFi也处于打开状态时的时间
     * {@hide}
     */
    public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which);
    /**
     * 得到手机蓝牙处于打开状态时的时间
     * {@hide}
     */
    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
}
``
从上面的源代码可以看出,在文件BatteryStats.java中定义了很多与电池电量和系统状态相关的函数和变量,有一些函数在声明时加上了@hide字样,说明这些接口因为不稳定或者其他方面的原因暂时被Google隐藏了,不能通过SDK进行访问,可能会在以后的版本中开放。

对于那些没有标记@hide接口的函数,则不属于Google官方声明的隐藏接口,但是同样可以将其看成是隐藏的,只不过Google短期内或者一直都不会将其开放,所以不会特别进行维护,其形式与有@hide的隐藏接口一致。

看完文件BatteryStats.java中定义的隐藏接口后,接下来看看文件BatteryStatsImpl.java,在此文件中继承了BatteryStats抽象类,对BatteryStats中的很多隐藏方法进行了实现,其具体代码如下所示:

public final class BatteryStatsImpl extends BatteryStats {
/省略了部分代码/

    @Override
    public int getUid() {
        return mUid;
    }
    @Override
    public long getTcpBytesReceived(int which) {
        if (which == STATS_LAST) {
            return mLoadedTcpBytesReceived;
        } else {
            long current = computeCurrentTcpBytesReceived();
            if (which == STATS_SINCE_UNPLUGGED) {
                current -= mTcpBytesReceivedAtLastUnplug;
            } else if (which == STATS_SINCE_CHARGED) {
                current += mLoadedTcpBytesReceived;
            }
            return current;
        }
    }
    @Override
    public long getTcpBytesSent(int which) {
        if (which == STATS_LAST) {
            return mLoadedTcpBytesSent;
        } else {
            long current = computeCurrentTcpBytesSent();
            if (which == STATS_SINCE_UNPLUGGED) {
                current -= mTcpBytesSentAtLastUnplug;
            } else if (which == STATS_SINCE_CHARGED) {
                current += mLoadedTcpBytesSent;
            }
            return current;
        }
    }
@Override public long getScreenOnTime(long batteryRealtime, int which) {
    return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override public long getScreenBrightnessTime(int brightnessBin,
        long batteryRealtime, int which) {
    return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
            batteryRealtime, which);
}
@Override public long getPhoneOnTime(long batteryRealtime, int which) {
    return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
}    

@Override public long getPhoneSignalStrengthTime(int strengthBin,

        long batteryRealtime, int which) {
    return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
            batteryRealtime, which);
}
@Override public long getPhoneSignalScanningTime(
        long batteryRealtime, int which) {
    return mPhoneSignalScanningTimer.getTotalTimeLocked(
            batteryRealtime, which);
}
@Override public int getPhoneSignalStrengthCount(int strengthBin, int which){
    return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
}
@Override public long getPhoneDataConnectionTime(int dataType,
        long batteryRealtime, int which) {
    return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
            batteryRealtime, which);
}
@Override public int getPhoneDataConnectionCount(int dataType, int which) {
    return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
}
@Override public long getWifiOnTime(long batteryRealtime, int which) {
    return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override public long getGlobalWifiRunningTime(long batteryRealtime, int 

which) {

    return mGlobalWifiRunningTimer.getTotalTimeLocked(batteryRealtime, 

which);

}
@Override public long getBluetoothOnTime(long batteryRealtime, int which) {
    return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
}

}

在上述代码中,BatteryStatsImpl继承了类BatteryStats,然后实现了其中的隐藏接口,这样当进行应用程序开发时就可以使用这些还未开放的隐藏接口了,具体使用隐藏接口的方法将在小节中详细介绍。

**2.3.2 调用隐藏接口**
在前面的内容中,以BatteryStats这个类为例详细分析了Android中存在的隐藏接口。在接下来的内容中,将分析在源代码中使用这些隐藏接口的方法,然后分析在应用程序开发过程中调用隐藏接口的方法。

Android系统中在Settings程序中使用类BatteryStats,主要用来统计一些系统功能模块的工作时间和耗电情况。Settings中使用BatteryStats类的是文件PowerUsageSummary.java,其存放路径为:

/packages/apps/settings/src/com/android/settings/fuelgauge
文件PowerUsageSummary.java的主要功能是统计系统中的电量信息,在此用到了一些BatteryStats类中的隐藏接口,下面具体分析其实现代码,其中部分典型代码如下所示:

public class PowerUsageSummary extends PreferenceFragment implements Runnable {

/*省略部分代码*/
//定义了BatteryStats相关的3个对象,涉及到跨进程通信
private static BatteryStatsImpl sStatsXfer;
IBatteryStats mBatteryInfo;
BatteryStatsImpl mStats;
//在onCreate中初始化mBatteryInfo对象
@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    if (icicle != null) {
        //对mStats对象赋值
        mStats = sStatsXfer;
    }
    addPreferencesFromResource(R.xml.power_usage_summary); 
    //初始化mBatteryInfo对象
    mBatteryInfo = IBatteryStats.Stub.asInterface(
            ServiceManager.getService("batteryinfo"));
    mUm =(UserManager)getActivity().getSystemService(Context.USER_SERVICE);
    mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
    mBatteryStatusPref = mAppListGroup.findPreference(KEY_BATTERY_STATUS);
    mPowerProfile = new PowerProfile(getActivity());
    setHasOptionsMenu(true);
}
    private void addPhoneUsage(long uSecNow) {
    long phoneOnTimeMs = mStats.getPhoneOnTime(uSecNow, mStatsType) / 1000;
    double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ ACTIVE)
                                                             * phoneOnTimeMs / 1000;
    addEntry(getActivity().getString(R.string.power_phone), DrainType.PHONE,

phoneOnTimeMs, R.drawable.ic_settings_voice_calls, phoneOnPower);

}

}

//当mStats没有初始化时则通过Parcel接口继续初始化
private void load() {
    try {
        byte[] data = mBatteryInfo.getStatistics();
        Parcel parcel = Parcel.obtain();
        parcel.unmarshall(data, 0, data.length);
        parcel.setDataPosition(0);
        mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
                .createFromParcel(parcel);
        mStats.distributeWorkLocked(BatteryStats.STATS_SINCE_CHARGED);
    } catch (RemoteException e) {
        Log.e(TAG, "RemoteException:", e);
    }
}
//得到屏幕的使用时间和耗电情况

private void addScreenUsage(long uSecNow) {

    double power = 0;
    // getScreenOnTime()为BatteryStats中的隐藏接口
    long screenOnTimeMs = mStats.getScreenOnTime(uSecNow, mStatsType) / 1000;
    power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_ SCREEN_ON);
    final double screenFullPower =
            mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
    for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
        double screenBinPower = screenFullPower * (i + )
                / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
        // getScreenBrightnessTime为BatteryStats中的隐藏接口
        long brightnessTime = mStats.getScreenBrightnessTime(i, uSecNow,
        mStatsType) / 1000;
        power += screenBinPower * brightnessTime;
        if (DEBUG) {
            Log.i(TAG, "Screen bin power = " + (int) screenBinPower + 
            ", time = " + brightnessTime);
        }
    }
    power /= 1000; 
    addEntry(getActivity().getString(R.string.power_screen),

DrainType.SCREEN, screenOnTimeMs, R.drawable.ic_settings_display, power);

}
//得到Wifi的使用时间和耗电情况
private void addWiFiUsage(long uSecNow) {
    // getWifiOnTime为BatteryStats中的隐藏接口
    long onTimeMs = mStats.getWifiOnTime(uSecNow, mStatsType) / 1000;
    // getGlobalWifiRunningTime为BatteryStats中的隐藏接口
    long runningTimeMs = mStats.getGlobalWifiRunningTime(uSecNow, mStatsType) / 1000;
    if (DEBUG) Log.i(TAG, "WIFI runningTime=" + runningTimeMs
            + " app runningTime=" + mAppWifiRunning);
    runningTimeMs -= mAppWifiRunning;
    if (runningTimeMs < 0) runningTimeMs = 0;
    double wifiPower = (onTimeMs * 0 /* TODO */
                 * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
                                                                    + runningTimeMs *

mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;

    if (DEBUG) Log.i(TAG, "WIFI power=" + wifiPower + " from procs=" +

mWifiPower);

    BatterySipper bs=addEntry(getActivity().getString(R.string.power_wifi), 
                                                                     DrainType.WIFI,
            runningTimeMs, R.drawable.ic_settings_wifi, wifiPower + mWifiPower);
    aggregateSippers(bs, mWifiSippers, "WIFI");
}
//得到蓝牙的使用时间和耗电情况
private void addBluetoothUsage(long uSecNow) {
    // getBluetoothOnTime为BatteryStats中的隐藏接口
    long btOnTimeMs = mStats.getBluetoothOnTime(uSecNow, mStatsType) / 1000;
                                                      double btPower = btOnTimeMs *
         mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
                                                                                / 1000;
   // getBluetoothPingCount为BatteryStats中的隐藏接口
    int btPingCount = mStats.getBluetoothPingCount();
    btPower += (btPingCount *

mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD)) / 1000;

    BatterySipper bs = addEntry(getActivity().getString(R.string.power_bluetooth),
                                                DrainType.BLUETOOTH, btOnTimeMs, 

R.drawable.ic_settings_bluetooth, btPower + mBluetoothPower);

    aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
}
上一篇:深入理解Tomcat系列之四:Engine和Host容器


下一篇:Java内部类超详细总结(含代码示例)