Loading cmds/bootanimation/BootAnimation.cpp +125 −21 Original line number Diff line number Diff line Loading @@ -107,9 +107,13 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; static const char U_FADE[] = "uFade"; static const char U_CROP_AREA[] = "uCropArea"; static const char U_START_COLOR_PREFIX[] = "uStartColor"; static const char U_END_COLOR_PREFIX[] = "uEndColor"; static const char U_COLOR_PROGRESS[] = "uColorProgress"; static const char A_UV[] = "aUv"; static const char A_POSITION[] = "aPosition"; static const char VERTEX_SHADER_SOURCE[] = R"( Loading @@ -121,6 +125,28 @@ static const char VERTEX_SHADER_SOURCE[] = R"( gl_Position = aPosition; vUv = aUv; })"; static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; uniform float uFade; uniform float uColorProgress; uniform vec4 uStartColor0; uniform vec4 uStartColor1; uniform vec4 uStartColor2; uniform vec4 uStartColor3; uniform vec4 uEndColor0; uniform vec4 uEndColor1; uniform vec4 uEndColor2; uniform vec4 uEndColor3; varying highp vec2 vUv; void main() { vec4 mask = texture2D(uTexture, vUv); vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress) + mask.g * mix(uStartColor1, uEndColor1, uColorProgress) + mask.b * mix(uStartColor2, uEndColor2, uColorProgress) + mask.a * mix(uStartColor3, uEndColor3, uColorProgress); gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; })"; static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; Loading @@ -128,7 +154,7 @@ static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( varying highp vec2 vUv; void main() { vec4 color = texture2D(uTexture, vUv); gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; })"; static const char TEXT_FRAG_SHADER_SOURCE[] = R"( precision mediump float; Loading Loading @@ -212,7 +238,8 @@ void BootAnimation::binderDied(const wp<IBinder>&) { requestExit(); } static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo) { static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo, bool premultiplyAlpha) { AImageDecoder* decoder = nullptr; AImageDecoder_createFromBuffer(encodedData, dataLength, &decoder); if (!decoder) { Loading @@ -226,6 +253,10 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm outInfo->stride = AImageDecoder_getMinimumStride(decoder); outInfo->flags = 0; if (!premultiplyAlpha) { AImageDecoder_setUnpremultipliedRequired(decoder, true); } const size_t size = outInfo->stride * outInfo->height; void* pixels = malloc(size); int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size); Loading @@ -239,13 +270,14 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm } status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, const char* name) { const char* name, bool premultiplyAlpha) { Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); if (asset == nullptr) return NO_INIT; AndroidBitmapInfo bitmapInfo; void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo); void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo, premultiplyAlpha); auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free }; asset->close(); Loading Loading @@ -293,9 +325,11 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, return NO_ERROR; } status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { status_t BootAnimation::initTexture(FileMap* map, int* width, int* height, bool premultiplyAlpha) { AndroidBitmapInfo bitmapInfo; void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo); void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo, premultiplyAlpha); auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free }; // FileMap memory is never released until application exit. Loading Loading @@ -675,9 +709,12 @@ GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { } void BootAnimation::initShaders() { bool dynamicColoringEnabled = mAnimation != nullptr && mAnimation->dynamicColoringEnabled; GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); GLuint imageFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); compileShader(GL_FRAGMENT_SHADER, dynamicColoringEnabled ? (const GLchar *)IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE : (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); GLuint textFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); Loading Loading @@ -869,6 +906,20 @@ static bool parseColor(const char str[7], float color[3]) { return true; } // Parse a color represented as a signed decimal int string. // E.g. "-2757722" (whose hex 2's complement is 0xFFD5EBA6). // If the input color string is empty, set color with values in defaultColor. static void parseColorDecimalString(const std::string& colorString, float color[3], float defaultColor[3]) { if (colorString == "") { memcpy(color, defaultColor, sizeof(float) * 3); return; } int colorInt = atoi(colorString.c_str()); color[0] = ((float)((colorInt >> 16) & 0xFF)) / 0xFF; // r color[1] = ((float)((colorInt >> 8) & 0xFF)) / 0xFF; // g color[2] = ((float)(colorInt & 0xFF)) / 0xFF; // b } static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); Loading Loading @@ -1010,6 +1061,8 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { return false; } char const* s = desString.string(); std::string dynamicColoringPartName = ""; bool postDynamicColoring = false; // Parse the description file for (;;) { Loading @@ -1028,7 +1081,13 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { char color[7] = "000000"; // default to black if unspecified char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; char dynamicColoringPartNameBuffer[ANIM_ENTRY_NAME_MAX]; char pathType; // start colors default to black if unspecified char start_color_0[7] = "000000"; char start_color_1[7] = "000000"; char start_color_2[7] = "000000"; char start_color_3[7] = "000000"; int nextReadPos; Loading @@ -1043,6 +1102,15 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { } else { animation.progressEnabled = false; } } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s", dynamicColoringPartNameBuffer, start_color_0, start_color_1, start_color_2, start_color_3)) { animation.dynamicColoringEnabled = true; parseColor(start_color_0, animation.startColors[0]); parseColor(start_color_1, animation.startColors[1]); parseColor(start_color_2, animation.startColors[2]); parseColor(start_color_3, animation.startColors[3]); dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer); } else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n", &pathType, &count, &pause, path, &nextReadPos) >= 4) { if (pathType == 'f') { Loading @@ -1055,6 +1123,16 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { // "clockPos1=%s, clockPos2=%s", // pathType, count, pause, path, framesToFadeCount, color, clockPos1, clockPos2); Animation::Part part; if (path == dynamicColoringPartName) { // Part is specified to use dynamic coloring. part.useDynamicColoring = true; part.postDynamicColoring = false; postDynamicColoring = true; } else { // Part does not use dynamic coloring. part.useDynamicColoring = false; part.postDynamicColoring = postDynamicColoring; } part.playUntilComplete = pathType == 'c'; part.framesToFadeCount = framesToFadeCount; part.count = count; Loading Loading @@ -1262,6 +1340,10 @@ bool BootAnimation::movie() { mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL); } if (mAnimation != nullptr && mAnimation->dynamicColoringEnabled) { initDynamicColors(); } playAnimation(*mAnimation); if (mTimeCheckThread != nullptr) { Loading Loading @@ -1315,6 +1397,27 @@ void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, fl sizeof(quadPositions) / sizeof(quadPositions[0]) / 2); } void BootAnimation::initDynamicColors() { for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { parseColorDecimalString( android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), mAnimation->endColors[i], mAnimation->startColors[i]); } glUseProgram(mImageShader); SLOGI("[BootAnimation] Dynamically coloring boot animation."); for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { float *startColor = mAnimation->startColors[i]; float *endColor = mAnimation->endColors[i]; glUniform4f(glGetUniformLocation(mImageShader, (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), startColor[0], startColor[1], startColor[2], 1 /* alpha */); glUniform4f(glGetUniformLocation(mImageShader, (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), endColor[0], endColor[1], endColor[2], 1 /* alpha */); } mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); } bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); nsecs_t frameDuration = s2ns(1) / animation.fps; Loading Loading @@ -1357,6 +1460,14 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t j=0 ; j<fcount ; j++) { if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break; // Color progress is // - the normalized animation progress between [0, 1] for the dynamic coloring part, // - 0 for parts that come before, // - 1 for parts that come after. float colorProgress = part.useDynamicColoring ? (float)j / fcount : (part.postDynamicColoring ? 1 : 0); processDisplayEvents(); const int animationX = (mWidth - animation.width) / 2; Loading @@ -1371,24 +1482,14 @@ bool BootAnimation::playAnimation(const Animation& animation) { glGenTextures(1, &frame.tid); glBindTexture(GL_TEXTURE_2D, frame.tid); int w, h; initTexture(frame.map, &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 /* don't premultiply alpha */); } const int xc = animationX + frame.trimX; const int yc = animationY + frame.trimY; Region clearReg(Rect(mWidth, mHeight)); clearReg.subtractSelf(Rect(xc, yc, xc+frame.trimWidth, yc+frame.trimHeight)); if (!clearReg.isEmpty()) { Region::const_iterator head(clearReg.begin()); Region::const_iterator tail(clearReg.end()); glEnable(GL_SCISSOR_TEST); while (head != tail) { const Rect& r2(*head++); glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height()); glClear(GL_COLOR_BUFFER_BIT); } glDisable(GL_SCISSOR_TEST); } // specify the y center as ceiling((mHeight - frame.trimHeight) / 2) // which is equivalent to mHeight - (yc + frame.trimHeight) const int frameDrawY = mHeight - (yc + frame.trimHeight); Loading @@ -1404,6 +1505,9 @@ bool BootAnimation::playAnimation(const Animation& animation) { glUseProgram(mImageShader); glUniform1i(mImageTextureLocation, 0); glUniform1f(mImageFadeLocation, fade); if (animation.dynamicColoringEnabled) { glUniform1f(mImageColorProgressLocation, colorProgress); } glEnable(GL_BLEND); drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight); glDisable(GL_BLEND); Loading cmds/bootanimation/BootAnimation.h +16 −4 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ public: }; struct Font { FileMap* map; FileMap* map = nullptr; Texture texture; int char_width; int char_height; Loading @@ -62,7 +62,7 @@ public: struct Animation { struct Frame { String8 name; FileMap* map; FileMap* map = nullptr; int trimX; int trimY; int trimWidth; Loading Loading @@ -90,6 +90,10 @@ public: uint8_t* audioData; int audioLength; Animation* animation; // Controls if dynamic coloring is enabled for this part. bool useDynamicColoring = false; // Defines if this part is played after the dynamic coloring part. bool postDynamicColoring = false; bool hasFadingPhase() const { return !playUntilComplete && framesToFadeCount > 0; Loading @@ -105,6 +109,10 @@ public: ZipFileRO* zip; Font clockFont; Font progressFont; // Controls if dynamic coloring is enabled for the whole animation. bool dynamicColoringEnabled = false; float startColors[4][3]; // Start colors of dynamic color transition. float endColors[4][3]; // End colors of dynamic color transition. }; // All callbacks will be called from this class's internal thread. Loading Loading @@ -163,8 +171,10 @@ private: int displayEventCallback(int fd, int events, void* data); void processDisplayEvents(); status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(FileMap* map, int* width, int* height); status_t initTexture(Texture* texture, AssetManager& asset, const char* name, bool premultiplyAlpha = true); status_t initTexture(FileMap* map, int* width, int* height, bool premultiplyAlpha = true); status_t initFont(Font* font, const char* fallback); void initShaders(); bool android(); Loading Loading @@ -194,6 +204,7 @@ private: void checkExit(); void handleViewport(nsecs_t timestep); void initDynamicColors(); sp<SurfaceComposerClient> mSession; AssetManager mAssets; Loading Loading @@ -226,6 +237,7 @@ private: GLuint mImageTextureLocation; GLuint mTextCropAreaLocation; GLuint mTextTextureLocation; GLuint mImageColorProgressLocation; }; // --------------------------------------------------------------------------- Loading cmds/bootanimation/OWNERS 0 → 100644 +3 −0 Original line number Diff line number Diff line dupin@google.com shanh@google.com jreck@google.com core/java/android/app/backup/BackupManager.java +26 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,32 @@ public class BackupManager { } } /** * Convenience method for callers who need to indicate that some other package or * some other user needs a backup pass. This can be useful in the case of groups of * packages that share a uid and/or have user-specific data. * <p> * This method requires that the application hold the "android.permission.BACKUP" * permission if the package named in the package argument does not run under the * same uid as the caller. This method also requires that the application hold the * "android.permission.INTERACT_ACROSS_USERS_FULL" if the user argument is not the * same as the user the caller is running under. * @param userId The user to back up * @param packageName The package name identifying the application to back up. * * @hide */ public static void dataChangedForUser(int userId, String packageName) { checkServiceBinder(); if (sService != null) { try { sService.dataChangedForUser(userId, packageName); } catch (RemoteException e) { Log.e(TAG, "dataChanged(userId,pkg) couldn't connect"); } } } /** * @deprecated Applications shouldn't request a restore operation using this method. In Android * P and later, this method is a no-op. Loading core/java/android/view/translation/UiTranslationManager.java +44 −4 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.util.ArrayMap; import android.util.Log; import android.view.View; import android.view.autofill.AutofillId; import android.widget.TextView; import com.android.internal.annotations.GuardedBy; Loading @@ -42,11 +43,50 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; // TODO(b/178044703): Describe what UI Translation is. /** * The {@link UiTranslationManager} class provides ways for apps to use the ui translation * <p>The {@link UiTranslationManager} class provides ways for apps to use the ui translation * function in framework. * * <p> The UI translation provides ways for apps to support inline translation for the views. For * example the system supports text translation for {@link TextView}. To support UI translation for * your views, you should override the following methods to provide the content to be translated * and deal with the translated result. Here is an example for {@link TextView}-like views: * * <pre><code> * public class MyTextView extends View { * public MyTextView(...) { * // implements how to show the translated result in your View in * // ViewTranslationCallback and set it by setViewTranslationCallback() * setViewTranslationCallback(new MyViewTranslationCallback()); * } * * public void onCreateViewTranslationRequest(int[] supportedFormats, * Consumer<ViewTranslationRequest> requestsCollector) { * // collect the information that needs to be translated * ViewTranslationRequest.Builder requestBuilder = * new ViewTranslationRequest.Builder(getAutofillId()); * requestBuilder.setValue(ViewTranslationRequest.ID_TEXT, * TranslationRequestValue.forText(etText())); * requestsCollector.accept(requestBuilder.build()); * } * * public void onProvideContentCaptureStructure( * ViewStructure structure, int flags) { * // set ViewTranslationResponse * super.onViewTranslationResponse(response); * } * } * </code></pre> * * <p>If your view provides its own virtual hierarchy (for example, if it's a browser that draws the * HTML using {@link android.graphics.Canvas} or native libraries in a different render process), * you must override {@link View#onCreateVirtualViewTranslationRequests(long[], int[], Consumer)} to * provide the content to be translated and implement * {@link View#onVirtualViewTranslationResponses(android.util.LongSparseArray)} for the translated * result. You also need to implement {@link android.view.translation.ViewTranslationCallback} to * handle the translated information show or hide in your {@link View}. */ public final class UiTranslationManager { Loading Loading @@ -248,14 +288,14 @@ public final class UiTranslationManager { } } // TODO(b/178044703): Fix the View API link when it becomes public. /** * Register for notifications of UI Translation state changes on the foreground activity. This * is available to the owning application itself and also the current input method. * <p> * The application whose UI is being translated can use this to customize the UI Translation * behavior in ways that aren't made easy by methods like * View#onCreateTranslationRequest(). * {@link View#onCreateViewTranslationRequest(int[], Consumer)}. * * <p> * Input methods can use this to offer complementary features to UI Translation; for example, * enabling outgoing message translation when the system is translating incoming messages in a Loading Loading
cmds/bootanimation/BootAnimation.cpp +125 −21 Original line number Diff line number Diff line Loading @@ -107,9 +107,13 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; static const char U_FADE[] = "uFade"; static const char U_CROP_AREA[] = "uCropArea"; static const char U_START_COLOR_PREFIX[] = "uStartColor"; static const char U_END_COLOR_PREFIX[] = "uEndColor"; static const char U_COLOR_PROGRESS[] = "uColorProgress"; static const char A_UV[] = "aUv"; static const char A_POSITION[] = "aPosition"; static const char VERTEX_SHADER_SOURCE[] = R"( Loading @@ -121,6 +125,28 @@ static const char VERTEX_SHADER_SOURCE[] = R"( gl_Position = aPosition; vUv = aUv; })"; static const char IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; uniform float uFade; uniform float uColorProgress; uniform vec4 uStartColor0; uniform vec4 uStartColor1; uniform vec4 uStartColor2; uniform vec4 uStartColor3; uniform vec4 uEndColor0; uniform vec4 uEndColor1; uniform vec4 uEndColor2; uniform vec4 uEndColor3; varying highp vec2 vUv; void main() { vec4 mask = texture2D(uTexture, vUv); vec4 color = mask.r * mix(uStartColor0, uEndColor0, uColorProgress) + mask.g * mix(uStartColor1, uEndColor1, uColorProgress) + mask.b * mix(uStartColor2, uEndColor2, uColorProgress) + mask.a * mix(uStartColor3, uEndColor3, uColorProgress); gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; })"; static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( precision mediump float; uniform sampler2D uTexture; Loading @@ -128,7 +154,7 @@ static const char IMAGE_FRAG_SHADER_SOURCE[] = R"( varying highp vec2 vUv; void main() { vec4 color = texture2D(uTexture, vUv); gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade); gl_FragColor = vec4(color.x, color.y, color.z, (1.0 - uFade)) * color.a; })"; static const char TEXT_FRAG_SHADER_SOURCE[] = R"( precision mediump float; Loading Loading @@ -212,7 +238,8 @@ void BootAnimation::binderDied(const wp<IBinder>&) { requestExit(); } static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo) { static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitmapInfo* outInfo, bool premultiplyAlpha) { AImageDecoder* decoder = nullptr; AImageDecoder_createFromBuffer(encodedData, dataLength, &decoder); if (!decoder) { Loading @@ -226,6 +253,10 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm outInfo->stride = AImageDecoder_getMinimumStride(decoder); outInfo->flags = 0; if (!premultiplyAlpha) { AImageDecoder_setUnpremultipliedRequired(decoder, true); } const size_t size = outInfo->stride * outInfo->height; void* pixels = malloc(size); int result = AImageDecoder_decodeImage(decoder, pixels, outInfo->stride, size); Loading @@ -239,13 +270,14 @@ static void* decodeImage(const void* encodedData, size_t dataLength, AndroidBitm } status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, const char* name) { const char* name, bool premultiplyAlpha) { Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); if (asset == nullptr) return NO_INIT; AndroidBitmapInfo bitmapInfo; void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo); void* pixels = decodeImage(asset->getBuffer(false), asset->getLength(), &bitmapInfo, premultiplyAlpha); auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free }; asset->close(); Loading Loading @@ -293,9 +325,11 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, return NO_ERROR; } status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { status_t BootAnimation::initTexture(FileMap* map, int* width, int* height, bool premultiplyAlpha) { AndroidBitmapInfo bitmapInfo; void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo); void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo, premultiplyAlpha); auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free }; // FileMap memory is never released until application exit. Loading Loading @@ -675,9 +709,12 @@ GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) { } void BootAnimation::initShaders() { bool dynamicColoringEnabled = mAnimation != nullptr && mAnimation->dynamicColoringEnabled; GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE); GLuint imageFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); compileShader(GL_FRAGMENT_SHADER, dynamicColoringEnabled ? (const GLchar *)IMAGE_FRAG_DYNAMIC_COLORING_SHADER_SOURCE : (const GLchar *)IMAGE_FRAG_SHADER_SOURCE); GLuint textFragmentShader = compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE); Loading Loading @@ -869,6 +906,20 @@ static bool parseColor(const char str[7], float color[3]) { return true; } // Parse a color represented as a signed decimal int string. // E.g. "-2757722" (whose hex 2's complement is 0xFFD5EBA6). // If the input color string is empty, set color with values in defaultColor. static void parseColorDecimalString(const std::string& colorString, float color[3], float defaultColor[3]) { if (colorString == "") { memcpy(color, defaultColor, sizeof(float) * 3); return; } int colorInt = atoi(colorString.c_str()); color[0] = ((float)((colorInt >> 16) & 0xFF)) / 0xFF; // r color[1] = ((float)((colorInt >> 8) & 0xFF)) / 0xFF; // g color[2] = ((float)(colorInt & 0xFF)) / 0xFF; // b } static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); Loading Loading @@ -1010,6 +1061,8 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { return false; } char const* s = desString.string(); std::string dynamicColoringPartName = ""; bool postDynamicColoring = false; // Parse the description file for (;;) { Loading @@ -1028,7 +1081,13 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { char color[7] = "000000"; // default to black if unspecified char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; char dynamicColoringPartNameBuffer[ANIM_ENTRY_NAME_MAX]; char pathType; // start colors default to black if unspecified char start_color_0[7] = "000000"; char start_color_1[7] = "000000"; char start_color_2[7] = "000000"; char start_color_3[7] = "000000"; int nextReadPos; Loading @@ -1043,6 +1102,15 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { } else { animation.progressEnabled = false; } } else if (sscanf(l, "dynamic_colors %" STRTO(ANIM_PATH_MAX) "s #%6s #%6s #%6s #%6s", dynamicColoringPartNameBuffer, start_color_0, start_color_1, start_color_2, start_color_3)) { animation.dynamicColoringEnabled = true; parseColor(start_color_0, animation.startColors[0]); parseColor(start_color_1, animation.startColors[1]); parseColor(start_color_2, animation.startColors[2]); parseColor(start_color_3, animation.startColors[3]); dynamicColoringPartName = std::string(dynamicColoringPartNameBuffer); } else if (sscanf(l, "%c %d %d %" STRTO(ANIM_PATH_MAX) "s%n", &pathType, &count, &pause, path, &nextReadPos) >= 4) { if (pathType == 'f') { Loading @@ -1055,6 +1123,16 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) { // "clockPos1=%s, clockPos2=%s", // pathType, count, pause, path, framesToFadeCount, color, clockPos1, clockPos2); Animation::Part part; if (path == dynamicColoringPartName) { // Part is specified to use dynamic coloring. part.useDynamicColoring = true; part.postDynamicColoring = false; postDynamicColoring = true; } else { // Part does not use dynamic coloring. part.useDynamicColoring = false; part.postDynamicColoring = postDynamicColoring; } part.playUntilComplete = pathType == 'c'; part.framesToFadeCount = framesToFadeCount; part.count = count; Loading Loading @@ -1262,6 +1340,10 @@ bool BootAnimation::movie() { mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL); } if (mAnimation != nullptr && mAnimation->dynamicColoringEnabled) { initDynamicColors(); } playAnimation(*mAnimation); if (mTimeCheckThread != nullptr) { Loading Loading @@ -1315,6 +1397,27 @@ void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, fl sizeof(quadPositions) / sizeof(quadPositions[0]) / 2); } void BootAnimation::initDynamicColors() { for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { parseColorDecimalString( android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""), mAnimation->endColors[i], mAnimation->startColors[i]); } glUseProgram(mImageShader); SLOGI("[BootAnimation] Dynamically coloring boot animation."); for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) { float *startColor = mAnimation->startColors[i]; float *endColor = mAnimation->endColors[i]; glUniform4f(glGetUniformLocation(mImageShader, (U_START_COLOR_PREFIX + std::to_string(i)).c_str()), startColor[0], startColor[1], startColor[2], 1 /* alpha */); glUniform4f(glGetUniformLocation(mImageShader, (U_END_COLOR_PREFIX + std::to_string(i)).c_str()), endColor[0], endColor[1], endColor[2], 1 /* alpha */); } mImageColorProgressLocation = glGetUniformLocation(mImageShader, U_COLOR_PROGRESS); } bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); nsecs_t frameDuration = s2ns(1) / animation.fps; Loading Loading @@ -1357,6 +1460,14 @@ bool BootAnimation::playAnimation(const Animation& animation) { for (size_t j=0 ; j<fcount ; j++) { if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break; // Color progress is // - the normalized animation progress between [0, 1] for the dynamic coloring part, // - 0 for parts that come before, // - 1 for parts that come after. float colorProgress = part.useDynamicColoring ? (float)j / fcount : (part.postDynamicColoring ? 1 : 0); processDisplayEvents(); const int animationX = (mWidth - animation.width) / 2; Loading @@ -1371,24 +1482,14 @@ bool BootAnimation::playAnimation(const Animation& animation) { glGenTextures(1, &frame.tid); glBindTexture(GL_TEXTURE_2D, frame.tid); int w, h; initTexture(frame.map, &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 /* don't premultiply alpha */); } const int xc = animationX + frame.trimX; const int yc = animationY + frame.trimY; Region clearReg(Rect(mWidth, mHeight)); clearReg.subtractSelf(Rect(xc, yc, xc+frame.trimWidth, yc+frame.trimHeight)); if (!clearReg.isEmpty()) { Region::const_iterator head(clearReg.begin()); Region::const_iterator tail(clearReg.end()); glEnable(GL_SCISSOR_TEST); while (head != tail) { const Rect& r2(*head++); glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height()); glClear(GL_COLOR_BUFFER_BIT); } glDisable(GL_SCISSOR_TEST); } // specify the y center as ceiling((mHeight - frame.trimHeight) / 2) // which is equivalent to mHeight - (yc + frame.trimHeight) const int frameDrawY = mHeight - (yc + frame.trimHeight); Loading @@ -1404,6 +1505,9 @@ bool BootAnimation::playAnimation(const Animation& animation) { glUseProgram(mImageShader); glUniform1i(mImageTextureLocation, 0); glUniform1f(mImageFadeLocation, fade); if (animation.dynamicColoringEnabled) { glUniform1f(mImageColorProgressLocation, colorProgress); } glEnable(GL_BLEND); drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight); glDisable(GL_BLEND); Loading
cmds/bootanimation/BootAnimation.h +16 −4 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ public: }; struct Font { FileMap* map; FileMap* map = nullptr; Texture texture; int char_width; int char_height; Loading @@ -62,7 +62,7 @@ public: struct Animation { struct Frame { String8 name; FileMap* map; FileMap* map = nullptr; int trimX; int trimY; int trimWidth; Loading Loading @@ -90,6 +90,10 @@ public: uint8_t* audioData; int audioLength; Animation* animation; // Controls if dynamic coloring is enabled for this part. bool useDynamicColoring = false; // Defines if this part is played after the dynamic coloring part. bool postDynamicColoring = false; bool hasFadingPhase() const { return !playUntilComplete && framesToFadeCount > 0; Loading @@ -105,6 +109,10 @@ public: ZipFileRO* zip; Font clockFont; Font progressFont; // Controls if dynamic coloring is enabled for the whole animation. bool dynamicColoringEnabled = false; float startColors[4][3]; // Start colors of dynamic color transition. float endColors[4][3]; // End colors of dynamic color transition. }; // All callbacks will be called from this class's internal thread. Loading Loading @@ -163,8 +171,10 @@ private: int displayEventCallback(int fd, int events, void* data); void processDisplayEvents(); status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(FileMap* map, int* width, int* height); status_t initTexture(Texture* texture, AssetManager& asset, const char* name, bool premultiplyAlpha = true); status_t initTexture(FileMap* map, int* width, int* height, bool premultiplyAlpha = true); status_t initFont(Font* font, const char* fallback); void initShaders(); bool android(); Loading Loading @@ -194,6 +204,7 @@ private: void checkExit(); void handleViewport(nsecs_t timestep); void initDynamicColors(); sp<SurfaceComposerClient> mSession; AssetManager mAssets; Loading Loading @@ -226,6 +237,7 @@ private: GLuint mImageTextureLocation; GLuint mTextCropAreaLocation; GLuint mTextTextureLocation; GLuint mImageColorProgressLocation; }; // --------------------------------------------------------------------------- Loading
cmds/bootanimation/OWNERS 0 → 100644 +3 −0 Original line number Diff line number Diff line dupin@google.com shanh@google.com jreck@google.com
core/java/android/app/backup/BackupManager.java +26 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,32 @@ public class BackupManager { } } /** * Convenience method for callers who need to indicate that some other package or * some other user needs a backup pass. This can be useful in the case of groups of * packages that share a uid and/or have user-specific data. * <p> * This method requires that the application hold the "android.permission.BACKUP" * permission if the package named in the package argument does not run under the * same uid as the caller. This method also requires that the application hold the * "android.permission.INTERACT_ACROSS_USERS_FULL" if the user argument is not the * same as the user the caller is running under. * @param userId The user to back up * @param packageName The package name identifying the application to back up. * * @hide */ public static void dataChangedForUser(int userId, String packageName) { checkServiceBinder(); if (sService != null) { try { sService.dataChangedForUser(userId, packageName); } catch (RemoteException e) { Log.e(TAG, "dataChanged(userId,pkg) couldn't connect"); } } } /** * @deprecated Applications shouldn't request a restore operation using this method. In Android * P and later, this method is a no-op. Loading
core/java/android/view/translation/UiTranslationManager.java +44 −4 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.util.ArrayMap; import android.util.Log; import android.view.View; import android.view.autofill.AutofillId; import android.widget.TextView; import com.android.internal.annotations.GuardedBy; Loading @@ -42,11 +43,50 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; // TODO(b/178044703): Describe what UI Translation is. /** * The {@link UiTranslationManager} class provides ways for apps to use the ui translation * <p>The {@link UiTranslationManager} class provides ways for apps to use the ui translation * function in framework. * * <p> The UI translation provides ways for apps to support inline translation for the views. For * example the system supports text translation for {@link TextView}. To support UI translation for * your views, you should override the following methods to provide the content to be translated * and deal with the translated result. Here is an example for {@link TextView}-like views: * * <pre><code> * public class MyTextView extends View { * public MyTextView(...) { * // implements how to show the translated result in your View in * // ViewTranslationCallback and set it by setViewTranslationCallback() * setViewTranslationCallback(new MyViewTranslationCallback()); * } * * public void onCreateViewTranslationRequest(int[] supportedFormats, * Consumer<ViewTranslationRequest> requestsCollector) { * // collect the information that needs to be translated * ViewTranslationRequest.Builder requestBuilder = * new ViewTranslationRequest.Builder(getAutofillId()); * requestBuilder.setValue(ViewTranslationRequest.ID_TEXT, * TranslationRequestValue.forText(etText())); * requestsCollector.accept(requestBuilder.build()); * } * * public void onProvideContentCaptureStructure( * ViewStructure structure, int flags) { * // set ViewTranslationResponse * super.onViewTranslationResponse(response); * } * } * </code></pre> * * <p>If your view provides its own virtual hierarchy (for example, if it's a browser that draws the * HTML using {@link android.graphics.Canvas} or native libraries in a different render process), * you must override {@link View#onCreateVirtualViewTranslationRequests(long[], int[], Consumer)} to * provide the content to be translated and implement * {@link View#onVirtualViewTranslationResponses(android.util.LongSparseArray)} for the translated * result. You also need to implement {@link android.view.translation.ViewTranslationCallback} to * handle the translated information show or hide in your {@link View}. */ public final class UiTranslationManager { Loading Loading @@ -248,14 +288,14 @@ public final class UiTranslationManager { } } // TODO(b/178044703): Fix the View API link when it becomes public. /** * Register for notifications of UI Translation state changes on the foreground activity. This * is available to the owning application itself and also the current input method. * <p> * The application whose UI is being translated can use this to customize the UI Translation * behavior in ways that aren't made easy by methods like * View#onCreateTranslationRequest(). * {@link View#onCreateViewTranslationRequest(int[], Consumer)}. * * <p> * Input methods can use this to offer complementary features to UI Translation; for example, * enabling outgoing message translation when the system is translating incoming messages in a Loading