《深入理解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");
}
时间: 2024-09-13 00:19:56

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

《Android安全技术揭秘与防范》——第1.1节Android的发展历史

第1章 Android简介Android安全技术揭秘与防范近年来我们对"Android"这个词已经不再陌生.在过去的几年时间里,Android的快速发展已经影响到了每个人的日常生活.如今Android不仅仅意味着一台手机.一部平板电脑,也可能是一台电视.一只手表.一部智能汽车.一副眼镜.然而,在一个生态系统形成的同时,总会有一群人希望通过一些不常规的手段谋取利益. 本章主要从Android黑色产业链与破解人员的动机来分析Android的安全问题. 1.1 Android的发展历史And

《Android安全技术揭秘与防范》——第2.1节Android应用程序概览

2.1 Android应用程序概览 Android开发秘籍(第2版) Android应用程序包含的功能五花八门,比如编辑文本.播放音乐.启动闹钟或是打开通讯录等.这些功能可以被分类对应到4类Android组件之中,如表2-1所示,每一类都对应一个Java基本类. 每个应用程序都由一个或多个这样的组件组成.当要用到某个组件时,Android操作系统就会将其初始化.其他应用程序在指定的权限内也可以使用它们. 随着在操作系统中展现多种功能(有些功能甚至与预期的应用程序无关,如呼入电话),每个组件经历了

《Android NFC开发实战详解》——6.2节Android NFC P2P开发基础

6.2 Android NFC P2P开发基础 Android NFC开发实战详解 本节主要介绍Android NFC P2P开发中的一些基础知识,为后续的实例开发提供基础.通过本章的学习,使读者熟悉Android中Beam实现的几种方式,Beam NDEF消息和接收Beam消息的方法,同时也会对第4章中提到的Intent过滤机制在P2P中的使用进行阐述. 6.2.1 Android Beam实现的几种方式 在Android中,目前,Beam功能实现的方式可以概括为三种,分别为setNdefPu

《Android NFC开发实战详解》——6.3节Android NFC P2P开发实例

6.3 Android NFC P2P开发实例Android NFC开发实战详解学习了Android NFC P2P开发的基础知识后,本节将以程序实例的形式对Android NFC P2P功能进行进一步阐述,其中包括setNdefPushMessageCallback.setNdefPushMessage.enableForeground NdefPush以及结合AAR功能的Beam功能的四个实例开发.通过本节的学习,读者可以根据具体场景实现自己的P2P功能的开发. 6.3.1 实例1:使用se

《Android NFC开发实战详解》——6.4节Android NFC P2P开发进阶

6.4 Android NFC P2P开发进阶 Android NFC开发实战详解 本节将介绍Android API 16+中引入的针对NFC P2P功能开发的新功能--文件传输进行介绍.该功能包括setBeamPushUrisCallback和setBeamPushUris两个方法.通过本节的介绍,大家可以结合NFC和蓝牙或WiFi很轻松的实现Android设备之间大数据(如图片.音乐等)的传输. 6.4.1 Beam实现文件传输的方法 Android4.1(Jelly Bean,Androi

《深入理解Android 5 源代码》——第2章,第2.5节编译源代码生成SDK

2.5 编译源代码生成SDK在Android 5.0的源代码的根目录下有一个SDK目录,所有和SDK相关的代码都放在这个目录中,包括镜像文件.模拟器和ADB等常用工具,以及SDK中的开发包的文档,可以通过编译的方式来生成开发需要的SDK,编译命令如下所示: $ Make SDK 当编译完成后,会在/out/host/linux-x86/sdk/目录下生成SDK,这个SDK是完全与源代码同步的,与官方网站上下载的SDK功能完全相同,包含了开发用的JAR包.模拟器管理工具和ADB调试工具,可以使用这

《深入理解Android:卷III A》一一1.1获取Android源代码

1.1获取Android源代码 在深入研究Android之前,首先必须获得一套Android的源代码.Google提供官方Android源代码的获取方法如下:https://source.android.com/source/downloading.html 这个页面介绍了使用repo脚本进行Android源码的下载的两个基本步骤. 1)首先通过repo init命令将当前文件夹初始化为repo脚本的工作区.其命令格式如下: repo init -u -b <分支名称> repo init命令

《深入理解Android》一第2章 浏览器工作原理及WebKit概览

第2章 浏览器工作原理及WebKit概览本章主要内容简述浏览器的工作原理介绍浏览器内核发展史概述WebKit架构第1章为读者说明了Android源码的编译环境本书内容概要,在本章中将阐述万维网技术的基本概念和浏览器的主要工作原理,并简单介绍和对比主流的全功能浏览器内核以及WebKit项目的历史和现状,最后着重描述WebKit内核的架构流程和设计思想.

Android群英传笔记——第一章:Android体系与系统架构

Android群英传笔记--第一章:Android体系与系统架构 图片都是摘抄自网络 今天确实挺忙的,不过把第一章的笔记做一下还是可以的,嘿嘿 1.1 Google的生态圈 还是得从Android的起源说起,Android是一个以Linux为基础的开源移动设备操作系统,主要用于智能手机和平板电脑,由Google成立的Open Handset Alliance(OHA,开放手持设备联盟)持续领导与开发中.Android已发布的最新版本为Android 6.0.1(M). Android系统最初由安