19b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot/* 2f7a9eea8fe577f2f5edbbe6e73891a54351286c6Benjamin Franz * Copyright 2014, The Android Open Source Project 39b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * 49b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * Licensed under the Apache License, Version 2.0 (the "License"); 59b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * you may not use this file except in compliance with the License. 69b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * You may obtain a copy of the License at 79b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * 8f7a9eea8fe577f2f5edbbe6e73891a54351286c6Benjamin Franz * http://www.apache.org/licenses/LICENSE-2.0 99b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * 109b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * Unless required by applicable law or agreed to in writing, software 119b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * distributed under the License is distributed on an "AS IS" BASIS, 129b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * See the License for the specific language governing permissions and 149b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot * limitations under the License. 159b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot */ 169b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot 17f7a9eea8fe577f2f5edbbe6e73891a54351286c6Benjamin Franzpackage com.android.managedprovisioning.common; 189b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot 193cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzakimport android.annotation.NonNull; 209b6180825b5984ddf506616d798cda649fd47248Nicolas Prevotimport android.content.Context; 219b6180825b5984ddf506616d798cda649fd47248Nicolas Prevotimport android.graphics.Bitmap; 22bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevotimport android.graphics.BitmapFactory; 233cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzakimport android.graphics.PorterDuff; 243d68a3d2985367feecb1e1dd8da5d219e9e23d3eNicolas Prevotimport android.graphics.drawable.BitmapDrawable; 253d68a3d2985367feecb1e1dd8da5d219e9e23d3eNicolas Prevotimport android.graphics.drawable.Drawable; 269b6180825b5984ddf506616d798cda649fd47248Nicolas Prevotimport android.net.Uri; 273cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak 28bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevotimport com.android.internal.annotations.VisibleForTesting; 29f7a9eea8fe577f2f5edbbe6e73891a54351286c6Benjamin Franzimport com.android.managedprovisioning.R; 303cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak 319b6180825b5984ddf506616d798cda649fd47248Nicolas Prevotimport java.io.File; 329b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot 339b6180825b5984ddf506616d798cda649fd47248Nicolas Prevotpublic class LogoUtils { 343cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak @VisibleForTesting static final int DEFAULT_LOGO_ID = R.drawable.ic_enterprise_blue_24dp; 353cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak 369b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot public static void saveOrganisationLogo(Context context, Uri uri) { 379b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot final File logoFile = getOrganisationLogoFile(context); 3890f58ca887207a527c80d7e9ccea97e205c960d4Victor Chang StoreUtils.copyUriIntoFile(context.getContentResolver(), uri, logoFile); 399b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot } 409b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot 413cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak /** 423cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak * @param colorTint optional color colorTint to apply to the logo 433cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak */ 443cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak public static @NonNull Drawable getOrganisationLogo(Context context, Integer colorTint) { 453d68a3d2985367feecb1e1dd8da5d219e9e23d3eNicolas Prevot final File logoFile = getOrganisationLogoFile(context); 46bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot Bitmap bitmap = null; 47bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot int maxWidth = (int) context.getResources().getDimension(R.dimen.max_logo_width); 48bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot int maxHeight = (int) context.getResources().getDimension(R.dimen.max_logo_height); 49bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot if (logoFile.exists()) { 50bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot bitmap = getBitmapPartiallyResized(logoFile.getPath(), maxWidth, maxHeight); 51bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot if (bitmap == null) { 52bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot ProvisionLogger.loge("Could not get organisation logo from " + logoFile); 539b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot } 549b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot } 553cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak 563cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak if (bitmap != null) { 573cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak return new BitmapDrawable(context.getResources(), 583cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak resizeBitmap(bitmap, maxWidth, maxHeight)); 593cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak } 603cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak 613cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak // fall back to a default logo 623cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak Drawable organisationLogo = context.getDrawable(DEFAULT_LOGO_ID); 633cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak if (colorTint != null) { 643cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak organisationLogo.setColorFilter(colorTint, PorterDuff.Mode.SRC_ATOP); 65bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot } 663cc3880a7d61101d439cf6c5fdd351e22fdc8f4fJakub Gielzak return organisationLogo; 67bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot } 68bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot 69bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot /** 70bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot * Decodes a bitmap from an input stream. 71bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot * If the actual dimensions of the bitmap are larger than the desired ones, will try to return a 72bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot * subsample. 73bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot * The point of using this method is that the entire image may be too big to fit entirely in 74bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot * memmory. Since we may not need the entire image anyway, it's better to only decode a 75bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot * subsample when possible. 76bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot */ 77bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot @VisibleForTesting 78bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot static Bitmap getBitmapPartiallyResized(String filePath, int maxDesiredWidth, 79bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot int maxDesiredHeight) { 80bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot BitmapFactory.Options bounds = new BitmapFactory.Options(); 81bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot // Firstly, let's just get the dimensions of the image. 82bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot bounds.inJustDecodeBounds = true; 83bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot BitmapFactory.decodeFile(filePath, bounds); 84bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot int streamWidth = bounds.outWidth; 85bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot int streamHeight = bounds.outHeight; 86bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot int ratio = Math.max(streamWidth / maxDesiredWidth, streamHeight / maxDesiredHeight); 87bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot if (ratio > 1) { 88bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot // Decodes a smaller bitmap. Note that this ratio will be rounded down to the nearest 89bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot // power of 2. The decoded bitmap will not have the expected size, but we'll do another 90bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot // round of scaling. 91bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot bounds.inSampleSize = ratio; 92bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot } 93bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot bounds.inJustDecodeBounds = false; 94bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot // Now, decode the actual bitmap 95bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot return BitmapFactory.decodeFile(filePath, bounds); 96bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot } 97bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot 98bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot /* 99bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot * Returns a new Bitmap with the specified maximum width and height. Does scaling if 100bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot * necessary. Keeps the ratio of the original image. 101bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot */ 102bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot @VisibleForTesting 103bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot static Bitmap resizeBitmap(Bitmap bitmap, int maxWidth, int maxHeight) { 104bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot int width = bitmap.getWidth(); 105bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot int height = bitmap.getHeight(); 106bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot double ratio = Math.max((double) width / maxWidth, (double) height / maxHeight); 107bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot // We don't scale up. 108bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot if (ratio > 1) { 109bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot width /= ratio; 110bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot height /= ratio; 111bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false); 112bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot } 113bdd62865ec624b214549fe9b370a89a8f306e49aNicolas Prevot return bitmap; 1149b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot } 1159b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot 1169b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot public static void cleanUp(Context context) { 1179b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot getOrganisationLogoFile(context).delete(); 1189b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot } 1199b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot 1209b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot private static File getOrganisationLogoFile(Context context) { 1219b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot return new File(context.getFilesDir() + File.separator + "organisation_logo"); 1229b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot } 1239b6180825b5984ddf506616d798cda649fd47248Nicolas Prevot} 124