127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler/*
227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * Copyright (C) 2016 The Android Open Source Project
327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler *
427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * except in compliance with the License. You may obtain a copy of the License at
627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler *
727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler *      http://www.apache.org/licenses/LICENSE-2.0
827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler *
927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * Unless required by applicable law or agreed to in writing, software distributed under the
1027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * KIND, either express or implied. See the License for the specific language governing
1227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * permissions and limitations under the License.
1327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler */
1427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
1527a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerpackage com.android.egg.neko;
1627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
1727a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.app.Notification;
1827a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.app.PendingIntent;
1927a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.content.Context;
2027a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.content.Intent;
2127a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.content.res.Resources;
2227a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.graphics.*;
2327a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.graphics.drawable.Drawable;
2427a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.graphics.drawable.Icon;
2527a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.os.Bundle;
2627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
271e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandlerimport java.io.ByteArrayOutputStream;
2827a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport java.util.Random;
2927a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport java.util.concurrent.ThreadLocalRandom;
3027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
3127a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport com.android.egg.R;
32a801d40531b71f8c75bb03bb8fec429f503e391eChris Wrenimport com.android.internal.logging.MetricsLogger;
3327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
3427a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerpublic class Cat extends Drawable {
35610f6ede251c44cb4cf0e8a993d8d88c121159f9Dan Sandler    public static final long[] PURR = {0, 40, 20, 40, 20, 40, 20, 40, 20, 40, 20, 40};
36610f6ede251c44cb4cf0e8a993d8d88c121159f9Dan Sandler
3727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private Random mNotSoRandom;
3827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private Bitmap mBitmap;
3927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private long mSeed;
4027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private String mName;
4127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private int mBodyColor;
42a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    private int mFootType;
43a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    private boolean mBowTie;
4427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
4527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private synchronized Random notSoRandom(long seed) {
4627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (mNotSoRandom == null) {
4727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            mNotSoRandom = new Random();
4827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            mNotSoRandom.setSeed(seed);
4927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
5027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return mNotSoRandom;
5127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
5227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
5327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final float frandrange(Random r, float a, float b) {
5427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return (b-a)*r.nextFloat() + a;
5527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
5627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
5727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final Object choose(Random r, Object...l) {
5827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return l[r.nextInt(l.length)];
5927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
6027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
6127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int chooseP(Random r, int[] a) {
6227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        int pct = r.nextInt(1000);
6327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int stop = a.length-2;
6427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        int i=0;
6527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        while (i<stop) {
6627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            pct -= a[i];
6727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            if (pct < 0) break;
6827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            i+=2;
6927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
7027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return a[i+1];
7127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
7227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
73a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    public static final int getColorIndex(int q, int[] a) {
74a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        for(int i = 1; i < a.length; i+=2) {
75a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren            if (a[i] == q) {
76a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren                return i/2;
77a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren            }
78a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        }
79a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        return -1;
80a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    }
81a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren
8227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_BODY_COLORS = {
8327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            180, 0xFF212121, // black
8427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            180, 0xFFFFFFFF, // white
8527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            140, 0xFF616161, // gray
8627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            140, 0xFF795548, // brown
8727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            100, 0xFF90A4AE, // steel
8827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            100, 0xFFFFF9C4, // buff
8927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            100, 0xFFFF8F00, // orange
9027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              5, 0xFF29B6F6, // blue..?
9127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              5, 0xFFFFCDD2, // pink!?
9227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              5, 0xFFCE93D8, // purple?!?!?
9327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              4, 0xFF43A047, // yeah, why not green
9427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              1, 0,          // ?!?!?!
9527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
9627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
9727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_COLLAR_COLORS = {
9827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFFFFFFFF,
9927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFF000000,
10027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFFF44336,
10127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFF1976D2,
10227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFFFDD835,
10327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFFFB8C00,
10427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFFF48FB1,
10527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFF4CAF50,
10627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
10727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
10827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_BELLY_COLORS = {
10927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            750, 0,
11027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFFFFFFFF,
11127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
11227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
11327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_DARK_SPOT_COLORS = {
11427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            700, 0,
11527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFF212121,
11627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFF6D4C41,
11727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
11827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
11927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_LIGHT_SPOT_COLORS = {
12027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            700, 0,
12127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            300, 0xFFFFFFFF,
12227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
12327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
12427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private CatParts D;
12527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
12627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static void tint(int color, Drawable ... ds) {
12727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        for (Drawable d : ds) {
12827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            if (d != null) {
12927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                d.mutate().setTint(color);
13027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            }
13127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
13227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
13327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
13427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static boolean isDark(int color) {
13527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int r = (color & 0xFF0000) >> 16;
13627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int g = (color & 0x00FF00) >> 8;
13727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int b = color & 0x0000FF;
13827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return (r + g + b) < 0x80;
13927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
14027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
14127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public Cat(Context context, long seed) {
14227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        D = new CatParts(context);
14327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        mSeed = seed;
14427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
14527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        setName(context.getString(R.string.default_cat_name,
1467c2e730f637ee40f2be642b08a3956895dbb178bDan Sandler                String.valueOf(mSeed % 1000)));
14727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
14827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Random nsr = notSoRandom(seed);
14927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
15027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        // body color
15127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        mBodyColor = chooseP(nsr, P_BODY_COLORS);
15227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (mBodyColor == 0) mBodyColor = Color.HSVToColor(new float[] {
15327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                nsr.nextFloat()*360f, frandrange(nsr,0.5f,1f), frandrange(nsr,0.5f, 1f)});
15427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
15527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(mBodyColor, D.body, D.head, D.leg1, D.leg2, D.leg3, D.leg4, D.tail,
15627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                D.leftEar, D.rightEar, D.foot1, D.foot2, D.foot3, D.foot4, D.tailCap);
15727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(0x20000000, D.leg2Shadow, D.tailShadow);
15827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (isDark(mBodyColor)) {
15927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tint(0xFFFFFFFF, D.leftEye, D.rightEye, D.mouth, D.nose);
16027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
16127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(isDark(mBodyColor) ? 0xFFEF9A9A : 0x20D50000, D.leftEarInside, D.rightEarInside);
16227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
16327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(chooseP(nsr, P_BELLY_COLORS), D.belly);
16427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(chooseP(nsr, P_BELLY_COLORS), D.back);
16527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int faceColor = chooseP(nsr, P_BELLY_COLORS);
16627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(faceColor, D.faceSpot);
16727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (!isDark(faceColor)) {
16827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tint(0xFF000000, D.mouth, D.nose);
16927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
17027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
171a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        mFootType = 0;
17227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (nsr.nextFloat() < 0.25f) {
173a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren            mFootType = 4;
17427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tint(0xFFFFFFFF, D.foot1, D.foot2, D.foot3, D.foot4);
17527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        } else {
17627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            if (nsr.nextFloat() < 0.25f) {
177a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren                mFootType = 2;
1784a1bcd966b1c271909f38b41031cc012e233fbddDan Sandler                tint(0xFFFFFFFF, D.foot1, D.foot3);
17927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            } else if (nsr.nextFloat() < 0.25f) {
180a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren                mFootType = 3; // maybe -2 would be better? meh.
1814a1bcd966b1c271909f38b41031cc012e233fbddDan Sandler                tint(0xFFFFFFFF, D.foot2, D.foot4);
18227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            } else if (nsr.nextFloat() < 0.1f) {
183a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren                mFootType = 1;
18427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                tint(0xFFFFFFFF, (Drawable) choose(nsr, D.foot1, D.foot2, D.foot3, D.foot4));
18527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            }
18627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
18727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
18827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(nsr.nextFloat() < 0.333f ? 0xFFFFFFFF : mBodyColor, D.tailCap);
18927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
19027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int capColor = chooseP(nsr, isDark(mBodyColor) ? P_LIGHT_SPOT_COLORS : P_DARK_SPOT_COLORS);
19127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(capColor, D.cap);
19227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        //tint(chooseP(nsr, isDark(bodyColor) ? P_LIGHT_SPOT_COLORS : P_DARK_SPOT_COLORS), D.nose);
19327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
19427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int collarColor = chooseP(nsr, P_COLLAR_COLORS);
19527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(collarColor, D.collar);
196a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        mBowTie = nsr.nextFloat() < 0.1f;
197a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        tint(mBowTie ? collarColor : 0, D.bowtie);
19827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
19927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
20027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static Cat create(Context context) {
20127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return new Cat(context, Math.abs(ThreadLocalRandom.current().nextInt()));
20227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
20327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
20427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public Notification.Builder buildNotification(Context context) {
20527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Bundle extras = new Bundle();
20627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        extras.putString("android.substName", context.getString(R.string.notification_name));
20727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Intent intent = new Intent(Intent.ACTION_MAIN)
20827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setClass(context, NekoLand.class)
20927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
21027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return new Notification.Builder(context)
21127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setSmallIcon(Icon.createWithResource(context, R.drawable.stat_icon))
2121e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler                .setLargeIcon(createNotificationLargeIcon(context))
21327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setColor(getBodyColor())
21427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setPriority(Notification.PRIORITY_LOW)
21527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setContentTitle(context.getString(R.string.notification_title))
21627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setShowWhen(true)
21727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setCategory(Notification.CATEGORY_STATUS)
21827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setContentText(getName())
21927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setContentIntent(PendingIntent.getActivity(context, 0, intent, 0))
22027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setAutoCancel(true)
221610f6ede251c44cb4cf0e8a993d8d88c121159f9Dan Sandler                .setVibrate(PURR)
22227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .addExtras(extras);
22327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
22427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
22527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public long getSeed() {
22627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return mSeed;
22727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
22827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
22927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    @Override
23027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public void draw(Canvas canvas) {
23127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int w = Math.min(canvas.getWidth(), canvas.getHeight());
23227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int h = w;
23327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
23427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (mBitmap == null || mBitmap.getWidth() != w || mBitmap.getHeight() != h) {
23527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
23627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            final Canvas bitCanvas = new Canvas(mBitmap);
23727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            slowDraw(bitCanvas, 0, 0, w, h);
23827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
23927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        canvas.drawBitmap(mBitmap, 0, 0, null);
24027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
24127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
24227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private void slowDraw(Canvas canvas, int x, int y, int w, int h) {
24327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        for (int i = 0; i < D.drawingOrder.length; i++) {
24427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            final Drawable d = D.drawingOrder[i];
24527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            if (d != null) {
24627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                d.setBounds(x, y, x+w, y+h);
24727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                d.draw(canvas);
24827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            }
24927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
25027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
25127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
25227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
25327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public Bitmap createBitmap(int w, int h) {
25427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (mBitmap != null && mBitmap.getWidth() == w && mBitmap.getHeight() == h) {
25527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            return mBitmap.copy(mBitmap.getConfig(), true);
25627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
25727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
25827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        slowDraw(new Canvas(result), 0, 0, w, h);
25927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return result;
26027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
26127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
2621e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler    public static Icon recompressIcon(Icon bitmapIcon) {
2631e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        if (bitmapIcon.getType() != Icon.TYPE_BITMAP) return bitmapIcon;
2641e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        final Bitmap bits = bitmapIcon.getBitmap();
2651e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        final ByteArrayOutputStream ostream = new ByteArrayOutputStream(
2661e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler                bits.getWidth() * bits.getHeight() * 2); // guess 50% compression
2671e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        final boolean ok = bits.compress(Bitmap.CompressFormat.PNG, 100, ostream);
2681e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        if (!ok) return null;
2691e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        return Icon.createWithData(ostream.toByteArray(), 0, ostream.size());
2701e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler    }
2711e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler
2721e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler    public Icon createNotificationLargeIcon(Context context) {
27327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Resources res = context.getResources();
2741e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        final int w = 2*res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
2751e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        final int h = 2*res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
2761e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler        return recompressIcon(createIcon(context, w, h));
2771e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler    }
27827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
2791e52909888fc27bc8d7f63ceeabba0a87b65e419Dan Sandler    public Icon createIcon(Context context, int w, int h) {
28027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
28127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Canvas canvas = new Canvas(result);
28227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Paint pt = new Paint();
28327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        float[] hsv = new float[3];
28427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        Color.colorToHSV(mBodyColor, hsv);
28527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        hsv[2] = (hsv[2]>0.5f)
28627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                ? (hsv[2] - 0.25f)
28727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                : (hsv[2] + 0.25f);
28827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        pt.setColor(Color.HSVToColor(hsv));
28927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        float r = w/2;
29027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        canvas.drawCircle(r, r, r, pt);
29127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        int m = w/10;
29227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
29327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        slowDraw(canvas, m, m, w-m-m, h-m-m);
29427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
29527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return Icon.createWithBitmap(result);
29627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
29727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
29827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    @Override
29927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public void setAlpha(int i) {
30027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
30127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
30227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
30327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    @Override
30427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public void setColorFilter(ColorFilter colorFilter) {
30527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
30627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
30727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
30827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    @Override
30927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public int getOpacity() {
31027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return PixelFormat.TRANSLUCENT;
31127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
31227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
31327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public String getName() {
31427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return mName;
31527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
31627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
31727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public void setName(String name) {
31827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        this.mName = name;
31927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
32027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
32127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public int getBodyColor() {
32227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return mBodyColor;
32327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
32427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
325a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    public void logAdd(Context context) {
326a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        logCatAction(context, "egg_neko_add");
327a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    }
328a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren
3291bdc770e664d7052ae277ea07bd40bd36037d822Chris Wren    public void logRename(Context context) {
3301bdc770e664d7052ae277ea07bd40bd36037d822Chris Wren        logCatAction(context, "egg_neko_rename");
3311bdc770e664d7052ae277ea07bd40bd36037d822Chris Wren    }
3321bdc770e664d7052ae277ea07bd40bd36037d822Chris Wren
333a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    public void logRemove(Context context) {
334a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        logCatAction(context, "egg_neko_remove");
335a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    }
336a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren
337a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    public void logShare(Context context) {
338a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        logCatAction(context, "egg_neko_share");
339a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    }
340a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren
341a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    private void logCatAction(Context context, String prefix) {
342a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        MetricsLogger.count(context, prefix, 1);
343a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        MetricsLogger.histogram(context, prefix +"_color",
344a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren                getColorIndex(mBodyColor, P_BODY_COLORS));
345a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        MetricsLogger.histogram(context, prefix + "_bowtie", mBowTie ? 1 : 0);
346a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren        MetricsLogger.histogram(context, prefix + "_feet", mFootType);
347a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren    }
348a801d40531b71f8c75bb03bb8fec429f503e391eChris Wren
34927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static class CatParts {
35027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leftEar;
35127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable rightEar;
35227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable rightEarInside;
35327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leftEarInside;
35427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable head;
35527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable faceSpot;
35627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable cap;
35727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable mouth;
35827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable body;
35927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable foot1;
36027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg1;
36127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable foot2;
36227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg2;
36327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable foot3;
36427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg3;
36527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable foot4;
36627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg4;
36727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable tail;
36827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg2Shadow;
36927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable tailShadow;
37027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable tailCap;
37127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable belly;
37227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable back;
37327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable rightEye;
37427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leftEye;
37527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable nose;
37627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable bowtie;
37727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable collar;
37827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable[] drawingOrder;
37927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
38027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public CatParts(Context context) {
38127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            body = context.getDrawable(R.drawable.body);
38227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            head = context.getDrawable(R.drawable.head);
38327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg1 = context.getDrawable(R.drawable.leg1);
38427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg2 = context.getDrawable(R.drawable.leg2);
38527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg3 = context.getDrawable(R.drawable.leg3);
38627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg4 = context.getDrawable(R.drawable.leg4);
38727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tail = context.getDrawable(R.drawable.tail);
38827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leftEar = context.getDrawable(R.drawable.left_ear);
38927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            rightEar = context.getDrawable(R.drawable.right_ear);
39027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            rightEarInside = context.getDrawable(R.drawable.right_ear_inside);
39127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leftEarInside = context.getDrawable(R.drawable.left_ear_inside);
39227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            faceSpot = context.getDrawable(R.drawable.face_spot);
39327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            cap = context.getDrawable(R.drawable.cap);
39427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            mouth = context.getDrawable(R.drawable.mouth);
39527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            foot4 = context.getDrawable(R.drawable.foot4);
39627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            foot3 = context.getDrawable(R.drawable.foot3);
39727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            foot1 = context.getDrawable(R.drawable.foot1);
39827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            foot2 = context.getDrawable(R.drawable.foot2);
39927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg2Shadow = context.getDrawable(R.drawable.leg2_shadow);
40027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tailShadow = context.getDrawable(R.drawable.tail_shadow);
40127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tailCap = context.getDrawable(R.drawable.tail_cap);
40227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            belly = context.getDrawable(R.drawable.belly);
40327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            back = context.getDrawable(R.drawable.back);
40427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            rightEye = context.getDrawable(R.drawable.right_eye);
40527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leftEye = context.getDrawable(R.drawable.left_eye);
40627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            nose = context.getDrawable(R.drawable.nose);
40727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            collar = context.getDrawable(R.drawable.collar);
40827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            bowtie = context.getDrawable(R.drawable.bowtie);
40927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            drawingOrder = getDrawingOrder();
41027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
41127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        private Drawable[] getDrawingOrder() {
41227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            return new Drawable[] {
41327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    collar,
41427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    leftEar, leftEarInside, rightEar, rightEarInside,
41527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    head,
41627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    faceSpot,
41727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    cap,
41827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    leftEye, rightEye,
41927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    nose, mouth,
42027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    tail, tailCap, tailShadow,
42127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    foot1, leg1,
42227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    foot2, leg2,
42327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    foot3, leg3,
42427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    foot4, leg4,
42527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    leg2Shadow,
42627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    body, belly,
42727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    bowtie
42827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            };
42927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
43027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
43127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler}
432