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