当前位置:   article > 正文

Android11增加对dpi屏幕密度的设置_android density在哪配置

android density在哪配置

硬件环境

soc:rk3568

android版本:11.0

零、原理讲解

1. 在rk的芯片中,有一块vendor_storage,其中内容掉电保存,用于厂商保存出厂设置,可以通过工厂烧写进去,也可以通过编程修改。

2. ro.sf.lcd_density这个属性可以修改屏幕密度,在每次安卓系统启动之前设置它,在启动的时候就会读取它,进行对属性的修改

3. 程序的逻辑流程如下

系统设置中修改density->保存到vendor_storage中对应节点->重启后读取对应节点内容->设置系统属性->启动->完成密度修改

一、内核修改

1.1 头文件

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

1.2 驱动

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");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250

1.3 赋予对应节点可读属性

device/rockchip/common/init.rk30board.rc

在这里插入图片描述

chmod 0666 /sys/storage/density
  • 1

二、增加设置

2.1 增加对应设置的入口

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>
  • 1
  • 2
  • 3

package/app/Settings/res/values-zh-rcN/strings.xml

<!-- Density box option -->
    <string name="screen_density">屏幕密度设置</string>
    <string name="screen_density_summary">160</string>
  • 1
  • 2
  • 3

2.2 增加对应选项列表

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.3 增加功能代码

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;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182

2.4 增加对功能代码的调用

package/app/Settings/src/com/android/settings/DisplaySettings.java

在这里插入图片描述

import com.android.settings.display.ScreenDensityPreferenceController;
....
controllers.add(new ScreenDensityPreferenceController(context));
  • 1
  • 2
  • 3

三、增加对属性读取

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

四、调试

教程不教人怎么调试就是害人

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

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/836973
推荐阅读
相关标签
  

闽ICP备14008679号