init.rc中文件中会通过import /init.${ro.hardware}.rc文件,这个ro.hardware应该是某个具体的属性,而这个ro.hardware赋值应该是在Init进程中赋值的。
这个ro.hardware值设置是在/system/core/init.c中实现的,其通过hardware来赋值,hardware首先被/proc/cpuinfo赋值,然后会检测comandline。
如果comandline中有参数为androidboot.hardware,那这个参数在init进程的解析中会用到,并会赋值给hardware。
也就是说如果cmdline中有androidboot.hardware,则ro.hardware的值就是这个值,如果没有则ro.hardware的值就是/proc/cpuinfo
例如我参与的 这个项目comandline中的androidboot.hardware = qilianp1,那么在init.rc中import的具体文件对应为,init.qilianp1.rc
修改ro.hardware属性路径在K5036CMCC\kernel-3.18\arch\arm64\kernel\setup.c 中找到c_show方法中seq_printf(m, "Hardware\t: %s\n", "MF0427");
我这里强制写成MF0427 修改完单编kernal 命令:make -j72 bootimage 完事烧一个boot.img
网上的文章都是怎么查看/proc/cpuinfo,一直以为这种东西没法改呢,我还是太天真了。/proc/cpuinfo是个文件,只读,想直接写肯定不行的。今天研究了一下,发现它的输出逻辑在:kernel/[品牌]/[机型代号]/arch/[cpu架构]/kernel/setup.c
,修改c_show(struct seq_file *m, void *v)
方法,用seq_printf
,想输出啥都可以。特地下Linux内核源码下来看,不止Android,其他Linux路径都是类似的。
cpu频率
平常我们通过shell命令查看cpu频率的办法,都是读取/sys/devices/system/cpu/cpu0/cpufreq
下的cpuinfo_min_freq
和cpuinfo_max_freq
,它们分别代表cpu的最小频率和最大频率,这个几个文件也是可以修改的,修改后并不是你的cpu就会变快,而是可以骗过某些软件,修改方法如下:在kernel/[品牌]/[型号]/drivers/cpufreq/cpufreq.c
找到
show_one(cpuinfo_min_freq, cpuinfo.min_freq);
show_one(cpuinfo_max_freq, cpuinfo.max_freq);
把它们注释掉,修改成以下两行
show_cpu_min_freq(cpuinfo_min_freq, cpuinfo.min_freq);
show_cpu_max_freq(cpuinfo_max_freq,cpuinfo.max_freq);
上面的show_one其实是一个宏定义,那我们也要创建相应的宏。
#if 0
show_one(cpuinfo_min_freq, cpuinfo.min_freq);
show_one(cpuinfo_max_freq, cpuinfo.max_freq);
#else
static ssize_t show_cpuinfo_min_freq(struct cpufreq_policy *policy, char *buf)
{ \
return sprintf(buf, "%u\n", 338000); //CPU mix frequency
}
static ssize_t show_cpuinfo_max_freq(struct cpufreq_policy *policy, char *buf)
{ \
return sprintf(buf, "%u\n", 2000000); //CPU max frequency
}
#endif
获取固件版本号:
Android.mk 添加LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt telephony-common ims-common \
mediatek-framework
import com.mediatek.custom.CustomProperties;
private String getSoft() {
String result = CustomProperties.getString(CustomProperties.MODULE_DM,
"SoftwareVersion", "MTK");
return result;
}
获取cpu:
private String getCpuName() {
String str = null;
try {
str = getCpuHardwareByFile();
if (TextUtils.isEmpty(str)) {
str = Build.HARDWARE;
}
} catch (Exception localException) {
str = Build.HARDWARE;
}
return str;
}
private String getCpuHardwareByFile() {
HashMap localHashMap = new HashMap();
Scanner localScanner = null;
try {
localScanner = new Scanner(new File("/proc/cpuinfo"));
while (localScanner.hasNextLine()) {
String[] arrayOfString = localScanner.nextLine().split(": ");
if (arrayOfString.length > 1) {
localHashMap.put(arrayOfString[0].trim(),
arrayOfString[1].trim());
}
}
} catch (Exception localException) {
localException.printStackTrace();
} finally {
if (localScanner != null) {
localScanner.close();
}
}
return (String) localHashMap.get("Hardware");
}
String[] cmdMode = new String[]{"/system/bin/sh","-c","echo" + " " + 0 + " > /proc/dummystep"};
| ||
Runtime.getRuntime().exec(cmdMode); |
获取手机电池百分比和电池容量方法
在智能手机的开发过程中,经常需要获取手机的电池信息。其实获取的方法很多,下面介绍下方法。
一:首先介绍获取电池容量。例如java反射方式获取。代码如下
package com.example.jamesfan.getbatterycapacity;
import android.content.Context;
public class BatteryInfo {
public String getCapaCity(Context context) {
Object mPowerProfile;
double mBatteryCapacity = 0;
String POWER_PROFILE_CLASS = "com.android.internal.os.PowerProfile";
try {
mPowerProfile = Class.forName(POWER_PROFILE_CLASS)
.getConstructor(Context.class)
.newInstance(context);
mBatteryCapacity = (double) Class.forName(POWER_PROFILE_CLASS)
.getMethod("getBatteryCapacity")
.invoke(mPowerProfile);
} catch (Exception e) {
e.printStackTrace();
}
return String.valueOf(mBatteryCapacity + " mAh");
}
如果是做项目,可以在如下默认文件中修改。一般第三方软件都是通过读取这里获取电池容量的。
文件路径:frameworks\base\core\res\res\xml\power_profile.xml
默认情况下是 1000 mAh,一般手机厂商会进行修改,便于第三方应用读取
<!-- This is the battery capacity in mAh (measured at nominal voltage) -->
<item name="battery.capacity">1000</item>
二:其次是通过广播方式接受电池信息。如下代码
package com.example.jamesfan.getbatterycapacity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.util.Log;
import android.widget.Toast;
public class BatteryReceiver extends BroadcastReceiver {
int mCurrentLevel = 0;
int m_total = 0;
String m_strPercent;
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if(action.equalsIgnoreCase(Intent.ACTION_BATTERY_CHANGED))
{
Log.i("james-fan","get battery change broad");
}
// mCurrentLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
//m_total = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
mCurrentLevel = intent.getExtras().getInt("level");// 获得当前电量
m_total = intent.getExtras().getInt("scale");// 获得总电量
int percent = mCurrentLevel * 100 / m_total;
m_strPercent =percent+ "%";
}
public int getCurrentLevel()
{
return mCurrentLevel;
}
public int getTotal()
{
return m_total;
}
public String getBatteryPercent()
{
return m_strPercent;
}
三:接下来是主函数,广播采用的是动态注册方式。也可以采用静态注册方法。
package com.example.jamesfan.getbatterycapacity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
BatteryReceiver m_receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
m_receiver = new BatteryReceiver();
registerReceiver(m_receiver, intentFilter);
Button showBatteryCapacity = (Button) findViewById(R.id.showBatteryCapacity);
Button showBatteryInfo = (Button) findViewById(R.id.showBatteryInfo);
//showBatteryCapacity.setOnClickListener(this);
showBatteryCapacity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
BatteryInfo batteryInfo = new BatteryInfo();
String strBatteryInfo = batteryInfo.getCapaCity(MainActivity.this);
Toast.makeText(MainActivity.this, strBatteryInfo, Toast.LENGTH_SHORT).show();
}
});
showBatteryInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String str;
str = "CurrentLevel =" + m_receiver.getCurrentLevel()
+ " Total=" + m_receiver.getTotal()
+ " percent=" + m_receiver.getBatteryPercent();
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(m_receiver);
}
}
kernel-3.18/fs/proc/meminfo.c 4+64改成6+128
@@ -15,7 +15,8 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include "internal.h"
+ #include <linux/uaccess.h>
+ #define IS_ERR(x) unlikely((unsigned long)(x) >= (unsigned long)-MAX_ERRNO)
void __attribute__((weak)) arch_report_meminfo(struct seq_file *m)
{
}
@@ -32,6 +33,14 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
unsigned long pages[NR_LRU_LISTS];
struct zone *zone;
int lru;
+ long ram_size;
+ long ram_free_size;
+ char buff[50];
+ struct file *fp = NULL;
+ int men;
+ int j;
+ int mlp;
+ mm_segment_t old_fs;
/*
* display in kilobytes.
@@ -81,6 +90,38 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
if (available < 0)
available = 0;
+ ram_size=K(i.totalram);
+ ram_free_size = K(i.freeram);
+ memset(buff,0x00,sizeof(buff));
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fp = filp_open("/data/prize_backup/RAM",O_RDONLY,0644);
+ if (IS_ERR(fp) || fp == NULL){
+ //ram_size= K(i.totalram);
+ ram_size=6*1024*1024;
+ }else{
+ fp->f_op->read(fp,buff,5,&fp->f_pos);
+ for (j = 0; j < 5; j++)
+ {
+ if (buff[j] == 'g' || buff[j] == 'G')
+ {
+ buff[j] = '\0';
+ break;
+ }
+ }
+ men = simple_strtol(buff,NULL,10);
+ if(men*1024*1024 > ram_size ){
+ ram_size=men*1024*1024;
+ }
+ filp_close(fp,NULL);
+ }
+ mlp = (ram_size - K(i.totalram)) >> 20;
+ if(mlp < 1){
+ ram_free_size = K(i.freeram);
+ }else{
+ ram_free_size = K(i.freeram) + mlp * 1024*1024;
+ }
+ set_fs(old_fs);
/*
* Tagged format, for easy grepping and expansion.
@@ -139,8 +180,8 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
"AnonHugePages: %8lu kB\n"
#endif
,
- K(i.totalram),
- K(i.freeram),
+ (ram_size),
+ (ram_free_size),
K(available),
K(i.bufferram),
K(cached),
kernel-3.18/fs/statfs.c
#include <linux/security.h>
#include <linux/uaccess.h>
#include "internal.h"
+ #include <asm/div64.h>
+ #include <linux/uaccess.h>
+ #define IS_ERR(x) unlikely((unsigned long)(x) >= (unsigned long)-MAX_ERRNO)
static int flags_by_mnt(int mnt_flags)
{
@@ -73,11 +76,44 @@ int vfs_statfs(struct path *path, struct kstatfs *buf)
return error;
}
EXPORT_SYMBOL(vfs_statfs);
+ int fd_get_rom(void){
+ int rom = 0;
+ char buff[50];
+ mm_segment_t old_fs;
+ struct file *fp = NULL;
+ int i;
+ memset(buff,0x00,sizeof(buff));
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fp = filp_open("/data/prize_backup/ROM",O_RDONLY,0644);
+ if (IS_ERR(fp) || fp == NULL){
+ rom = 128;
+ }else{
+ fp->f_op->read(fp,buff,50,&fp->f_pos);
+ for (i = 0; i < 50; i++)
+ {
+ if (buff[i] == 'g' || buff[i] == 'G')
+ {
+ buff[i] = '\0';
+ //buff[i+1] = NULL;
+ break;
+ }
+ }
+ rom = simple_strtol(buff,NULL,10);
+ filp_close(fp,NULL);
+ }
+ set_fs(old_fs);
+ return rom;
+ }
int user_statfs(const char __user *pathname, struct kstatfs *st)
{
struct path path;
int error;
+ int rom;
+ long romsize;
+ long romsized;
+ int mlp;
+ int result;
unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
retry:
error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
@@ -89,6 +125,33 @@ retry:
goto retry;
}
}
+ if (((strcmp("/data/media", pathname) == 0) || (strcmp("/data", pathname) == 0) || (strcmp("/storage/emulated/0", pathname) == 0)
+ || (strcmp("/storage/emulated/0/", pathname) == 0))&& st != 0) {
+ rom = fd_get_rom();
+ romsize = st->f_blocks;
+ romsized = st->f_blocks;
+ if(rom*1024*256 > romsize){
+ romsize = rom*1024*256;
+ romsized = rom*1024*256;
+ }
+ mlp = do_div(romsize, st->f_blocks);
+
+ result = romsize;
+
+ if(st->f_bavail <= (1000* 1024 / 4)){
+
+ }else{
+ st->f_bavail = (romsized - (st->f_blocks - st->f_bavail)) - 3 * 1024 * 1024 /2;
+ }
+
+ if(st->f_bfree <= (1000* 1024 / 4)){
+
+ }else{
+ st->f_bfree = (romsized - (st->f_blocks - st->f_bfree)) - 3 * 1024 * 1024 / 2;
+ }
+
+ st->f_blocks = romsized;
+ }
return error;
}