国外网站模版,旅游网站大全,网页游戏在线玩不用实名,北京 网站开发 排行AOSP开机动画调测技术点(基于Android13)
开机动画替换 首先#xff0c;在你的计算机上创建一个名为bootanimation的文件夹#xff0c;并将part0、part1和desc.txt这三个文件复制到该文件夹中。这些文件包含了开机动画的图像…
AOSP开机动画调测技术点(基于Android13)
开机动画替换 首先在你的计算机上创建一个名为bootanimation的文件夹并将part0、part1和desc.txt这三个文件复制到该文件夹中。这些文件包含了开机动画的图像帧和描述信息。 在命令行中切换到bootanimation文件夹并执行以下命令将文件夹中的内容打包成一个名为bootanimation.zip的压缩文件
zip -r -0 bootanimation.zip part0 part1 desc.txt这个命令的含义是将当前目录下的part0、part1和desc.txt三个文件打包成一个名为bootanimation.zip的压缩文件。
-r表示递归地将指定目录下的所有文件和子目录都包含在压缩文件中。-0表示使用不进行压缩的存储模式即不对文件进行压缩处理直接存储到压缩包中。
使用ADBAndroid Debug Bridge将生成的bootanimation.zip文件复制到设备的/system/media/目录中。请注意这一步需要设备具有root权限以及重新挂载/system分区。你可以使用以下命令完成这一步骤
adb root
adb remount
adb push bootanimation.zip /system/media/执行以下命令来启动新的开机动画 adb shell setprop service.bootanim.exit 0adb shell setprop ctl.start bootanim现在你可以观察到新的开机动画效果。如果想退出新的开机动画执行以下命令 adb shell setprop service.bootanim.exit 1Android开机动画(desc.txt)格式
开机动画分为2个阶段的图片资源加载part0和part2 加载规则在desc.txt文件中进行描述
desc.txt part0 part1part0与part1中的图片需要按照数字大小顺序标记。
desc.txt内容如下
通用参数
第一行定义了动画的一般参数
WIDTH HEIGHT FPS [PROGRESS]WIDTH: 动画的宽度像素HEIGHT: 动画的高度像素FPS: 每秒的帧数例如60PROGRESS: 是否在最后一部分显示进度百分比 百分比将以x坐标为基准在动画高度的1/3处显示。
动态着色属性
如果使用动态着色功能则提供一个可选的行来指定动态着色属性的格式。如果不使用动态着色则可以跳过此行。
动画部分
接下来根据以下格式提供多行来定义动画的各个部分
TYPE COUNT PAUSE PATH [FADE [#RGBHEX [CLOCK1 [CLOCK2]]]]TYPE: 单个字符表示此动画段的类型 p – 该部分会播放除非在启动结束之前被中断c – 该部分将播放到完成无论如何f – 与 p 类似但在继续播放的同时指定的帧数正在淡出。只有第一个被中断的 f 部分会被淡出其他后续的 f 部分会被跳过。 COUNT: 播放动画的次数或者为0以无限循环直到启动完成PAUSE: 此部分结束后延迟的帧数PATH: 包含此部分帧图片的目录例如 part0FADE: (仅适用于 f 类型) 被中断时要淡出的帧数其中 0 表示立即淡出使 f ... 0 的行为类似于 p并且不将其视为淡出部分RGBHEX: (可选) 背景颜色表示为 #RRGGBBCLOCK1, CLOCK2: (可选) 绘制当前时间用于手表的坐标 如果只提供 CLOCK1则它是时钟的y坐标x坐标默认为 c如果同时提供 CLOCK1 和 CLOCK2则 CLOCK1 是x坐标CLOCK2 是y坐标值可以是正整数、负整数或 c c – 将文本居中n – 将文本定位到距起始位置的n像素处在x轴上为左边缘在y轴上为底部边缘-n – 将文本定位到距结束位置的n像素处在x轴上为右边缘在y轴上为顶部边缘 示例 -24 或 c -24 将文本定位到距离屏幕顶部24像素处水平居中16 c 将文本定位到距离屏幕左侧16像素处垂直居中-32 32 将文本定位到距离屏幕边缘向上32像素向左32像素的位置
此外还有一个特殊的类型 $SYSTEM它加载并播放 /system/media/bootanimation.zip。 以上是关于Android开机动画的desc.txt配置文件的格式说明。该文件定义了动画的属性和各个部分的行为。
源码分析
frameworks/base/cmds/bootanimation
.
├── Android.bp
├── audioplay.cpp
├── audioplay.h
├── BootAnimation.cpp
├── BootAnimation.h
├── bootanimation_main.cpp
├── BootAnimationUtil.cpp
├── BootAnimationUtil.h
├── bootanim.rc
├── FORMAT.md
└── OWNERS
定义服务
开启动画启动规则定义在bootanim.rc中
service bootanim /system/bin/bootanimationclass core animationuser graphicsgroup graphics audiodisabledoneshotioprio rt 0task_profiles MaxPerformance开机动画的服务配置文件字段解释如下
service: 指明服务的名称为bootanim即开机动画服务。/system/bin/bootanimation: 指定了开机动画的执行文件路径为/system/bin/bootanimation。class core animation: 表示此服务属于核心服务并且是与动画相关的服务。user graphics: 指定服务运行的用户为graphics。group graphics audio: 指定服务运行的组为graphics audio表示具有这两个组的权限。disabled: 表示此服务当前处于禁用状态不会自动启动。oneshot: 表示此服务只执行一次完成任务后即退出。ioprio rt 0: 设置了I/O调度优先级。task_profiles MaxPerformance: 指定了任务的性能规格为最大性能。
根据你提供的信息开机动画服务当前处于禁用状态不会自动启动。
启动开机动画
开机动画在SurfaceFlinger初始化完成之后播放
//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() {............//启动mStartPropertySetThread线程播放开机动画mStartPropertySetThread getFactory().createStartPropertySetThread(presentFenceReliable);if (mStartPropertySetThread-Start() ! NO_ERROR) {ALOGE(Run StartPropertySetThread failed!);}
}那么看看StartPropertySetThread线程中具体如何运行
//frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp
bool StartPropertySetThread::threadLoop() {// Set property service.sf.present_timestamp, consumer need check its readinessproperty_set(kTimestampProperty, mTimestampPropertyValue ? 1 : 0);// Clear BootAnimation exit flagproperty_set(service.bootanim.exit, 0);property_set(service.bootanim.progress, 0);// Start BootAnimation if not startedproperty_set(ctl.start, bootanim);// Exit immediatelyreturn false;
}在StartPropertySetThread中通过设置属性方式启动动画播放。
所以如果需要手动运行bootanimation 需要通过下面命令完成
setprop service.bootanim.exit 0
setprop ctl.start bootanim接下来我们进入bootanimation实现的代码分析动画播放的具体流程。
动画播放流程
首先从main函数分析开机动画运行在一个线程中
//frameworks/base/cmds/bootanimation/bootanimation_main.cpp
int main()
{
spBootAnimation boot new BootAnimation(audioplay::createAnimationCallbacks());
waitForSurfaceFlinger();
boot-run(BootAnimation, PRIORITY_DISPLAY);
}找寻开机动画文件
//frameworks/base/cmds/bootanimation/BootAnimation.cpp
void BootAnimation::onFirstRef() {......preloadAnimation();......
}
bool BootAnimation::preloadAnimation() {//查找开机动画findBootAnimationFile();if (!mZipFileName.isEmpty()) {//加载开机动画mAnimation loadAnimation(mZipFileName);return (mAnimation ! nullptr);}return false;
}
//找寻开机动画文件主要流程即在该函数中完成
void BootAnimation::findBootAnimationFile() {......//加密设备开机动画路径static const std::vectorstd::string encryptedBootFiles {PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE,};// 启动动画路径static const std::vectorstd::string bootFiles {APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE}; ......
}加载开机动画文件并解析desc文件
//frameworks/base/cmds/bootanimation/BootAnimation.cpp
BootAnimation::Animation* BootAnimation::loadAnimation(const String8 fn) {if (mLoadedFiles.indexOf(fn) 0) {SLOGE(File \%s\ is already loaded. Cyclic ref is not allowed,fn.string());return nullptr;}ZipFileRO *zip ZipFileRO::open(fn);if (zip nullptr) {SLOGE(Failed to open animation zip \%s\: %s,fn.string(), strerror(errno));return nullptr;}ALOGD(%s is loaded successfully, fn.string());//解析bootanimation.zip并填充AnimationAnimation *animation new Animation;animation-fileName fn;animation-zip zip;animation-clockFont.map nullptr;mLoadedFiles.add(animation-fileName);//解析desc.txt文件并填充Animation对象parseAnimationDesc(*animation);if (!preloadZip(*animation)) {releaseAnimation(animation);return nullptr;}mLoadedFiles.remove(fn);return animation;
}初始化显示参数
//frameworks/base/cmds/bootanimation/BootAnimation.cpp
status_t BootAnimation::readyToRun() {//设置分辨率、创建Surface等
ui::Size resolution displayMode.resolution;resolution limitSurfaceSize(resolution.width, resolution.height);// create the native surfacespSurfaceControl control session()-createSurface(String8(BootAnimation),resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565);}// initialize opengl and eglEGLDisplay display eglGetDisplay(EGL_DEFAULT_DISPLAY);eglInitialize(display, nullptr, nullptr);
进入最终播放流程
//frameworks/base/cmds/bootanimation/BootAnimation.cpp
bool BootAnimation::threadLoop() {bool result;initShaders();// 初始化着色器// 为启动视频功能进行初始化mStartbootanimaTime 0;mBootVideoTime -1;//Android还支持播放视频文件这样可以方便广告植入开展开机广告业务if (mVideoAnimation) {result video();} else {// 如果没有启动动画文件那么使用默认的安卓logo动画。if (mZipFileName.isEmpty()) {ALOGD(No animation file);result android();} else {result movie();}}// 关闭回调mCallbacks-shutdown();eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);eglDestroyContext(mDisplay, mContext);eglDestroySurface(mDisplay, mSurface);mFlingerSurface.clear();mFlingerSurfaceControl.clear();eglTerminate(mDisplay);eglReleaseThread();IPCThreadState::self()-stopProcess();return result;
}bool BootAnimation::movie() {if (mAnimation nullptr) {mAnimation loadAnimation(mZipFileName);}......playAnimation(*mAnimation);......releaseAnimation(mAnimation);......
}bool BootAnimation::playAnimation(const Animation animation) {const size_t pcount animation.parts.size();nsecs_t frameDuration s2ns(1) / animation.fps;for (size_t i0 ; ipcount ; i) {const Animation::Part part(animation.parts[i]);const size_t fcount part.frames.size();// Handle animation packageif (part.animation ! nullptr) {playAnimation(*part.animation);if (exitPending())break;continue; //to next part}/////使用gl绘制每一帧的图像//第2轮及以后的播放if (r 0) {glBindTexture(GL_TEXTURE_2D, frame.tid);} else {//第一轮播放需要初始化glGenTextures(1, frame.tid);glBindTexture(GL_TEXTURE_2D, frame.tid);int w, h;// Set decoding option to alpha unpremultiplied so that the R, G, B channels// of transparent pixels are preserved.initTexture(frame.map, w, h, false /* dont premultiply alpha */);}////}
}
动画退出时机
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private void performEnableScreen() {////if (!mBootAnimationStopped) {Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, Stop bootanim, 0);// stop boot animation// formerly we would just kill the process, but we now ask it to exit so it// can choose where to stop the animation.SystemProperties.set(service.bootanim.exit, 1);mBootAnimationStopped true;}///
}