Android12 添加開機鈴聲

系統默認是沒有播放開機鈴聲的功能,MTK有一套自己的開機鈴聲處理邏輯,代碼在/vendor/mediatek/proprietary/operator/frameworks/bootanimation/MtkBootanimation下,但是在10之后MTK就不在維護這部分代碼了。直接使用會有很多編譯報錯,現在把MTK播放鈴聲的邏輯移植過來。

移植鈴聲播放功能
  • /frameworks/base/cmds/bootanimation/BootAnimation.cpp
index 958558669ef..3b4eb12ee00 100755
--- a/frameworks/base/cmds/bootanimation/BootAnimation.cpp
+++ b/frameworks/base/cmds/bootanimation/BootAnimation.cpp
@@ -59,10 +59,20 @@#include "BootAnimation.h"+#include <media/IMediaHTTPService.h>
+#include <media/mediaplayer.h>
+#include <media/MediaPlayerInterface.h>
+#define ANIM_PATH_MAX 255#define STR(x)   #x#define STRTO(x) STR(x)+#define PATH_COUNT 2
+static const char* mAudioPath[2][PATH_COUNT] =
+    {{"/system/media/bootaudio.mp3", "/custom/media/bootaudio.mp3"} , /*  bootaudio path  */
+     {"/system/media/shutaudio.mp3", "/custom/media/shutaudio.mp3"} /*  shutaudio path  */
+    };
+namespace android {using ui::DisplayMode;
@@ -123,6 +133,11 @@ BootAnimation::BootAnimation(sp<Callbacks> callbacks)} else {mShuttingDown = true;}
+
+    bPlayMP3 = true;
+    mBootVideoPlayState = MEDIA_NOP;
+    bAudioStarted = false;
+ALOGD("%sAnimationStartTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",elapsedRealtime());}
@@ -136,6 +151,50 @@ BootAnimation::~BootAnimation() {elapsedRealtime());}+BootVideoListener::BootVideoListener(const sp<BootAnimation> &bootanim) {
+    ALOGD("[MtkBootAnimation %s %d]",__FUNCTION__,__LINE__);
+    mBootanim = bootanim;
+}
+BootVideoListener::~BootVideoListener() {
+    ALOGD("[MtkBootAnimation %s %d]",__FUNCTION__,__LINE__);
+}
+void BootVideoListener::notify(int msg, int ext1, int ext2, const Parcel *obj) {
+    ALOGD("[MtkBootAnimation %s %d] msg=%d ext1=%d ext2=%d",__FUNCTION__,__LINE__, msg, ext1, ext2);
+    if(msg == MEDIA_PLAYBACK_COMPLETE || msg == MEDIA_SEEK_COMPLETE) {
+        mBootanim->setBootVideoPlayState(MEDIA_PLAYBACK_COMPLETE);
+        ALOGD("[MtkBootAnimation %s %d] media player complete",__FUNCTION__,__LINE__);
+    }
+    if(msg == MEDIA_ERROR || msg == MEDIA_SKIPPED) {
+        mBootanim->setBootVideoPlayState(MEDIA_ERROR);
+        ALOGD("[MtkBootAnimation %s %d] media player error",__FUNCTION__,__LINE__);
+    }
+    if(msg == MEDIA_STARTED) {
+        mBootanim->setBootAudioStarted();
+        ALOGD("[MtkBootAnimation %s %d] AudioStarted",__FUNCTION__,__LINE__);
+    }
+#ifdef MTK_AOSP_ENHANCEMENT
+    if(msg ==  MEDIA_ERROR_TYPE_NOT_SUPPORTED || msg ==  MEDIA_ERROR_BAD_FILE
+        || msg == MEDIA_ERROR_CANNOT_CONNECT_TO_SERVER) {
+        mBootanim->setBootVideoPlayState(MEDIA_ERROR);
+        ALOGD("[MtkBootAnimation %s %d] media player error",__FUNCTION__,__LINE__);
+    }
+#endif
+    if(obj == NULL){
+        ALOGD("[MtkBootAnimation %s %d]obj is null \n",__FUNCTION__,__LINE__);
+    }
+}
+void BootAnimation::setBootVideoPlayState(int playState){
+    mBootVideoPlayState = playState;
+    ALOGD("[MtkBootAnimation %s %d]mBootVideoPlayState=%d",__FUNCTION__,__LINE__, mBootVideoPlayState);
+}
+
+void BootAnimation::setBootAudioStarted(void)
+{
+    AutoMutex _l(mMyLock);
+    bAudioStarted = true;
+    mCondition.signal();
+}
+void BootAnimation::onFirstRef() {status_t err = mSession->linkToComposerDeath(this);SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
@@ -606,6 +665,51 @@ void BootAnimation::findBootAnimationFile() {}bool BootAnimation::threadLoop() {
+    sp<MediaPlayer> mediaplayer;
+    const char* resourcePath = initAudioPath();
+    status_t mediastatus = NO_ERROR;
+    if (resourcePath != NULL) {
+        bPlayMP3 = true;
+        ALOGD("sound file path: %s", resourcePath);
+        mediaplayer = new MediaPlayer();
+        mediastatus = mediaplayer->setDataSource(NULL, resourcePath, NULL);
+
+        sp<BootVideoListener> listener = new BootVideoListener(this);
+        mediaplayer->setListener(listener);
+
+        if (mediastatus == NO_ERROR) {
+            ALOGD("mediaplayer is initialized");
+            Parcel* attributes = new Parcel();
+            attributes->writeInt32(AUDIO_USAGE_MEDIA);            //usage
+            attributes->writeInt32(AUDIO_CONTENT_TYPE_MUSIC);     //audio_content_type_t
+            attributes->writeInt32(AUDIO_SOURCE_DEFAULT);         //audio_source_t
+            attributes->writeInt32(0);                            //audio_flags_mask_t
+            attributes->writeInt32(1);                            //kAudioAttributesMarshallTagFlattenTags of mediaplayerservice.cpp
+            attributes->writeString16(String16("BootAnimationAudioTrack")); // tags
+            mediaplayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *attributes);
+            mediaplayer->setAudioStreamType(AUDIO_STREAM_MUSIC);
+            //mediaplayer->setVolume(1.0, 1.0);
+            mediastatus = mediaplayer->prepare();
+        }
+        if (mediastatus == NO_ERROR) {
+            ALOGD("media player is prepared");
+            mediastatus = mediaplayer->start();
+        }
+
+    }else{
+        bPlayMP3 = false;
+    }
+
+    //mediaplayer start is an async API, and it will be ready after mediaserver parsing all
+    // components which will take some time and cause aduio and video not sync.
+    if (bPlayMP3 && mediastatus == NO_ERROR) {
+        AutoMutex _l(mMyLock);
+        if (!bAudioStarted) {
+            status_t err = mCondition.waitRelative(mMyLock, s2ns(40));
+            ALOGD("audio started re %d", err);
+        }
+    }
+bool result;// We have no bootanimation file, so we use the stock android logo// animation.
@@ -615,6 +719,15 @@ bool BootAnimation::threadLoop() {result = movie();}+    if (resourcePath != NULL) {
+        if (mediastatus == NO_ERROR) {
+            ALOGD("mediaplayer was stareted successfully, now it is going to be stoped");
+            mediaplayer->stop();
+            mediaplayer->disconnect();
+            mediaplayer.clear();
+        }
+    }
+mCallbacks->shutdown();eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);eglDestroyContext(mDisplay, mContext);
@@ -694,7 +807,13 @@ bool BootAnimation::android() {if (sleepTime > 0)usleep(sleepTime);-        checkExit();
+        if(!bPlayMP3){
+            checkExit();
+        }else{
+            if(mBootVideoPlayState == MEDIA_PLAYBACK_COMPLETE || mBootVideoPlayState == MEDIA_ERROR) {
+               checkExit();
+            }
+        }} while (!exitPending());glDeleteTextures(1, &mAndroid[0].name);
@@ -1363,7 +1482,13 @@ bool BootAnimation::playAnimation(const Animation& animation) {} while (err<0 && errno == EINTR);}-                checkExit();
+                if(!bPlayMP3){
+                    checkExit();
+                }else{
+                    if(mBootVideoPlayState == MEDIA_PLAYBACK_COMPLETE || mBootVideoPlayState == MEDIA_ERROR) {
+                       checkExit();
+                    }
+                }}usleep(part.pause * ns2us(frameDuration));
@@ -1612,6 +1737,23 @@ status_t BootAnimation::TimeCheckThread::readyToRun() {return NO_ERROR;}+const char* BootAnimation::initAudioPath() {
+    int index = 0;
+    if (mShuttingDown) {
+        index = 1;
+    } else {
+        index = 0;
+    }
+
+    for (int i = 0; i < PATH_COUNT; i++) {
+        if (access(mAudioPath[index][i], F_OK) == 0) {
+            ALOGD("initAudioPath: audio path = %s", mAudioPath[index][i]);
+            return mAudioPath[index][i];
+        }
+    }
+    return NULL;
+}
+// ---------------------------------------------------------------------------} // namespace android
  • /frameworks/base/cmds/bootanimation/BootAnimation.h
index f8a31c6d879..2e3c0c2430e 100755
--- a/frameworks/base/cmds/bootanimation/BootAnimation.h
+++ b/frameworks/base/cmds/bootanimation/BootAnimation.h
@@ -33,6 +33,8 @@#include <EGL/egl.h>#include <GLES/gl.h>+#include <media/mediaplayer.h>
+namespace android {class Surface;
@@ -129,6 +131,8 @@ public:explicit BootAnimation(sp<Callbacks> callbacks);virtual ~BootAnimation();
+    void setBootVideoPlayState(int playState);
+    void setBootAudioStarted(void);sp<SurfaceComposerClient> session() const;@@ -193,6 +197,14 @@ private:void handleViewport(nsecs_t timestep);+    const char* initAudioPath();
+
+    bool bPlayMP3;
+    bool bAudioStarted;
+    int mBootVideoPlayState;
+    Mutex  mMyLock;
+    Condition mCondition;
+sp<SurfaceComposerClient>       mSession;AssetManager mAssets;Texture     mAndroid[2];
@@ -220,6 +232,14 @@ private:Animation* mAnimation = nullptr;};+class BootVideoListener: public MediaPlayerListener{
+public:
+                BootVideoListener(const sp<BootAnimation> &player);
+    virtual     ~BootVideoListener();
+    virtual void notify(int msg, int ext1, int ext2, const Parcel *obj);
+    sp<BootAnimation> mBootanim;
+};
+// ---------------------------------------------------------------------------}; // namespace android
添加lib庫
  • /frameworks/base/cmds/bootanimation/Android.bp
--- a/frameworks/base/cmds/bootanimation/Android.bp
+++ b/frameworks/base/cmds/bootanimation/Android.bp
@@ -73,5 +73,6 @@ cc_library_shared {"libEGL","libGLESv1_CM","libgui",
+        "libmedia",],}
第一次開機鈴聲不全
  • /frameworks/av/services/audioflinger/Threads.cpp
--- a/frameworks/av/services/audioflinger/Threads.cpp
+++ b/frameworks/av/services/audioflinger/Threads.cpp
@@ -5734,6 +5734,17 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTractrack->mHasVolumeController = false;}+            //add begin
+            char mvalue[PROPERTY_VALUE_MAX];
+            property_get("service.bootanim.exit", mvalue, "");
+            if (strcmp(mvalue,"0") == 0){
+                ALOGE("bootanim volume setting");
+                vlf = 0.25f;
+                vrf = 0.25f;
+            }
+            //add end
+// XXX: these things DON'T need to be done each timemAudioMixer->setBufferProvider(trackId, track);mAudioMixer->enable(trackId);
添加權限
  • /device/mediatek/sepolicy/bsp/plat_private/audioserver.te
--- a/device/mediatek/sepolicy/bsp/plat_private/audioserver.te
+++ b/device/mediatek/sepolicy/bsp/plat_private/audioserver.te
@@ -9,3 +9,5 @@ allow audioserver mtk_perf_service:service_manager find;allow audioserver debuglog_data_file:dir { relabelto create_dir_perms };allow audioserver debuglog_data_file:file create_file_perms;
+
+allow audioserver bootanim_system_prop:file { read open getattr map};
復制鈴聲文件
  • /vendor/audio-logo/products/resource-copy.mk
LOCAL_PATH:= vendor/audio-logo/
#boot animation
zip_files:= $(notdir $(wildcard $(LOCAL_PATH)/animation/*.zip))
PRODUCT_COPY_FILES += $(foreach file, $(zip_files), \$(LOCAL_PATH)/animation/$(file):system/media/$(file))#boot/shut audio
mp3_files:= $(notdir $(wildcard $(LOCAL_PATH)/animation/*.mp3))
PRODUCT_COPY_FILES += $(foreach file, $(mp3_files), \$(LOCAL_PATH)/animation/$(file):system/media/$(file))

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/72576.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72576.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/72576.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

3.6V-30V寬壓輸入降壓同步IC內置MOS,電流4A/5A/6A,可以滿足汽車應急電源,BMS電池,電池組USB口輸出等儲能應用

今天給大家介紹一下這三款產品&#xff0c;分別是CJ92340,輸入電壓4.5V-30V&#xff0c;輸出可調&#xff0c;電流負載能力可達4A&#xff0c;頻率350KHZ。CJ92350,輸入電壓3.6V-30V&#xff0c;輸出可調&#xff0c;頻率可調&#xff0c;帶載能力達5A。CJ92360,輸入電壓3.6V-3…

代碼隨想錄算法訓練營第35天 | 01背包問題二維、01背包問題一維、416. 分割等和子集

一、01背包問題二維 二維數組&#xff0c;一維為物品&#xff0c;二維為背包重量 import java.util.Scanner;public class Main{public static void main(String[] args){Scanner scanner new Scanner(System.in);int n scanner.nextInt();int bag scanner.nextInt();int[…

010---基于Verilog HDL的分頻器設計

文章目錄 摘要一、時序圖二、程序設計2.1 rtl2.2 tb 三、仿真分析四、實用性 摘要 文章為學習記錄。繪制時序圖&#xff0c;編碼。通過修改分頻值參數&#xff0c;實現一定范圍分頻值內的任意分頻器設計。 一、時序圖 二、程序設計 2.1 rtl module divider #(parameter D…

維度建模事實表技術基礎解析(以電商場景為例)

維度建模事實表技術基礎解析(以電商場景為例) 1. 事實表結構 定義:事實表是維度建模的核心,由外鍵(關聯維度表)、度量值(可量化的業務指標)及退化維度(冗余的維度屬性)組成。其本質是記錄業務過程中的度量事件,例如電商訂單金額、商品庫存量等。 場景識別:適用于…

Redis 主從復制、哨兵與集群的關系及工作原理詳解

一、核心概念與關系 Redis 的 主從復制、哨兵&#xff08;Sentinel&#xff09; 和 集群&#xff08;Cluster&#xff09; 是逐步演進的高可用與分布式解決方案&#xff0c;三者關系如下&#xff1a; 主從復制&#xff1a;數據冗余與讀寫分離的基礎。 哨兵&#xff1a;在主從…

確認機制的分類及其區別與聯系探討

在傳輸控制中&#xff0c;確認機制&#xff08;ACK 機制&#xff09;作為反饋模塊在實現擁塞控制、丟包恢復和狀態監測等功能中起到了至關重要的作用。今天我將基于之前發表的論文研究成果&#xff0c;對確認機制的分類進行系統梳理&#xff0c;并討論各類機制之間的區別與聯系…

115 道 MySQL 面試題,從簡單到深入!

1. 什么是數據庫事務&#xff1f; 數據庫事務是一個作為單個邏輯工作單元執行的一系列操作。事務具有ACID屬性&#xff0c;即原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔離性&#xff08;Isolation&#xff09;和持久性&#xf…

Linux - 網絡套接字

一、網絡編程 1&#xff09;地址結構 1. IP地址結構 struct in_addr&#xff1a;是用于表示 IPv4 地址 的結構體&#xff0c;定義在頭文件 <netinet/in.h> 中。它的主要作用是存儲一個 32 位的 IPv4 地址&#xff0c;通常與 struct sockaddr_in 一起使用。 struct in_a…

程序員學商務英語之Visiting the Factory

Dialogue-1 Arranging a Visit安排參觀 I was wondering if you would / could lend me a million bucks, you know, I’m trying to start / run my own business. 我想知道你是否能夠借給我一百萬美金&#xff0c;你知道&#xff0c;我正在創業。 Take off your tie befor…

機器視覺運動控制一體機在天地蓋同步跟隨貼合解決方案

市場應用背景 紙盒天地蓋是一種包裝形式&#xff0c;廣泛應用于消費電子、食品禮盒、奢侈品及化妝品等領域。其采用高強度紙板&#xff0c;經過預組裝處理&#xff0c;結構堅固穩定&#xff0c;能有效保護產品并提升品牌形象。隨著包裝行業快速發展&#xff0c;市場對天地蓋的…

【智能體Agent】ReAct智能體的實現思路和關鍵技術

基于ReAct&#xff08;Reasoning Acting&#xff09;框架的自主智能體 import re from typing import List, Tuplefrom langchain_community.chat_message_histories.in_memory import ChatMessageHistory from langchain_core.language_models.chat_models import BaseChatM…

Electron打包工具對比

在 Electron 生態中&#xff0c;打包工具的選擇直接影響開發效率、配置復雜度和最終應用的性能。以下是主流的 Electron 打包工具及其優劣分析&#xff0c;結合你的 Vue 項目需求&#xff0c;我會在最后給出推薦方案&#xff1a; 一、主流 Electron 打包工具對比 1. Electron …

云原生系列之本地k8s環境搭建

前置條件 Windows 11 家庭中文版&#xff0c;版本號 23H2 云原生環境搭建 操作系統啟用wsl(windows subsystem for linux) 開啟wsl功能&#xff0c;如下圖 安裝并開啟github加速器 FastGithub 2.1 下載地址&#xff1a;點擊下載 2.2 解壓安裝文件fastgithub_win-x64.zip 2…

【計算機網絡入門】TCP擁塞控制

目錄 1. TCP擁塞控制和TCP流量控制的區別 2. 檢測到擁塞該怎么辦 2.1 如何判斷網絡擁塞&#xff1f; 3. 慢開始算法 擁塞避免算法 4.快重傳事件->快恢復算法 5. 總結 1. TCP擁塞控制和TCP流量控制的區別 TCP流量控制是控制端對端的數據發送量。是局部的概念。 TCP擁…

Spring Boot 整合 JMS-ActiveMQ,并安裝 ActiveMQ

1. 安裝 ActiveMQ 1.1 下載 ActiveMQ 訪問 ActiveMQ 官方下載頁面&#xff0c;根據你的操作系統選擇合適的版本進行下載。這里以 Linux 系統&#xff0c;Java環境1.8版本為例&#xff0c;下載 apache-activemq-5.16.7-bin.tar.gz。 1.2 解壓文件 將下載的壓縮包解壓到指定目…

《幾何原本》命題I.13

《幾何原本》命題I.13 兩條直線相交&#xff0c;鄰角是兩個直角或者相加等于 18 0 ° 180^{\circ} 180°。 若兩角相等&#xff0c;則根據定義&#xff0c;兩角為直角。 兩角若不相等&#xff0c;如圖&#xff0c;則 ( ∠ 1 ∠ 2 ) ∠ 3 ∠ 1 ( ∠ 2 ∠ 3 ) 9 0 ° …

優先級隊列:通過堆的形式實現

描述: 大頂堆: 小頂堆: 索引位置查找: 代碼實現: package com.zy.queue_code.deque;/*** @Author: zy* @Date: 2025-03-05-15:51* @Description:*/ public interface Priority

《OpenCV》—— dlib庫

文章目錄 dlib庫是什么&#xff1f;OpenCV庫與dlib庫對比dlib庫安裝dlib——人臉應用實例——人臉檢測dlib——人臉應用實例——人臉關鍵點定位dlib——人臉應用實例——人臉輪廓繪制 dlib庫是什么&#xff1f; OpenCV庫與dlib庫對比 dlib庫安裝 dlib——人臉應用實例——人臉檢…

藍橋與力扣刷題(藍橋 旋轉)

題目&#xff1a;圖片旋轉是對圖片最簡單的處理方式之一&#xff0c;在本題中&#xff0c;你需要對圖片順時針旋轉 90 度。 我們用一個 nm的二維數組來表示一個圖片&#xff0c;例如下面給出一個 34 的 圖片的例子&#xff1a; 1 3 5 7 9 8 7 6 3 5 9 7 這個圖片順時針旋轉…

隨機播放音樂 偽隨機

import java.util.*;/*** https://cloud.tencent.com.cn/developer/news/1045747* 偽隨機播放音樂*/ public class MusicPlayer {private List<String> allSongs; // 所有歌曲列表private List<String> playedSongs; // 已經播放過的歌曲列表private Map<String…