【笔记】Android Telephony 漫游SPN显示定制(Roaming Alpha Tag)

一、功能名词简介和显示规则

Alpha Tag:运营商名称标识符,也是用于标识运营商的一个名称。客户需求描述常用名词,对开发而言都是SPN/PLMN功能模块的内容,状态栏左上角的运营商名称显示。

SPN相关文章:

【笔记】SPN和PLMN 运营商网络名称显示_spn plmn-CSDN博客

Android U 配置 WiFiCalling 场景下PLMN/SPN 显示的代码逻辑介绍

网络运营商名称显示规则:

MTK平台的设计,对运营商名称的显示rule 是基于sim相关协议来实现的。优先级是Eons>nitz> XML配置(spn-con.xml)。EONS具有最高优先级,如果拿不到的EONS的情况下,要去读NITZ里的name。(Reference :FAQ08919)

  • EONS (Enhanced Operator Name String,“增强型运营商名称字符串”):是在 GSM 网络中引入的一种机制,用于向移动设备发送关于当前所处位置和网络状态的更详细和更准确的信息,以便于移动设备更好地显示和呈现运营商信息。在传统的 GSM 网络中,运营商名称(即 SPN)通常只包含运营商的品牌名称或简称,例如“China Mobile”或“AT&T”。这种信息的显示可能无法反映出当前所处的具体位置或网络状态,例如是否在漫游状态、网络类型、是否处于特殊服务状态等。为了解决这个问题,EONS 引入了更多的信息,以便于移动设备能够更好地显示和呈现运营商信息。
  • NITZ (Network Identity and Time Zone,“网络识别码和时区”):它是一种用于向移动设备发送网络识别码和时区信息的协议,通常在移动设备启动时或网络状态发生变化时进行同步更新。

二、代码逻辑

基于 Android T&U 版本分析。

(一)T和U代码差异

两个版本有差异,主要是Android U 删除了 SubscriptionController类,新增SubscriptionManagerService类。在Android T代码中也有备注setPlmnSpn接口适用maxSDK是R,有过渡提示。

  • T:SubscriptionController.java setPlmnSpn
  • U:SubscriptionManagerService.java getCarrierName 
【Android T】SubscriptionController/setPlmnSpn接口
【Android T】SubscriptionController/setPlmnSpn接口

在ServiceStateTracker.java中,T上同事更新plmn,但U上已经不再更新SPN,也没有setPlmnSpn接口。

【Android T】ServiceStateTracker- onSubscriptionsChanged()
【Android T】ServiceStateTracker- onSubscriptionsChanged()-setPlmnSpn
【Android U】ServiceStateTracker- onSubscriptionsChanged()
【Android U】ServiceStateTracker- onSubscriptionsChanged()
【Android U】updateSpn
【Android U】updateSpnDisplay

(二)【Android T】setPlmnSpn

onSubscriptionsChanged() => setPlmnSpn() => setCarrierText() =>refreshCachedActiveSubscriptionInfoList() & notifySubscriptionInfoChanged()

Android T 更新SPN代码流程:

  1. onSubscriptionsChanged()
  2. setPlmnSpn()
  3. setCarrierText()
  4. refreshCachedActiveSubscriptionInfoList() & notifySubscriptionInfoChanged()

ServiceStateTracker.java​

frameworks/opt/telephony/src/java/com/android/internal/telephony/ServiceStateTracker.java

在网络状态变化时SST内部类SstSubscriptionsChangedListener监听收到onSubscriptionsChanged() 回调,去更新PLMN和SPN。

【Android T】SubscriptionController/setPlmnSpn接口
【Android T】setPlmnSpn
onSubscriptionsChanged()
    private class SstSubscriptionsChangedListener extends OnSubscriptionsChangedListener {/*** Callback invoked when there is any change to any SubscriptionInfo. Typically* this method would invoke {@link SubscriptionManager#getActiveSubscriptionInfoList}*/@Overridepublic void onSubscriptionsChanged() {if (DBG) log("SubscriptionListener.onSubscriptionInfoChanged");final int curSubId = mPhone.getSubId();// If the sub info changed, but the subId is the same, then we're done.if (mSubId == curSubId) return;// If not, then the subId has changed, so we need to remember the old subId,// even if the new subId is invalid (likely).mPrevSubId = mSubId;mSubId = curSubId;mPhone.notifyPhoneStateChanged();setDataNetworkTypeForPhone(mSS.getRilDataRadioTechnology());//setPlmnSpn 更新PLMN/SPNif (mSpnUpdatePending) {mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(), mCurShowPlmn,mCurPlmn, mCurShowSpn, mCurSpn);mSpnUpdatePending = false;}//更新相关Settings设置内容。// Remove old network selection sharedPreferences since SP key names are now// changed to include subId. This will be done only once when upgrading from an// older build that did not include subId in the names.SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);String oldNetworkSelection = sp.getString(Phone.NETWORK_SELECTION_KEY, "");String oldNetworkSelectionName = sp.getString(Phone.NETWORK_SELECTION_NAME_KEY, "");String oldNetworkSelectionShort = sp.getString(Phone.NETWORK_SELECTION_SHORT_KEY, "");if (!TextUtils.isEmpty(oldNetworkSelection)|| !TextUtils.isEmpty(oldNetworkSelectionName)|| !TextUtils.isEmpty(oldNetworkSelectionShort)) {SharedPreferences.Editor editor = sp.edit();editor.putString(Phone.NETWORK_SELECTION_KEY + mSubId,oldNetworkSelection);editor.putString(Phone.NETWORK_SELECTION_NAME_KEY + mSubId,oldNetworkSelectionName);editor.putString(Phone.NETWORK_SELECTION_SHORT_KEY + mSubId,oldNetworkSelectionShort);editor.remove(Phone.NETWORK_SELECTION_KEY);editor.remove(Phone.NETWORK_SELECTION_NAME_KEY);editor.remove(Phone.NETWORK_SELECTION_SHORT_KEY);editor.commit();}// Once sub id becomes valid, we need to update the service provider name// displayed on the UI again. The old SPN update intents sent to// MobileSignalController earlier were actually ignored due to invalid sub id.updateSpnDisplay();}};

SubscriptionController.java

    /*** Generate and set carrier text based on input parameters* @param showPlmn flag to indicate if plmn should be included in carrier text* @param plmn plmn to be included in carrier text* @param showSpn flag to indicate if spn should be included in carrier text* @param spn spn to be included in carrier text* @return true if carrier text is set, false otherwise*/@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)public boolean setPlmnSpn(int slotIndex, boolean showPlmn, String plmn, boolean showSpn,String spn) {synchronized (mLock) {int subId = getSubIdUsingPhoneId(slotIndex);if (mContext.getPackageManager().resolveContentProvider(SubscriptionManager.CONTENT_URI.getAuthority(), 0) == null ||!SubscriptionManager.isValidSubscriptionId(subId)) {// No place to store this info. Notify registrants of the change anyway as they// might retrieve the SPN/PLMN text from the SST sticky broadcast.// TODO: This can be removed once SubscriptionController is not running on devices// that don't need it, such as TVs.if (DBG) logd("[setPlmnSpn] No valid subscription to store info");notifySubscriptionInfoChanged();return false;}String carrierText = "";if (showPlmn) {carrierText = plmn;if (showSpn) {//当PLMN和SPN不相同时,就会显示PLMN-SPN// Need to show both plmn and spn if both are not same.if(!Objects.equals(spn, plmn)) {String separator = mContext.getString(com.android.internal.R.string.kg_text_message_separator).toString();carrierText = new StringBuilder().append(carrierText).append(separator).append(spn).toString();}}} else if (showSpn) {carrierText = spn;}setCarrierText(carrierText, subId);return true;}}/*** Set carrier text by simInfo index* @param text new carrier text* @param subId the unique SubInfoRecord index in database* @return the number of records updated*/private int setCarrierText(String text, int subId) {if (DBG) logd("[setCarrierText]+ text:" + text + " subId:" + subId);enforceModifyPhoneState("setCarrierText");// Now that all security checks passes, perform the operation as ourselves.final long identity = Binder.clearCallingIdentity();try {boolean update = true;int result = 0;SubscriptionInfo subInfo = getSubscriptionInfo(subId);if (subInfo != null) {update = !TextUtils.equals(text, subInfo.getCarrierName());}if (update) {ContentValues value = new ContentValues(1);value.put(SubscriptionManager.CARRIER_NAME, text);result = mContext.getContentResolver().update(SubscriptionManager.getUriForSubscriptionId(subId), value, null, null);// Refresh the Cache of Active Subscription Info ListrefreshCachedActiveSubscriptionInfoList();notifySubscriptionInfoChanged();} else {if (DBG) logd("[setCarrierText]: no value update");}return result;} finally {Binder.restoreCallingIdentity(identity);}}

(三) 【Android U】SetCarrierName

pollStateDone() 等 => updateSpnDisplay() => updateSpnDisplayCdnr() => notifySpnDisplayUpdate() => mSubscriptionManagerService.setCarrierName =>  mSubscriptionDatabaseManager.setCarrierName(subId, carrierName);

Android U 更新SPN代码流程:

  1. updateSpnDisplay()
  2. updateSpnDisplayCdnr()
  3. notifySpnDisplayUpdate()——先获取spn再set
  4. setCarrierName() 从manager到database

ServiceStateTracker.java

/frameworks/opt/telephony/src/java/com/android/internal/telephony/ServiceStateTracker.java

    private void notifySpnDisplayUpdate(CarrierDisplayNameData data) {int subId = mPhone.getSubId();// Update ACTION_SERVICE_PROVIDERS_UPDATED if any value changesif (mSubId != subId|| data.shouldShowPlmn() != mCurShowPlmn|| data.shouldShowSpn() != mCurShowSpn|| !TextUtils.equals(data.getSpn(), mCurSpn)|| !TextUtils.equals(data.getDataSpn(), mCurDataSpn)|| !TextUtils.equals(data.getPlmn(), mCurPlmn)) {final String log = String.format("updateSpnDisplay: changed sending intent, "+ "rule=%d, showPlmn='%b', plmn='%s', showSpn='%b', spn='%s', "+ "dataSpn='%s', subId='%d'",getCarrierNameDisplayBitmask(mSS),data.shouldShowPlmn(),data.getPlmn(),data.shouldShowSpn(),data.getSpn(),data.getDataSpn(),subId);mCdnrLogs.log(log);if (DBG) log("updateSpnDisplay: " + log);Intent intent = new Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);intent.putExtra(TelephonyManager.EXTRA_SHOW_SPN, data.shouldShowSpn());intent.putExtra(TelephonyManager.EXTRA_SPN, data.getSpn());intent.putExtra(TelephonyManager.EXTRA_DATA_SPN, data.getDataSpn());intent.putExtra(TelephonyManager.EXTRA_SHOW_PLMN, data.shouldShowPlmn());intent.putExtra(TelephonyManager.EXTRA_PLMN, data.getPlmn());SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);if (SubscriptionManager.isValidSubscriptionId(subId)) {mSubscriptionManagerService.setCarrierName(subId, TextUtils.emptyIfNull(getCarrierName(data.shouldShowPlmn(), data.getPlmn(),data.shouldShowSpn(), data.getSpn())));}}mCurShowSpn = data.shouldShowSpn();mCurShowPlmn = data.shouldShowPlmn();mCurSpn = data.getSpn();mCurDataSpn = data.getDataSpn();mCurPlmn = data.getPlmn();}@NonNullprivate String getCarrierName(boolean showPlmn, String plmn, boolean showSpn, String spn) {String carrierName = "";if (showPlmn) {carrierName = plmn;if (showSpn) {// Need to show both plmn and spn if both are not same.if (!Objects.equals(spn, plmn)) {String separator = mPhone.getContext().getString(com.android.internal.R.string.kg_text_message_separator).toString();carrierName = new StringBuilder().append(carrierName).append(separator).append(spn).toString();}}} else if (showSpn) {carrierName = spn;}return carrierName;}private void updateSpnDisplayCdnr() {log("updateSpnDisplayCdnr+");CarrierDisplayNameData data = mCdnr.getCarrierDisplayNameData();notifySpnDisplayUpdate(data);log("updateSpnDisplayCdnr-");}@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)@VisibleForTestingpublic void updateSpnDisplay() {if (mCarrierConfig.getBoolean(CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL)) {updateSpnDisplayCdnr();} else {updateSpnDisplayLegacy();}}

会触发SPN更新的场景(即调用updateSpnDisplay)
  •  BroadcastReceiveronReceive()
    • Intent.ACTION_LOCALE_CHANGED
    • TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED
  • handleMessage()
    • EVENT_ICC_CHANGED
    • EVENT_SIM_RECORDS_LOADED
    • EVENT_IMS_CAPABILITY_CHANGED
    • EVENT_RUIM_RECORDS_LOADED
  • setImsRegistrationState()
  • pollStateDone()

三、开发方案

  • T上只用subscriptions状态变化的时候会通过setPlmnSpn(其showPlmn和showSpn的逻辑再U上的getCarrierName接口中)更新名称内容,因此可以在设置spn的入口定制。
  • U上SST中包含很多carriername更新的场景,都是在notifySpnDisplayUpdate生效SPN更新 ,而此接口中都是通过get获取后再set设置信的,因此可以在getCarrierName获取的时候再定制内容。
【Android U】SST  notifySpnDisplayUpdate()
【Android U】SST  notifySpnDisplayUpdate()

(一)Android T 定制在 setPlmnSpn

Android T 上,可以在  SubscriptionController.java 中修改setPlmnSpn()接口内部逻辑,定制CarrierText(最终显示的字符串内容)。

    /*** Generate and set carrier text based on input parameters* @param showPlmn flag to indicate if plmn should be included in carrier text* @param plmn plmn to be included in carrier text* @param showSpn flag to indicate if spn should be included in carrier text* @param spn spn to be included in carrier text* @return true if carrier text is set, false otherwise*/@UnsupportedAppUsagepublic boolean setPlmnSpn(int slotIndex, boolean showPlmn, String plmn, boolean showSpn,String spn) {synchronized (mLock) {int subId = getSubIdUsingPhoneId(slotIndex);//原生逻辑 if (showPlmn) {//...}//在最终更新运营商字符串之前实现定制carrierText = customizeCarrierText(carrierText, subId);setCarrierText(carrierText, subId); //原生逻辑return true;}}//客制化private String customizeCarrierText(String carrierText, int subId) {String customizeCarrierText= carrierText;TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);if (tm != NULL) {String simNumeric = tm.getSimOperatorNumeric(subId); //卡本身的mccmnc,区别于漫游的网络final ServiceState serviceState = tm.getServiceState();boolean isRoaming =  (serviceState != null)  ? serviceState.getRoaming() : false;//根据卡和网络状态定制举例if(serviceState != null && "46001".equals(simNumeric) && isInService(serviceState)){customizeCarrierText= "CCC";}}return customizeCarrierText;}

(二)Android U 定制在 getCarrierName

Android U上,可在获取SPN后定制内容,

    private void notifySpnDisplayUpdate(CarrierDisplayNameData data) {int subId = mPhone.getSubId();// Update ACTION_SERVICE_PROVIDERS_UPDATED if any value changesif (SubscriptionManager.isValidSubscriptionId(subId)) {mSubscriptionManagerService.setCarrierName(subId, TextUtils.emptyIfNull(getCarrierName(data.shouldShowPlmn(), data.getPlmn(),data.shouldShowSpn(), data.getSpn())));}}@NonNullprivate String getCarrierName(boolean showPlmn, String plmn, boolean showSpn, String spn) {String carrierName = "";if (showPlmn) {carrierName = plmn;if (showSpn) {// Need to show both plmn and spn if both are not same.if (!Objects.equals(spn, plmn)) {String separator = mPhone.getContext().getString(com.android.internal.R.string.kg_text_message_separator).toString();carrierName = new StringBuilder().append(carrierName).append(separator).append(spn).toString();}}} else if (showSpn) {carrierName = spn;}//定制carrierName = customizeCarrierText(carrierName, mPhone.getSubId());return carrierName;}private String customizeCarrierText(String carrierText, int subId) {String customizedCarrierText = carrierText;TelephonyManager tm = (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);tm = tm.createForSubscriptionId(subId);    //优化双卡逻辑if (tm != null && !tm.isWifiCallingAvailable()) { //不更新WFC场景int phoneId = mPhone.getPhoneId();String simNumeric = tm.getSimOperatorNumeric(subId);    //卡MCCMNCfinal ServiceState serviceState = tm.getServiceState();String operatorNumeric = (serviceState != null) ? serviceState.getOperatorNumeric() : null;    //注册网络的MCCMNC,如果是漫游,会跟simNumeric不同String gid1 = tm.getGroupIdLevel1(subId);//Avoid NullPointerExceptionboolean isRoaming = serviceState == null ? false : serviceState.getRoaming();Log.d("customizeCarrierText: operatorNumeric:" + operatorNumeric + ", simNumeric:" + simNumeric);if (TextUtils.isEmpty(simNumeric)) {simNumeric = mPhone.getOperatorNumeric();}if("46000".equals(operatorNumeric) && "310260".equals(simNumeric)) {//定制期望显示customizedCarrierText = "Visible";}Log.d("customizeCarrierText: simNumeric = " + simNumeric + ", operatorNumeric = " + operatorNumeric + ", customizedCarrierText = " + customizedCarrierText);}return customizedCarrierText;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/728024.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

重装系统后正版office如何安装

前言 重装系统后,正版office如何安装 登录官网 https://www.microsoft.com 下载office https://account.microsoft.com/services

OA系统看飞书,能把繁杂场景设计的这么流畅,绝对是高手。

OA系统看飞书,能把繁杂场景设计的这么流畅,绝对是高手。 2023-08-18 23:33贝格前端工场 飞书是一款功能强大、操作流畅的企业协作工具,它提供了丰富的功能和灵活的场景设计,使得用户在使用过程中能够更加高效地协作和沟通。 以…

ChatMASTER部署教程

项目简介 ChatMASTER,基于AI大模型api实现的自建后端Chat服务,支出同步响应及流式响应,完美呈现打印机效果。支持一键切换ChatGPT(3.5、4.0)模型、文心一言(支持Stable-Diffusion-XL作图)、通义千问、讯飞星火、智谱清言(ChatGLM)等主流模型…

IP形象设计是什么设计?如何做?

随着市场竞争的激烈,越来越多的企业开始关注品牌形象的塑造和推广。在品牌形象中,知识产权形象设计是一个非常重要的方面。在智能和互联网的趋势下,未来的知识产权形象设计可能更加关注数字和社交网络。通过数字技术和社交媒体平台&#xff0…

ospf虚链路实验简述

1、ospf虚链路实验简述 ospf虚链路配置 为解决普通区域不在骨干区域旁,通过配置Vlink-peer实现不同区域网络设备之间建立逻辑上的连接。 实验拓扑图 r1: sys sysname r1 undo info enable int loopb 0 ip add 1.1.1.1 32 ip add 200.200.200.200 32 quit int e0/0/…

Leetcode 239:滑动窗口最大值

题意 大小为 k 的滑动窗口从整数数组 nums 的最左侧移到最右侧,只能看到滑动窗口中的 k 个数字,窗口每次向右移动一位。 返回滑动窗口的最大值。 示例 1: 输入:nums [1,3,-1,-3,5,3,6,7], k 3 输出:[3,3,5,5,6,7] …

一家新店怎么快速出体验分?教大家一个简单好用的方法,建议收藏

大家好,我是电商花花。 在现在直播电商时代,抖音电商已经成为了一种新兴的商业模式,在抖音小店的项目上,店铺体验分成为了抖音小店能否成功的一个关键因素之一。 店铺的体验分越高,我们店铺的权重才会更高&#xff0…

04.if判断

04.if判断 01.if判断02.运算符2.比较(关系)运算符3.逻辑运算符4.三目运算符(三元表达式) (03)5.if-else6.if-elif结构 04.if嵌套7.if嵌套 01.if判断 if判断基本格式 基本格式 if 要判断的条件:…

1.BOM-获取元素(获取元素、修改属性)

web Api基本认知 作用:通过JS去操作html页面和浏览器(实现浏览器中的某些功能) 分类: DOM(网页):Document Object Model(文档对象模型) BOM(浏览器):Borwser Object Model(浏览器对象模型) DOM DOM树 将网页中标签的关系以树状…

【MySQL知识体系】第2章 数据库与表的创建(一)

第2章 数据库与表的创建 2.1 数据库操作 2.2 表操作 文章目录 第2章 数据库与表的创建2.1 数据库操作2.1.1 创建第一个数据库2.1.2 更新数据库名称(数据库创建后无法修改名称)2.1.3 删除数据库2.1.4 取个合适的数据库名称 第2章 数据库与表的创建 2.1 数…

在 echarts 的 rich 中使用 iconfont 图标库图标作为 backgroundColor.image 值的方法

实现步骤 1、引入 iconfont.js。该脚本执行时&#xff0c;会在 body 下插入一个 svg 标签&#xff0c;标签下包含了图标库中的 svg 图标 path。 <script src"your/iconfont/path/iconfont.js"></script>或者 import your/iconfont/path/iconfont.js2、…

【学习心得】websocket协议简介并与http协议对比

一、轮询和长轮询 在websocket协议出现之前&#xff0c;要想实现服务器和客户端的双向持久通信采取的是Ajax轮询。它的原理是每隔一段时间客户端就给服务器发送请求找服务器要数据。 让我们通过一个生活化的比喻来解释轮询和长轮询假设你正在与一位不怎么主动说话的老大爷&…

基于R语言lavaan的SEM在复杂统计建模中的科研技术新突破

此外&#xff0c;我们还将深入探讨R语言的基础知识、结构方程模型的基本原理、lavaan程序包的使用方法等内容。无论是潜变量分析、复合变量分析&#xff0c;还是非线性/非正态/缺失数据处理、分类变量分析、分组数据处理等复杂问题&#xff0c;我们都将一一为您解析。 希望通过…

3.7作业

网络聊天室&#xff1a; 程序代码&#xff1a; ser.c #include <myhead.h> //定义消息类型结构体 struct xiaoxi {char type;char name[20];char text[100]; };int main(int argc, const char* argv[]) {// 创建套接字int sfd socket(AF_INET, SOCK_STREAM, 0);if (s…

Spring源码:手写AOP

文章目录 一、概念1、AOP是什么&#xff1f;2、相关概念1&#xff09;目标对象Target2&#xff09;通知Advice3&#xff09;连接点Joinpoint4&#xff09;切点Pointcut5&#xff09;切面Aspect6&#xff09;织入Weaving 二、分析三、实现1、实现Advice1&#xff09;前置通知2&a…

企业微信HOOK协议,新设备二次验证处理

提示设备强制二次验证问题已处理 HOOK&#xff1a;https://www.showdoc.com.cn/1663062930779972/7859611259700402密码&#xff1a;999999999

大数据冷热分离方案

数据冷热分离方案 1、背景 ​ 随着业务的发展&#xff0c;在线表中的数据会逐渐增加。常规业务都有冷热数据现象明显的特性&#xff08;需要访问的都是近期产生的热数据&#xff1b;时间久远的冷数据出于备份、备案溯源等诉求会进行在线保留&#xff09;。在业务表数据 量可控…

安卓玩机工具推荐----高通芯片9008端口读写分区 备份分区 恢复分区 制作线刷包 工具操作解析

上期解析了下adb端口备份分区的有关操作 安卓玩机工具推荐----ADB状态读写分区 备份分区 恢复分区 查看分区号 工具操作解析 在以往的博文中对于高通芯片机型的分区读写已经分享了很多。相关类似博文 安卓备份分区----手动查询安卓系统分区信息 导出系统分区的一些基本操作 …

0x04_数组_指针_字符串

数组 数组的定义与使用 数组是具有一定顺序关系的若干相同类型变量的集合体&#xff0c;组成数组的变量称为该数组的元素。 给出下面程序的输出&#xff1a; #include <iostream> using namespace std; int main() {int a[10], b[10];for(int i 0; i < 10; i) {a[…

python 基础知识点(蓝桥杯python科目个人复习计划59)

今日复习内容&#xff1a;做题 例题1&#xff1a;建造房屋 问题描述&#xff1a; 小蓝和小桥是两位年轻的建筑师&#xff0c;他们正在设计一座新的城市。 在这个城市中&#xff0c;有N条街道&#xff0c;每条街道上有M个位置可以建造房屋&#xff08;一个位置只能建造一个房…