Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7464ac9b authored by Ed Coyne's avatar Ed Coyne
Browse files

Allow IO During boot process, BootActions.

NOTE: this is only compiled into products with PRODUCT_IOT=true.

Introduce BootActions that a developer can provide to manipulate IO
before the android framework comes up on boot.

We will look for a configuration file at /oem/app/etc/boot_action.conf and
expect it to tell us the name of a shared library. We will then fetch
this library from /oem/app/lib/${arch}/ and load it. We expect it to export
boot_action_init(), boot_action_shutdown(), and optionally
boot_action_start_part(int partNumber, int playNumber).

We will then call boot_action_init() during boot after PeripheralManager
is up and call boot_action_shutdown() when the android framework is up
and we are going to start loading APKs.

We will also call boot_action_start_part(*) when each part of the boot
animation is started, use this if you want to synchronize the boot
action and the boot animation.

Boot actions run in a restricted environment and in general can only
make calls to PeripheralManager.

Bug: 37992717
Test: Pushed to local imx7d to test boot actions, pushed to bullhead test that animation+sound still works.
Change-Id: I9e53a17567f8028ea84486d637e1d231ee1125e1
parent 2cb3f596
Loading
Loading
Loading
Loading
+25 −4
Original line number Diff line number Diff line
@@ -8,10 +8,6 @@ bootanimation_CommonCFlags += -Wall -Werror -Wunused -Wunreachable-code
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
    bootanimation_main.cpp \
    audioplay.cpp \

LOCAL_CFLAGS += ${bootanimation_CommonCFlags}

LOCAL_SHARED_LIBRARIES := \
@@ -24,6 +20,29 @@ LOCAL_SHARED_LIBRARIES := \
    liblog \
    libutils \

LOCAL_SRC_FILES:= \
    BootAnimationUtil.cpp \

ifeq ($(PRODUCT_IOT),true)
LOCAL_SRC_FILES += \
    iot/iotbootanimation_main.cpp \
    iot/BootAction.cpp

LOCAL_SHARED_LIBRARIES += \
    libandroidthings \
    libbase \
    libbinder

LOCAL_STATIC_LIBRARIES += cpufeatures

else

LOCAL_SRC_FILES += \
    bootanimation_main.cpp \
    audioplay.cpp \

endif  # PRODUCT_IOT

LOCAL_MODULE:= bootanimation

LOCAL_INIT_RC := bootanim.rc
@@ -45,6 +64,8 @@ LOCAL_CFLAGS += ${bootanimation_CommonCFlags}
LOCAL_SRC_FILES:= \
    BootAnimation.cpp

LOCAL_CFLAGS += ${bootanimation_CommonCFlags}

LOCAL_C_INCLUDES += \
    external/tinyalsa/include \
    frameworks/wilhelm/include
+7 −10
Original line number Diff line number Diff line
@@ -96,11 +96,9 @@ static constexpr size_t TEXT_POS_LEN_MAX = 16;

// ---------------------------------------------------------------------------

BootAnimation::BootAnimation(InitCallback initCallback,
                             PlayPartCallback partCallback)
BootAnimation::BootAnimation(sp<Callbacks> callbacks)
        : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
        mTimeFormat12Hour(false), mTimeCheckThread(NULL),
        mInitCallback(initCallback), mPlayPartCallback(partCallback) {
        mTimeFormat12Hour(false), mTimeCheckThread(NULL), mCallbacks(callbacks) {
    mSession = new SurfaceComposerClient();

    std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
@@ -357,6 +355,8 @@ bool BootAnimation::android()
    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");

    mCallbacks->init({});

    // clear screen
    glShadeModel(GL_FLAT);
    glDisable(GL_DITHER);
@@ -424,6 +424,7 @@ void BootAnimation::checkExit() {
    int exitnow = atoi(value);
    if (exitnow) {
        requestExit();
        mCallbacks->shutdown();
    }
}

@@ -777,9 +778,7 @@ bool BootAnimation::preloadZip(Animation& animation)
        }
    }

    if (mInitCallback != nullptr) {
        mInitCallback(animation.parts);
    }
    mCallbacks->init(animation.parts);

    zip->endIteration(cookie);

@@ -887,9 +886,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
            if(exitPending() && !part.playUntilComplete)
                break;

            if (mPlayPartCallback != nullptr) {
                mPlayPartCallback(i, part, r);
            }
            mCallbacks->playPart(i, part, r);

            glClearColor(
                    part.backgroundColor[0],
+22 −18
Original line number Diff line number Diff line
@@ -93,22 +93,27 @@ public:
        Font clockFont;
    };

    // Callback will be called during initialization after we have loaded
    // All callbacks will be called from this class's internal thread.
    class Callbacks : public RefBase {
    public:
        // Will be called during initialization after we have loaded
        // the animation and be provided with all parts in animation.
    typedef std::function<void(const Vector<Animation::Part>& parts)> InitCallback;
        virtual void init(const Vector<Animation::Part>& /*parts*/) {}

    // Callback will be called while animation is playing before each part is
        // Will be called while animation is playing before each part is
        // played. It will be provided with the part and play count for it.
        // It will be provided with the partNumber for the part about to be played,
        // as well as a reference to the part itself. It will also be provided with
        // which play of that part is about to start, some parts are repeated
        // multiple times.
    typedef std::function<void(int partNumber, const Animation::Part& part, int playNumber)>
            PlayPartCallback;
        virtual void playPart(int /*partNumber*/, const Animation::Part& /*part*/,
                              int /*playNumber*/) {}

        // Will be called when animation is done and thread is shutting down.
        virtual void shutdown() {}
    };

    // Callbacks may be null and will be called from this class's internal
    // thread.
    BootAnimation(InitCallback initCallback, PlayPartCallback partCallback);
    BootAnimation(sp<Callbacks> callbacks);

    sp<SurfaceComposerClient> session() const;

@@ -170,8 +175,7 @@ private:
    String8     mZipFileName;
    SortedVector<String8> mLoadedFiles;
    sp<TimeCheckThread> mTimeCheckThread = nullptr;
    InitCallback mInitCallback = nullptr;
    PlayPartCallback mPlayPartCallback = nullptr;
    sp<Callbacks> mCallbacks;
};

// ---------------------------------------------------------------------------
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

#include "BootAnimationUtil.h"

#include <inttypes.h>

#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>

namespace android {

bool bootAnimationDisabled() {
    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.nobootanimation", value, "0");
    if (atoi(value) > 0) {
      return false;
    }

    property_get("ro.boot.quiescent", value, "0");
    return atoi(value) > 0;
}

void waitForSurfaceFlinger() {
    // TODO: replace this with better waiting logic in future, b/35253872
    int64_t waitStartTime = elapsedRealtime();
    sp<IServiceManager> sm = defaultServiceManager();
    const String16 name("SurfaceFlinger");
    const int SERVICE_WAIT_SLEEP_MS = 100;
    const int LOG_PER_RETRIES = 10;
    int retry = 0;
    while (sm->checkService(name) == nullptr) {
        retry++;
        if ((retry % LOG_PER_RETRIES) == 0) {
            ALOGW("Waiting for SurfaceFlinger, waited for %" PRId64 " ms",
                  elapsedRealtime() - waitStartTime);
        }
        usleep(SERVICE_WAIT_SLEEP_MS * 1000);
    };
    int64_t totalWaited = elapsedRealtime() - waitStartTime;
    if (totalWaited > SERVICE_WAIT_SLEEP_MS) {
        ALOGI("Waiting for SurfaceFlinger took %" PRId64 " ms", totalWaited);
    }
}

}  // namespace android
+25 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

namespace android {

// Returns true if boot animation is disabled.
bool bootAnimationDisabled();

// Waits until the surface flinger is up.
void waitForSurfaceFlinger();

}  // namespace android
Loading