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

Commit 2969a90e authored by Mohammed Althaf T's avatar Mohammed Althaf T 😊
Browse files

Merge branch 'epic326-u-a14' into 'v1-u'

Port changes from Android T

See merge request !9
parents 9c5ccec5 82de2633
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
*.iml
.project
.classpath
.project.properties
gen/
bin/
.idea/
.gradle/
local.properties
gradle/
build/
gradlew*
.DS_Store
+6 −23
Original line number Diff line number Diff line
@@ -3,10 +3,6 @@ apply plugin: 'kotlin-android'

android {
    namespace = "com.android.app.animation"
    testNamespace = "com.android.app.animation.tests"
    defaultConfig {
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    sourceSets {
        main {
@@ -14,30 +10,17 @@ android {
            res.srcDirs = ['res']
            manifest.srcFile 'AndroidManifest.xml'
        }
        androidTest {
            java.srcDirs = ["tests/src", "tests/robolectric/src"]
            manifest.srcFile 'tests/AndroidManifest.xml'
        }
    }

    lintOptions {
        abortOnError false
    }
    tasks.lint.enabled = false
    tasks.withType(JavaCompile) {
        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
    }
    kotlinOptions {
        jvmTarget = '1.8'
        freeCompilerArgs = ["-Xjvm-default=all"]
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }

    addFrameworkJar('framework-14.jar')
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0"
    implementation "androidx.core:core-animation:1.0.0-alpha02"
    implementation "androidx.core:core-animation:1.0.0"
    implementation "androidx.core:core-ktx:1.9.0"
    androidTestImplementation libs.robolectric
    androidTestImplementation "androidx.test.ext:junit:1.1.3"
    androidTestImplementation "androidx.test:rules:1.4.0"
}
+9 −10
Original line number Diff line number Diff line
plugins {
    id 'com.android.library'
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
    namespace = "com.android.launcher3.icons"
    sourceSets {
        main {
            java.srcDirs = ['src', 'src_full_lib']
            java.srcDirs = ['src']
            manifest.srcFile 'AndroidManifest.xml'
            res.srcDirs = ['res']
        }
    }
    lint {
        abortOnError false
    }

    tasks.withType(JavaCompile) {
        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }

    addFrameworkJar('framework-14.jar')
}

dependencies {
    implementation "androidx.core:core"
    implementation "androidx.core:core-ktx:1.9.0"
}
+87 −7
Original line number Diff line number Diff line
@@ -27,9 +27,12 @@ import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.Log;
import android.view.ViewDebug;

import androidx.core.graphics.ColorUtils;

/**
 * Used to draw a notification dot on top of an icon.
 */
@@ -38,10 +41,17 @@ public class DotRenderer {
    private static final String TAG = "DotRenderer";

    // The dot size is defined as a percentage of the app icon size.
    private static final float SIZE_PERCENTAGE = 0.228f;
    private static final float SIZE_PERCENTAGE = 0.21f;
    private static final float SIZE_PERCENTAGE_WITH_COUNT = 0.28f;

    // The max number to draw on dots
    private static final int MAX_COUNT = 999;

    private final float mCircleRadius;
    private final Paint mCirclePaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);
    private final Paint mCircleShadowPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);

    private final Paint mTextPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);

    private final Bitmap mBackgroundWithShadow;
    private final float mBitmapOffset;
@@ -51,14 +61,22 @@ public class DotRenderer {
    private final float[] mLeftDotPosition;

    private static final int MIN_DOT_SIZE = 1;
    private final Rect mTextRect = new Rect();
    private final boolean mDisplayCount;

    public DotRenderer(int iconSizePx, Path iconShapePath, int pathSize) {
        int size = Math.round(SIZE_PERCENTAGE * iconSizePx);
        this(iconSizePx, iconShapePath, pathSize, false, null);
    }

    public DotRenderer(int iconSizePx, Path iconShapePath, int pathSize, Boolean displayCount, Typeface typeface) {
        mDisplayCount = displayCount;
        int size = Math.round((displayCount ? SIZE_PERCENTAGE_WITH_COUNT : SIZE_PERCENTAGE) * iconSizePx);
        if (size <= 0) {
            size = MIN_DOT_SIZE;
        }
        ShadowGenerator.Builder builder = new ShadowGenerator.Builder(Color.TRANSPARENT);
        builder.ambientShadowAlpha = 88;
        mBackgroundWithShadow = builder.setupBlurForSize(size).createPill(size, size);
        mBackgroundWithShadow = builder.setupBlurForSize(size).createPill(size, displayCount ? (size - 25) : size);
        mCircleRadius = builder.radius;

        mBitmapOffset = -mBackgroundWithShadow.getHeight() * 0.5f; // Same as width.
@@ -66,6 +84,10 @@ public class DotRenderer {
        // Find the points on the path that are closest to the top left and right corners.
        mLeftDotPosition = getPathPoint(iconShapePath, pathSize, -1);
        mRightDotPosition = getPathPoint(iconShapePath, pathSize, 1);

        mTextPaint.setTextSize(size * 0.65f);
        mTextPaint.setTextAlign(Paint.Align.LEFT);
        mTextPaint.setTypeface(typeface);
    }

    private static float[] getPathPoint(Path path, float size, float direction) {
@@ -101,6 +123,10 @@ public class DotRenderer {
     * Draw a circle on top of the canvas according to the given params.
     */
    public void draw(Canvas canvas, DrawParams params) {
        draw(canvas, params, 0);
    }

    public void draw(Canvas canvas, DrawParams params, int numNotifications) {
        if (params == null) {
            Log.e(TAG, "Invalid null argument(s) passed in call to draw.");
            return;
@@ -120,16 +146,68 @@ public class DotRenderer {
        float offsetY = Math.max(0, canvasBounds.top - (dotCenterY + mBitmapOffset));

        // We draw the dot relative to its center.
        canvas.translate(dotCenterX + offsetX, dotCenterY + offsetY);
        float dx = dotCenterX + offsetX;
        float dy = dotCenterY + offsetY - 15f;

        if (numNotifications > 9 && numNotifications < 1000) {
            canvas.translate(dx - 17f, dy);
        } else if (numNotifications > 0) {
            canvas.translate(dx - 12f, dy);
        }

        canvas.scale(params.scale, params.scale);

        mCirclePaint.setColor(Color.BLACK);
        canvas.drawBitmap(mBackgroundWithShadow, mBitmapOffset, mBitmapOffset, mCirclePaint);
        mCirclePaint.setColor(params.dotColor);
        canvas.drawCircle(0, 0, mCircleRadius, mCirclePaint);
        mCircleShadowPaint.setColor(params.shadowDotColor);

        if (numNotifications >= 10 && numNotifications < 1000) {
            canvas.drawRoundRect(new RectF(-mCircleRadius + 10, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCircleShadowPaint);
            canvas.drawRoundRect(new RectF(-mCircleRadius + 10, -mCircleRadius, mCircleRadius + 20, mCircleRadius), 50, 50, mCirclePaint);
        } else if (numNotifications > 0) {
            canvas.drawCircle(5, 10, mCircleRadius, mCircleShadowPaint);
            canvas.drawCircle(5, 10, mCircleRadius, mCirclePaint);
        }

        if (mDisplayCount && numNotifications > 0) {
            // Draw the numNotifications text
            mTextPaint.setColor(getCounterTextColor(Color.WHITE));
            mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
            mTextPaint.setTextSize(32f);
            String text = numToNotation(numNotifications);
            mTextPaint.getTextBounds(text, 0, text.length(), mTextRect);
            float y = mTextRect.height() / 2f - mTextRect.bottom;
            if (numNotifications < 10) {
                canvas.drawText(text, -4f, 22f, mTextPaint);
            } else if (numNotifications < 100) {
                canvas.drawText(text, -3f, y, mTextPaint);
            } else if (numNotifications >= 1000) {
                canvas.drawText(text, -14f, 20f, mTextPaint);
            } else {
                canvas.drawText(text, -12f, y, mTextPaint);
            }
        }

        canvas.restore();
    }

    private String numToNotation(int num) {
        if (num < 1000) {
            return String.valueOf(num);
        } else {
            return num / 1000 + "k";
        }
    }

    /**
     * Returns the color to use for the counter text based on the dot's background color.
     *
     * @param dotBackgroundColor The color of the dot background.
     * @return The color to use on the counter text.
     */
    private int getCounterTextColor(int dotBackgroundColor) {
        return ColorUtils.setAlphaComponent(dotBackgroundColor, 0xFF);
    }

    public static class DrawParams {
        /** The color (possibly based on the icon) to use for the dot. */
        @ViewDebug.ExportedProperty(category = "notification dot", formatToHexString = true)
@@ -146,5 +224,7 @@ public class DotRenderer {
        /** Whether the dot should align to the top left of the icon rather than the top right. */
        @ViewDebug.ExportedProperty(category = "notification dot")
        public boolean leftAlign;
        @ViewDebug.ExportedProperty(category = "notification dot", formatToHexString = true)
        public int shadowDotColor;
    }
}
+35 −1
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ public class IconProvider {
    public static final boolean ATLEAST_T = BuildCompat.isAtLeastT();

    private static final String ICON_METADATA_KEY_PREFIX = ".dynamic_icons";
    private static final String MONTH_BG_ICON_METADATA_KEY_PREFIX = ".month_dynamic_icons";
    private static final String DAY_FG_ICON_METADATA_KEY_PREFIX = ".day_dynamic_icons";

    private static final String SYSTEM_STATE_SEPARATOR = " ";

@@ -173,7 +175,9 @@ public class IconProvider {
                    .metaData;
            final Resources resources = pm.getResourcesForApplication(mCalendar.getPackageName());
            final int id = getDynamicIconId(metadata, resources);
            if (id != ID_NULL) {
            final int[] monthDayIds = getDynamicBackgroundIconId(metadata, resources);
            if (id != ID_NULL && (monthDayIds == null ||
                    monthDayIds[0] == ID_NULL || monthDayIds[1] == ID_NULL )) {
                if (DEBUG) Log.d(TAG, "Got icon #" + id);
                Drawable drawable = resources.getDrawableForDensity(id, iconDpi, null /* theme */);
                if (ATLEAST_T && drawable instanceof AdaptiveIconDrawable && td != null) {
@@ -191,6 +195,10 @@ public class IconProvider {
                    }
                }
                return drawable;
            } else if (monthDayIds != null) {
                Drawable background = resources.getDrawableForDensity(monthDayIds[0], iconDpi, null /* theme */);
                Drawable foreground = resources.getDrawableForDensity(monthDayIds[1], iconDpi, null /* theme */);
                return new AdaptiveIconDrawable(background, foreground);
            }
        } catch (PackageManager.NameNotFoundException e) {
            if (DEBUG) {
@@ -225,6 +233,28 @@ public class IconProvider {
        }
    }

    private int[] getDynamicBackgroundIconId(Bundle metadata, Resources resources) {
        if (metadata == null) {
            return null;
        }
        String bgKey = mCalendar.getPackageName() + MONTH_BG_ICON_METADATA_KEY_PREFIX;
        String fgKey = mCalendar.getPackageName() + DAY_FG_ICON_METADATA_KEY_PREFIX;
        final int bgArrayId = metadata.getInt(bgKey, ID_NULL);
        final int fgArrayId = metadata.getInt(fgKey, ID_NULL);
        if (bgArrayId == ID_NULL || fgArrayId == ID_NULL) {
            return null;
        }
        try {
            return new int[] {resources.obtainTypedArray(bgArrayId).getResourceId(getMonth(), ID_NULL),
                    resources.obtainTypedArray(fgArrayId).getResourceId(getDay(), ID_NULL)};
        } catch (Resources.NotFoundException e) {
            if (DEBUG) {
                Log.d(TAG, "package defines '" + bgKey + " and " + fgKey + "' but corresponding array not found");
            }
            return null;
        }
    }

    /**
     * @return Today's day of the month, zero-indexed.
     */
@@ -232,6 +262,10 @@ public class IconProvider {
        return Calendar.getInstance().get(Calendar.DAY_OF_MONTH) - 1;
    }

    private static int getMonth() {
        return Calendar.getInstance().get(Calendar.MONTH);
    }

    private static ComponentName parseComponentOrNull(Context context, int resId) {
        String cn = context.getString(resId);
        return TextUtils.isEmpty(cn) ? null : ComponentName.unflattenFromString(cn);