mtk 主题功能学习笔记

1. 如何添加一套自己的主题

这里以Jb3为例:

添加资源

  在mediatek/frameworks/themes/ 下面添加一个新的主题文件夹.可以参看原有的主题theme-res-mint/theme-res-mocha/theme-res-raspberry/.

只要将对应图片资源放到对应的文件夹下面就可以了.

 

系统编译时, theme-res-xxx下面android.mk配置的

$(shell perl $(LOCAL_PATH)/copy_res.pl $(LOCAL_PATH))

会执行copy_res.pl 将theme-res-xxx 下面的资源统一拷贝到theme-res-xxx 下面的res 文件夹下面

如何将添加的主题资源编译到固件里面去

  在alps/build/target/product/common.mk文件中,找到MTK_THEMENANAGER_APP这个关键字,在如下这个判断中,添加自己的资源包的名字

     ifeq($(strip $(MTK_THEMEMANAGER_APP)),yes)

     PRODUCT_PACKAGES += theme-res-mint \

                              theme-res-mocha \

theme-res-raspberry \

                              theme-res-xxx

    endif

 

如果需要主题里面需要增加其他资源,比如: mipmap raw 等.

mipmap文件夹下的应用图标可以直接放在themes-res-xxxx相应应用程序的res/mipmap-xxxx下,修改copy-res.pl的 if (substr($mkdirinres, 0, 8) ne "drawable") {next;}添加mipmap的判断即可让目前的MTK ThemeManager识别到mipmap下的资源。

这是一种修改app icon的方法.这种方法不仅可以将launcher 里面显示的icon 改掉,还可以把从系统级别上起到效果.

如何添加额外的图片资源(默认的3个主题都没有的图片)

frameworks/base/data/etc/thememap.xml

frameworks/base/libs/androidfw/MTKThemeManager.cpp

 

查了一下源码,系统里面具体那些文件会根据主题的不同而不同的,是有什么决定的呢?图片资源和主题是如果一一映射的.

thememap.xml 里面配置了这些信息,下面举一个例子:

<Module name="Browser" path="/system/app/Browser.apk">

     <item>progress.9.png</item>

     <item>textfield_active_holo_dark.9.png</item>

     <item>bookmarks_widget_thumb_selector_focused.9.png</item>

     <item>bookmarks_widget_thumb_selector_pressed.9.png</item>

</Module>

上面就是Browser 浏览器和主题相关的图片资源了.

一个应用对应一个Module, name 的值就对应的编译过程中对应的LOCAL_PACKAGE_NAME, path 就是路径.

如何设定默认主题为mint,mocha或raspberry

以mint主题为例:

1,修改文件 frameworks/base/core/java/android/content/res/Configuration.java,将变量 SKIN_UNDEFINED 值赋为 "/system/framework/theme-res-mint.apk";

 

 2,修改文件 frameworks/base/libs/androidfw/AssetManager.cpp,修改变量 static const char* kDefaultThemePath的值为:

"/system/framework/theme-res-mint.apk".

mtk 的主题功能涉及到了那些代码

packages/apps/Settings/src/com/mediatek/thememanager

frameworks/base/libs/androidfw/MTKThemeManager.cpp

frameworks/base/data/etc/thememap.xml

ThemeManager.java

@Override

    public void onItemClick(AdapterView<?> parent, View view,int position,long id) {

       mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND);

        if (mCurrentPosition != position) {

            newSetThemeTask(this.getActivity()).execute(position);

            mCurrentPosition = position;

        } else {

           mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);

        }

    }

 

private class SetThemeTask extends AsyncTask<Integer, Void, Void> {

        public SetThemeTask(Context context) {

            mContext = context;

        }

        @Override

        protected Void doInBackground(Integer... types) {

            int position = types[0];

            IActivityManager am = ActivityManagerNative.getDefault();

            try {

                // The mThemeDatas list will be cleared when onDestroy is called,

                // so null pointer exception would happens when calling mThemeDatas.get(position),

                // synchronized set theme and destroy to fix this issue.

                synchronized (mLock) {

                    if (mThemeDatas == null) {

                        Xlog.e(TAG"doInBackground error occured, mThemeDatas becomes null.");

                    }

                    Configuration config = am.getConfiguration();

                    config.skin =mThemeDatas.get(position).getThemePath()

                            .toString();

                    Xlog.d(TAG"doInBackground() am.updateConfiguration() config.skin = "

                            + config.skin);

                    am.updateConfiguration(config);

                }

            } catch (RemoteException e) {

                Xlog.e(TAG"Update configuration for theme changed failed.");

                e.printStackTrace();

            }

            return null;

具体可以继续查看ActivityManagerService.java 的相关方法

updateConfiguration(xxx),这个方法主要是修改persist.sys.skin 这个属性的值

具体原理的分析

谁来解析这个thememap .xml文件呢?

MTKThemeManager.cpp 类负责这个工作,没有想到是个cpp,本来以为是个java 类.应该是c++的解析速度更快.

主要是函数: void MTKThemeManager::parseThemeMapIfNeeded() 来完成这个工作.(为方便阅读,删除部分不重要的代码)

static const char* kThemeMapFile = "/system/etc/theme/thememap.xml";

static const char* kThemeModuleName = "Module";

static const char* kThemePathAttr = "path";

static const char* kThemeItemName = "item";

// kThemeMapFile 就是之前提到的参与到随主题功能切换的资源图片的文件

 

void MTKThemeManager::parseThemeMapIfNeeded()

{

    /* Load theme map xml file. */

    TiXmlDocument* pDoc = new TiXmlDocument(kThemeMapFile);

    pDoc->LoadFile(); //加载文件

 

    /* Get the root node(thememap) and the first module child node.*/

    TiXmlElement *pRootElement = pDoc->RootElement();

    TiXmlElement *pFirstModuleElement = pRootElement->FirstChildElement(kThemeModuleName);

 

    /* Get module node count to create the path map array.*/

int moduleCnt = getChildNodeCount(kThemeModuleName,pRootElement, pFirstModuleElement);

 //得到总的参与到主题功能里面的app 数量

 

    mPathMap = new ThemePathMap[moduleCnt];

   

    MTKThemeManager::mModuleCount = moduleCnt;

 

    TiXmlNode *pModuleNode = pFirstModuleElement;

    TiXmlNode *pItemNode = NULL;

    TiXmlNode *pFirstItemElement = NULL;

    int itemCnt = 0;

    int moduleIndex = 0;

    int tempIndex = 0;

 

    /* Parse the whole xml by module. */

    while (pModuleNode != NULL) {

        mPathMap[moduleIndex].path = ((TiXmlElement*)pModuleNode)->Attribute(kThemePathAttr);

   

        pFirstItemElement = pModuleNode->FirstChildElement(kThemeItemName);

        itemCnt = getChildNodeCount(kThemeItemName,pModuleNode, pFirstItemElement);

        mPathMap[moduleIndex].fileCount = itemCnt;

        if (itemCnt == 0) {

            mPathMap[moduleIndex].fileList = NULL;

            continue;

        }

 

// itemFileList  :保存解析的信息,可以供查询

        ThemeFileList *itemFileList = newThemeFileList[itemCnt];

 

        pItemNode = pFirstItemElement;

        tempIndex = 0;

        /* Parse all items in the current module pModuleNode. */

        while (pItemNode != NULL) {

            itemFileList[tempIndex++].fileName = ((TiXmlElement*)pItemNode)->GetText();

          

            pItemNode = (TiXmlElement *)pModuleNode->IterateChildren(kThemeItemName, pItemNode);

        }

 

        mPathMap[moduleIndex].fileList = itemFileList;

        moduleIndex++;

 

        pModuleNode = (TiXmlElement *)pRootElement->IterateChildren(kThemeModuleName, pModuleNode);

    }

}

 

 

又是谁调用了MTKThemeManager 的  parseThemeMapIfNeeded 方法:

在frameworks/base/libs/androidfw/AssetManager.cpp 里面可以看到

构造函数

AssetManager::AssetManager(CacheMode cacheMode)

    : mLocale(NULL), mVendor(NULL),

      mResources(NULL), mConfig(new ResTable_config),

      mCacheMode(cacheMode), mCacheValid(false)

{

    //……….

#if MTK_THEMEMANAGER_APP   

    mThemePath = new asset_path()

 #ifdef THEME_NO_BUILD

    ALOGV("THEME_NO_BUILD is set for host.");

 #else

      mThemeManager = MTKThemeManager::getInstance();

    mThemeManager->parseThemeMapIfNeeded();

 #endif

#endif

}

AssetManager  在构造函数里面调用了 mThemeManager->parseThemeMapIfNeeded() 来解析

thememap.xml .

 

继续跟踪AssetManager   里面还有哪里使用mThemeManager .

函数getAssetFromTheme  里面调用了mThemeManager mThemeManager->isFileInMap

mThemeManager->isFileInMap 就是判断文件fileName 的资源是否是在thememap.xml 里面有着类似以下对应的信息

<Module name="Browser" path="/system/app/Browser.apk">

<item>progress.9.png</item>

isFileInMap 会调用方法

findFileInList(ThemeFileList *fileList, int listLen, const char* fileName) 来查询该文件是否在thememap.xml 的映射范围之内

Asset* AssetManager::getAssetFromTheme(int which, const char* fileName,

        asset_path themePath, AccessMode mode) {

    Asset* pAsset = NULL;

    char* assetPath = (char*) mAssetPaths.itemAt(which).path.string();

    if (0 == strncmp(assetPath, kISmsPath, 22)) {

         assetPath = "/data/app/ISmsService.apk";

    }

   

    if (mThemeManager != NULL && mThemeManager->isFileInMap(assetPath,

            fileName)) { //判断文件是否在主题map 范围之内

        themePath.type = mAssetPaths.itemAt(which).type;

 

        if (which == 0x00) { // frameworks resource use default filename to access

            pAsset = openNonAssetInPathLocked(fileName, mode,themePath);

        } else { // applications resource

            char* apkFileName = (char*) malloc(strlen(fileName) + 60);

            memset(apkFileName, 0x00, strlen(fileName) + 60);

              appendApkPath(assetPath, fileName, apkFileName);

            pAsset = openNonAssetInPathLocked(apkFileName, mode,themePath);

            free(apkFileName);

            apkFileName = NULL;

        }

    }

 

    return pAsset;

}

 

同样逆推,会发现openNonAsset 调用了getAssetFromTheme

 

系统如何获取图片等资源

当我们调用Resources.java 来获取图片等资源的时候会调用getDrawable 方法, getDrawable最终把这还是使用loadDrawable 方法来处理.

Resources.java

public Drawable getDrawable(int id) throws NotFoundException {

TypedValue value;

synchronized (mAccessLock) {

            value = mTmpValue;

            if (value == null) {

                value = new TypedValue();

            } else {

                mTmpValue = null;

            }

            getValue(id, value, true);

   }

 Drawable res = loadDrawable(value, id);

synchronized (mAccessLock) {

            if (mTmpValue == null) {

                mTmpValue = value;

            }

}

return res;

}

 

loadDrawable 方法在获取资源的时候会先判断该资源是否在缓存中,如果在缓存中就直接获取返回,如果没有就继续查询.同时使用color配置的图片的资源也会先去缓存中读取,这样可以提高代码的效率.如果还是没有找到就会调用AssetManager.java 的openNonAsset 方法,再接着分析会发现调用的是Jni 的一个方法openNonAssetNative,Jni 最终会去调用AssetManager.cpp 的openNonAsset的方法来根据不同主题去获取对应的资源.

 

frameworks/base/core/jni/android_util_AssetManager.cpp  àopenNonAssetNative

static jint android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,

jint cookie,

jstring fileName,

jint mode)

{

    AssetManager* am = assetManagerForJavaObject(env, clazz);

if (am == NULL) {

return 0;

}

 

    ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);

 

ScopedUtfChars fileName8(env, fileName);

if (fileName8.c_str() == NULL) {

return -1;

}

 

if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM

&& mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {

jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");

return -1;

}

 

    Asset* a = cookie

        ? am->openNonAsset((void*)cookie, fileName8.c_str(), (Asset::AccessMode)mode)

        : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);

 

if (a == NULL) {

jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());

return -1;

}

 

//printf("Created Asset Stream: %p\n", a);

 

return (jint)a;

}

 

Resources.java

Drawable loadDrawable(TypedValue value, int id)

            throws NotFoundException {

 

         if (TRACE_FOR_PRELOAD) {

                   // Log only framework resources

                   if ((id >>> 24) == 0x1) {//framework resources id 是以0x1 开头, mediatek Resource id 是一0x2 开头3方资源一般以0x7 开头

                            final String name = getResourceName(id);

                            if (name != null) android.util.Log.d("PreloadDrawable", name);

                   }

         }

 

         boolean isColorDrawable = false;

         if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&

                            value.type <= TypedValue.TYPE_LAST_COLOR_INT) {

                   isColorDrawable = true;

         }

         final long key = isColorDrawable ? value.data :

                            (((long) value.assetCookie) << 32) | value.data;

 

         Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);//从缓存中读取,如果缓存中已经存在,就直接获取并返回,缓存中没有的话就继续执行下面的代码去查询获取对应的资源文件.

 

         if (dr != null) {

                   return dr;

         }

         Drawable.ConstantState cs = null;

 

         /// M: Theme manager @{

         Boolean checkPreload = true;

         if (FeatureOption.MTK_THEMEMANAGER_APP) {

                   String skin= Configuration.getSkin();

                   if ((skin != null) &&

                            !(skin.equals(sDefaultSkin))){

                            checkPreload = false;

                   }

         }

         /// @}

 

//使用color配置的图片可以也直接从缓存中读取,提高效率.

         if (checkPreload) {/// M: Theme manager

                   if (isColorDrawable) {

                            cs = sPreloadedColorDrawables.get(key);

                   } else {

                            cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);

                   }

         }/// M: Theme manager

 

         if (cs != null) {

                   dr = cs.newDrawable(this);

         } else {

                   if (isColorDrawable) {

                            dr = new ColorDrawable(value.data);

                   }

 

                   if (dr == null) {

                            if (value.string == null) {

                                     throw new NotFoundException(

                                                        "Resource is not a Drawable (color or path): " + value);

                            }

 

                            String file = value.string.toString();

 

                            if (TRACE_FOR_MISS_PRELOAD) {

                                     // Log only framework resources

                                     if ((id >>> 24) == 0x1) {

                                               final String name = getResourceName(id);

                                               if (name != null) android.util.Log.d(TAG, "Loading framework drawable #"

                                                                 + Integer.toHexString(id) + ": " + name

                                                                 + " at " + file);

                                     }

                            }

 

                            if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "

                                               + value.assetCookie + ": " + file);

 

                            if (file.endsWith(".xml")) {

                                     Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);

                                     try {

                                               XmlResourceParser rp = loadXmlResourceParser(

                                                                 file, id, value.assetCookie, "drawable");

                                               dr = Drawable.createFromXml(this, rp);

                                               rp.close();

                                     } catch (Exception e) {

                                               Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

                                               NotFoundException rnf = new NotFoundException(

                                                        "File " + file + " from drawable resource ID #0x"

                                                        + Integer.toHexString(id));

                                               rnf.initCause(e);

                                               throw rnf;

                                     }

                                     Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

 

                            } else {

                                     Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);

                                     try {

                                               InputStream is = mAssets.openNonAsset(

                                                                 value.assetCookie, file, AssetManager.ACCESS_STREAMING);

         //System.out.println("Opened file " + file + ": " + is);

                                               dr = Drawable.createFromResourceStream(this, value, is,

                                                                 file, null);

                                               is.close();

         //System.out.println("Created stream: " + dr);

                                     } catch (Exception e) {

                                               Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

                                               NotFoundException rnf = new NotFoundException(

                                                        "File " + file + " from drawable resource ID #0x"

                                                        + Integer.toHexString(id));

                                               rnf.initCause(e);

                                               throw rnf;

                                     }

                                     Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

                            }

                   }

         }

 

         if (dr != null) {

                   dr.setChangingConfigurations(value.changingConfigurations);

                   cs = dr.getConstantState();

                   if (cs != null) {

                            if (mPreloading) {

                                     final int changingConfigs = cs.getChangingConfigurations();

                                     if (isColorDrawable) {

                                               if (verifyPreloadConfig(changingConfigs, 0, value.resourceId,

                                                                 "drawable")) {

                                                        sPreloadedColorDrawables.put(key, cs);

                                               }

                                     } else {

                                               if (verifyPreloadConfig(changingConfigs,

                                                                 LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {

                                                        if ((changingConfigs&LAYOUT_DIR_CONFIG) == 0) {

                                                                 // If this resource does not vary based on layout direction,

                                                                 // we can put it in all of the preload maps.

                                                                 sPreloadedDrawables[0].put(key, cs);

                                                                 sPreloadedDrawables[1].put(key, cs);

                                                        } else {

                                                                 // Otherwise, only in the layout dir we loaded it for.

                                                                 final LongSparseArray<Drawable.ConstantState> preloads

                                                                                    = sPreloadedDrawables[mConfiguration.getLayoutDirection()];

                                                                 preloads.put(key, cs);

                                                        }

                                               }

                                     }

                            } else {

                                     synchronized (mAccessLock) {

                                               //Log.i(TAG, "Saving cached drawable @ #" +

                                               //        Integer.toHexString(key.intValue())

                                               //        + " in " + this + ": " + cs);

                                               if (isColorDrawable) {

                                                        mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));

                                               } else {

                                                        mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));

                                               }

                                     }

                            }

                   }

         }

 

         return dr;

}

 

系统如何根据不同主题来选择对应的资源

应用层获取资源的时候,不管当前系统使用的那个主题,同一个图片资源的id都是一样的,当前系统是如何根据这个id 来返回对应的图片资源呢?

 

系统在获取资源的时候,会根据是否选择了其他的主题来修改获取对应图片的Asset 对象

AssetManager.cpp

Asset* AssetManager::openNonAsset(void* cookie, const char* fileName,AccessMode mode)

{

    const size_t which = ((size_t)cookie)-1;

#if MTK_THEMEMANAGER_APP  

memset(kThemeApkPath, 0x00, 100);

//获取当前的主题.java 里面可以使用Configuration 的 getSkin方法

    property_get("persist.sys.skin", kThemeApkPath, kDefaultThemePath);

    mThemePath->path.setTo(kThemeApkPath);

#endif

    AutoMutex _l(mLock);

    if (mCacheMode != CACHE_OFF && !mCacheValid)

        loadFileNameCacheLocked();

#if MTK_THEMEMANAGER_APP

    if (which < mAssetPaths.size()) {

        Asset* pAsset = getAssetFromTheme(which, fileName, *mThemePath,mode);

//获取主题对应Asset 对象,如果对应的图片文件不在主题所修能修改文件(Map)里面就会返回null.

        if (pAsset == NULL) {

            pAsset = openNonAssetInPathLocked(

                    fileName, mode, mAssetPaths.itemAt(which));

        }

        if (pAsset != NULL) {

            return pAsset != kExcludedAsset ? pAsset : NULL;

        }

    }

#else

   //……….

#endif

    return NULL;

}

 

AssetManager.cpp

Asset* AssetManager::getAssetFromTheme(int which, const char* fileName,

                   asset_path themePath, AccessMode mode) {

         Asset* pAsset = NULL;

char* assetPath = (char*) mAssetPaths.itemAt(which).path.string();

if (0 == strncmp(assetPath, kISmsPath, 22)) {

assetPath = "/data/app/ISmsService.apk";

    }

   

    if (mThemeManager != NULL && mThemeManager->isFileInMap(assetPath,

                            fileName)) {

                   ALOGV("filename mapped success which = %d, fileName = %s.\n", which,

                                     fileName);

                   themePath.type = mAssetPaths.itemAt(which).type;

 

                   if (which == 0x00) { // frameworks resource use default filename to access

                            pAsset = openNonAssetInPathLocked(fileName, mode, themePath);

                   } else { // applications resource

                            char* apkFileName = (char*) malloc(strlen(fileName) + 60);

                            memset(apkFileName, 0x00, strlen(fileName) + 60);

              appendApkPath(assetPath, fileName, apkFileName);

                            pAsset = openNonAssetInPathLocked(apkFileName, mode, themePath);

                            free(apkFileName);

                            apkFileName = NULL;

                   }

         }

 

         return pAsset;

}

 

同时在frameworks/base/core/java/android/content/res/Resources.java 里面发现Resources.java也可以根据资源的类型和当前主题来调用对应的资源.

public Bitmap getThemeImage(String themePackagePath, String itemType) {

    Bitmap bitmap = null;

    int cookie = 0;       

//………………………..

    cookie = getAssets().addAssetPath(themePackagePath);

    StringBuilder themeDrawablePath = new StringBuilder("res/drawable-");

themeDrawablePath.append(generateCurrentDensitySuffix());       

    themeDrawablePath.append(itemType + ".png");

    //……….

    try {               

        InputStream is = getAssets().openNonAsset(cookie, themeDrawablePath.toString());

        bitmap = BitmapFactory.decodeStream(is);

    } catch (IOException e) {

        Log.e(TAG, "IOException happend when getThemeImage cookie = " + cookie);

    }

    return bitmap;

}

 

Framework java层和C++ 层是如何工作的。

AssetManager.java 和 AssetManager.cpp 之间的关联是通过C++文件android_util_AssetManager.cpp 来实现的。

 

frameworks/base/core/jni/android_util_AssetManager.cpp

设置应是如何把用户选择的主题通知到系统

用户单击主题item 的时候,会调用异步更新类SetThemeTask 来通知framework 层来更新AssetManager ,这样在系统调用资源的时候,如果该资源是在主题功能范围之内就会使用主题里面的资源,而不去默认的应用里面找。

ThemeManager.java

@Override

public void onItemClick(AdapterView<?> parent, View view, int position,long id) {

   mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND);

   if (mCurrentPosition != position) {

      new SetThemeTask(this.getActivity()).execute(position);//根据实际选择的theme 来通知framework.

      mCurrentPosition = position;

   } else {

      mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);

   }

}

 

private class SetThemeTask extends AsyncTask<Integer, Void, Void> {

    public SetThemeTask(Context context) {

       mContext = context;

    }

 

    @Override

    protected Void doInBackground(Integer... types) {

       int position = types[0];

       IActivityManager am = ActivityManagerNative.getDefault();

       try {

           // The mThemeDatas list will be cleared when onDestroy is called,

           // so null pointer exception would happens when calling mThemeDatas.get(position),

           // synchronized set theme and destroy to fix this issue.

           synchronized (mLock) {

              if (mThemeDatas == null) {

                  Xlog.e(TAG, "doInBackground error occured, mThemeDatas becomes null.");

              }

              Configuration config = am.getConfiguration();

              config.skin = mThemeDatas.get(position).getThemePath()

                     .toString();

              Xlog.d(TAG, "doInBackground() am.updateConfiguration() config.skin = "

                     + config.skin);

              am.updateConfiguration(config); // 调用这个方法更新config.skin 之后,会导致重新调用oncreate() 方法。

           }

       } catch (RemoteException e) {

           Xlog.e(TAG, "Update configuration for theme changed failed.");

           e.printStackTrace();

       }

       return null;

    }

 

    @Override

    protected void onPreExecute() {

       showSetThemeDialog();

    }

 

    @Override

    protected void onPostExecute(Void unused) {

       mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);

    }

 

    private Context mContext;

}

 

生成学习笔记文档:5G 带宽, 5G 的那个信号就是带宽高,速度快,但是信号衰减比较快。就说你看一般隔墙的话,我穿透穿墙能力比较弱,但是现在的话可能有它那种多个辫子的那种多天线那种的话可能信号也比较好,也解决了这个问题啊。就是几乘几的那种,刚才看到的那个 memory 的那种 8 × 8 那个也都攻克这些东西,还刚才说这个信道,就是说是刚才说的,刚才说到了 22.4G 的话,它分为 14 个信道看,有从 2.2412 一直到2484,中间是有一些是这些红的,就是一些禁止的信道, DFS 就是禁。还有 5G 这边的, 5G 这边的话是从 5 这些就是红色的话,这是一些每个国家的。 你看等还再说一下这个FCC,包括这个 FCC 就是说他们是美国的一些标准,他们一些你要进这个国家,他要通过这个 FCC 认证,还有这个ETSS,欧洲的一些标准。当然中国也有中国的一些标准,它,但基本上主要是以这两个标准为那个的,这 5G 上面有信道就多一些,多很多,它从 36 一直到165,对应的每个频率就是这是它有表的 5180 一直到5825,当然现在还有6G6G,不,不在这个,不在我们这个范围,我们没写啊。 那现在的可能 Wifi 7 都出来了,我们这个还是比较low,这个 d 中间的这个 DFS 是一些军用信道,因为的话你开启了,民用的话,开启的话会干扰一些军用的那个军,军用的一些设备,所以说他们当面临就是说这些都是要规避的,就是到了那个 5252605280 这些东西就是设备的它自动跳。 但有些禁止的,它就这些560,它是禁止的,这些一些国家在美国那边它禁止的,欧洲在那边它有些indoors,还有一些 indoors 就是说是户室内的那些一些室内的一些协议,就是就房间里面的一些协议这个一些特性,包括 Japan 这些信道,每个反正每个国家它都有一些信道是允许的,一些信道是不允许的。 TPC 的话就是为了避免功率过大造成对其他干扰的一种一个协议对应里面的可能是一个控制的一个域里面的一个字段。这个大概知道你用到有没有,工作中可能用到这些DFS,你工作中会用到这个 DFS 的,就是如果搞 Wifi 的话, DFS 是比较常见的,它有些里面要特性,可能要移植的这个。我们是因为我们是方案商,方案商的话提供的是不是哦?对,就是高通,或者是因为我们用的那个芯片一般是高通或者 MTK 的,他们一般他,我们我把他叫方案商,就是方案商的话他们会提供的给我们的一套代码,然后的话这个他会有一个默认的国家码,就刚才看到那些就是这个这些你要出口到这些国家的话,他都要匹配这些国家码,这些国家码对应的就是一些信道的,每个信道的一些参数,功率的参数,什么东西的都要遵循别人国家的法律。 你既要遵循国家的国家法律,第二个也是要那个我们的射频那边要把针对,要调优,就是说把那个功率也要调大,尽量尽可能调大一点,然后而且还相互不要干扰,然后他们会通过各种各样的测试达到一个最优化,然后再发货发出去,就是方案上就是高通或者 MTK 的话,他们给的是默认国家出口的手机,我用海外出口海外的那个手机,它会根据一线的数据来去配这些国家嘛。 就是我们先因为每个国家的法律不同,它要根据。嗯,有些国家会根据一个个国家的它那个值去设置那个一个二进制的文件,这个如果做的时候,到时候会跟大家说,射频领域就会根据在每个国家的在它最大的功率内去按信道去调优,然后保证既不违反它的国家的那个功率超标,也可以达到那个 Wifi 这边的信号最优,它就是信号强,信号强的话就是说是你的传速度就快,但是功耗也要大,但是它一个要达到平衡的。达到平一种平衡的常用的认证标准。就是刚才看到有 CE 欧盟的,但他那边写的是 ETS 那。诶,那个那写的我们一般叫 CE 啊,还有FCC,就美国的那种,中国的叫SRRC,这中国的一些标准。 这个是MEMO,那边 MEMO 的话是多屏,叫多用户、多入多出技术,它是 8021 ACE 标准里面的一个第二个里程碑,它这个就是。这个就是改善那个网络资源利用率,加上了 Memo 的速度,就是 double 或者是多倍啊。但当然这里面的技术我也不太懂,这里面只是知道一些基本的概念。 他这个就是说是ACC,用流 AC 的话有 80 兆带宽,实际有实际传输率也 350 兆,但是到了两个设备的话,如果接入网络的话,他只能轮着来,所以说每个设备就是只能平分了,数据传输速率减慢,但是到了 Memo 的时候他就用了一种什么技术吧?就是拨速成型技术,将信号从时域、频域、空域分成三部分,这个比较高深,这个就是说通过他这种技术使用,使得三个信号接入的信号就是互不干扰,每个每台设备的得到资源是相等的,且数据传输能同时进行,所以它速度就是摸用了多种那种硬件还有软件的技术,导致使它这个信号使它这个速率大幅提升,这是 MEMO 的特点。 再说一下那个 Wifi 的连接过程,这个就是它这个 Wifi 连接过程,它其实是遵循那个刚才说到的,就一一开始我们就说到 80211 协议那个来的,它是就是 AP 侧,就是AP,就是我们的也不是 AP 侧, AP 就是手机端,包括或者是其他的一些 STA 设备。sorry,sorry,说错了,这个是AP,是路由器。 sorry 说错了,口误啊。 就发送 Beacon 管理帧,就是说数据包是,就是它像那个Beacon,就是像那个,像一个路。嗯,怎么说?就是路标一样的一个东西,就灯塔一样东西,它就发,就是在那广播就在那发,然后的话手机那边它往那个就是往空气中广播,然后手机就会你手机是个接收状态。 ST 就是手机那边接收面,它感应到这个,接触到这个 Beacon 帧,它就会在你的那个手机的 Wifi 列表里面,它会把它解析出来,解析到那个解析出来,然后是通过层层的那种解析,然后到了显示到我们的 Wifi 列表里面,诶?列表里面显示到哪个?有多少个 AP 会发这个Beacon,然后你的那个上面就会显示出来它,诶诶,就是就是那个 Wifi 列表,大家的 Wifi SS,这个 SSID 就是刚才说的那个是路由器的名字啊。 它这个就,然后就是,然后你要想连接的话就是点一下,然后的话输入密码,当然也可以不输密码就空口,就是那种 open 的, open 状, open 的那种状态,然后去对连接进行请求,然后对身份进行认证,这个对应 auth AP 侧就对身份认证,对那个 auth 进行ACK,就是请求回应,然后这里发起关联,对应的这个流程是这样的,就是STA,就是 proper request,然后它一个响应。 但这个 Beacon 的没有写在里面,这个只是说是发起连接的过程,写了一下,这就是 ST 发起 proper request,然后 AP 路由器就发给 proper response,然后就开始进行auth,auth, au authcation,就是鉴权,然后 auth 就响应,然后就认证那个密码通过之后,然后它会发起,然后由 s 就是 ST 发起那个,这就关联,就是关联请求,然后就关联请求响应这个这时候它们就连上了,这就是它的一个简单的一个过程。但中间还有一些什么加密,什么这里面没写。 这第二个写了,刚刚才那个是开放网络的开发过程,还有一些这个里面包括加密的在这个关联的时候,下面还有那个EAPOL,这个 EAP 的四步连四步。握手,这个是你这个是搞 Wifi 的,这边都是要熟悉,要知道这些的这些东西的这边是就是密钥的交换四步握手之后才能真正连上,我们这边的话加一加密的类型,一般的话它有什么WAP、WEP、WPA,这比较早的还有WPA2,还有现在最新的WPA3。这个就是在这个过程中它有各种各样的加密方式,它里面会进行各种算法的一些处理,加密解密的处理,包括密钥的再展示一下签到二维码,是吧?你稍等一下啊。这个可能有同学要签到啊。可以了,可以了,我继续啊。 跑哪了?sorry,这个。 四不握手啊。 就是对于那种 WPA 这个加密方式的,还 WPA 有p, WPA 一代、第二代,是吧?在 PSK 这种类型的,它要有一个什么预分享的,一个叫预分享 key 进行认证,对 EAP 的 EAP 类型的 EAP 后面也是一种加密类型,这边也有,因为又分为这么种,这么多种,还有反正比较多的这个种类,但我细节我们不需要太,就我们知道就行,这个大概知道就行了。 这个里面 PDK 的话它主要是通过生成这个是,也是简单地说了一下生成临时密钥,然后用于加密的一些加密钥的生成、交换、安装,还有个主握手这个搞 Wifi 的时候,平时中可能会遇到这个东西,有时候它有时候连不上了用户的,因为路由器是很多种的,它有些连不上了,它可能是我在 MTK 那边遇到过一种,就是这个东西出错了,它里面一个buffer,它里面一个缓冲的东西出问题了,然后的话是导致它有时候连不上啊。但是这种多出问题的一般是出现兼容性的问题的时候,兼容性的东西的时候可能会遇到,但是也比较少。 就刚才说的那个,这就是刚才说的那个 Beacon 帧, Beacon 帧就是就路由器以一定的间隔时间,它会去间隔发布,就是告诉它它是以它是它像个灯一样的,就是告诉外界自己你这个东西存在就像一闪一闪的这种,哼,可以理解,一闪一闪的就是那个 Beacon 这里面的,这就是从那个,这个,就是那个抓到那个帧里面看到的那个具体的一个值,它发出来里面通过我们的控口设备或者是控口设备就能抓到这些路由器发的那个必肯帧。 这个当然它这个所有的帧都是遵循 80211 协议,这里面的一些子类型,就是子类型里面就是里面的每个把它展开,你这是一通过一个软件展开的,用 Wireshark 或者是Omnipeek,它是到时候需要用的话,你们导师会提供给你们的。这个可以开始了解一下协议的具体协议就是长这个样子,这个里面看到的就是source, source 就是发布的源,就是这个一个叫owner,这个是什么?这个名字的一个路由器发的,它的类型就是目标就是广播 destination 目的地,但是因为它是广播的形式,就是它也不知道是发给谁,因为它是,它就是自己在那发,它没有说目标的存在,目,就是发给有没有明确的目标,所以它叫广播类型,这个是info,这是它的介绍,这是这个协议的介绍,这个你用那个软件它又能看到这些东西,它这个帧 proper request,你看到那个协议 802 协议的话。 它里面也还有很多类型,一个管理帧是比较重要的,就是你如果分析那些连接不成功,或者是分析那些东西连接问题的时候,包括一些没连上的问题,它都你这些Tab,你可能要看一下中间是哪一步出现问题。这个 FF 表示就是未知的,就是广播类型的,所以他这个 source address 就是这个,就是那个路由器的SSID,这个后面就是它的 Mac 地址,就是每个路由器它都有 Mac 地址,包括你我们的手机也有 Mac 地址,因为它没有接收,因为我这上面没有显示的连接,我后面会讲。 这个是它支持的一些速率,你看这个兆,一兆、两兆、 5.5 兆、 11 兆,这是它的速率。这下面有其他的解释。 sport 它。这个是它扩展这样自动搞,sorry,等一下,这是个连接过程,请求过程的应答,这是发的 property 啊。哦,这个是auth,这刚说的是那个auth,就是认证的时候他发的一个,诶,这怎么自动跳了?稍等一下,sorry,稍等一下,这个它自动滑了,这个这是,这是扩,这是它扩展的一些extend,这扩充扩展支持的一些速率一直到 54 兆,这证明这个路由器支持到 54 兆的。还有这个就是prop,刚才说的是 prop request,这个是 prop re- response,就是响应,这也是它的那个,这展开看这个不用细节,不用细究,就是大概了解一下就行了。 这就是手机端对目标认证的时候,就是 Auth 认证的时候就是直接获取获。哎呀,怎么自动滑了?自动滚的?它这边你看 Tab 这个地方就变了,就变成那个 auth 了,这管理帧,这也是管理帧, Tab 类型就等于 0 管理帧,那这个因为它开始已经认证了,所以说它之前已经有目标的 Mac 地址了,目标地址了,这个是,这个就是手机的地址,这个就是路由器的地址,然后它们两个之间开始交互了啊。这,这,这就是连接成功了,这就successful,这就连,这就一个连接的过程。 这个只是 auth 成功了。sorry, auth 成功了。这个应该是关联accession,这就是关联的请求第二步,那个关联的请关联的那个空口包这里面,然后这里面的是什么不支持 Web 协议,这个是一些特性,它都是都在,都是通过这里面的二点,每个字,每个每一位它都有它的含义的,它这个它都会给你打出来,这个就是对刚才那个关联的请求进行回应,就是刚才那个握手连接的那几个过程。 然后的话,到了这一步的话, AP 对客户端的连接请求给了回应,这是在它这个 auth 阶段就已经结束了,连接完成了就 successful 了,然后它就可以正常进行数据收发了。我们这常用的 Wifi 分析的工具有 Wireshark 和wlanpick,它抓出来就是这个样子,这个是用一个 wireshark 抓出来的,它有个你们如你要熟悉,你看这个这种应用request,然后响应就是的response,又有个ACK,每次发一个它都有个 ACK 的,然后有个 auth ACK,这就是个,这是一个比较清晰的一个连接的过程啊。 然后有一 p 加密四步握手,然后那个 BA 这每个里面都有响应,这个,嗯,到时候可以再抓一下,用工具抓一下,试试这个信号这里面的,然后这个是信道channel,刚才说的 Wifi 的信道,这个 single signal,这是信号强度,这是包的那个长度,每个包的长度这里面 revolution 就是间隔的时间,这就是源的那个发起的那个 Mac 地址,还有接收的 Mac 地址,这是BSID,当然这是 BSID 的 Mac 地址,就是路由器的 Mac 地址,它都因为它都是一样的,都是这个门都连上是它的,所以说都一样啊。 还有一些 flag 这些细节,到时候再看一下,如果在分析这个连接过程中不是用的开放网络的话,那我们这个,这,咱这是个开放网络,这个不是开放网络,不,不是开放网络,这有加密的分析过程中要提供密钥给他,要不然的话你的那个空口是解不开的啊。就是到时候遇到这种类似的问题的话,我是要把它记录下来,要不然的话你这个解不出来,你也分析不了。 这个是常见的空口里面常见状态的ARP,还有DHCP, DHCP 就是路由器给的那个路由器给每个,因为你的手机里面是在路由器那边没有登记它,所以是相当于在那手机在路由器那边登记一下它给你个 Mac 地址,给你i,给你个 IP 地址,每个,每一个连上路由器的它都会走到这个地方,没有。sorry,怎么又跳过去了?没有连上的话,没有。如果这个 DHCP 状态它没有给你分配,那,那么那么你的那个手机是上不了网的连,等于说还没有连接成功啊。 我们在那个日常的处理问题中,有时候会遇到这种问题,当路由器那个连满了这个 DHCP 给它分配不了了,或者是加入什么,加入什么,分不它,就它在这边就会分不成功,就是查原因了啊。还有漫游空口里面还漫游状态,就是我们比如说从一个地方到另外一个地方,在一个空间内从一个地方走到另外一个地方,它那个信号变弱的时候,我们刚才说到的就是它这个手机之间,会,手机和路由器之间会发现漫游的话,在空口里面就会看到这些,就看到这个打印有关键字,还 disso- disassociate,这就是断了,断开了就是断了,还包括里面还有什么 associate 等等等,有好几个,好多少个,这具体的话可以到这个里面去看啊。 这个当时从那个 优快云 上扫的还有reset,就是网络和路由器之间,手机和路由器之间断了,然后它有时候会发一个 reset 过来,然后表示里面断开了,具体的话这就不打开看了,后面还有这个,到时候文档发给大家,大家可以到那个去搜一下,就有框架流程的话, Wifi 的框架它分为上层,就是我们说的 application framework,就应用层的framework,以 frame framework 框架那边,因为它里面有涉及到的有setting。 它一般我们看到的 Wifi 这边看到的就是从 setting 里面打开它,这个也是或者是由 AP APK 那边有,就是 APP 那边它里面也肯定也有控制录,控制 Wifi 的东西,它里面有API,各种 API 去控制 Wifi 的一些动作啥的,但是我们就讲一些比较简单的,简单的框架,这个叫安卓点 net 点 Wifi 上层,它是通过这个 banner 有点像进程间之间通信的,一个一个,一个工具,一个,怎么说是进程间通信的一个一种方法?你们如果是安卓这方面应该学过,安卓的话应该了解这个东西,这是安卓上面搞的一个东西,里面这个 Wifi 里面的话,它是有一些服务在里面,就包括我们有 Wifi service,就基本的最基本的服务,它这里面还有一些 NL 80211 这个它子服务,还有 Wifi client,它是监控 Wifi 状态的一个东西,它中间也是通过你这个东西,是底层,是 c 里面搞的东西, c 里面是 Linux kernel 那边的东西,它是中间,它们中间要这个 Wifi service。 它是 Java 层的,所以说它们之间要通信,涉及到一些进程间通信,他们就要anner去搞,包括里面还有 Wifi p to p service,这里面这是 p to p,就是 p to p 那边相关的一些特性,你只有 Wifi service 就管一些,就是ST,就是联网。 扫描那些东西,它都在这个里面, p to p,就是 p to p 相关那些东西,直连那些投屏那些,它是这个里面单独在管,还有Wifi、 aware 这个是他们新增的一些service,这个我们用的,我这边用到的不多,还有 Wifi RTT service,这个是负责那个间隔的, RTT 就是传输的,就是和路由器之间的一个时间的一个一个服务,和路由器传输时间的一个服务,这个我们这边用的也不多,我们主要关注这个东西。 还有这个 Wifi p to p 这个东西多一点,它们中间是和底层怎么交互呢?是通过idle,最开始是通过hidle,现在是改成 idle 了。 idle 之间通信里面有,还有 wander 车, split client 是我们 Wifi 里面最重要的一个东西, split client 这个等于WPA, split client,这是它的一个,这也是个开源的一个框架,但是安卓把它给搞过来了,移到这个代码里面去了,所以说就它这里面一个服务, WPA split client,这个这是号层的,这是和,但这个是 wonder 号,这是每个厂家自己是可选的,这个不见得有,这个是我们必须要掌握的,有我们就要,必须要打交道的这个东西。 还有一个 host apt、error,这个是热点相关的,这个是wonder,那个这刚才是大概介绍了一下,这里面是一些分层的,这些是 Wifi setting,还有 Wifi framework,就是属于 Java 层的, Java 层和那个经和它通,它跟底型底层那个交互的话,它就是通过这个 JNI 实现的方式,通过 JNI 去控制它。然后还有 host 一些 WP subscriber 层的话是一个单独的一个服务,这是单独的,他釉拎出来了,然后的话然后剩下再到内核,这个内核的话包括驱动的一些东西都在这里面往里面分配,被 NL 变8021,这还,这,这个 Netlink 8021 还subscriber,这个从subscriber, WP subscriber 往下发给驱动发东西,这在内核空间里面搞的这个sorry,我这边看到的不太挡住了,这个是他这个从网上找的一些那个流程,它层层地递交下来。 包括这个Wifi,刚才少,还少说了一点, Wifi 里面的话 framework 层它有很多状态机,它有几十个状态机,现在可能精简了一点,也,但是也有十几个状态机,它从开一直到打开状态,一直到什么扫描,每个里面都有一堆状态机。这个我们在,因为我们是驱动这边,所以说我们只是大概了解一下有这些东西就行了,但是我们不需要不用太管它,除非是这个状态机的话,一般是这种enable,包括 enable 那个状态机那些也是一大堆东西在里面,如果进去看的话,有人把人看晕,这个我们除非是要魔改,就是那些对于那些因为一很多厂商他是有一些快文审这些要求,就是打开要比原生要快,或者小米,或者是荣耀,或者是那个什么OPPO。 他们那边对待这些状态机可能有所优化,有的不,但也不是所有都优化了,有的东西它可能优化它优化了一些,但不是所有的,因为状态机太多了,那一般不改它的这些东西,否则的话你后面要维护也挺麻烦的。这是 Wifi monitor,这个服务都是你如果搞 Freemark 的话,它就是都能看到它们 Wifi service,我们这,但是我们搞 Wifi 的话一般要对上面也要也了解它在干嘛的这个基础的那个东西。岳龙这边你后面也要看一下这个东西是干嘛的啊?监控的 monitor 这些东西是干嘛的要了解一下。还有 native Wifi,native,它这是从上往下走这些东西,都是这些东西的话一般都是不怎么变化的,在这个我们在荣耀那边做的时候,他们做了一些处理,但是主要做的主要是一些监控方面的,就是一些我监控方面的,就看他监控他这个每个状态有没有出现问题啊。 那他之前中间用了很多文件的,在哪个仓里面?这个大概列了一下这个,当然这个是这个图来不及搞嘛?这从网上搞的,但是大概是在这个路径下,他们因为他们升级,每次升级 control 升级的话,它对这个东西它都有可能有所变化,路径可能有点变化,但是到时候具体具道、具体问题具体分析。 这刚才也说了,就是 Wifi service 是负责 Wifi 功能的核心服务。 free mark Wifi 功能的主入口,这个 Wifi manager 是 Wifi 模块向外部透出来的接口,这个 Wifi manager 它是一般给上层用的,就是那种应用程序用的,就是它有些比如说开关Wifi,什么什么查询,那个什么 Wifi 的信号,什么东西它是偷,很多时候通过这个类它给搞出来一个东西,然后让你外部能查询,它不是让你直接控制 Wifi 的,它是整体将通通为一个接口一样的,相当通,一个代理的代理,一个接口。然后有应用层,就 APK 那边应用层和底层之间。诶,搞一些,公布了一些可以他可以查询的一些接口给他,给上层用。 这是你刚刚说的那个状态机里面,它里面是每个动作,它其实有一大堆状态机,什么扫描、连接、获取、IP、漫游,它都是状态,都对应的都是一个状态机。状态机里面又分为一些子状态机, Wifi monitor 就是这个,就 Wifi monitor 就是给 subclient 下发给这个状态机的一个一个服务,这个状态机这个 Wifi native 就是 Wifi s 状态机就给 subclient 执行的一个东西,一个服务也在里面。 state 刚才就说过的,我们驱动你最用到的这个东西,很多时候都通过它去查,通过它去搜一下它,看看一下 Wifi 的各种状态当时处于什么状态,然后再根据它现在的是不是该处于那种状态来判断它这个问题出在哪。就是很多时候我们主要通过它去看状态机,大概说一下,那么一开始这就是上层的一个状态机,就是一层、二层、三层万物,它这个最开始有个父类,然后一个这是个连接的一个状态机,云状态机一共有 L2L2 层链路层的一个状态机, L2 层又分为什么obtain?这个是好像获取 IP 的一个,这个是我时间久了我忘了,这个是连上的一个状态机,这个是漫游的状态机,这是断掉的状态机,断这断掉中的状态机,那些是断掉已断开的状态机。 反正这几十个这个图太多都画不下,大概介绍一下这个上次改对这个状态,对,这个 freemarker 要搞 freemarker 的同学,这个东西肯定要熟悉一下,要了解一下 default 状态,就是没有打开驱动,没有加载这个这connected,这个native,这种 s native 这种表示类型已打开,然后处于这种连接状态的状态机的话,它就会发生这个在那个,这个是属于安卓 log 会打出来这个,然后的话这个状态机的话它这个是处于会发这个广播出来。 从log,我们到时从 log 都可能会看到扫描连接的时候会发这个东西出来,连上了之后它也会发这个断连,它也会发这个,然后在你做 a 做 APP 那边的话就可以监控到这个东西,然后看它你连上了要做什么动作,断开要做什么动作,你这个代码里面就会就可以做一些逻辑处理。 这个是链路层已经连上了这个 L2 就是 level 2,这是 OSS 的那个网络模型里面的第二层数据链路层,表示数据链路已经建立完成了,这个这跟上,这个跟上面。是啊,跟上还不太一样。 state change,这个也是 DHCP 获取 IP 的状态,这个就是对上面那对刚才那张图的一个大概的解释,这就是连上的状态广播,这是获取它这个obtain,这获取 IP 的时候这个好像这个忘了,这个太久了,忘了。这状态机算发的什么广告?我忘掉了,哼,到时候也感兴趣可以看一下。 漫游的时候是,对,这个就是漫游的时候,它处于漫游状态的话,它会连到另外一个热点,它是触发这个状态机断开的,触发这个状,这也是触发了 status change,这个得跟这个是其实是一样的,它因状态发生变化,它都会发这个广播,因为这个写得比较早。 这是安还是安卓 q 的?你状态机的话,它这个是肥马克那边的,之前说的就肥马克那边,它这个状态机是会根据每个版本它都会变化,多多少少会变化一点,有时候到特别是跨了几个版本之后,它的状态机有时候会简化这些。如果是搞 Freemark 的话,看一下这上面它这个状态机的变化过程,这些 default state、connect、 model 这些东西,这是变化过程,它在每个变化过程中它一般都会带一些信息出来,这些 SSID 这个名字,这是这个这些东西,这BSSID,这些路由器的名字它都会搞出来。 Mac 地址这个也是它,在它也会链路的时候,它会带那个RSSI,就是 Wifi 的那些信号,还有当前的那个连的是 5G 还2.4G,这个 SC 忘了是啥了,这是连接速度866,这跟我们那个下层看的不一样,它这个东西跟我们看的那个底层看的东西不太一样。 这就说一下那个split,介绍一下 split client 这块是刚才说过是开源代码,谷歌修改后加入移动安卓平台,其实 split client 比那个安卓历史还要早,在其他的一些平台上也用过,比如它加入了很多对NFC,就是刚才那说的 80218021 协议,也是 NFC 的一种,它能支持很多这种加密的方式。它实际的工作的原理就是通过socket,那 li- Linux 它是主要是通过 socket 之间很多通信,而且这个 wclient 也能通过调用驱动对 Wifi 进行芯片进行操作。 那你看从这个图上可以看到它加密类型,那连接的时候加密类型进行处理,然后这个 Netlink 80211,这个是Netlink,是它那个 Linux 和用户态,和用户空间,和那个内核空间进行一个框架的一个一一一一种方法啊。这个你们到时候搞那个 Linux 可能应该会了解到的。在这个用户空间还有个内核空间,这写了用 socket 一个通讯机制,这这它这个驱动从上到下它这个东西都是遵循这个 80211 协议,从上到下都是的。 芯片介绍 WCN 的芯片,我们叫WCN,其实就是WCN,也可以理解成为短剧芯片介绍,因为我们现在的它不仅仅是Wifi,它里面也有,它有几合一, 3 合一或者四合一,它这种芯片里面也集成了那个Wifi、蓝牙,还有 FM 这些叫我们现在搞的这个项目都是 33950 WCN 39503988。 这些它都支持几合一的,它里面每个里面它支持的这种协议,它这个每个芯片的话它都有说明书的,到时候你如果了解的话,到时候进入项的话会要了解这里面细节的话,会发说明书给大家看一下,到时候你们可以查一下它的命令,查一下它一些命令,它所但是都纯英文的写得比较多,遇到那些命令或者是下版本或替换什么?替换什么?替换什么文件啊?高通或者是 MTK 的文件,他们都可以看说明书去查,但特性它包括一些 Wifi 的特性,它也可以从那里面说明书里面查到,这时候客户可能问你 Wifi 支持什么特性,什么东西?他了解什么细节,一般都是从这个说明上去查,它是最官方的,因为它的特性非常多,已经也不是每个人都能了解所有的,所以说从那个上面查是比较准的。 还有就是这个数据推荐,如果是最后一次数据推荐,就是这个有个电子版的这个一个叫做邓,一个一个一个姓邓的一个作者写的这个安卓Wifi。一下他从源码,包括从他的从上到下他都把它都写了,这是个大牛写的,但是看了,看着人把人看晕啊。还有一个 Linux 要熟悉一下, Linux 一些基本的东西要了解一下,你还有一些 TCP IP 的,我们这些写遇到一些解析的,比如说要碰到一些连接过程,包括一些吞吐的过程,一些性能过程,他都要对那些空口,就刚才看到的那些空口要进行熟悉,那些东西它都是遵循,其实遵循 TCP / IP 协议的这个这卷一其实可以看一下,这个也是这个是可能编译相关的,允许看这个东西有点用,这边这个主要是讲完了这个,这些这些这个文档上都 PPT 都已经讲完了。这个。这个是他们的,这个是,嗯, B2 里面搞的一些学习路线,这到时候也可以参考一下。看大家有没有什么问题啊? 这是基本的讲了一下,中间遇到过程中,因为这些都是些理论性的东西,过程在工作过程中遇到各种问题,它虽然理论上要懂,也要熟悉一下,然后过程中的问题还灵活处理啊。 再搞这搞的 Wifi 的话,到时候会根据问题来解决,对应上这些理论知识。 没有问题的话,那加伟,那个加伟在不在?加伟的,要不就先这样,刚好一个小时啊。 这个,那好,谢谢各位参加啊。那我停止共享了,谢谢各位啊。有问题大家可以找我,哈哈。
最新发布
09-18
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值