nginx反代cloudflare https站点

自己域名反代自己在 cloudflare 的域名进行加速 #PROXY-START/ location  ~* .(php|jsp|cgi|asp|aspx)$ { proxy_pass https://你的域名; proxy_set_header Host 你的域名; #向后端传递访客 ip proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; #向后端传递访客 ip proxy_ssl_name 你的域名; proxy_ssl_server_name on; } location / { proxy_pass https://你的域名; proxy_set_header Host 你的域名; #向后端传递访客 ip proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; #向后端传递访客 ip (反代CF增加规则) proxy_ssl_name 你的域名; … Read more

Android13 SplashScreen功能源码分析、移除和客制化

SplashScreen功能从android12开始添加,本文章分析了SplashScreen的启动流程,整体和独立App移除方案以及客制化 获取SplashScreen的window名称 在开发者模式将Animation scale调成10x,adb shell输入命令: dumpsys window windows 获取结果,以下为Splash Screen对应的Window信息 Window #8 Window{9d4659b u0 Splash Screen com.google.android.gm}:     mDisplayId=0 rootTaskId=12 mSession=Session{3fbadb0 1074:u0a10116} mClient=android.os.BinderProxy@d8c05aa     mOwnerUid=10116 showForAllUsers=true package=com.google.android.gm appop=NONE     mAttrs={(0,0)(fillxfill) sim={adjust=pan} ty=APPLICATION_STARTING fmt=TRANSLUCENT wanim=0x7f1603e6       fl=NOT_FOCUSABLE NOT_TOUCHABLE LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR ALT_FOCUSABLE_IM HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS       pfl=SHOW_FOR_ALL_USERS USE_BLAST APPEARANCE_CONTROLLED FIT_INSETS_CONTROLLED       apr=LIGHT_STATUS_BARS LIGHT_NAVIGATION_BARS       bhv=DEFAULT       fitSides=}     Requested w=3840 h=2160 mLayoutSeq=1595     mBaseLayer=21000 mSubLayer=0    mToken=ActivityRecord{2e6ad9e u0 com.google.android.gm/.ConversationListActivityGmail} t12}     mActivityRecord=ActivityRecord{2e6ad9e u0 com.google.android.gm/.ConversationListActivityGmail} t12}     mAppDied=false    drawnStateEvaluated=true    mightAffectAllDrawn=true     mViewVisibility=0x0 mHaveFrame=true mObscured=false     mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]     mFullConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw720dp w1280dp h696dp 480dpi lrg long land finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 – 3840, 2160) mAppBounds=Rect(0, 0 – 3840, 2160) mMaxBounds=Rect(0, 0 – 3840, 2160) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_0} s.1 fontWeightAdjustment=0}     mLastReportedConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw720dp w1280dp h696dp 480dpi lrg long land finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 – 3840, 2160) mAppBounds=Rect(0, 0 – 3840, 2160) mMaxBounds=Rect(0, 0 – 3840, 2160) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_0} s.1 fontWeightAdjustment=0}     mHasSurface=true isReadyForDisplay()=true mWindowRemovalAllowed=false     Frames: parent=[0,0][3840,2160] display=[0,0][3840,2160] frame=[0,0][3840,2160] last=[0,0][3840,2160] insetsChanged=false      surface=[0,0][0,0]     WindowStateAnimator{28bc62d Splash Screen com.google.android.gm}:       mSurface=Surface(name=Splash Screen com.google.android.gm)/@0xfb34762       Surface: shown=true layer=0 alpha=1.0 rect=(0.0,0.0)  transform=(1.0, 0.0, 0.0, 1.0)       mDrawState=HAS_DRAWN       mLastHidden=false       mEnterAnimationPending=false      mSystemDecorRect=[0,0][0,0]     mForceSeamlesslyRotate=false seamlesslyRotate: pending=null    isOnScreen=true     isVisible=true     keepClearAreas: restricted=[], unrestricted=[] 以上获取window名字关键字Splash Screen,在整机代码库framework/base目录下搜索: grep -nr "Splash Screen" 搜索结果:根据搜索结果,定位为framework/base/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StaringSurfaceDrawer.java 311行。  /**       * Called when a task need a splash screen starting window.       *       * @param suggestType The suggestion type to draw the splash screen.       */      void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,              @StartingWindowType int suggestType) { …            params.setTitle("Splash Screen " + activityInfo.packageName);          // TODO(b/173975965) tracking performance          // Prepare the splash screen content view on splash screen worker thread in parallel, so the          // content view won't be blocked by binder call like addWindow and relayout.          // 1. Trigger splash screen worker thread to create SplashScreenView before/while          // Session#addWindow.          // 2. Synchronize the SplashscreenView to splash screen thread before Choreographer start … Read more

LineageOS 20/AOSP 生成并替换默认系统签名

LineageOS 20/AOSP 生成并替换默认系统签名 本文介绍如何将Lineageos中的testKey替换成releaseKey,基于LineageOS android13。 生成系统签名 LineageOS编译默认使用test-keys,位于build/target/product/security目录: Android.bp                 networkstack.pk8       sdk_sandbox.x509.pem Android.mk                 networkstack.x509.pem  shared.pk8 bluetooth.pk8              platform.keystore      shared.x509.pem bluetooth.x509.pem         platform.p12           testkey.pk8 cts_uicc_2021.pk8          platform.pem           testkey.x509.pem cts_uicc_2021.x509.pem     platform.pk8           verity_key fsverity-release.x509.der  platform.x509.pem      verity.pk8 media.pk8                  README                 verity.x509.pem media.x509.pem             sdk_sandbox.pk8 test-keys是公开的,任何app拿到testkey都可以使用系统签名,所以对外发布的版本需要使用自己生成的release-keys.生成系统签名在android系统源码根目录执行下面的脚本: subject='/C=CN/ST=Beijing/L=Beijing View/O=Xiaomi/OU=MIUI/CN=MIUI/emailAddress=miui@xiaomi.com'mkdir ~/.android-certsfor x in releasekey platform shared media networkstack; do      ./development/tools/make_key ~/.android-certs/$x "$subject";   done 上面脚本会在用户根目录下创建.android-certs目录,并在该目录下生成 releaseKey、platform、shared、media、networkstack几种key文件。提示输入密码直接回车即可。 lili@adam:~/.android-certs$ lsmedia.pk8         networkstack.x509.pem  releasekey.pk8       shared.x509.pem media.x509.pem    platform.pk8           releasekey.x509.pem networkstack.pk8  platform.x509.pem      shared.pk8 $subject 可以根据自己的公司信息修改。subject每个参数的代表的意思如下: C —> Country Name (2 letter code) ST —> State or Province Name (full name) L —> Locality Name (eg, city) O —> Organization Name (eg, company) OU —> Organizational Unit Name (eg, section) CN —> Common Name (eg, your name or your server’s hostname) emailAddress —> Contact email address 以上每种key分别生成了两个文件,.x509.pem后缀的是证书文件,包含key的公共信息。.pk8后缀的是私钥。android构建使用的5种key都在build/target/product/security目录下: testKey包的默认签名 platform 平台核心包的test key sharedhome/contracts进程共享内容的test key mediamedia/download系统的test key networkstack网络系统的test key. 独立的包可以在其模块的Android.mk里面设置LOCAL_CERTIFICATE设置签名。 LOCAL_CERTIFICATE := platform 也可以指定key路基本: LOCAL_CERTIFICATE := device/xiaomi/security/special 指定系统签名为release-Keys 首先,将上面生成的系统签名文件拷贝到 build/target/product/security目录下: cd build/target/product/security   cp -f ~/.android-certs/* ./ 修改build/make/core/config.mk: ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE   DEFAULT_SYSTEM_DEV_CERTIFICATE := $(PRODUCT_DEFAULT_DEV_CERTIFICATE) else    DEFAULT_SYSTEM_DEV_CERTIFICATE := build/make/target/product/security/testkey … Read more

AOSP System app Android.bp集成Leakcanary检测内存泄漏

本文以Settings模块为例,继承Leakcanary 2.12 确定依赖的aar和jar包。 两种方式确定,一种方式是在android studio中通过在build.gradle中引入leaknacary,然后查看external libraries中新增的以来,到maven center下载对应版本的jar包和aar包。 另一种方式是直接在github release页面下载leakcanary源码自行编译出aar和jar依赖。 Settings集成leakcanary 定位到packages/apps/Settings目录。将依赖的jar包和aar包拷贝到libs目录. 在libs目录下新建Android.bp文件: java_import {     name: "leakcanary-object-watcher",     jars: ["leakcanary-object-watcher-2.12.jar"],     libs: ["shark-log"],     sdk_version: "current", } java_import {     name: "okio-2.2.2",     jars: ["okio-2.2.2.jar"],     sdk_version: "current", } java_import {     name: "shark",     jars: ["shark-2.12.jar"],     libs: ["shark-graph","okio-2.2.2"],     sdk_version: "current", } java_import {     name: "shark-android",     jars: ["shark-android-2.12.jar"],     libs: ["shark"],     sdk_version: "current", } java_import {     name: "shark-graph",     jars: ["shark-graph-2.12.jar"],     libs: ["shark-hprof","okio-2.2.2"],     sdk_version: "current", } java_import {     name: "shark-hprof",     jars: ["shark-hprof-2.12.jar"],     libs: ["shark-log"],     sdk_version: "current", } java_import {     name: "shark-log",     jars: ["shark-log-2.12.jar"],     sdk_version: "current", } android_library_import {     name: "leakcanary-android-utils",     aars: ["leakcanary-android-utils-2.12.aar"], … Read more

open TV’s expanded PiP in android 13 mobile or tablet

    android 13 for TV推出了expanded PiP功能,但是只在android 13的电视上作用,在手机或者平板上,即使开了android.software.expanded_picture_in_picture feature也无法使用expanded pip。 经研究可通过修改framwork代码,将TV的expanded pip feature移植到手机或平板,在手机和平板上开启expanded pip功能,以下以手机为例。  开启android.software.expanded_picture_in_picture feature  修改frameworks/native/data/etc/handheld_core_hardware.xml文件,追加以下配置: <feature name="android.software.expanded_picture_in_picture" notLowRam="true" />  2. 移植TV 代码 修改 framework/base/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java  /*  * Copyright (C) 2021 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package com.android.wm.shell.dagger; import android.content.Context; import android.content.pm.LauncherApps; import android.os.Handler; import android.os.SystemClock; import android.os.UserManager; import android.view.Choreographer; import android.view.WindowManager; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.UiEventLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.TaskViewTransitions; import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.bubbles.BubbleController; import com.android.wm.shell.bubbles.BubbleData; import com.android.wm.shell.bubbles.BubbleDataRepository; … Read more

Android PiP画中画支持

Android 画中画支持 Android8.0开始支持Activity进入画中画模式。画中画是一种特殊类型的多窗口模式。它允许用户在固定在屏幕一角的小窗口观看视频的同时在应用之间切换或浏览主屏幕上的内容。让App进入画中画,需要将Activity设置成支持画中画。 画中画交互 在触屏设备设备上,用户可以拖拽PiP窗口到另一个位置,从Android S(12)开始,用户也可以: 单击窗口显示PiP菜单。 双击窗口切换PiP窗口最大或者最小。 通过拖动窗口到窗口边缘,隐藏PiP窗口,如果要取消隐藏,可以点击可见部分或直接将拖拽出来。 通过双指缩放调整PiP大小。 App声明PiP支持 默认系统不支持App进入PiP模式,需要在App manifest里设置android:supportsPictureInPicture="true",并指定activity处理configuration改变来防止activity重启。 <activity android:name="VideoActivity"     android:supportsPictureInPicture="true"     android:configChanges=         "screenSize|smallestScreenSize|screenLayout|orientation"     … 进入PiP 在移动设备上从Android12开始,可以通过给activity设置setAutoEnterEnabled flag为true,就不用在onUserLeaveHint时调用enterPictureInPictureMode()方法进入PiP了。 App页面适配 进入和退出PiP时会触发Activity.onPictureInPictureModeChanged()或Fragment.onPictureInPictureModeChanged()方法。需要重写这些回调方法来重新布局activity。当App进入PiP模式的时候,用户无法与app的UI元素交互,小窗口页面不需要呈现太多内容。 @Override public void onPictureInPictureModeChanged (boolean isInPictureInPictureMode, Configuration newConfig) {     if (isInPictureInPictureMode) {         // Hide the full-screen UI (controls, etc.) while in PiP mode.     } else {         // Restore the full-screen UI.         …     } } 添加App交互 原生通过PictureInPictureParams.Builder.setActions()方法来设置交互,比如视频暂停、播放等。 生命周期影响 当activity进入PiP模式后,会触发onPause()生命周期,需要在这里做特殊处理,比如全屏播放时进入PiP不需要暂停视频,而其他情况下onPause()后需要暂停,可以这么处理。 @Override public void onPause() {     // If called while in PiP mode, do not pause playback     if (isInPictureInPictureMode()) {         // Continue playback         …     } else {         // Use existing playback logic for paused Activity behavior.         …     } } 在onPause()里通过isInPictureInPictureMode()方法判断当前是否处于PiP模式。当activity退出PiP进入全屏模式的时候,会触发onResume()生命周期。

在Ubuntu22.0.4上安装jadx

在Ubuntu22.0.4上安装jadx 获取jadx版本号 curl -s "https://api.github.com/repos/skylot/jadx/releases/latest" | grep -Po '"tag_name": "vK[0-9.]+' 输出: lili@adam:~/development/reverse/tools$ curl -s "https://api.github.com/repos/skylot/jadx/releases/latest" | grep -Po '"tag_name": "vK[0-9.]+' 1.4.6 得到当前最新jadx版本号是1.4.6。2.下载jadx curl -Lo jadx.zip "https://github.com/skylot/jadx/releases/latest/download/jadx-${JADX_VERSION}.zip" lili@adam:~/development/reverse/tools$ curl -Lo jadx.zip "https://github.com/skylot/jadx/releases/latest/download/jadx-1.4.6.zip"   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                  Dload  Upload   Total   Spent    Left  Speed   0     0    0     0    0     0      0      0 –:–:–  0:00:01 –:–:–     0 100     9  100     9    0     0      3      0  0:00:03  0:00:02  0:00:01     3 lili@adam:~/development/reverse/tools$ ls jadx.zip 解压压缩包 lili@adam:~/development/reverse/tools$ unzip jadx.zip -d jadx-temp 添加jadx到环境变量vim打开~/.profile文件,添加最下面添加下面的代码 # add jadx   if [ -d "$HOME/development/reverse/tools/jadx-temp/bin" ] ; then     PATH="$HOME/development/reverse/tools/jadx-temp/bin:$PATH" fi 然后 source ~/.profile 检查jadx是否安装成功 lili@adam:~$ jadx –version 1.4.6 测试jadx lili@adam:~/development/reverse/apks$ jadx-gui tiktok.apk Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't load library: /usr/lib/jvm/java-11-openjdk-amd64/lib/libawt_xawt.so at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2633) at java.base/java.lang.Runtime.load0(Runtime.java:768) at java.base/java.lang.System.load(System.java:1837) at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method) at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2445) at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2501) at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2700) at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2651) at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:830) at java.base/java.lang.System.loadLibrary(System.java:1873) at java.desktop/java.awt.Toolkit$3.run(Toolkit.java:1399) at java.desktop/java.awt.Toolkit$3.run(Toolkit.java:1397) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.desktop/java.awt.Toolkit.loadLibraries(Toolkit.java:1396) at java.desktop/java.awt.Toolkit.<clinit>(Toolkit.java:1429) at java.desktop/java.awt.Component.<clinit>(Component.java:621) at jadx.gui.settings.JadxSettings.<clinit>(JadxSettings.java:51) at jadx.gui.settings.JadxSettingsAdapter.load(JadxSettingsAdapter.java:64) at jadx.gui.JadxGUI.main(JadxGUI.java:24) 我执行jadx-gui报错了,因为jdk不完整。运行下面命令 sudo apt install openjdk-11-jdk –fix-missing 再次尝试打开jadx-gui jadx-gui tiktok.apk

Android上使用termux开启ssh,并在pc端连接

Android上使用termux开启ssh,并在pc端连接 需求背景 看同事在公司的android设备上装termux想搞远程adb,周末自己在家也想着玩玩。首先在手机上安装了termux,接下来需要在手机上敲一堆命令有点麻烦,所以想着在手机上开启ssh,就可以通过局域网内的pc连接手机的ssh在电脑上敲命令了。 termux可以在https://f-droid.org/zh_Hans/packages/com.termux/或https://github.com/termux/termux-app/releases下载安装。 手机端操作步骤 termux内安装openssh pkg update  pkg install openssh 设置ssh密码 passwd 输入两遍密码就设置完成了 开启ssh服务 sshd 如果提示:sshd: no hostkeys available — exiting. 就输入下面命令 ssh-keygen -A 查看用户 whoami 查看手机ip ifconfig PC端操作步骤 以上在手机上通过termux安装了openssh,开启了ssh服务,拿到了用户名和手机ip,接下来在就能在pc端连接手机ssh了。Windows上可以用putty、xshell、securecrt、termius等工具连接ssh,我pc装的是ubuntu,可以直接通过命令连接。 ssh -p 8022 u0_a182@192.168.31.29 8022是openssh的默认端口,u0_a182是手机上通过whoami得到的用户名,192.168.31.29是我手机的局域网ip。

install selenium,chrome,ChromeDriver on Aliyun CentOS ECS

install selenium  yum install selenium 2. install chrome   yum install epel-release yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 3.install ChromeDriver    3.1 check chrome version   google-chrome-stable –version Google Chrome 102.0.5005.115   3.2 download the ChromeDriver match the chrome and install it     go to the taobao mirror page https://npm.taobao.org/mirrors/chromedriver/ wget  unzip chromedirver_linux64.zip   mv chromedriver /usr/bin/ chmod 777 /usr/bin/chromedriver 3.3 check ChromeDriver  Version chromedriver -v

Android Context Analysis

Android Context 分析 继承结构类图: ContextWrapper是上下文的包装类,ContextImpl是上下文的实现类,Activity是ContextThemeWrapper的直接子类。 getApplicationContext都做了什么   翻看ContextWrapper源码: public class ContextWrapper extends Context {             Context mBase;     public ContextWrapper(Context base) {         mBase = base;     }          /**      * Set the base context for this ContextWrapper.  All calls will then be      * delegated to the base context.  Throws      * IllegalStateException if a base context has already been set.      *       * @param base The new base context for this wrapper.      */     protected void attachBaseContext(Context base) {         if (mBase != null) {             throw new IllegalStateException("Base context already set");         }         mBase = base;     }    @Override     public Context getApplicationContext() {         return mBase.getApplicationContext();     }     ….      }     ContextWrapper的getApplicationContext方法直接调用mBase的getApplicationContext方法,mBase实际上是ContextImpl类实例,通过上面源码看到,在ContextWrapper类的attachBaseContext方法为其赋值。   什么时候调用的Application的attachBaseContext方法?  在ContextWrapper子类Application类的attach方法中: final void attach(Context context) {         attachBaseContext(context);         mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;     } 而Application的attach方法是在Instrumentation类的newApplication方法中调用. static public Application newApplication(Class<?> clazz, Context context)             throws InstantiationException, IllegalAccessException,              ClassNotFoundException {         Application app = (Application)clazz.newInstance();         app.attach(context);         return app;     } 继续向上追溯,Instrumentation的newApplication方法是在LoadApk的makeApplication方法中调用: public Application makeApplication(boolean forceDefaultAppClass,             Instrumentation instrumentation) {         if (mApplication != null) {             return mApplication;         }         Application app = null; … Read more