[SPRD] 版本修改集锦

[SPRD] 版本修改集锦

1、预装 app

一般就三种情况,预装不可卸载,预装可卸载恢复出厂恢复,预装可卸载恢复出厂不能恢复

可参考 内置apk

1.1、预装不可卸载

这种情况 app 最终位于 system/app 或 system/priv-app 即可,作为系统应用,不可卸载

Android.mk 中不配置输出路径则默认打包到 system/app

要想打包到 system/priv-app 则配置 LOCAL_PRIVILEGED_MODULE := true

1.2、预装可卸载恢复出厂恢复

这种情况就比较特殊了,不同的厂商会有自己的方法。

MTK 将 app 依旧作为系统 app,增加了一个包名清单可配置要卸载的系统应用,

这样就确保了能卸载,恢复出厂系统应用又能自动恢复。

RK 也是将 app 作为系统 app,通过放置到特殊文件夹确保可卸载,卸载时会将包名写入缓存文件,

恢复出厂系统会读取缓存文件判断是否需要安装对应 app。

SQRD 也有自己的方法,将 app 打包到 system/vital-app 或 system/preloadapp 即可

这两个目录区别如下

preloadapp 目录中的应用在开机的过程是异步安装的(有利于加快开机速度),存在开机后在 home 界面,

该目录下的应用一个个显示出来的现象。如果是开机急于使用的应用,

例如说在 Launcher 上配置了文件夹存放第三方应用,建议放在 vital-app 目录中,如果不要求开机即使用,建议存放在 preloadapp 目录。

vital-app 目录中的应用在开机的过程中是同步安装的,开机后不会出现上述 preloadapp 下应用一个个出现的现象,

但是会造成开机时间相应变长。一般需要开机进入待机就要安装好的应用(如输入法应用)才建议预置到该目录。

Android.mk 中增加配置

LOCAL_MODULE_PATH := $(TARGET_OUT)/preloadapp

LOCAL_MODULE_PATH := $(TARGET_OUT)/vital-app

1.3、预装可卸载恢复出厂不能恢复

这种情况一般都是将 app 打包到 data/app 目录即可

Android.mk 中增加配置

LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)

10.0 存在 bug data/app 中放置了 apk,烧写后系统不能正常启动,会自动进入 recovery 界面,提示需要清除 usedata 数据

也就是 data/app 下的 apk。解决办法 androidQ(10.0) 预装集成apk到data分区

2、系统主题风格切换

apk 中有很多资源文件,包括应用图标和名称。国产手机在系统主题切换这块做的很顶,网上思路很多,这里用一种偷懒的办法单机版本。

aosp 本身 app 图标和名称是非常丑的,这就需要我们给它美化一番。

2.1、获取这些 app 包名

按个点击进入这些 app,依次执行 adb shell dumpsys window | findstr mCurrentFocus 获取包名

2.2、自己搜罗一套精美 icon

2.3、开始替换之旅

替换图标

将 icon 资源文件 copy 至 frameworks/base/core/res/res/drawable-xhdpi/

配置 icon 为 drawable 资源

frameworks/base/core/res/res/values/symbols.xml

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

根据包名替换对应 drawable 资源

frameworks/base/core/java/android/app/ApplicationPackageManager.java

@@ -114,6 +114,11 @@ import java.util.Map;

import java.util.Objects;

import java.util.Set;

+import java.util.HashMap;

+import java.util.HashSet;

+import android.graphics.BitmapFactory;

+import com.android.internal.R;

+

/** @hide */

public class ApplicationPackageManager extends PackageManager {

private static final String TAG = "ApplicationPackageManager";

@@ -123,6 +128,10 @@ public class ApplicationPackageManager extends PackageManager {

// Default flags to use with PackageManager when no flags are given.

private final static int sDefaultFlags = PackageManager.GET_SHARED_LIBRARY_FILES;

+ //20210323 cczheng add for Chromium icon S

+ private static HashMap appMaps = new HashMap<>();

+ private static String[] appName={"com.android.deskclock","com.android.settings",

+ "com.android.calendar","com.android.email",

+ "com.android.music","com.mediatek.camera",

+ "com.android.fmradio","com.android.calculator2",

+ "com.android.documentsui", "com.android.soundrecorder",

+ "com.android.gallery3d","com.mediatek.filemanager",

+ "com.android.browser","com.android.mms",

+ "com.android.dialer","com.android.contacts",

+ "com.android.stk","com.android.quicksearchbox","com.google.android.apps.maps",

+ "com.android.vending","com.google.android.videos","com.google.android.calendar",

+ "com.google.android.gm","com.google.android.music","com.google.android.apps.photos",

+ "com.google.android.googlequicksearchbox"};

+

+ private static int[] appImg={R.drawable.ic_app_deskclock,R.drawable.ic_app_settings,

+ R.drawable.ic_app_calendar,R.drawable.ic_app_email,

+ R.drawable.ic_app_music,R.drawable.ic_app_camera,

+ R.drawable.ic_app_fmradio,R.drawable.ic_app_calculator2,

+ R.drawable.ic_app_download, R.drawable.ic_app_sounder,

+ R.drawable.ic_app_gallery,R.drawable.ic_app_filemanager,

+ R.drawable.ic_app_browser, R.drawable.ic_app_mms,

+ R.drawable.ic_app_dialer, R.drawable.ic_app_contacts,

+ R.drawable.ic_app_stk,R.drawable.ic_app_quicksearchbox,R.drawable.ic_app_map,

+ R.drawable.ic_app_store,R.drawable.ic_app_vedio,R.drawable.ic_app_calendar,

+ R.drawable.ic_app_email,R.drawable.ic_app_music,R.drawable.ic_app_gallery,

+ R.drawable.ic_app_quicksearchbox};//E

private final Object mLock = new Object();

@@ -1656,6 +1665,10 @@ public class ApplicationPackageManager extends PackageManager {

IPackageManager pm) {

mContext = context;

mPM = pm;

+ ////20210323 cczheng add for Chromium icon S

+ for(int i=0;i

+ appMaps.put(appName[i],new Integer(appImg[i]));

+ }//E

}

@Override

@@ -2832,6 +2848,10 @@ public class ApplicationPackageManager extends PackageManager {

if (dr == null) {

dr = itemInfo.loadDefaultIcon(this);

}

+ //20210323 cczheng add for Chromium icon S

+ if(appMaps.containsKey(itemInfo.packageName)){

+ dr =mContext.getResources().getDrawable(appMaps.get(itemInfo.packageName).intValue());

+ }//E

return dr;

}

frameworks/base/core/java/android/content/pm/LauncherActivityInfo.java

+import java.util.HashMap;

+import java.util.HashSet;

+import android.os.SystemProperties;

+import android.graphics.BitmapFactory;

+import com.android.internal.R;

+

@@ -40,6 +46,10 @@ public class LauncherActivityInfo {

private ActivityInfo mActivityInfo;

private ComponentName mComponentName;

private UserHandle mUser;

+ //20210323 cczheng add for Chromium icon S

+ private static HashMap appMaps = new HashMap<>();

+ private static String[] appName={"com.android.deskclock","com.android.settings",

+ "com.android.calendar","com.android.email",

+ "com.android.music","com.mediatek.camera",

+ "com.android.fmradio","com.android.calculator2",

+ "com.android.documentsui", "com.android.soundrecorder",

+ "com.android.gallery3d","com.mediatek.filemanager",

+ "com.android.browser","com.android.mms",

+ "com.android.dialer","com.android.contacts",

+ "com.android.stk","com.android.quicksearchbox","com.google.android.apps.maps",

+ "com.android.vending","com.google.android.videos","com.google.android.calendar",

+ "com.google.android.gm","com.google.android.music","com.google.android.apps.photos",

+ "com.google.android.googlequicksearchbox"};

+

+ private static int[] appImg={R.drawable.ic_app_deskclock,R.drawable.ic_app_settings,

+ R.drawable.ic_app_calendar,R.drawable.ic_app_email,

+ R.drawable.ic_app_music,R.drawable.ic_app_camera,

+ R.drawable.ic_app_fmradio,R.drawable.ic_app_calculator2,

+ R.drawable.ic_app_download, R.drawable.ic_app_sounder,

+ R.drawable.ic_app_gallery,R.drawable.ic_app_filemanager,

+ R.drawable.ic_app_browser, R.drawable.ic_app_mms,

+ R.drawable.ic_app_dialer, R.drawable.ic_app_contacts,

+ R.drawable.ic_app_stk,R.drawable.ic_app_quicksearchbox,R.drawable.ic_app_map,

+ R.drawable.ic_app_store,R.drawable.ic_app_vedio,R.drawable.ic_app_calendar,

+ R.drawable.ic_app_email,R.drawable.ic_app_music,R.drawable.ic_app_gallery,

+ R.drawable.ic_app_quicksearchbox};//E

@@ -57,6 +67,10 @@ public class LauncherActivityInfo {

LauncherActivityInfo(Context context) {

mPm = context.getPackageManager();

+ ////20210323 cczheng add for Chromium icon S

+ for(int i=0;i

+ appMaps.put(appName[i],new Integer(appImg[i]));

+ }//E

}

@@ -118,6 +132,13 @@ public class LauncherActivityInfo {

if (icon == null) {

icon = mActivityInfo.loadIcon(mPm);

}

+ ////20210323 cczheng add for Chromium icon S

+ if(appMaps.containsKey(mActivityInfo.packageName)){

+ try {

+ icon = mPm.getResourcesForApplication(mActivityInfo.applicationInfo).getDrawable(appMaps.get(mActivityInfo.packageName).intValue());

+ } catch (NameNotFoundException | Resources.NotFoundException exc) {

+ }

+ }//E

return icon;

}

去除图标默认增加的白边

Android 8~Android 11 去掉 Launcher3 默认给 icon 增加的白边

替换名称

launcher3 桌面名称

packages/apps/Launcher3/src/com/android/launcher3/BubbleTextView.java

@@ -291,7 +291,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,

mDotParams.color = IconPalette.getMutedColor(info.iconColor, 0.54f);

setIcon(iconDrawable);

- setText(info.title);

+ //20210323 cczheng add for Chromium name S

+ if ("Chromium".equals(info.title)) {

+ String appName = getContext().getResources().getString(com.android.internal.R.string.browserName);

+ setText(appName);

+ android.util.Log.d("Launcher3","appName="+appName);

+ }else {//E

+ setText(info.title);

+ }

if (info.contentDescription != null) {

setContentDescription(info.isDisabled()

? getContext().getString(R.string.disabled_app_label, info.contentDescription)

Settings 应用详情名称

frameworks/base/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java

@@ -1590,6 +1590,10 @@ public class ApplicationsState {

this.mounted = true;

CharSequence label = info.loadLabel(context.getPackageManager());

this.label = label != null ? label.toString() : info.packageName;

+ //20210323 cczheng add for Chromium name S

+ if ("org.chromium.chrome".equals(info.packageName)) {

+ this.label = context.getResources().getString(com.android.internal.R.string.browserName);

+ }//E

}

}

}

3、开关机动画、铃声

开机动画资源 bootanimation.zip

关机机动画资源 shutdownanimation.zip

开机铃声资源 bootsound.mp3

注:名称不能改动,将上面三个资源预置到 system/media 目录下

关机动画不能正常播放 bug

frameworks/base/cmds/bootanimation/BootAnimation.cpp

@@ -1088,6 +1088,14 @@ bool BootAnimation::playAnimation(const Animation& animation)

continue; //to next part

}

+

+#ifdef BOOTANIMATION_EXT

+ if (mShuttingDown && mfd == -1 && mWaitForComplete && (i==(pcount-1))) {

+ ALOGD("shutdown animation finished, quit");

+ property_set("service.bootanim.end", "1");

+ }

+#endif

+

for (int r=0 ; !part.count || r

// Exit any non playuntil complete parts immediately

if(exitPending() && !part.playUntilComplete)

@@ -1172,12 +1180,12 @@ bool BootAnimation::playAnimation(const Animation& animation)

if(exitPending() && !part.count && mCurrentInset >= mTargetInset)

break;

}

-#ifdef BOOTANIMATION_EXT

- if (mShuttingDown && mfd == -1 && mWaitForComplete) {

- ALOGD("shutdown animation part1 finished, quit");

- property_set("service.bootanim.end", "1");

- }

-#endif

frameworks/base/services/core/java/com/android/server/power/ShutdownAnimation.java

@@ -38,6 +38,7 @@ public class ShutdownAnimation {

try {

mPlayAnim = true;

Slog.i(TAG, "exec the bootanimation ");

+ SystemProperties.set("service.wait_for_bootanim", "1");

SystemProperties.set("service.bootanim.exit", "0");

SystemProperties.set("service.bootanim.end", "0");

SystemProperties.set("service.bootanim.shutdown", "1");

4、双卡改单卡配置

请在 device/sprd/sharkl3/s9863a1h10/s9863a1h10_Natv.mk (项目对应的具体工程文件)最下面添加如下代码。

SIM_COUNT := 1 PRODUCT_PROPERTY_OVERRIDES := persist.vendor.radio.phone_count=1 persist.radio.multisim.config=ssss $(PRODUCT_PROPERTY_OVERRIDES)

5、OTA 相关

通用打包指令,通用校验方法,通用升级方法

RecoverySystem.verifyPackage() 对 ota 升级包进行校验,报错 log 如下

libvintf: Could not open /proc/config.gz: 13

2021-03-26 11:27:14.981 2495-2758/com.wxtx.systemupdate W/libvintf: Cannot fetch or parse /proc/config.gz: Permission denied

2021-03-26 11:27:14.981 2495-2758/com.wxtx.systemupdate W/libvintf: Cannot fetch or parse kernel sepolicy version: Operation not permitted

2021-03-26 11:27:14.992 2495-2758/com.wxtx.systemupdate W/VintfObject: VintfObject.verify() returns 1: Runtime info and framework compatibility matrix are incompatible: kernelSepolicyVersion = 0 but required >= 30

2021-03-26 11:27:15.002 2495-2758/com.wxtx.systemupdate W/System.err: java.security.SignatureException: package compatibility verification failed

2021-03-26 11:27:15.003 2495-2758/com.wxtx.systemupdate W/System.err: at android.os.RecoverySystem.verifyPackage(RecoverySystem.java:350)

2021-03-26 11:27:15.003 2495-2758/com.wxtx.systemupdate W/System.err: at com.wxtx.systemdownload.helper.SystemUpgrade$2.onConfirmUpdate(SystemUpgrade.java:141)

2021-03-26 11:27:15.003 2495-2758/com.wxtx.systemupdate W/System.err: at com.wxtx.systemdownload.helper.SystemUpgrade$2.run(SystemUpgrade.java:129)

解决办法如下

system/sepolicy/private/system_app.te system/sepolicy/prebuilts/api/29.0/private/system_app.te

allow system_app config_gz:file { read open };

allow system_app selinuxfs:file { read open };

device/sprd/sharkle/common/sepolicy/uncrypt.te

allow uncrypt mmcblk_device:blk_file { open write };

allow uncrypt userdata_block_device:blk_file { open write };

allow uncrypt system_app_data_file:dir {read};

allow uncrypt system_app_data_file:file {read};

# For GOTA

allow uncrypt self:capability { fowner sys_admin };

allow uncrypt ota_package_file:file { write };

# For inner local ota update in /data/meida/0

allow uncrypt media_rw_data_file:file { open getattr read ioctl write };

allow uncrypt media_rw_data_file:dir { open getattr read search };

allow uncrypt metadata_file:dir { search };

https://blog.csdn.net/u010867436/article/details/107206349/

https://blog.csdn.net/m1126125223/article/details/101015976

6、解锁 OEM 方法

展讯设备解锁需要在 linux 环境下执行相关指令

sudo apt-get install android-tools-adb sudo apt-get install android-tools-fastboot

1、虚拟机-可移动设备-选中手机从主机切换为虚拟机

2、adb devices 显示 no permissions lsusb 获取设备 vid 和 pid

sudo vim /etc/udev/rules.d/51-android.rules 没有这个文件就自己新建一个

SUBSYSTEM==“usb”,ATTRS{idVendor}“vid”,ATTRS{idProduct}“pid”,MODE=“0666”

sudo chmod a+rx /etc/udev/rules.d/51-vboxadd.rules

3、重新插拔设备,齐活

环境搞定了,接下来整理需要的几个关键文件

将下面三个文件 copy 到新建文件夹中

signidentifier_unlockbootloader.sh rsa4096_vbmeta.pem fastboot

vendor\sprd\proprietories-source\packimage_scripts\signidentifier_unlockbootloader.sh vendor\sprd\proprietories-source\packimage_scripts\signimage\sprd\config\rsa4096_vbmeta.pem

4、开始解锁

4.1、获取设备 Product SN 序列号 a、设备开机后连接ubuntu电脑,执行adb reboot bootloader,将设备启动到fastboot模式。 b、通过下面的命令获取SN序列号

$ sudo ./fastboot oem get_identifier_token (bootloader) Identifier token:

(bootloader) 3631313536383435303133303839 3538383432353430353737363239 OKAY [ 0.018s] Finished. Total time: 0.018s

4.2、生成解锁凭证certificate.bin Linux 环境下使用完整 SN 序列号生成证书(certificate.bin)。

生成证书的命令 $./signidentifier_unlockbootloader.sh 3631313536383435303133303839 rsa4096_vbmeta.pem certificate.bin

4.3、使用证书 certificate.bin 解锁

a、设备开机后连接ubuntu电脑,执行adb reboot bootloader,将设备启动到fastboot模式。 b、ubuntu电脑上执行如下的解锁指令

$ sudo ./fastboot flashing unlock_bootloader certificate.bin [sudo] password for liuyg: Sending ‘unlock_message’ (0 KB) OKAY [ 0.000s] unlocking bootloader OKAY [ 59.671s] Finished. Total time: 59.671s

c、按设备音量-键确认

4.4、完成 重启设备后,引导加载程序会先检查设备状态是 LOCKED 还是 UNLOCKED。 如果设备状态是UNLOCKED,设备在开机第一帧 Logo 界面左上角会显示: “INFO: LOCK FLAG IS : UNLOCK!!!” “WARNING: LOCK FLAG IS : UNLOCK, SKIP VERIFY!!! ”

7、状态栏左上角显示运营商信息

frameworks\base\packages\SystemUI\res\values\config.xml

true

以前都是自己加一个在状态栏右边的,现在发现源码中其实已经自带了,打开这个配置就行

CollapsedStatusBarFragment.java --> initOperatorName() OperatorNameView.java

8、状态栏右边增加 SIM 未插入图标

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBarPolicy.java

import android.database.ContentObserver;

-

+import android.telephony.TelephonyManager;

bar at boot

@@ -263,6 +263,8 @@ public class PhoneStatusBarPolicy

});

+ updateNoSim();

+

}

@Override

@@ -405,6 +407,19 @@ public class PhoneStatusBarPolicy

mIconController.setIconVisibility(mSlotSpeakerphone, visible);

}/

+ private final void updateNoSim() {

+ int iconId = R.drawable.ic_qs_no_sim;

+ String contentDescription =

+ mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);

+ TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

+ int simState = telMgr.getSimState();

+ if (simState == TelephonyManager.SIM_STATE_ABSENT) {

+ android.util.Log.d("PhoneStatusBarPolicy", "simState="+simState);

+ mIconController.setIcon("nosim", iconId, contentDescription);

+ mIconController.setIconVisibility("nosim", true);

+ }

+ }

private final void updateBluetooth() {

int iconId = R.drawable.stat_sys_data_bluetooth_connected;

9、Launcher3 去除 HotSeat 栏

packages\apps\Launcher3\src\com\android\launcher3\DeviceProfile.java

hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize, dm) + (isVerticalBarLayout()

? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)

: (res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size)

+ hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx));

android.util.Log.d("DeviceProfile","1 hotseatBarSizePx="+hotseatBarSizePx);

+ hotseatBarSizePx = 0;//set 0 hide hotseat

// Calculate all of the remaining variables.

updateAvailableDimensions(dm, res);

// Hotseat

if (isVerticalLayout) {

hotseatBarSizePx = iconSizePx + hotseatBarSidePaddingStartPx

+ hotseatBarSidePaddingEndPx;

android.util.Log.d("DeviceProfile","3 hotseatBarSizePx="+hotseatBarSizePx);

+ hotseatBarSizePx = 0;//set 0 hide hotseat

}

hotseatCellHeightPx = iconSizePx;

// We want the edges of the hotseat to line up with the edges of the workspace, but the

// icons in the hotseat are a different size, and so don't line up perfectly. To account

// for this, we pad the left and right of the hotseat with half of the difference of a

// workspace cell vs a hotseat cell.

float workspaceCellWidth = (float) widthPx / inv.numColumns;

+ float hotseatCellWidth = 0;//(float) widthPx / inv.numHotseatIcons;

int hotseatAdjustment = Math.round((workspaceCellWidth - hotseatCellWidth) / 2);

mHotseatPadding.set(

hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx,

hotseatBarTopPaddingPx,

hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx,

hotseatBarBottomPaddingPx + mInsets.bottom + cellLayoutBottomPaddingPx);

10、移动数据流量开关增加密码对话框

frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml

frameworks/base/packages/SystemUI/res/values/strings.xml

frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java

frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java

frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java

packages/apps/Settings/src/com/android/settings/accounts/TopLevelAccountEntryPreferenceController.java

packages/apps/Settings/src/com/android/settings/network/telephony/MobileDataPreferenceController.java

+ "输入密码"

+ "开启"

+ "取消"

+ "错误! 再试一次"

+ Input password

+ ON

+ CANCEL

+ Error! Try again

frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java

@@ -443,6 +443,43 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {

mNoMan.notifyAsUser(

TAG_TEMPERATURE, SystemMessage.NOTE_THERMAL_SHUTDOWN, n, UserHandle.ALL);

}

+ // add start

+ @Override

+ public void showOpenMobileDataAlarm() {

+ mHandler.post(() -> showOpenMobileDataAlarmInternal());

+ }

+

+ private void showOpenMobileDataAlarmInternal() {

+ final android.widget.EditText editText = new android.widget.EditText(mContext);

+ editText.setInputType(0x00000012);

+ final SystemUIDialog d = new SystemUIDialog(mContext, R.style.Theme_SystemUI_Dialog_Alert);

+ d.setCancelable(true);

+ d.setTitle(R.string.title_data);

+ d.setView(editText);

+ d.setShowForAllUsers(true);

+ d.setPositiveButton((R.string.title_data_ok),

+ (dialogInterface, which) -> {

+ String password = editText.getText().toString();

+ String password2 = android.os.SystemProperties.get("persist.pdd.data.password", "123456");

+ if (TextUtils.isEmpty(password) || !password2.equals(password)) {

+ android.widget.Toast.makeText(mContext, R.string.title_passerror,

+ android.widget.Toast.LENGTH_LONG).show();

+ }else{

+ //adb shell settings get global mobile_data

+ Settings.Global.putInt(mContext.getContentResolver(),

+ Settings.Global.MOBILE_DATA, 1);

+ }

+ });

+ d.setNegativeButton((R.string.title_data_cancel),

+ (dialogInterface, which) -> {

+ });

+ d.setOnDismissListener(dialogInterface -> {

+ Settings.Global.putInt(mContext.getContentResolver(), "pdd_mobile_data", 0);

+ });

+ d.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

+ d.show();

+ }

+ // add end

@Override

public void showUsbHighTemperatureAlarm() {

frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java

@@ -55,6 +55,10 @@ import java.util.Arrays;

import java.util.concurrent.Future;

import com.sprd.systemui.power.SprdPowerUI;

+import android.app.AlertDialog;

+import android.content.DialogInterface;

+import android.widget.EditText;

+

public class PowerUI extends SystemUI {

static final String TAG = "PowerUI";

@@ -153,6 +157,20 @@ public class PowerUI extends SystemUI {

doUsbThermalEventListenerRegistration();

}

});

+ // add

+ resolver.registerContentObserver(

+ Settings.Global.getUriFor("pdd_mobile_data"),

+ false /*notifyForDescendants*/,

+ new ContentObserver(mHandler) {

+ @Override

+ public void onChange(boolean selfChange) {

+ int state = Settings.Global.getInt(mContext.getContentResolver(),

+ "pdd_mobile_data", 0);

+ if (state == 1) {

+ mWarnings.showOpenMobileDataAlarm();

+ }

+ }

+ });//end

initThermalEventListeners();

}

@@ -220,6 +238,7 @@ public class PowerUI extends SystemUI {

filter.addAction(Intent.ACTION_SCREEN_OFF);

filter.addAction(Intent.ACTION_SCREEN_ON);

filter.addAction(Intent.ACTION_USER_SWITCHED);

+ filter.addAction("cn.pdd.action.opendata");

mContext.registerReceiver(this, filter, null, mHandler);

}

@@ -313,6 +332,8 @@ public class PowerUI extends SystemUI {

mScreenOffTime = -1;

} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {

mWarnings.userSwitched();

+ }else if ("cn.pdd.action.opendata".equals(action)) {

+ //mWarnings.showOpenMobileDataAlarm();

} else {

Slog.w(TAG, "unknown intent: " + intent);

}

@@ -654,6 +675,9 @@ public class PowerUI extends SystemUI {

void showHighTemperatureWarning();

+ //

+ void showOpenMobileDataAlarm();

+

/**

* Display USB port overheat alarm

*/

frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java

protected void handleClick() {

/* UNISOC: bug 916022 @{ */

Log.d(TAG, "handleClick mHasEvent : " + mHasEvent);

+

+ // add start

+ int state = Settings.Global.getInt(mContext.getContentResolver(),Settings.Global.MOBILE_DATA, 1);

+ if (state == 0) {

+ Settings.Global.putInt(mContext.getContentResolver(), "pdd_mobile_data", 1);

+ return;

+ }//end

+

if (mHasEvent) {

return;

}

packages/apps/Settings/src/com/android/settings/network/telephony/MobileDataPreferenceController.java

import com.android.settingslib.core.lifecycle.events.OnStop;

import java.util.List;

+

+import android.provider.Settings;

+import android.provider.Settings.Global;

/**

* Preference controller for "Mobile data"

*/

@@ -99,6 +102,7 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon

@Override

public boolean handlePreferenceTreeClick(Preference preference) {

+ android.util.Log.d("MobileDataController","handlePreferenceTreeClick");

if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {

if (mNeedDialog) {

showDialog(mDialogType);

@@ -111,8 +115,13 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon

@Override

public boolean setChecked(boolean isChecked) {

+ // add start

+ if (isChecked) {

+ Settings.Global.putInt(mContext.getContentResolver(), "pdd_mobile_data", 1);

+ return false;

+ }//end

mNeedDialog = isDialogNeeded();

-

+ android.util.Log.d("MobileDataController","setChecked="+isChecked+" mNeedDialog="+mNeedDialog);

if (!mNeedDialog) {

// Update data directly if we don't need dialog

MobileNetworkUtils.setMobileDataEnabled(mContext, mSubId, isChecked, false);

11、返回键删除正在编辑的 EditText 内容

frameworks\base\core\java\android\app\Activity.java

import android.widget.EditText;

public boolean onKeyUp(int keyCode, KeyEvent event) {

if (getApplicationInfo().targetSdkVersion

>= Build.VERSION_CODES.ECLAIR) {

if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()

&& !event.isCanceled()) {

/* onBackPressed();

return true;*/

//cczheng add start

if (isResumed()) {

View decorView = this.getWindow().getDecorView();

if (decorView != null) {

View focus = decorView.findFocus();

if (focus!=null && focus instanceof EditText) {

EditText editText = (EditText)focus;

CharSequence text = editText.getText();

if (text!=null && text.length()>0) {

int delKeyCode = KeyEvent.KEYCODE_DEL;

editText.onKeyDown(delKeyCode, new KeyEvent(KeyEvent.ACTION_DOWN, delKeyCode));

return true;

}

}

}

onBackPressed(); //MTK modify END

return true;

} else {

return false;

}//cczheng add end

}

}

return false;

}

11、去除 Launcher 图标右上角未读消息小圆点提示

Settings.Secure.putInt(getContentResolver(), Settings.Secure.NOTIFICATION_BADGING, 0);

12、WIFI 已连接,但无法访问互联网

展讯自己把 CAPTIVE_PORTAL_MODE 默认值修改为0了,所以当你真正连接到没有物联网的wifi时,不会提示无法访问互联网。

注释这个 CAPTIVE_PORTAL_MODE 默认赋值就行

adb shell settings get global captive_portal_mode

0:彻底禁用检测1:检测到需要登录则弹窗提醒2:检测到需要登录则自动断开此热点并不再自动连接

frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java

//loadIntegerSetting(stmt, Settings.Global.CAPTIVE_PORTAL_MODE,

// R.integer.captive_portal_mode);

这个放开后,wifi 连接后会有校验,真正能上网的wifi也会提示无法访问互联网

将下面校验网址改成国内可以访问到的即可

packages/modules/NetworkStack/res/values/config.xml

http://www.googleapis.cn/generate_204

http://www.googleapis.cn/generate_204

去除展讯自己加的wifi连接成功后网络主界面多增当前连接Preference

packages/apps/Settings/src/com/android/settings/network/MultiNetworkHeaderController.java

@Override

public int getAvailabilityStatus() {

return CONDITIONALLY_UNAVAILABLE;

}

https://blog.csdn.net/weixin_44008788/article/details/115797278

13、WLAN 直连默认名称、WLAN 热点名称、蓝牙默认名称

frameworks\opt\net\wifi\service\java\com\android\server\wifi\p2p\WifiP2pServiceImpl.java

private String getPersistedDeviceName() {

String deviceName = mFrameworkFacade.getStringSetting(mContext,

Settings.Global.WIFI_P2P_DEVICE_NAME);

if (deviceName == null) {

// We use the 4 digits of the ANDROID_ID to have a friendly

// default that has low likelihood of collision with a peer

String id = mFrameworkFacade.getSecureStringSetting(mContext,

Settings.Secure.ANDROID_ID);

String ssid = WifiFeaturesUtils.FeatureProperty.SUPPORT_SPRD_P2P_CUSTOMIZED_NAME;

/*if (ssid != null && ssid.isEmpty()) {

return "Android_" + id.substring(0, 4);

} else {

return ssid;

}*/

//cczheng change default wifip2p name

return android.os.SystemProperties.get("ro.product.model");

}

return deviceName;

}

frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiApConfigStore.java

private WifiConfiguration getDefaultApConfiguration() {

WifiConfiguration config = new WifiConfiguration();

config.apBand = WifiConfiguration.AP_BAND_2GHZ;

String ssid = WifiFeaturesUtils.FeatureProperty.SUPPORT_SPRD_SOFTAP_CUSTOMIZED_NAME;

if (ssid != null && ssid.isEmpty()) {

config.SSID = mContext.getResources().getString(

R.string.wifi_tether_configure_ssid_default) + "_" + getRandomIntForDefaultSsid();

} else {

config.SSID = ssid;

}

//cczheng change default wifiAP name add

config.SSID = android.os.SystemProperties.get("ro.product.model");

//cczheng end

config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);

String randomUUID = UUID.randomUUID().toString();

//first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx

config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9, 13);

return config;

}

device/generic/common/bluetooth/bdroid_buildcfg.h

#define _BDROID_BUILDCFG_H

-#define BTM_DEF_LOCAL_NAME "Android Bluedroid"

+// #define BTM_DEF_LOCAL_NAME "Android Bluedroid"

+#define BTM_DEF_LOCAL_NAME "HTCOne"

#endif

system/bt/internal_include/bt_target.h

* product model name is used as the default local name.

*/

#ifndef BTM_DEF_LOCAL_NAME

-#define BTM_DEF_LOCAL_NAME ""

+#define BTM_DEF_LOCAL_NAME "HTCOne"

#endif

— a/alps/system/bt/btif/src/btif_dm.cc +++ b/alps/system/bt/btif/src/btif_dm.cc @@ -3361,7 +3361,14 @@ static char* btif_get_default_local_name() { static char* btif_get_default_local_name() { if (btif_default_local_name[0] == ‘\0’) { int max_len = sizeof(btif_default_local_name) - 1; if (BTM_DEF_LOCAL_NAME[0] != ‘\0’) { strncpy(btif_default_local_name, BTM_DEF_LOCAL_NAME, max_len); } else { char prop_model[PROPERTY_VALUE_MAX]; osi_property_get(PROPERTY_PRODUCT_MODEL, prop_model, “”);

strncpy(btif_default_local_name, prop_model, max_len);

// strncpy(btif_default_local_name, prop_model, max_len);

if (strncmp(prop_model, "IK-WST08", 5) == 0){

strncpy(btif_default_local_name, prop_model, max_len);

}else{

char temp[] = "Android Bluedroid";

strncpy(btif_default_local_name, temp, max_len);

}//end

} btif_default_local_name[max_len] = ‘\0’; }

14、系统默认打开深色主题背景功能

1、Provision 中修改默认值 DARK_MODE_DIALOG_SEEN packages/apps/Provision/src/com/android/provision/DefaultActivity.java

Settings.Secure.putInt(getContentResolver(), Settings.Secure.DARK_MODE_DIALOG_SEEN, 1);

2、Settings 中开机启动后再次调用 setNightMode

vendor/sprd/platform/packages/apps/Settings/src/com/sprd/settings/timerpower/AlarmInitReceiver.java

+import android.app.UiModeManager;

+import android.provider.Settings;

+

public class AlarmInitReceiver extends BroadcastReceiver {

private Context mContext;

@@ -46,6 +49,12 @@ public class AlarmInitReceiver extends BroadcastReceiver {

Log.v("AlarmInitReceiver ---- intent = " + intent);

if(Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {

isBoot = true;

+ String keyMode = Settings.System.getString(context.getContentResolver(),"test.pdd.night");

+ if (!"1".equals(keyMode)) {

+ context.getSystemService(UiModeManager.class).setNightMode(UiModeManager.MODE_NIGHT_YES);

+ Log.v("AlarmInitReceiver ---- MODE_NIGHT_YES");

+ Settings.System.putString(context.getContentResolver(), "test.pdd.night", "1");

+ }

}

if (null == mHanderThread) {

Log.v("onReceive mHanderThread is null.");

15、系统默认关闭超级省电模式

超级省电模式 功能由 ro.sys.pwctl.ultrasaving 控制,

1 启用超级省电模式,系统中包含相关菜单

0 关闭超级省电模式

./device/sprd/sharkl5Pro/common/features/base/config.mk:76: ro.sys.pwctl.ultrasaving=1 ./device/sprd/sharkl5Pro/common/features/base/config.mk:79: ro.sys.pwctl.ultrasaving=0 ./device/sprd/sharkl3/common/features/base/config.mk:63: ro.sys.pwctl.ultrasaving=1 ./device/sprd/sharkl3/common/features/base/config.mk:66: ro.sys.pwctl.ultrasaving=0 ./device/sprd/sharkle/common/features/base/config.mk:28: ro.sys.pwctl.ultrasaving=1 ./device/sprd/sharkle/common/features/base/config.mk:31: ro.sys.pwctl.ultrasaving=0 ./device/sprd/pike2/common/features/base/config.mk:27: ro.sys.pwctl.ultrasaving=1 ./device/sprd/pike2/common/features/base/config.mk:30: ro.sys.pwctl.ultrasaving=0 ./device/sprd/qogirn6pro/common/features/base/config.mk:76: ro.sys.pwctl.ultrasaving=1 ./device/sprd/qogirn6pro/common/features/base/config.mk:79: ro.sys.pwctl.ultrasaving=0

16、Launcher3 空白长按弹出 popwindow 功能跳转定制

packages\apps\Launcher3\src\com\android\launcher3\views\OptionsPopupView.java

options.add(new OptionItem(R.string.contact_button_text, R.drawable.ic_setting,

ControlType.SETTINGS_BUTTON, OptionsPopupView::startContact));

public static boolean startContact(View view) {

Launcher launcher = Launcher.getLauncher(view.getContext());

launcher.startActivity(new Intent()

.setComponent(new android.content.ComponentName("com.android.contacts",

"com.android.contacts.activities.PeopleActivity"))

.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

return true;

}

17、设备壁纸页面直接跳转

想要直接跳转到系统自带所有壁纸详细页面,WallpaperPicker2 中并没有暴露直接页面 IndividualPickerActivity

packages\apps\WallpaperPicker2\AndroidManifest.xml

android:label="@string/app_name"

android:theme="@style/WallpaperTheme"

android:resizeableActivity="true"

android:parentActivityName="com.android.wallpaper.picker.TopLevelPickerActivity">

解决 IndividualPickerActivity 中加载数据 mCategory 为 null 问题,默认的数据加载 Application 中 load 一次后,其它各个

子页面直接使用即可,我们现在直接跳转子页面,很显然数据是拿不到的,所以就得自己规避这个问题。

通过传递参数 mode 来区分是直接跳转还是原有从主页点击进入,direct 模式下先主动 load 一遍数据,等数据

load 成功后再显示界面

startActivity(new Intent() .setComponent(new android.content.ComponentName(“com.android.wallpaper”, “com.android.wallpaper.picker.individual.IndividualPickerActivity”)) .putExtra(“com.android.wallpaper.category_collection_id”, “on_device_wallpapers”) .putExtra(“mode”, “direct”) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

packages\apps\WallpaperPicker2\src\com\android\wallpaper\picker\individual\IndividualPickerActivity.java

import android.os.Handler;

import android.os.Message;

import com.android.wallpaper.module.WallpapersInjector;

import com.android.wallpaper.model.CategoryReceiver;

Bundle savedInstanceState;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

this.savedInstanceState = savedInstanceState;

setContentView(R.layout.activity_single_fragment_with_toolbar);

if ("direct".equals(getIntent().getStringExtra("mode"))) {

android.util.Log.i(TAG,"setInjector WallpapersInjector");

InjectorProvider.setInjector(new WallpapersInjector());

InjectorProvider.getInjector().getCategoryProvider(this).fetchCategories(new CategoryReceiver() {

@Override

public void onCategoryReceived(Category category) {

android.util.Log.d(TAG,"onCategoryReceived "+ category.getCollectionId());

if ("on_device_wallpapers".equals(category.getCollectionId())) {

mHandler.sendEmptyMessage(100);

}

}

@Override

public void doneFetchingCategories() {

}

}, true);

}else{

doRealyView();

}

}

private Handler mHandler = new Handler() {

public void handleMessage(Message msg) {

doRealyView();

}

};

private void doRealyView(){

// Set toolbar as the action bar.

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

setSupportActionBar(toolbar);

mPreviewIntentFactory = new PreviewActivityIntentFactory();

Injector injector = InjectorProvider.getInjector();

mWallpaperPersister = injector.getWallpaperPersister(this);

mLiveWallpaperStatusChecker = injector.getLiveWallpaperStatusChecker(this);

FragmentManager fm = getSupportFragmentManager();

Fragment fragment = fm.findFragmentById(R.id.fragment_container);

mCategoryCollectionId = (savedInstanceState == null)

? getIntent().getStringExtra(EXTRA_CATEGORY_COLLECTION_ID)

: savedInstanceState.getString(KEY_CATEGORY_COLLECTION_ID);

android.util.Log.d(TAG,"mCategoryCollectionId="+mCategoryCollectionId);

mCategory = injector.getCategoryProvider(this).getCategory(mCategoryCollectionId);

if (mCategory == null) {

android.util.Log.e(TAG,"getOnDeviceCategory=");

// mCategory = getOnDeviceCategory(this);

}

if (mCategory == null) {

DiskBasedLogger.e(TAG, "Failed to find the category: " + mCategoryCollectionId, this);

// We either were called with an invalid collection Id, or we're restarting with no

// saved state, or with a collection id that doesn't exist anymore.

// In those cases, we cannot continue, so let's just go back.

finish();

return;

}

setTitle(mCategory.getTitle());

getSupportActionBar().setTitle(mCategory.getTitle());

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

toolbar.getNavigationIcon().setTint(getColor(R.color.toolbar_icon_color));

toolbar.getNavigationIcon().setAutoMirrored(true);

boolean isInMultiWindowMode = isInMultiWindowMode();

android.util.Log.e(TAG,"isInMultiWindowMode="+isInMultiWindowMode);

getWindow().setStatusBarColor(0);//for bug StatusBar show half

getWindow().getDecorView().setSystemUiVisibility(

getWindow().getDecorView().getSystemUiVisibility()

| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

getWindow().getDecorView().setOnApplyWindowInsetsListener((view, windowInsets) -> {

view.setPadding(

isInMultiWindowMode ? windowInsets.getSystemWindowInsetLeft() : view.getPaddingLeft(),

windowInsets.getSystemWindowInsetTop(),

isInMultiWindowMode ? windowInsets.getSystemWindowInsetRight() : view.getPaddingRight(),

view.getPaddingBottom());

// Consume only the top inset (status bar), to let other content in the Activity consume

// the nav bar (ie, by using "fitSystemWindows")

if (BuildCompat.isAtLeastQ()) {

WindowInsets.Builder builder = new WindowInsets.Builder(windowInsets);

android.util.Log.i(TAG,"left="+windowInsets.getSystemWindowInsetLeft()

+" right="+windowInsets.getStableInsetRight()

+" bottom="+windowInsets.getSystemWindowInsetBottom());

builder.setSystemWindowInsets(Insets.of(windowInsets.getSystemWindowInsetLeft(),

0, windowInsets.getStableInsetRight(),

windowInsets.getSystemWindowInsetBottom()));

return builder.build();

} else {

return windowInsets.replaceSystemWindowInsets(

windowInsets.getSystemWindowInsetLeft(),

0, windowInsets.getStableInsetRight(),

windowInsets.getSystemWindowInsetBottom());

}

});

if (fragment == null) {

fragment = injector.getIndividualPickerFragment(mCategoryCollectionId);

fm.beginTransaction()

.add(R.id.fragment_container, fragment)

.commit();

}

}

18、横屏紧急拨号界面不居中显示问题

packages/apps/PhoneCommon/res/layout-land/dialpad_key.xml packages/apps/PhoneCommon/res/layout-land/dialpad_key_one.xml packages/apps/PhoneCommon/res/layout-land/dialpad_key_pound.xml packages/apps/PhoneCommon/res/layout-land/dialpad_key_star.xml packages/apps/PhoneCommon/res/layout-land/dialpad_key_zero.xml

去除这个属性

android:orientation="horizontal"

android:baselineAligned="false">

19、系统蓝牙名称兼容修改

蓝牙名称真正获取值的地方位于 system/bt/btif/src/btif_dm.cc btif_get_default_local_name()

原有逻辑先读取 BTM_DEF_LOCAL_NAME 是否不为空,为空则读取设备 ro.product.model 值

先将默认 Android Bluedroid 值清空 device/generic/common/bluetooth/bdroid_buildcfg.h

+#define BTM_DEF_LOCAL_NAME ""

+// #define BTM_DEF_LOCAL_NAME "Android Bluedroid"

#endif

system/bt/internal_include/bt_target.h

#ifndef BTM_DEF_LOCAL_NAME

+#define BTM_DEF_LOCAL_NAME ""

+// #define BTM_DEF_LOCAL_NAME "Android Bluedroid"

#endif

然后从prop中读取兼容名称配置

system/bt/btif/src/btif_dm.cc static char* btif_get_default_local_name() { if (btif_default_local_name[0] == ‘\0’) { int max_len = sizeof(btif_default_local_name) - 1; if (BTM_DEF_LOCAL_NAME[0] != ‘\0’) { strncpy(btif_default_local_name, BTM_DEF_LOCAL_NAME, max_len); } else { char prop_model[PROPERTY_VALUE_MAX]; osi_property_get(PROPERTY_PRODUCT_MODEL, prop_model, “”);

// strncpy(btif_default_local_name, prop_model, max_len);

// change this

if (strncmp(prop_model, "AVSCK", 5) == 0){

strncpy(btif_default_local_name, prop_model, max_len);

}else{

char temp[] = "HTC ONE";

strncpy(btif_default_local_name, temp, max_len);

}//end

} btif_default_local_name[max_len] = ‘\0’; } return btif_default_local_name; }

# 20、设置锁屏后锁屏界面默认显示向上滑动已解锁

**frameworks/base/packages/SystemUI/res/layout/keyguard_bottom_area.xml**

```java

android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"

android:accessibilityLiveRegion="polite" />

+

+

+ android:id="@+id/unlock_text"

+ android:layout_width="match_parent"

+ android:layout_height="wrap_content"

+ android:text="@string/keyguard_unlock"

+ android:gravity="center"

+ android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"/>

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

public void onUnlockHintStarted() {

mFalsingManager.onUnlockHintStarted();

- mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);

+ // mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);//remove click don't auto swap change

}

21、去除12新加调用相机时右上角小绿点

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\events\PrivacyDotViewController.kt

val contentDescription: String? = null

) {

fun shouldShowDot(): Boolean {

- return systemPrivacyEventIsActive && !shadeExpanded && !qsExpanded

+ //return systemPrivacyEventIsActive && !shadeExpanded && !qsExpanded

+ return false

}

22、横屏 Activity 调用键盘静止全屏覆盖

Activity 设置 style

+

相关推荐

武魂2暗月攻略,玩转暗月副本,掌握这些技巧让你一路通关!_武魂2暗月攻略
十种螺有毒!爱吃螺的街坊注意,这些螺不能吃,中毒后无药可治!
c语言合法的字符常量如何判断
mobile365体育投注备用

c语言合法的字符常量如何判断

📅 06-30 👁️ 4301
泰拉瑞亚满月怎么触发 满月怎么召唤
365bet提款多久到

泰拉瑞亚满月怎么触发 满月怎么召唤

📅 07-05 👁️ 4075
有免费的电子邮箱吗?
mobile365体育投注备用

有免费的电子邮箱吗?

📅 07-09 👁️ 6571
足球相关规则
bt365备用网站

足球相关规则

📅 08-16 👁️ 122