目录

Android12-添加开机铃声

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::prepareTrac
                 track->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 time
             mAudioMixer->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))