赞
踩
soc:rk3568
android版本:11.0
1. 在rk的芯片中,有一块vendor_storage,其中内容掉电保存,用于厂商保存出厂设置,可以通过工厂烧写进去,也可以通过编程修改。
2. ro.sf.lcd_density
这个属性可以修改屏幕密度,在每次安卓系统启动之前设置它,在启动的时候就会读取它,进行对属性的修改
3. 程序的逻辑流程如下
系统设置中修改density->保存到vendor_storage中对应节点->重启后读取对应节点内容->设置系统属性->启动->完成密度修改
include/linux/soc/rockchip/rk_vendor_storage.h
增加一个ID DENSITY_ID对应density的属性保存
/* * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. */ #ifndef __PLAT_RK_VENDOR_STORAGE_H #define __PLAT_RK_VENDOR_STORAGE_H #define RSV_ID 0 #define SN_ID 1 #define WIFI_MAC_ID 2 #define LAN_MAC_ID 3 #define BT_MAC_ID 4 #define HDCP_14_HDMI_ID 5 #define HDCP_14_DP_ID 6 #define HDCP_2X_ID 7 #define DRM_KEY_ID 8 #define PLAYREADY_CERT_ID 9 #define ATTENTION_KEY_ID 10 #define PLAYREADY_ROOT_KEY_0_ID 11 #define PLAYREADY_ROOT_KEY_1_ID 12 #define SENSOR_CALIBRATION_ID 13 #define IMEI_ID 15 #define LAN_RGMII_DL_ID 16 #define EINK_VCOM_ID 17 /* 增加的ID */ #define ORIENTATION_ID 50 #define DENSITY_ID 51 int rk_vendor_read(u32 id, void *pbuf, u32 size); int rk_vendor_write(u32 id, void *pbuf, u32 size); int rk_vendor_register(void *read, void *write); bool is_rk_vendor_ready(void); #endif
driver/soc/rockchip/storage_vendor.c
增加对id的过滤,对density节点的创建
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/workqueue.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include <linux/device.h> #include <linux/uaccess.h> #include <linux/soc/rockchip/rk_vendor_storage.h> #include <linux/string.h> #define VENDOR_GET_MAX 32 /* 定义数据大小 */ struct storage_data { char orientation[VENDOR_GET_MAX]; char density[VENDOR_GET_MAX]; struct kobject *s_kobj; }; static struct storage_data *gdata = NULL; struct storage_attribute { struct attribute attr; ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,char *buf); ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n); }; static int read_storage(struct storage_data *sData, int id); static int write_storage(struct storage_data *sData, int id, const char *buff); static ssize_t orientation_storage_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { if(gdata == NULL){ return -1; } if(read_storage(gdata, ORIENTATION_ID) > 0){ return sprintf(buf, "%s\n", gdata->orientation); } else { return sprintf(buf, "%s\n","null"); } } static ssize_t orientation_storage_write(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { int ret = -1; if(gdata==NULL){ return -1; } ret = write_storage(gdata, ORIENTATION_ID, buf); if(ret!=0){ return ret; } return n; } static ssize_t density_storage_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { if(gdata==NULL){ return -1; } if(read_storage(gdata, DENSITY_ID) > 0){ return sprintf(buf, "%s\n", gdata->density); } else { return sprintf(buf, "%s\n","null"); } } static ssize_t density_storage_write(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { int ret = -1; if(gdata==NULL){ return -1; } ret = write_storage(gdata, DENSITY_ID, buf); if(ret!=0){ return ret; } return n; } static struct storage_attribute storage_data_attribute[] = { /* node_name permision show_func store_func */ __ATTR(orientation, S_IRUGO | S_IWUSR, orientation_storage_show, orientation_storage_write), __ATTR(density, S_IRUGO | S_IWUSR, density_storage_show, density_storage_write), }; /* 读取vendorstorage分区数据 */ static int read_storage(struct storage_data *sData, int id) { char str[VENDOR_GET_MAX] = {0}; int ret = -1; memset(str, 0, VENDOR_GET_MAX); ret = rk_vendor_read(id, str, (VENDOR_GET_MAX-1)); if (ret > 0) { switch (id) { case ORIENTATION_ID: strcpy(sData->orientation, str); if(strlen(sData->orientation) <= 0 ){ strcpy(sData->orientation, "null"); } break; case DENSITY_ID: strcpy(sData->density, str); if(strlen(sData->density) <= 0 ){ strcpy(sData->density, "null"); } break; default: goto set_null; } }else { goto set_null; } return ret; set_null: switch (id) { case ORIENTATION_ID: strcpy(sData->orientation, "null"); break; case DENSITY_ID: strcpy(sData->density, "null"); break; default: break; } return ret; } /* 向vendorstorage分区写入数据 */ static int write_storage(struct storage_data *sData, int id, const char *buff) { char str[VENDOR_GET_MAX]; int ret = -1; memset(str, 0, VENDOR_GET_MAX); strcpy(str, buff); ret = rk_vendor_write(id, str, (VENDOR_GET_MAX-1)); if (ret == 0) { printk("%s: Data storage succeeded: %s\n",__func__,str); } else { printk("%s: Data storage failure: %s\n",__func__,str); } return ret; } static int storage_probe(struct platform_device *pdev) { struct storage_data *sData; int ret = -1; sData = kzalloc(sizeof(struct storage_data), GFP_KERNEL); if (!sData) return -ENOMEM; /* /sys下创建storage目录读写接口 */ sData->s_kobj = kobject_create_and_add("storage", NULL); if (!sData->s_kobj) return -1; /* storage目录下创建读写接口 */ ret = sysfs_create_file(sData->s_kobj, &storage_data_attribute[0].attr); if (ret != 0) { printk("%s: create sysfs_create_file error\n",__func__); return ret; } ret = sysfs_create_file(sData->s_kobj, &storage_data_attribute[1].attr); if (ret != 0) { printk("%s: create sysfs_create_file error\n",__func__); return ret; } gdata = sData; platform_set_drvdata(pdev,sData); return 0; } static int storage_remove(struct platform_device *pdev) { struct storage_data *sData = platform_get_drvdata(pdev); kfree(sData); return 0; } #ifdef CONFIG_OF static struct of_device_id storage_of_match[] = { { .compatible = "storage-vendor" }, }; MODULE_DEVICE_TABLE(of, storage_of_match); #endif static struct platform_driver storage_driver = { .probe = storage_probe, .remove = storage_remove, .driver = { .name = "storage_vendor", .owner = THIS_MODULE, #ifdef CONFIG_OF .of_match_table = of_match_ptr(storage_of_match), #endif }, }; static int __init storage_vendor_init(void) { return platform_driver_register(&storage_driver); } static void __exit storage_vendor_exit(void) { platform_driver_unregister(&storage_driver); } late_initcall(storage_vendor_init); module_exit(storage_vendor_exit); MODULE_DESCRIPTION("storage vendor driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:storage vendor");
device/rockchip/common/init.rk30board.rc
chmod 0666 /sys/storage/density
package/app/Settings/res/values/strings.xml
<!-- Density box option -->
<string name="screen_density">Screen Density Options</string>
<string name="screen_density_summary">160</string>
package/app/Settings/res/values-zh-rcN/strings.xml
<!-- Density box option -->
<string name="screen_density">屏幕密度设置</string>
<string name="screen_density_summary">160</string>
package/app/Settings/res/values/arrays.xml
<!-- Screen rotate options -->
<string-array name="screen_density_entries">
<item>120</item>
<item>160</item>
<item>200</item>
<item>240</item>
</string-array>
<string-array name="screen_density_values" translatable="false">
<item>120</item>
<item>160</item>
<item>200</item>
<item>240</item>
</string-array>
package/app/Settings/src/com/android/settings/display/ScreenDensityPreferenceController.java
package com.android.settings.display; import android.app.settings.SettingsEnums; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.text.TextUtils; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import androidx.annotation.VisibleForTesting; import androidx.preference.ListPreference; import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import android.content.Intent; import java.util.ArrayList; import java.util.List; import java.util.Objects; import android.util.Log; import java.io.File; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; public class ScreenDensityPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener { private static final String TAG = "ScreenDensity"; private static final String KEY_SCREEN_DENSITY = "screen_density"; private static final String STORAGE_PATH = "/sys/storage/density"; private static final String DENSITY_120 = "120"; private static final String DENSITY_160 = "160"; private static final String DENSITY_200 = "200"; private static final String DENSITY_240 = "240"; Context mContext; public ScreenDensityPreferenceController(Context context) { super(context); mContext = context; } @Override public String getPreferenceKey() { return KEY_SCREEN_DENSITY; } @Override public boolean isAvailable() { return true; } /* 获取分区保存的屏幕密度参数,并显示出来 */ @Override public void updateState(Preference preference) { ListPreference pref = (ListPreference) preference; /* 读取保存在分区的屏幕密度参数 */ String density = ReadFile(STORAGE_PATH); switch(density){ case "D120" : density = DENSITY_120; break; case "D160" : density = DENSITY_160; break; case "D200" : density = DENSITY_200; break; case "D240" : density = DENSITY_240; break; default : density = DENSITY_160; break; } /* 更新界面显示当前屏幕密度的参数 */ pref.setSummary(density); pref.setValue(density); } /* 获取人工设置的屏幕密度参数,并保存到分区中*/ @Override public boolean onPreferenceChange(Preference preference, Object newValue) { ListPreference pref = (ListPreference) preference; int value = Integer.parseInt((String) newValue); String density = "0"; /* value是界面选择的旋转参数,并转换为带R标志参数 */ switch(value){ case 120 : density = "D120"; break; case 160 : density = "D160"; break; case 200 : density = "D200"; break; case 240 : density = "D240"; break; default : density = "D160"; break; } /* 将设置的屏幕密度的参数写入分区中保存 */ int ret = WriteFile(STORAGE_PATH, density); if(ret == 0){ pref.setSummary((String) newValue); Log.d(TAG,"density = " + density); /* 弹出重启选项按键 */ new AlertDialog.Builder(mContext) .setTitle("设置重启后生效") .setMessage("是否立刻重启") .setCancelable(true) .setPositiveButton("立刻重启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { /* 数据写入成功后,自动重启系统使其生效 */ Intent intent = new Intent(Intent.ACTION_REBOOT); intent.putExtra("nowait", 1); intent.putExtra("interval", 1); intent.putExtra("window", 0); mContext.sendBroadcast(intent); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }) .show(); } return true; } /* 读取底层接口数据函数 */ public String ReadFile(String filePath) { File file = new File(filePath); if((file != null) && file.exists()) { try { FileInputStream fs= new FileInputStream(file); BufferedReader reader= new BufferedReader(new InputStreamReader(fs)); String density = reader.readLine(); fs.close(); Log.d(TAG, "===== read density:" + density + "======"); return density; } catch(IOException e) { e.printStackTrace(); } } return null; } /* 把数据写入底层接口函数 */ public int WriteFile(String filePath, String density) { Log.d(TAG,"WriteFile, write density = " + density); File file = new File(filePath); if((file == null) || !file.exists()) { Log.e(TAG, "write error: " + filePath); return -1; } try { FileOutputStream fos = new FileOutputStream(file); PrintWriter pWriter = new PrintWriter(fos); pWriter.println(density); pWriter.flush(); pWriter.close(); fos.close(); return 0; } catch(IOException ret) { Log.d(TAG,"write error:" + ret); return -1; } } }
package/app/Settings/src/com/android/settings/DisplaySettings.java
import com.android.settings.display.ScreenDensityPreferenceController;
....
controllers.add(new ScreenDensityPreferenceController(context));
system/core/init/init.cpp
在SecondStageMain()中增加以下内容
注意:如果在别的mk(比如device.mk、rk3568_r.mk等)文件中有对
ro.sf.lcd_density
属性的修改,请去除,否则会覆盖以下代码设置的属性
std::string density; if (ReadFileToString("/sys/storage/density", &density)) { if(strstr(density.c_str(), "D120")){ SetProperty("ro.sf.lcd_density", "120"); } else if(strstr(density.c_str(), "D160")){ SetProperty("ro.sf.lcd_density", "160"); } else if(strstr(density.c_str(), "D200")){ SetProperty("ro.sf.lcd_density", "200"); } else if(strstr(density.c_str(), "D240")){ SetProperty("ro.sf.lcd_density", "240"); } else { SetProperty("ro.sf.lcd_density", "160"); } LOG(ERROR) << "Density: open /sys/storage/density " << density; } else { LOG(ERROR) << "Prientation: Unable to open /sys/storage/density"; SetProperty("ro.sf.lcd_density", "160"); }
教程不教人怎么调试就是害人
1.检查vendor_storage节点
cat /sys/storage/density
ls -l /sys/storage/density
2.检查系统属性
getprop |grep ro.sf.lcd_density
3.查看log
logcat -b all | grep density
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。