Remove unused drawable and bitmap code
Test: manual
Change-Id: Ibd7d78a45d1e4a1ebef1d080983480d276f71382
diff --git a/car-apps-common/src/com/android/car/apps/common/AccountImageChangeObserver.java b/car-apps-common/src/com/android/car/apps/common/AccountImageChangeObserver.java
deleted file mode 100644
index cbfe5a4..0000000
--- a/car-apps-common/src/com/android/car/apps/common/AccountImageChangeObserver.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import static android.Manifest.permission.GET_ACCOUNTS;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.annotation.RequiresPermission;
-import android.content.ContentUris;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.Contacts;
-import android.text.TextUtils;
-
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-
-/**
- * @hide
- */
-public class AccountImageChangeObserver {
- private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
-
- private static final Object sObserverInstanceLock = new Object();
- private static AccountImageChangeObserver sObserver;
-
- private class ContactChangeContentObserver extends ContentObserver {
- private final Account mWatchedAccount;
- private final LinkedHashSet<Uri> mUrisToNotify;
- private final Object mLock = new Object();
- private final Context mContext;
- private String mCurrentImageUri;
-
- public ContactChangeContentObserver(Context context, Account watchedAccount) {
- super(null);
- mWatchedAccount = watchedAccount;
- mUrisToNotify = new LinkedHashSet<>();
- mContext = context;
- mCurrentImageUri = AccountImageHelper.getAccountPictureUri(mContext, mWatchedAccount);
- }
-
- @Override
- public boolean deliverSelfNotifications() {
- return true;
- }
-
- public void addUriToNotifyList(Uri uri) {
- synchronized (mLock) {
- mUrisToNotify.add(uri);
- }
- }
-
- @Override
- public void onChange(boolean selfChange) {
- String newUri = AccountImageHelper.getAccountPictureUri(mContext, mWatchedAccount);
-
- if (TextUtils.equals(mCurrentImageUri, newUri)) {
- // no change, no need to notify
- return;
- }
-
- synchronized (mLock) {
- for (Uri uri : mUrisToNotify) {
- mContext.getContentResolver().notifyChange(uri, null);
- }
-
- mCurrentImageUri = newUri;
- }
- }
- }
-
- private final HashMap<String, ContactChangeContentObserver> mObserverMap;
-
-
- /**
- * get the singleton AccountImageChangeObserver for the application
- */
- public final static AccountImageChangeObserver getInstance() {
- if (sObserver == null) {
- synchronized (sObserverInstanceLock) {
- if (sObserver == null) {
- sObserver = new AccountImageChangeObserver();
- }
- }
- }
- return sObserver;
- }
-
- public AccountImageChangeObserver() {
- mObserverMap = new HashMap<>();
- }
-
- @RequiresPermission(GET_ACCOUNTS)
- public synchronized void registerChangeUriIfPresent(BitmapWorkerOptions options) {
- Uri imageUri = options.getResourceUri();
- // Only register URIs that match the Account Image URI schema, and
- // have a change notify URI specified.
- if (imageUri != null && UriUtils.isAccountImageUri(imageUri)) {
- Uri changeNotifUri = UriUtils.getAccountImageChangeNotifyUri(imageUri);
- imageUri = imageUri.buildUpon().clearQuery().build();
-
- if (changeNotifUri == null) {
- // No change Notiy URI specified
- return;
- }
-
- String accountName = UriUtils.getAccountName(imageUri);
- Context context = options.getContext();
-
- if (accountName != null && context != null) {
- Account thisAccount = null;
- for (Account account : AccountManager.get(context).
- getAccountsByType(GOOGLE_ACCOUNT_TYPE)) {
- if (account.name.equals(accountName)) {
- thisAccount = account;
- break;
- }
- }
- if (thisAccount != null) {
- ContactChangeContentObserver observer;
-
- if (mObserverMap.containsKey(thisAccount.name)) {
- observer = mObserverMap.get(thisAccount.name);
- if (observer != null) {
- observer.addUriToNotifyList(changeNotifUri);
- }
- } else {
- long contactId = getContactIdForAccount(context, thisAccount);
- if (contactId != -1) {
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI,
- contactId);
- observer = new ContactChangeContentObserver(context, thisAccount);
- mObserverMap.put(thisAccount.name, observer);
- observer.addUriToNotifyList(changeNotifUri);
- context.getContentResolver().registerContentObserver(contactUri, false,
- observer);
- }
- }
- }
- }
- }
- }
-
- private long getContactIdForAccount(Context context, Account account) {
- // Look up this account in the contacts database.
- String[] projection = new String[] {
- ContactsContract.Data._ID,
- ContactsContract.Data.CONTACT_ID,
- ContactsContract.Data.LOOKUP_KEY
- };
- String selection =
- ContactsContract.CommonDataKinds.Email.ADDRESS + " LIKE ?";
- String[] selectionArgs = new String[] { account.name };
- Cursor c = null;
- long contactId = -1;
- String lookupKey = null;
- try {
- c = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
- projection, selection, selectionArgs, null);
- if (c.moveToNext()) {
- contactId = c.getLong(1);
- lookupKey = c.getString(2);
- }
- } finally {
- if (c != null) {
- c.close();
- }
- }
-
- if (contactId != -1 && !TextUtils.isEmpty(lookupKey)) {
- return contactId;
- }
-
- return -1;
- }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/BitmapDownloader.java b/car-apps-common/src/com/android/car/apps/common/BitmapDownloader.java
deleted file mode 100644
index 9600585..0000000
--- a/car-apps-common/src/com/android/car/apps/common/BitmapDownloader.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.util.Log;
-import android.util.LruCache;
-import android.widget.ImageView;
-
-import java.lang.ref.SoftReference;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
-/**
- * Downloader class which loads a resource URI into an image view.
- * <p>
- * This class adds a cache over BitmapWorkerTask.
- */
-public class BitmapDownloader {
-
- private static final String TAG = "BitmapDownloader";
-
- private static final boolean DEBUG = false;
-
- private static final int CORE_POOL_SIZE = 5;
-
- private static final Executor BITMAP_DOWNLOADER_THREAD_POOL_EXECUTOR =
- Executors.newFixedThreadPool(CORE_POOL_SIZE);
-
- // 1/4 of max memory is used for bitmap mem cache
- private static final int MEM_TO_CACHE = 4;
-
- // hard limit for bitmap mem cache in MB
- private static final int CACHE_HARD_LIMIT = 32;
-
- /**
- * bitmap cache item structure saved in LruCache
- */
- private static class BitmapItem {
- /**
- * cached bitmap
- */
- Bitmap mBitmap;
- /**
- * indicate if the bitmap is scaled down from original source (never scale up)
- */
- boolean mScaled;
-
- public BitmapItem(Bitmap bitmap, boolean scaled) {
- mBitmap = bitmap;
- mScaled = scaled;
- }
- }
-
- private LruCache<String, BitmapItem> mMemoryCache;
-
- private static BitmapDownloader sBitmapDownloader;
-
- private static final Object sBitmapDownloaderLock = new Object();
-
- // Bitmap cache also uses size of Bitmap as part of key.
- // Bitmap cache is divided into following buckets by height:
- // TODO: Pano currently is caring more about height, what about width in key?
- // height <= 128, 128 < height <= 512, height > 512
- // Different bitmap cache buckets save different bitmap cache items.
- // Bitmaps within same bucket share the largest cache item.
- private static final int[] SIZE_BUCKET = new int[]{128, 512, Integer.MAX_VALUE};
-
- public static abstract class BitmapCallback {
- SoftReference<BitmapWorkerTask> mTask;
-
- public abstract void onBitmapRetrieved(Bitmap bitmap);
- }
-
- /**
- * get the singleton BitmapDownloader for the application
- */
- public final static BitmapDownloader getInstance(Context context) {
- if (sBitmapDownloader == null) {
- synchronized(sBitmapDownloaderLock) {
- if (sBitmapDownloader == null) {
- sBitmapDownloader = new BitmapDownloader(context);
- }
- }
- }
- return sBitmapDownloader;
- }
-
- public BitmapDownloader(Context context) {
- int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
- .getMemoryClass();
- memClass = memClass / MEM_TO_CACHE;
- if (memClass > CACHE_HARD_LIMIT) {
- memClass = CACHE_HARD_LIMIT;
- }
- int cacheSize = 1024 * 1024 * memClass;
- mMemoryCache = new LruCache<String, BitmapItem>(cacheSize) {
- @Override
- protected int sizeOf(String key, BitmapItem bitmap) {
- return bitmap.mBitmap.getByteCount();
- }
- };
- }
-
- /**
- * load bitmap in current thread, will *block* current thread.
- * @deprecated
- */
- @Deprecated
- public final Bitmap loadBitmapBlocking(final BitmapWorkerOptions options) {
- final boolean hasAccountImageUri = UriUtils.isAccountImageUri(options.getResourceUri());
- Bitmap bitmap = null;
- if (hasAccountImageUri) {
- AccountImageChangeObserver.getInstance().registerChangeUriIfPresent(options);
- } else {
- bitmap = getBitmapFromMemCache(options);
- }
-
- if (bitmap == null) {
- BitmapWorkerTask task = new BitmapWorkerTask(null) {
- @Override
- protected Bitmap doInBackground(BitmapWorkerOptions... params) {
- final Bitmap bitmap = super.doInBackground(params);
- if (bitmap != null && !hasAccountImageUri) {
- addBitmapToMemoryCache(params[0], bitmap, isScaled());
- }
- return bitmap;
- }
- };
-
- return task.doInBackground(options);
- }
- return bitmap;
- }
-
- /**
- * Loads the bitmap into the image view.
- */
- public void loadBitmap(final BitmapWorkerOptions options, final ImageView imageView) {
- cancelDownload(imageView);
- final boolean hasAccountImageUri = UriUtils.isAccountImageUri(options.getResourceUri());
- Bitmap bitmap = null;
- if (hasAccountImageUri) {
- AccountImageChangeObserver.getInstance().registerChangeUriIfPresent(options);
- } else {
- bitmap = getBitmapFromMemCache(options);
- }
-
- if (bitmap != null) {
- imageView.setImageBitmap(bitmap);
- } else {
- BitmapWorkerTask task = new BitmapWorkerTask(imageView) {
- @Override
- protected Bitmap doInBackground(BitmapWorkerOptions... params) {
- Bitmap bitmap = super.doInBackground(params);
- if (bitmap != null && !hasAccountImageUri) {
- addBitmapToMemoryCache(params[0], bitmap, isScaled());
- }
- return bitmap;
- }
- };
- imageView.setTag(R.id.imageDownloadTask, new SoftReference<BitmapWorkerTask>(task));
- task.execute(options);
- }
- }
-
- /**
- * Loads the bitmap.
- * <p>
- * This will be sent back to the callback object.
- */
- public void getBitmap(final BitmapWorkerOptions options, final BitmapCallback callback) {
- cancelDownload(callback);
- final boolean hasAccountImageUri = UriUtils.isAccountImageUri(options.getResourceUri());
- final Bitmap bitmap = hasAccountImageUri ? null : getBitmapFromMemCache(options);
- if (hasAccountImageUri) {
- AccountImageChangeObserver.getInstance().registerChangeUriIfPresent(options);
- }
-
- BitmapWorkerTask task = new BitmapWorkerTask(null) {
- @Override
- protected Bitmap doInBackground(BitmapWorkerOptions... params) {
- if (bitmap != null) {
- return bitmap;
- }
- final Bitmap bitmap = super.doInBackground(params);
- if (bitmap != null && !hasAccountImageUri) {
- addBitmapToMemoryCache(params[0], bitmap, isScaled());
- }
- return bitmap;
- }
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- callback.onBitmapRetrieved(bitmap);
- }
- };
- callback.mTask = new SoftReference<BitmapWorkerTask>(task);
- task.executeOnExecutor(BITMAP_DOWNLOADER_THREAD_POOL_EXECUTOR, options);
- }
-
- /**
- * Cancel download<p>
- * @param key {@link BitmapCallback} or {@link ImageView}
- */
- @SuppressWarnings("unchecked")
- public boolean cancelDownload(Object key) {
- BitmapWorkerTask task = null;
- if (key instanceof ImageView) {
- ImageView imageView = (ImageView)key;
- SoftReference<BitmapWorkerTask> softReference =
- (SoftReference<BitmapWorkerTask>) imageView.getTag(R.id.imageDownloadTask);
- if (softReference != null) {
- task = softReference.get();
- softReference.clear();
- }
- } else if (key instanceof BitmapCallback) {
- BitmapCallback callback = (BitmapCallback) key;
- if (callback.mTask != null) {
- task = callback.mTask.get();
- callback.mTask = null;
- }
- }
- if (task != null) {
- return task.cancel(true);
- }
- return false;
- }
-
- private static String getBucketKey(String baseKey, Bitmap.Config bitmapConfig, int width) {
- for (int i = 0; i < SIZE_BUCKET.length; i++) {
- if (width <= SIZE_BUCKET[i]) {
- return new StringBuilder(baseKey.length() + 16).append(baseKey)
- .append(":").append(bitmapConfig == null ? "" : bitmapConfig.ordinal())
- .append(":").append(SIZE_BUCKET[i]).toString();
- }
- }
- // should never happen because last bucket is Integer.MAX_VALUE
- throw new RuntimeException();
- }
-
- private void addBitmapToMemoryCache(BitmapWorkerOptions key, Bitmap bitmap, boolean isScaled) {
- if (!key.isMemCacheEnabled()) {
- return;
- }
- String bucketKey = getBucketKey(
- key.getCacheKey(), key.getBitmapConfig(), bitmap.getHeight());
- BitmapItem bitmapItem = mMemoryCache.get(bucketKey);
- if (bitmapItem != null) {
- Bitmap currentBitmap = bitmapItem.mBitmap;
- // If somebody else happened to get a larger one in the bucket, discard our bitmap.
- // TODO: need a better way to prevent current downloading for the same Bitmap
- if (currentBitmap.getWidth() >= bitmap.getWidth() && currentBitmap.getHeight()
- >= bitmap.getHeight()) {
- return;
- }
- }
- if (DEBUG) {
- Log.d(TAG, "add cache "+bucketKey+" isScaled = "+isScaled);
- }
- bitmapItem = new BitmapItem(bitmap, isScaled);
- mMemoryCache.put(bucketKey, bitmapItem);
- }
-
- private Bitmap getBitmapFromMemCache(BitmapWorkerOptions key) {
- if (key.getHeight() != BitmapWorkerOptions.MAX_IMAGE_DIMENSION_PX) {
- // 1. find the bitmap in the size bucket
- String bucketKey =
- getBucketKey(key.getCacheKey(), key.getBitmapConfig(), key.getHeight());
- BitmapItem bitmapItem = mMemoryCache.get(bucketKey);
- if (bitmapItem != null) {
- Bitmap bitmap = bitmapItem.mBitmap;
- // now we have the bitmap in the bucket, use it when the bitmap is not scaled or
- // if the size is larger than or equals to the output size
- if (!bitmapItem.mScaled) {
- return bitmap;
- }
- if (bitmap.getHeight() >= key.getHeight()) {
- return bitmap;
- }
- }
- // 2. find un-scaled bitmap in smaller buckets. If the un-scaled bitmap exists
- // in higher buckets, we still need to scale it down. Right now we just
- // return null and let the BitmapWorkerTask to do the same job again.
- // TODO: use the existing unscaled bitmap and we don't need to load it from resource
- // or network again.
- for (int i = SIZE_BUCKET.length - 1; i >= 0; i--) {
- if (SIZE_BUCKET[i] >= key.getHeight()) {
- continue;
- }
- bucketKey = getBucketKey(key.getCacheKey(), key.getBitmapConfig(), SIZE_BUCKET[i]);
- bitmapItem = mMemoryCache.get(bucketKey);
- if (bitmapItem != null && !bitmapItem.mScaled) {
- return bitmapItem.mBitmap;
- }
- }
- return null;
- }
- // 3. find un-scaled bitmap if size is not specified
- for (int i = SIZE_BUCKET.length - 1; i >= 0; i--) {
- String bucketKey =
- getBucketKey(key.getCacheKey(), key.getBitmapConfig(), SIZE_BUCKET[i]);
- BitmapItem bitmapItem = mMemoryCache.get(bucketKey);
- if (bitmapItem != null && !bitmapItem.mScaled) {
- return bitmapItem.mBitmap;
- }
- }
- return null;
- }
-
- public Bitmap getLargestBitmapFromMemCache(BitmapWorkerOptions key) {
- // find largest bitmap matching the key
- for (int i = SIZE_BUCKET.length - 1; i >= 0; i--) {
- String bucketKey =
- getBucketKey(key.getCacheKey(), key.getBitmapConfig(), SIZE_BUCKET[i]);
- BitmapItem bitmapItem = mMemoryCache.get(bucketKey);
- if (bitmapItem != null) {
- return bitmapItem.mBitmap;
- }
- }
- return null;
- }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/BitmapWorkerOptions.java b/car-apps-common/src/com/android/car/apps/common/BitmapWorkerOptions.java
deleted file mode 100644
index 5f22e79..0000000
--- a/car-apps-common/src/com/android/car/apps/common/BitmapWorkerOptions.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import android.content.Context;
-import android.content.Intent.ShortcutIconResource;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.text.TextUtils;
-
-/**
- * Options for loading bitmap resources from different sources and for scaling to an appropriate
- * resolution.
- */
-public class BitmapWorkerOptions {
-
- /** Max image size handled by android.graphics */
- static final int MAX_IMAGE_DIMENSION_PX = 2048;
-
- /** flag to force disable memory cache */
- public static final int CACHE_FLAG_MEM_DISABLED = 1;
- /** TODO support disk cache options */
- public static final int CACHE_FLAG_DISK_DISABLED = 2;
-
- private ShortcutIconResource mIconResource;
- private Uri mResourceUri;
-
- private int mWidth;
- private int mHeight;
- private Context mContext;
- private int mCacheFlag;
- private Bitmap.Config mBitmapConfig;
-
- private String mKey;
-
- /**
- * Builds options for a bitmap worker task.
- */
- public static class Builder {
-
- private String mPackageName;
- private String mResourceName;
- private Uri mResourceUri;
-
- private int mWidth;
- private int mHeight;
- private Context mContext;
- private int mCacheFlag;
- private Bitmap.Config mBitmapConfig;
-
- public Builder(Context context) {
- mWidth = MAX_IMAGE_DIMENSION_PX;
- mHeight = MAX_IMAGE_DIMENSION_PX;
- mContext = context;
- mCacheFlag = 0;
- mBitmapConfig = null;
- }
-
- public BitmapWorkerOptions build() {
- BitmapWorkerOptions options = new BitmapWorkerOptions();
-
- if (!TextUtils.isEmpty(mPackageName)) {
- options.mIconResource = new ShortcutIconResource();
- options.mIconResource.packageName = mPackageName;
- options.mIconResource.resourceName = mResourceName;
- }
-
- final int largestDim = Math.max(mWidth, mHeight);
- if (largestDim > MAX_IMAGE_DIMENSION_PX) {
- double scale = (double) MAX_IMAGE_DIMENSION_PX / largestDim;
- mWidth *= scale;
- mHeight *= scale;
- }
-
- options.mResourceUri = mResourceUri;
- options.mWidth = mWidth;
- options.mHeight = mHeight;
- options.mContext = mContext;
- options.mCacheFlag = mCacheFlag;
- options.mBitmapConfig = mBitmapConfig;
- if (options.mIconResource == null && options.mResourceUri == null) {
- throw new RuntimeException("Both Icon and ResourceUri are null");
- }
- return options;
- }
-
- public Builder resource(String packageName, String resourceName) {
- mPackageName = packageName;
- mResourceName = resourceName;
- return this;
- }
-
- public Builder resource(ShortcutIconResource iconResource) {
- mPackageName = iconResource.packageName;
- mResourceName = iconResource.resourceName;
- return this;
- }
-
- public Builder resource(Uri resourceUri) {
- mResourceUri = resourceUri;
- return this;
- }
-
- public Builder width(int width) {
- if (width > 0) {
- mWidth = width;
- } else {
- throw new IllegalArgumentException("Can't set width to " + width);
- }
- return this;
- }
-
- public Builder height(int height) {
- if (height > 0) {
- mHeight = height;
- } else {
- throw new IllegalArgumentException("Can't set height to " + height);
- }
- return this;
- }
-
- public Builder cacheFlag(int flag) {
- mCacheFlag = flag;
- return this;
- }
-
- public Builder bitmapConfig(Bitmap.Config config) {
- mBitmapConfig = config;
- return this;
- }
-
- }
-
- /**
- * Private constructor.
- * <p>
- * Use a {@link Builder} to create.
- */
- private BitmapWorkerOptions() {
- }
-
- public ShortcutIconResource getIconResource() {
- return mIconResource;
- }
-
- public Uri getResourceUri() {
- return mResourceUri;
- }
-
- public int getWidth() {
- return mWidth;
- }
-
- public int getHeight() {
- return mHeight;
- }
-
- public Context getContext() {
- return mContext;
- }
-
- public boolean isFromResource() {
- return getIconResource() != null ||
- UriUtils.isAndroidResourceUri(getResourceUri())
- || UriUtils.isShortcutIconResourceUri(getResourceUri());
- }
-
- /**
- * Combination of CACHE_FLAG_MEM_DISABLED and CACHE_FLAG_DISK_DISABLED,
- * 0 for fully cache enabled
- */
- public int getCacheFlag() {
- return mCacheFlag;
- }
-
- public boolean isMemCacheEnabled() {
- return (mCacheFlag & CACHE_FLAG_MEM_DISABLED) == 0;
- }
-
- public boolean isDiskCacheEnabled() {
- return (mCacheFlag & CACHE_FLAG_DISK_DISABLED) == 0;
- }
-
- /**
- * @return preferred Bitmap config to decode bitmap, null for auto detect.
- * Use {@link Builder#bitmapConfig(Bitmap.Config)} to change it.
- */
- public Bitmap.Config getBitmapConfig() {
- return mBitmapConfig;
- }
-
- public String getCacheKey() {
- if (mKey == null) {
- mKey = mIconResource != null ? mIconResource.packageName + "/"
- + mIconResource.resourceName : mResourceUri.toString();
- }
- return mKey;
- }
-
- @Override
- public String toString() {
- if (mIconResource == null) {
- return "URI: " + mResourceUri;
- } else {
- return "PackageName: " + mIconResource.packageName + " Resource: " + mIconResource
- + " URI: " + mResourceUri;
- }
- }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/BitmapWorkerTask.java b/car-apps-common/src/com/android/car/apps/common/BitmapWorkerTask.java
deleted file mode 100644
index aa8d67f..0000000
--- a/car-apps-common/src/com/android/car/apps/common/BitmapWorkerTask.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.Context;
-import android.content.Intent.ShortcutIconResource;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.util.Log;
-import android.util.TypedValue;
-import android.widget.ImageView;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.net.HttpURLConnection;
-import java.net.URL;
-
-/**
- * AsyncTask which loads a bitmap.
- * <p>
- * The source of this can be another package (via a resource), a URI (content provider), or
- * a file path.
- *
- * @see BitmapWorkerOptions
- * @hide
- */
-public class BitmapWorkerTask extends AsyncTask<BitmapWorkerOptions, Void, Bitmap> {
-
- private static final String TAG = "BitmapWorker";
- private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
-
- private static final boolean DEBUG = false;
-
- private static final int SOCKET_TIMEOUT = 10000;
- private static final int READ_TIMEOUT = 10000;
-
- private final WeakReference<ImageView> mImageView;
- // a flag for if the bitmap is scaled from original source
- protected boolean mScaled;
-
- public BitmapWorkerTask(ImageView imageView) {
- mImageView = new WeakReference<ImageView>(imageView);
- mScaled = false;
- }
-
- @Override
- protected Bitmap doInBackground(BitmapWorkerOptions... params) {
-
- return retrieveBitmap(params[0]);
- }
-
- protected Bitmap retrieveBitmap(BitmapWorkerOptions workerOptions) {
- try {
- if (workerOptions.getIconResource() != null) {
- return getBitmapFromResource(workerOptions.getContext(),
- workerOptions.getIconResource(),
- workerOptions);
- } else if (workerOptions.getResourceUri() != null) {
- if (UriUtils.isAndroidResourceUri(workerOptions.getResourceUri())
- || UriUtils.isShortcutIconResourceUri(workerOptions.getResourceUri())) {
- // Make an icon resource from this.
- return getBitmapFromResource(workerOptions.getContext(),
- UriUtils.getIconResource(workerOptions.getResourceUri()),
- workerOptions);
- } else if (UriUtils.isWebUri(workerOptions.getResourceUri())) {
- return getBitmapFromHttp(workerOptions);
- } else if (UriUtils.isContentUri(workerOptions.getResourceUri())) {
- return getBitmapFromContent(workerOptions);
- } else if (UriUtils.isAccountImageUri(workerOptions.getResourceUri())) {
- return getAccountImage(workerOptions);
- } else {
- Log.e(TAG, "Error loading bitmap - unknown resource URI! "
- + workerOptions.getResourceUri());
- }
- } else {
- Log.e(TAG, "Error loading bitmap - no source!");
- }
- } catch (IOException e) {
- Log.e(TAG, "Error loading url " + workerOptions.getResourceUri(), e);
- return null;
- } catch (RuntimeException e) {
- Log.e(TAG, "Critical Error loading url " + workerOptions.getResourceUri(), e);
- return null;
- }
-
- return null;
- }
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- if (mImageView != null) {
- final ImageView imageView = mImageView.get();
- if (imageView != null) {
- imageView.setImageBitmap(bitmap);
- }
- }
- }
-
- private Bitmap getBitmapFromResource(Context context, ShortcutIconResource iconResource,
- BitmapWorkerOptions outputOptions) throws IOException {
- if (DEBUG) {
- Log.d(TAG, "Loading " + iconResource.toString());
- }
- try {
- Object drawable = loadDrawable(context, iconResource);
- if (drawable instanceof InputStream) {
- // Most of these are bitmaps, so resize properly.
- return decodeBitmap((InputStream) drawable, outputOptions);
- } else if (drawable instanceof Drawable){
- return createIconBitmap((Drawable) drawable, outputOptions);
- } else {
- Log.w(TAG, "getBitmapFromResource failed, unrecognized resource: " + drawable);
- return null;
- }
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Could not load package: " + iconResource.packageName + "! NameNotFound");
- return null;
- } catch (NotFoundException e) {
- Log.w(TAG, "Could not load resource: " + iconResource.resourceName + "! NotFound");
- return null;
- }
- }
-
- public final boolean isScaled() {
- return mScaled;
- }
-
- private Bitmap decodeBitmap(InputStream in, BitmapWorkerOptions options)
- throws IOException {
- CachedInputStream bufferedStream = null;
- BitmapFactory.Options bitmapOptions = null;
- try {
- bufferedStream = new CachedInputStream(in);
- // Let the bufferedStream be able to mark unlimited bytes up to full stream length.
- // The value that BitmapFactory uses (1024) is too small for detecting bounds
- bufferedStream.setOverrideMarkLimit(Integer.MAX_VALUE);
- bitmapOptions = new BitmapFactory.Options();
- bitmapOptions.inJustDecodeBounds = true;
- if (options.getBitmapConfig() != null) {
- bitmapOptions.inPreferredConfig = options.getBitmapConfig();
- }
- bitmapOptions.inTempStorage = ByteArrayPool.get16KBPool().allocateChunk();
- bufferedStream.mark(Integer.MAX_VALUE);
- BitmapFactory.decodeStream(bufferedStream, null, bitmapOptions);
-
- float heightScale = (float) bitmapOptions.outHeight / options.getHeight();
- float widthScale = (float) bitmapOptions.outWidth / options.getWidth();
- // We take the smaller value because we will crop the result later.
- float scale = heightScale < widthScale ? heightScale : widthScale;
-
- bitmapOptions.inJustDecodeBounds = false;
- if (scale >= 4) {
- // Sampling looks really, really bad. So sample part way and then smooth
- // the result with bilinear interpolation.
- bitmapOptions.inSampleSize = (int) scale / 2;
- }
- // Reset buffer to original position and disable the overrideMarkLimit
- bufferedStream.reset();
- bufferedStream.setOverrideMarkLimit(0);
-
- Bitmap bitmap = BitmapFactory.decodeStream(bufferedStream, null, bitmapOptions);
- // We need to check isCancelled() and throw away the result if we are cancelled because
- // if we're loading over HTTP, canceling an AsyncTask causes the HTTP library to throw
- // an exception, which the bitmap library then eats and returns a partially decoded
- // bitmap. This behavior no longer will happen in lmp-mr1.
- if (bitmap == null || isCancelled()) {
- return null;
- }
-
- Bitmap result = bitmap;
- if (options.getWidth() < bitmap.getWidth()
- || options.getHeight() < bitmap.getHeight()) {
- result = BitmapUtils.scaleBitmap(bitmap, options.getWidth(), options.getHeight());
- mScaled = true;
- }
-
- if (result != bitmap) {
- bitmap.recycle();
- }
- return result;
-
- } finally {
- if (bitmapOptions != null) {
- ByteArrayPool.get16KBPool().releaseChunk(bitmapOptions.inTempStorage);
- }
- if (bufferedStream != null) {
- bufferedStream.close();
- }
- }
- }
-
- private Bitmap getBitmapFromHttp(BitmapWorkerOptions options) throws IOException {
- URL url = new URL(options.getResourceUri().toString());
- if (DEBUG) {
- Log.d(TAG, "Loading " + url);
- }
- HttpURLConnection connection = null;
- try {
- connection = (HttpURLConnection) url.openConnection();
- connection.setConnectTimeout(SOCKET_TIMEOUT);
- connection.setReadTimeout(READ_TIMEOUT);
- InputStream in = new BufferedInputStream(connection.getInputStream());
- return decodeBitmap(in, options);
- } finally {
- if (DEBUG) {
- Log.d(TAG, "loading done "+url);
- }
- if (connection != null) {
- connection.disconnect();
- }
- }
- }
-
- private Bitmap getBitmapFromContent(BitmapWorkerOptions options) throws IOException {
- InputStream bitmapStream =
- options.getContext().getContentResolver().openInputStream(options.getResourceUri());
- if (bitmapStream != null) {
- return decodeBitmap(bitmapStream, options);
- } else {
- Log.w(TAG, "Content provider returned a null InputStream when trying to " +
- "open resource.");
- return null;
- }
- }
-
- /**
- * load drawable for non-bitmap resource or InputStream for bitmap resource without
- * caching Bitmap in Resources. So that caller can maintain a different caching
- * storage with less memory used.
- * @return either {@link Drawable} for xml and ColorDrawable <br>
- * or {@link InputStream} for Bitmap resource
- */
- private static Object loadDrawable(Context context, ShortcutIconResource r)
- throws NameNotFoundException {
- Resources resources = context.getPackageManager()
- .getResourcesForApplication(r.packageName);
- if (resources == null) {
- return null;
- }
- resources.updateConfiguration(context.getResources().getConfiguration(),
- context.getResources().getDisplayMetrics());
- final int id = resources.getIdentifier(r.resourceName, null, null);
- if (id == 0) {
- Log.e(TAG, "Couldn't get resource " + r.resourceName + " in resources of "
- + r.packageName);
- return null;
- }
- TypedValue value = new TypedValue();
- resources.getValue(id, value, true);
- if ((value.type == TypedValue.TYPE_STRING && value.string.toString().endsWith(".xml")) || (
- value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT)) {
- return resources.getDrawable(id);
- }
- return resources.openRawResource(id, value);
- }
-
- private static Bitmap createIconBitmap(Drawable drawable, BitmapWorkerOptions workerOptions) {
- // Some drawables have an intrinsic width and height of -1. In that case
- // size it to our output.
- int width = drawable.getIntrinsicWidth();
- if (width == -1) {
- width = workerOptions.getWidth();
- }
- int height = drawable.getIntrinsicHeight();
- if (height == -1) {
- height = workerOptions.getHeight();
- }
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
- drawable.draw(canvas);
- return bitmap;
- }
-
- public static Drawable getDrawable(Context context, ShortcutIconResource iconResource)
- throws NameNotFoundException {
- Resources resources =
- context.getPackageManager().getResourcesForApplication(iconResource.packageName);
- if (resources == null) {
- return null;
- }
- resources.updateConfiguration(context.getResources().getConfiguration(),
- context.getResources().getDisplayMetrics());
- int id = resources.getIdentifier(iconResource.resourceName, null, null);
- if (id == 0) {
- throw new NameNotFoundException();
- }
-
- return resources.getDrawable(id);
- }
-
- @SuppressWarnings("deprecation")
- private Bitmap getAccountImage(BitmapWorkerOptions options) {
- String accountName = UriUtils.getAccountName(options.getResourceUri());
- Context context = options.getContext();
-
- if (accountName != null && context != null) {
- Account thisAccount = null;
- for (Account account : AccountManager.get(context).
- getAccountsByType(GOOGLE_ACCOUNT_TYPE)) {
- if (account.name.equals(accountName)) {
- thisAccount = account;
- break;
- }
- }
- if (thisAccount != null) {
- String picUriString = AccountImageHelper.getAccountPictureUri(context, thisAccount);
- if (picUriString != null) {
- BitmapWorkerOptions.Builder optionBuilder =
- new BitmapWorkerOptions.Builder(context)
- .width(options.getWidth())
- .height(options.getHeight())
- .cacheFlag(options.getCacheFlag())
- .bitmapConfig(options.getBitmapConfig())
- .resource(Uri.parse(picUriString));
- return BitmapDownloader.getInstance(context)
- .loadBitmapBlocking(optionBuilder.build());
- }
- return null;
- }
- }
- return null;
- }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/ByteArrayPool.java b/car-apps-common/src/com/android/car/apps/common/ByteArrayPool.java
deleted file mode 100644
index 676b7dc..0000000
--- a/car-apps-common/src/com/android/car/apps/common/ByteArrayPool.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public final class ByteArrayPool {
-
- public static final int CHUNK16K = 16 * 1024;
- public static final int DEFAULT_MAX_NUM = 8;
-
- private final static ByteArrayPool sChunk16K = new ByteArrayPool(CHUNK16K, DEFAULT_MAX_NUM);
-
- private final ArrayList<byte[]> mCachedBuf;
- private final int mChunkSize;
- private final int mMaxNum;
-
- private ByteArrayPool(int chunkSize, int maxNum) {
- mChunkSize = chunkSize;
- mMaxNum = maxNum;
- mCachedBuf = new ArrayList<byte[]>(mMaxNum);
- }
-
- /**
- * get singleton of 16KB byte[] pool
- */
- public static ByteArrayPool get16KBPool() {
- return sChunk16K;
- }
-
- public byte[] allocateChunk() {
- synchronized (mCachedBuf) {
- int size = mCachedBuf.size();
- if (size > 0) {
- return mCachedBuf.remove(size - 1);
- }
- return new byte[mChunkSize];
- }
- }
-
- public void clear() {
- synchronized (mCachedBuf) {
- mCachedBuf.clear();
- }
- }
-
- public void releaseChunk(byte[] buf) {
- if (buf == null || buf.length != mChunkSize) {
- return;
- }
- synchronized (mCachedBuf) {
- if (mCachedBuf.size() < mMaxNum) {
- mCachedBuf.add(buf);
- }
- }
- }
-
- public void releaseChunks(List<byte[]> bufs) {
- synchronized (mCachedBuf) {
- for (int i = 0, c = bufs.size(); i < c; i++) {
- if (mCachedBuf.size() == mMaxNum) {
- break;
- }
- byte[] buf = bufs.get(i);
- if (buf != null && buf.length == mChunkSize) {
- mCachedBuf.add(bufs.get(i));
- }
- }
- }
- }
-
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/CachedInputStream.java b/car-apps-common/src/com/android/car/apps/common/CachedInputStream.java
deleted file mode 100644
index f365424..0000000
--- a/car-apps-common/src/com/android/car/apps/common/CachedInputStream.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A replacement of BufferedInputStream (no multiple thread): <p>
- * - use list of byte array (chunks) instead of keep growing a single byte array (more efficent)
- * <br>
- * - support overriding the markLimit passed in mark() call (The value that BitmapFactory
- * uses 1024 is too small for detecting bitmap bounds and reset()) <br>
- * @hide
- */
-public class CachedInputStream extends FilterInputStream {
-
- private static final int CHUNK_SIZE = ByteArrayPool.CHUNK16K;
-
- private ArrayList<byte[]> mBufs = new ArrayList<byte[]>();
- private int mPos = 0; // current read position inside the chunk buffers
- private int mCount = 0; // total validate bytes in chunk buffers
- private int mMarkPos = -1; // marked read position in chunk buffers
- private int mOverrideMarkLimit; // to override readlimit of mark() call
- private int mMarkLimit; // effective marklimit
- private byte[] tmp = new byte[1]; // tmp buffer used in read()
-
- public CachedInputStream(InputStream in) {
- super(in);
- }
-
- @Override
- public boolean markSupported() {
- return true;
- }
-
- /**
- * set the value that will override small readlimit passed in mark() call.
- */
- public void setOverrideMarkLimit(int overrideMarkLimit) {
- mOverrideMarkLimit = overrideMarkLimit;
- }
-
- public int getOverrideMarkLimit() {
- return mOverrideMarkLimit;
- }
-
- @Override
- public void mark(int readlimit) {
- readlimit = readlimit < mOverrideMarkLimit ? mOverrideMarkLimit : readlimit;
- if (mMarkPos >= 0) {
- // for replacing existing mark(), discard anything before mPos
- // and move mMarkPos to mPos
- int chunks = mPos / CHUNK_SIZE;
- if (chunks > 0) {
- // trim the header buffers
- int removedBytes = chunks * CHUNK_SIZE;
- List<byte[]> subList = mBufs.subList(0, chunks);
- releaseChunks(subList);
- subList.clear();
- mPos = mPos - removedBytes;
- mCount = mCount - removedBytes;
- }
- }
- mMarkPos = mPos;
- mMarkLimit = readlimit;
- }
-
- @Override
- public void reset() throws IOException {
- if (mMarkPos < 0) {
- throw new IOException("mark has been invalidated");
- }
- mPos = mMarkPos;
- }
-
- @Override
- public int read() throws IOException {
- // TODO, not efficient, but the function is not called by BitmapFactory
- int r = read(tmp, 0, 1);
- if (r <= 0) {
- return -1;
- }
- return tmp[0] & 0xFF;
- }
-
- @Override
- public void close() throws IOException {
- if (in!=null) {
- in.close();
- in = null;
- }
- releaseChunks(mBufs);
- }
-
- private static void releaseChunks(List<byte[]> bufs) {
- ByteArrayPool.get16KBPool().releaseChunks(bufs);
- }
-
- private byte[] allocateChunk() {
- return ByteArrayPool.get16KBPool().allocateChunk();
- }
-
- private boolean invalidate() {
- if (mCount - mMarkPos > mMarkLimit) {
- mMarkPos = -1;
- mCount = 0;
- mPos = 0;
- releaseChunks(mBufs);
- mBufs.clear();
- return true;
- }
- return false;
- }
-
- @Override
- public int read(byte[] buffer, int offset, int count) throws IOException {
- if (in == null) {
- throw streamClosed();
- }
- if (mMarkPos == -1) {
- int reads = in.read(buffer, offset, count);
- return reads;
- }
- if (count == 0) {
- return 0;
- }
- int copied = copyMarkedBuffer(buffer, offset, count);
- count -= copied;
- offset += copied;
- int totalReads = copied;
- while (count > 0) {
- if (mPos == mBufs.size() * CHUNK_SIZE) {
- mBufs.add(allocateChunk());
- }
- int currentBuf = mPos / CHUNK_SIZE;
- int indexInBuf = mPos - currentBuf * CHUNK_SIZE;
- byte[] buf = mBufs.get(currentBuf);
- int end = (currentBuf + 1) * CHUNK_SIZE;
- int leftInBuffer = end - mPos;
- int toRead = count > leftInBuffer ? leftInBuffer : count;
- int reads = in.read(buf, indexInBuf, toRead);
- if (reads > 0) {
- System.arraycopy(buf, indexInBuf, buffer, offset, reads);
- mPos += reads;
- mCount += reads;
- totalReads += reads;
- offset += reads;
- count -= reads;
- if (invalidate()) {
- reads = in.read(buffer, offset, count);
- if (reads >0 ) {
- totalReads += reads;
- }
- break;
- }
- } else {
- break;
- }
- }
- if (totalReads == 0) {
- return -1;
- }
- return totalReads;
- }
-
- private int copyMarkedBuffer(byte[] buffer, int offset, int read) {
- int totalRead = 0;
- while (read > 0 && mPos < mCount) {
- int currentBuf = mPos / CHUNK_SIZE;
- int indexInBuf = mPos - currentBuf * CHUNK_SIZE;
- byte[] buf = mBufs.get(currentBuf);
- int end = (currentBuf + 1) * CHUNK_SIZE;
- if (end > mCount) {
- end = mCount;
- }
- int leftInBuffer = end - mPos;
- int toRead = read > leftInBuffer ? leftInBuffer : read;
- System.arraycopy(buf, indexInBuf, buffer, offset, toRead);
- offset += toRead;
- read -= toRead;
- totalRead += toRead;
- mPos += toRead;
- }
- return totalRead;
- }
-
- @Override
- public int available() throws IOException {
- if (in == null) {
- throw streamClosed();
- }
- return mCount - mPos + in.available();
- }
-
- @Override
- public long skip(long byteCount) throws IOException {
- if (in == null) {
- throw streamClosed();
- }
- if (mMarkPos <0) {
- return in.skip(byteCount);
- }
- long totalSkip = 0;
- totalSkip = mCount - mPos;
- if (totalSkip > byteCount) {
- totalSkip = byteCount;
- }
- mPos += totalSkip;
- byteCount -= totalSkip;
- while (byteCount > 0) {
- if (mPos == mBufs.size() * CHUNK_SIZE) {
- mBufs.add(allocateChunk());
- }
- int currentBuf = mPos / CHUNK_SIZE;
- int indexInBuf = mPos - currentBuf * CHUNK_SIZE;
- byte[] buf = mBufs.get(currentBuf);
- int end = (currentBuf + 1) * CHUNK_SIZE;
- int leftInBuffer = end - mPos;
- int toRead = (int) (byteCount > leftInBuffer ? leftInBuffer : byteCount);
- int reads = in.read(buf, indexInBuf, toRead);
- if (reads > 0) {
- mPos += reads;
- mCount += reads;
- byteCount -= reads;
- totalSkip += reads;
- if (invalidate()) {
- if (byteCount > 0) {
- totalSkip += in.skip(byteCount);
- }
- break;
- }
- } else {
- break;
- }
- }
- return totalSkip;
- }
-
- private static IOException streamClosed() {
- return new IOException("stream closed");
- }
-
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/DrawableDownloader.java b/car-apps-common/src/com/android/car/apps/common/DrawableDownloader.java
deleted file mode 100644
index a13fb18..0000000
--- a/car-apps-common/src/com/android/car/apps/common/DrawableDownloader.java
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.Intent.ShortcutIconResource;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-import android.util.LruCache;
-import android.widget.ImageView;
-
-import java.lang.ref.SoftReference;
-import java.util.ArrayList;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
-/**
- * Downloader class which loads a resource URI into an image view or triggers a callback
- * <p>
- * This class adds a LRU cache over DrawableLoader.
- * <p>
- * Calling getBitmap() or loadBitmap() will return a RefcountBitmapDrawable with initial refcount =
- * 2 by the cache table and by caller. You must call releaseRef() when you are done with the resource.
- * The most common way is using RefcountImageView, and releaseRef() for you. Once both RefcountImageView
- * and LRUCache removes the refcount, the underlying bitmap will be used for decoding new bitmap.
- * <p>
- * If the URI does not point to a bitmap (e.g. point to a drawable xml, we won't cache it and we
- * directly return a regular Drawable).
- */
-public class DrawableDownloader {
-
- private static final String TAG = "DrawableDownloader";
-
- private static final boolean DEBUG = false;
-
- private static final int CORE_POOL_SIZE = 5;
-
- // thread pool for loading non android-resources such as http, content
- private static final Executor BITMAP_DOWNLOADER_THREAD_POOL_EXECUTOR =
- Executors.newFixedThreadPool(CORE_POOL_SIZE);
-
- private static final int CORE_RESOURCE_POOL_SIZE = 1;
-
- // thread pool for loading android resources, we use separate thread pool so
- // that network loading will not block local android icons
- private static final Executor BITMAP_RESOURCE_DOWNLOADER_THREAD_POOL_EXECUTOR =
- Executors.newFixedThreadPool(CORE_RESOURCE_POOL_SIZE);
-
- // 1/4 of max memory is used for bitmap mem cache
- private static final int MEM_TO_CACHE = 4;
-
- // hard limit for bitmap mem cache in MB
- private static final int CACHE_HARD_LIMIT = 32;
-
- /**
- * bitmap cache item structure saved in LruCache
- */
- private static class BitmapItem {
- int mOriginalWidth;
- int mOriginalHeight;
- ArrayList<BitmapDrawable> mBitmaps = new ArrayList<BitmapDrawable>(3);
- int mByteCount;
- public BitmapItem(int originalWidth, int originalHeight) {
- mOriginalWidth = originalWidth;
- mOriginalHeight = originalHeight;
- }
-
- // get bitmap from the list
- BitmapDrawable findDrawable(BitmapWorkerOptions options) {
- for (int i = 0, c = mBitmaps.size(); i < c; i++) {
- BitmapDrawable d = mBitmaps.get(i);
- // use drawable with original size
- if (d.getIntrinsicWidth() == mOriginalWidth
- && d.getIntrinsicHeight() == mOriginalHeight) {
- return d;
- }
- // if specified width/height in options and is smaller than
- // cached one, we can use this cached drawable
- if (options.getHeight() != BitmapWorkerOptions.MAX_IMAGE_DIMENSION_PX) {
- if (options.getHeight() <= d.getIntrinsicHeight()) {
- return d;
- }
- } else if (options.getWidth() != BitmapWorkerOptions.MAX_IMAGE_DIMENSION_PX) {
- if (options.getWidth() <= d.getIntrinsicWidth()) {
- return d;
- }
- }
- }
- return null;
- }
-
- @SuppressWarnings("unused")
- BitmapDrawable findLargestDrawable(BitmapWorkerOptions options) {
- return mBitmaps.size() == 0 ? null : mBitmaps.get(0);
- }
-
- void addDrawable(BitmapDrawable d) {
- int i = 0, c = mBitmaps.size();
- for (; i < c; i++) {
- BitmapDrawable drawable = mBitmaps.get(i);
- if (drawable.getIntrinsicHeight() < d.getIntrinsicHeight()) {
- break;
- }
- }
- mBitmaps.add(i, d);
- mByteCount += RecycleBitmapPool.getSize(d.getBitmap());
- }
-
- void clear() {
- for (int i = 0, c = mBitmaps.size(); i < c; i++) {
- BitmapDrawable d = mBitmaps.get(i);
- if (d instanceof RefcountBitmapDrawable) {
- ((RefcountBitmapDrawable) d).getRefcountObject().releaseRef();
- }
- }
- mBitmaps.clear();
- mByteCount = 0;
- }
- }
-
- public static abstract class BitmapCallback {
- SoftReference<DrawableLoader> mTask;
-
- public abstract void onBitmapRetrieved(Drawable bitmap);
- }
-
- private Context mContext;
- private LruCache<String, BitmapItem> mMemoryCache;
- private RecycleBitmapPool mRecycledBitmaps;
-
- private static DrawableDownloader sBitmapDownloader;
-
- private static final Object sBitmapDownloaderLock = new Object();
-
- /**
- * get the singleton BitmapDownloader for the application
- */
- public final static DrawableDownloader getInstance(Context context) {
- if (sBitmapDownloader == null) {
- synchronized(sBitmapDownloaderLock) {
- if (sBitmapDownloader == null) {
- sBitmapDownloader = new DrawableDownloader(context);
- }
- }
- }
- return sBitmapDownloader;
- }
-
- private static String getBucketKey(String baseKey, Bitmap.Config bitmapConfig) {
- return new StringBuilder(baseKey.length() + 16).append(baseKey)
- .append(":").append(bitmapConfig == null ? "" : bitmapConfig.ordinal())
- .toString();
- }
-
- public static Drawable getDrawable(Context context, ShortcutIconResource iconResource)
- throws NameNotFoundException {
- return DrawableLoader.getDrawable(context, iconResource);
- }
-
- private DrawableDownloader(Context context) {
- mContext = context;
- int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
- .getMemoryClass();
- memClass = memClass / MEM_TO_CACHE;
- if (memClass > CACHE_HARD_LIMIT) {
- memClass = CACHE_HARD_LIMIT;
- }
- int cacheSize = 1024 * 1024 * memClass;
- mMemoryCache = new LruCache<String, BitmapItem>(cacheSize) {
- @Override
- protected int sizeOf(String key, BitmapItem bitmap) {
- return bitmap.mByteCount;
- }
- @Override
- protected void entryRemoved(
- boolean evicted, String key, BitmapItem oldValue, BitmapItem newValue) {
- if (evicted) {
- oldValue.clear();
- }
- }
- };
- mRecycledBitmaps = new RecycleBitmapPool();
- }
-
- /**
- * trim memory cache to 0~1 * maxSize
- */
- public void trimTo(float amount) {
- if (amount == 0f) {
- mMemoryCache.evictAll();
- } else {
- mMemoryCache.trimToSize((int) (amount * mMemoryCache.maxSize()));
- }
- }
-
- /**
- * load bitmap in current thread, will *block* current thread.
- * @deprecated
- */
- @Deprecated
- public final Drawable loadBitmapBlocking(BitmapWorkerOptions options) {
- final boolean hasAccountImageUri = UriUtils.isAccountImageUri(options.getResourceUri());
- Drawable bitmap = null;
- if (hasAccountImageUri) {
- AccountImageChangeObserver.getInstance().registerChangeUriIfPresent(options);
- } else {
- bitmap = getBitmapFromMemCache(options);
- }
-
- if (bitmap == null) {
- DrawableLoader task = new DrawableLoader(null, mRecycledBitmaps) {
- @Override
- protected Drawable doInBackground(BitmapWorkerOptions... params) {
- final Drawable bitmap = super.doInBackground(params);
- if (bitmap != null && !hasAccountImageUri) {
- addBitmapToMemoryCache(params[0], bitmap, this);
- }
- return bitmap;
- }
- };
- return task.doInBackground(options);
- }
- return bitmap;
- }
-
- /**
- * Loads the bitmap into the image view.
- */
- public void loadBitmap(BitmapWorkerOptions options, final ImageView imageView) {
- cancelDownload(imageView);
- final boolean hasAccountImageUri = UriUtils.isAccountImageUri(options.getResourceUri());
- Drawable bitmap = null;
- if (hasAccountImageUri) {
- AccountImageChangeObserver.getInstance().registerChangeUriIfPresent(options);
- } else {
- bitmap = getBitmapFromMemCache(options);
- }
-
- if (bitmap != null) {
- imageView.setImageDrawable(bitmap);
- } else {
- DrawableLoader task = new DrawableLoader(imageView, mRecycledBitmaps) {
- @Override
- protected Drawable doInBackground(BitmapWorkerOptions... params) {
- Drawable bitmap = super.doInBackground(params);
- if (bitmap != null && !hasAccountImageUri) {
- addBitmapToMemoryCache(params[0], bitmap, this);
- }
- return bitmap;
- }
- };
- imageView.setTag(R.id.imageDownloadTask, new SoftReference<DrawableLoader>(task));
- scheduleTask(task, options);
- }
- }
-
- /**
- * Loads the bitmap.
- * <p>
- * This will be sent back to the callback object.
- */
- public void getBitmap(BitmapWorkerOptions options, final BitmapCallback callback) {
- cancelDownload(callback);
- final boolean hasAccountImageUri = UriUtils.isAccountImageUri(options.getResourceUri());
- final Drawable bitmap = hasAccountImageUri ? null : getBitmapFromMemCache(options);
- if (hasAccountImageUri) {
- AccountImageChangeObserver.getInstance().registerChangeUriIfPresent(options);
- }
-
- if (bitmap != null) {
- callback.onBitmapRetrieved(bitmap);
- return;
- }
- DrawableLoader task = new DrawableLoader(null, mRecycledBitmaps) {
- @Override
- protected Drawable doInBackground(BitmapWorkerOptions... params) {
- final Drawable bitmap = super.doInBackground(params);
- if (bitmap != null && !hasAccountImageUri) {
- addBitmapToMemoryCache(params[0], bitmap, this);
- }
- return bitmap;
- }
-
- @Override
- protected void onPostExecute(Drawable bitmap) {
- callback.onBitmapRetrieved(bitmap);
- }
- };
- callback.mTask = new SoftReference<DrawableLoader>(task);
- scheduleTask(task, options);
- }
-
- private static void scheduleTask(DrawableLoader task, BitmapWorkerOptions options) {
- if (options.isFromResource()) {
- task.executeOnExecutor(BITMAP_RESOURCE_DOWNLOADER_THREAD_POOL_EXECUTOR, options);
- } else {
- task.executeOnExecutor(BITMAP_DOWNLOADER_THREAD_POOL_EXECUTOR, options);
- }
- }
-
- /**
- * Cancel download<p>
- * @param key {@link BitmapCallback} or {@link ImageView}
- */
- @SuppressWarnings("unchecked")
- public boolean cancelDownload(Object key) {
- DrawableLoader task = null;
- if (key instanceof ImageView) {
- ImageView imageView = (ImageView)key;
- SoftReference<DrawableLoader> softReference =
- (SoftReference<DrawableLoader>) imageView.getTag(R.id.imageDownloadTask);
- if (softReference != null) {
- task = softReference.get();
- softReference.clear();
- }
- } else if (key instanceof BitmapCallback) {
- BitmapCallback callback = (BitmapCallback)key;
- if (callback.mTask != null) {
- task = callback.mTask.get();
- callback.mTask = null;
- }
- }
- if (task != null) {
- return task.cancel(true);
- }
- return false;
- }
-
- private void addBitmapToMemoryCache(BitmapWorkerOptions key, Drawable bitmap,
- DrawableLoader loader) {
- if (!key.isMemCacheEnabled()) {
- return;
- }
- if (!(bitmap instanceof BitmapDrawable)) {
- return;
- }
- String bucketKey = getBucketKey(key.getCacheKey(), key.getBitmapConfig());
- BitmapItem bitmapItem = mMemoryCache.get(bucketKey);
- if (DEBUG) {
- Log.d(TAG, "add cache "+bucketKey);
- }
- if (bitmapItem != null) {
- // remove and re-add to update size
- mMemoryCache.remove(bucketKey);
- } else {
- bitmapItem = new BitmapItem(loader.getOriginalWidth(), loader.getOriginalHeight());
- }
- if (bitmap instanceof RefcountBitmapDrawable) {
- RefcountBitmapDrawable refcountDrawable = (RefcountBitmapDrawable) bitmap;
- refcountDrawable.getRefcountObject().addRef();
- }
- bitmapItem.addDrawable((BitmapDrawable) bitmap);
- mMemoryCache.put(bucketKey, bitmapItem);
- }
-
- private Drawable getBitmapFromMemCache(BitmapWorkerOptions key) {
- String bucketKey =
- getBucketKey(key.getCacheKey(), key.getBitmapConfig());
- BitmapItem item = mMemoryCache.get(bucketKey);
- if (item != null) {
- return createRefCopy(item.findDrawable(key));
- }
- return null;
- }
-
- public BitmapDrawable getLargestBitmapFromMemCache(BitmapWorkerOptions key) {
- String bucketKey =
- getBucketKey(key.getCacheKey(), key.getBitmapConfig());
- BitmapItem item = mMemoryCache.get(bucketKey);
- if (item != null) {
- return (BitmapDrawable) createRefCopy(item.findLargestDrawable(key));
- }
- return null;
- }
-
- private Drawable createRefCopy(Drawable d) {
- if (d != null) {
- if (d instanceof RefcountBitmapDrawable) {
- RefcountBitmapDrawable refcountDrawable = (RefcountBitmapDrawable) d;
- refcountDrawable.getRefcountObject().addRef();
- d = new RefcountBitmapDrawable(mContext.getResources(),
- refcountDrawable);
- }
- return d;
- }
- return null;
- }
-
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/DrawableLoader.java b/car-apps-common/src/com/android/car/apps/common/DrawableLoader.java
deleted file mode 100644
index a9379f0..0000000
--- a/car-apps-common/src/com/android/car/apps/common/DrawableLoader.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.Context;
-import android.content.Intent.ShortcutIconResource;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.util.Log;
-import android.util.TypedValue;
-import android.widget.ImageView;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.net.URLConnection;
-
-/**
- * AsyncTask which loads a bitmap.
- * <p>
- * The source of this can be another package (via a resource), a URI (content provider), or
- * a file path.
- * @see BitmapWorkerOptions
- * @hide
- */
-class DrawableLoader extends AsyncTask<BitmapWorkerOptions, Void, Drawable> {
-
- private static final String TAG = "DrawableLoader";
- private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
-
- private static final boolean DEBUG = false;
-
- private static final int SOCKET_TIMEOUT = 10000;
- private static final int READ_TIMEOUT = 10000;
-
- private final WeakReference<ImageView> mImageView;
- private int mOriginalWidth;
- private int mOriginalHeight;
- private final RecycleBitmapPool mRecycledBitmaps;
-
- private final RefcountObject.RefcountListener mRefcountListener =
- new RefcountObject.RefcountListener() {
- @Override
- @SuppressWarnings("rawtypes")
- public void onRefcountZero(RefcountObject object) {
- mRecycledBitmaps.addRecycledBitmap((Bitmap) object.getObject());
- }
- };
-
-
- DrawableLoader(ImageView imageView, RecycleBitmapPool recycledBitmapPool) {
- mImageView = new WeakReference<ImageView>(imageView);
- mRecycledBitmaps = recycledBitmapPool;
- }
-
- public int getOriginalWidth() {
- return mOriginalWidth;
- }
-
- public int getOriginalHeight() {
- return mOriginalHeight;
- }
-
- @Override
- protected Drawable doInBackground(BitmapWorkerOptions... params) {
-
- return retrieveDrawable(params[0]);
- }
-
- protected Drawable retrieveDrawable(BitmapWorkerOptions workerOptions) {
- try {
- if (workerOptions.getIconResource() != null) {
- return getBitmapFromResource(workerOptions.getIconResource(), workerOptions);
- } else if (workerOptions.getResourceUri() != null) {
- if (UriUtils.isAndroidResourceUri(workerOptions.getResourceUri())
- || UriUtils.isShortcutIconResourceUri(workerOptions.getResourceUri())) {
- // Make an icon resource from this.
- return getBitmapFromResource(
- UriUtils.getIconResource(workerOptions.getResourceUri()),
- workerOptions);
- } else if (UriUtils.isWebUri(workerOptions.getResourceUri())) {
- return getBitmapFromHttp(workerOptions);
- } else if (UriUtils.isContentUri(workerOptions.getResourceUri())) {
- return getBitmapFromContent(workerOptions);
- } else if (UriUtils.isAccountImageUri(workerOptions.getResourceUri())) {
- return getAccountImage(workerOptions);
- } else {
- Log.e(TAG, "Error loading bitmap - unknown resource URI! "
- + workerOptions.getResourceUri());
- }
- } else {
- Log.e(TAG, "Error loading bitmap - no source!");
- }
- } catch (IOException e) {
- Log.e(TAG, "Error loading url " + workerOptions.getResourceUri(), e);
- return null;
- } catch (RuntimeException e) {
- Log.e(TAG, "Critical Error loading url " + workerOptions.getResourceUri(), e);
- return null;
- }
-
- return null;
- }
-
- @Override
- protected void onPostExecute(Drawable bitmap) {
- if (mImageView != null) {
- final ImageView imageView = mImageView.get();
- if (imageView != null) {
- imageView.setImageDrawable(bitmap);
- }
- }
- }
-
- @Override
- protected void onCancelled(Drawable result) {
- if (result instanceof RefcountBitmapDrawable) {
- // Remove the extra refcount created by us, DrawableDownloader LruCache
- // still holds one to the bitmap
- RefcountBitmapDrawable d = (RefcountBitmapDrawable) result;
- d.getRefcountObject().releaseRef();
- }
- }
-
- private Drawable getBitmapFromResource(ShortcutIconResource iconResource,
- BitmapWorkerOptions outputOptions) throws IOException {
- if (DEBUG) {
- Log.d(TAG, "Loading " + iconResource.toString());
- }
- try {
- Object drawable = loadDrawable(outputOptions.getContext(), iconResource);
- if (drawable instanceof InputStream) {
- // Most of these are bitmaps, so resize properly.
- return decodeBitmap((InputStream)drawable, outputOptions);
- } else if (drawable instanceof Drawable){
- Drawable d = (Drawable) drawable;
- mOriginalWidth = d.getIntrinsicWidth();
- mOriginalHeight = d.getIntrinsicHeight();
- return d;
- } else {
- Log.w(TAG, "getBitmapFromResource failed, unrecognized resource: " + drawable);
- return null;
- }
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Could not load package: " + iconResource.packageName + "! NameNotFound");
- return null;
- } catch (NotFoundException e) {
- Log.w(TAG, "Could not load resource: " + iconResource.resourceName + "! NotFound");
- return null;
- }
- }
-
- private Drawable decodeBitmap(InputStream in, BitmapWorkerOptions options)
- throws IOException {
- CachedInputStream bufferedStream = null;
- BitmapFactory.Options bitmapOptions = null;
- try {
- bufferedStream = new CachedInputStream(in);
- // Let the bufferedStream be able to mark unlimited bytes up to full stream length.
- // The value that BitmapFactory uses (1024) is too small for detecting bounds
- bufferedStream.setOverrideMarkLimit(Integer.MAX_VALUE);
- bitmapOptions = new BitmapFactory.Options();
- bitmapOptions.inJustDecodeBounds = true;
- if (options.getBitmapConfig() != null) {
- bitmapOptions.inPreferredConfig = options.getBitmapConfig();
- }
- bitmapOptions.inTempStorage = ByteArrayPool.get16KBPool().allocateChunk();
- bufferedStream.mark(Integer.MAX_VALUE);
- BitmapFactory.decodeStream(bufferedStream, null, bitmapOptions);
-
- mOriginalWidth = bitmapOptions.outWidth;
- mOriginalHeight = bitmapOptions.outHeight;
- int heightScale = 1;
- int height = options.getHeight();
- if (height > 0) {
- heightScale = bitmapOptions.outHeight / height;
- }
-
- int widthScale = 1;
- int width = options.getWidth();
- if (width > 0) {
- widthScale = bitmapOptions.outWidth / width;
- }
-
- int scale = heightScale > widthScale ? heightScale : widthScale;
- if (scale <= 1) {
- scale = 1;
- } else {
- int shift = 0;
- do {
- scale >>= 1;
- shift++;
- } while (scale != 0);
- scale = 1 << (shift - 1);
- }
-
- if (DEBUG) {
- Log.d("BitmapWorkerTask", "Source bitmap: (" + bitmapOptions.outWidth + "x"
- + bitmapOptions.outHeight + "). Max size: (" + options.getWidth() + "x"
- + options.getHeight() + "). Chosen scale: " + scale + " -> " + scale);
- }
-
- // Reset buffer to original position and disable the overrideMarkLimit
- bufferedStream.reset();
- bufferedStream.setOverrideMarkLimit(0);
- Bitmap bitmap = null;
- try {
- bitmapOptions.inJustDecodeBounds = false;
- bitmapOptions.inSampleSize = scale;
- bitmapOptions.inMutable = true;
- bitmapOptions.inBitmap = mRecycledBitmaps.getRecycledBitmap(
- mOriginalWidth / scale, mOriginalHeight / scale);
- bitmap = BitmapFactory.decodeStream(bufferedStream, null, bitmapOptions);
- } catch (RuntimeException ex) {
- Log.e(TAG, "RuntimeException" + ex + ", trying decodeStream again");
- bufferedStream.reset();
- bufferedStream.setOverrideMarkLimit(0);
- bitmapOptions.inBitmap = null;
- bitmap = BitmapFactory.decodeStream(bufferedStream, null, bitmapOptions);
- }
- if (bitmap == null) {
- Log.d(TAG, "bitmap was null");
- return null;
- }
- RefcountObject<Bitmap> object = new RefcountObject<Bitmap>(bitmap);
- object.addRef();
- object.setRefcountListener(mRefcountListener);
- RefcountBitmapDrawable d = new RefcountBitmapDrawable(
- options.getContext().getResources(), object);
- return d;
- } finally {
- Log.w(TAG, "couldn't load bitmap, releasing resources");
- if (bitmapOptions != null) {
- ByteArrayPool.get16KBPool().releaseChunk(bitmapOptions.inTempStorage);
- }
- if (bufferedStream != null) {
- bufferedStream.close();
- }
- }
- }
-
- private Drawable getBitmapFromHttp(BitmapWorkerOptions options) throws IOException {
- URL url = new URL(options.getResourceUri().toString());
- if (DEBUG) {
- Log.d(TAG, "Loading " + url);
- }
- try {
- // TODO use volley for better disk cache
- URLConnection connection = url.openConnection();
- connection.setConnectTimeout(SOCKET_TIMEOUT);
- connection.setReadTimeout(READ_TIMEOUT);
- InputStream in = connection.getInputStream();
- return decodeBitmap(in, options);
- } catch (SocketTimeoutException e) {
- Log.e(TAG, "loading " + url + " timed out");
- }
- return null;
- }
-
- private Drawable getBitmapFromContent(BitmapWorkerOptions options)
- throws IOException {
- Uri resourceUri = options.getResourceUri();
- if (resourceUri != null) {
- try {
- InputStream bitmapStream =
- options.getContext().getContentResolver().openInputStream(resourceUri);
-
- if (bitmapStream != null) {
- return decodeBitmap(bitmapStream, options);
- } else {
- Log.w(TAG, "Content provider returned a null InputStream when trying to " +
- "open resource.");
- return null;
- }
- } catch (FileNotFoundException e) {
- Log.e(TAG, "FileNotFoundException during openInputStream for uri: "
- + resourceUri.toString());
- return null;
- }
- } else {
- Log.w(TAG, "Get null resourceUri from BitmapWorkerOptions.");
- return null;
- }
- }
-
- /**
- * load drawable for non-bitmap resource or InputStream for bitmap resource without
- * caching Bitmap in Resources. So that caller can maintain a different caching
- * storage with less memory used.
- * @return either {@link Drawable} for xml and ColorDrawable <br>
- * or {@link InputStream} for Bitmap resource
- */
- private static Object loadDrawable(Context context, ShortcutIconResource r)
- throws NameNotFoundException {
- Resources resources = context.getPackageManager()
- .getResourcesForApplication(r.packageName);
- if (resources == null) {
- return null;
- }
- resources.updateConfiguration(context.getResources().getConfiguration(),
- context.getResources().getDisplayMetrics());
- final int id = resources.getIdentifier(r.resourceName, null, null);
- if (id == 0) {
- Log.e(TAG, "Couldn't get resource " + r.resourceName + " in resources of "
- + r.packageName);
- return null;
- }
- TypedValue value = new TypedValue();
- resources.getValue(id, value, true);
- if ((value.type == TypedValue.TYPE_STRING && value.string.toString().endsWith(".xml")) || (
- value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT)) {
- return resources.getDrawable(id);
- }
- return resources.openRawResource(id, value);
- }
-
- public static Drawable getDrawable(Context context, ShortcutIconResource iconResource)
- throws NameNotFoundException {
- Resources resources =
- context.getPackageManager().getResourcesForApplication(iconResource.packageName);
- resources.updateConfiguration(context.getResources().getConfiguration(),
- context.getResources().getDisplayMetrics());
- int id = resources.getIdentifier(iconResource.resourceName, null, null);
- if (id == 0) {
- throw new NameNotFoundException();
- }
- return resources.getDrawable(id);
- }
-
- @SuppressWarnings("deprecation")
- private Drawable getAccountImage(BitmapWorkerOptions options) {
- String accountName = UriUtils.getAccountName(options.getResourceUri());
- Context context = options.getContext();
-
- if (accountName != null && context != null) {
- Account thisAccount = null;
- for (Account account : AccountManager.get(context).
- getAccountsByType(GOOGLE_ACCOUNT_TYPE)) {
- if (account.name.equals(accountName)) {
- thisAccount = account;
- break;
- }
- }
- if (thisAccount != null) {
- String picUriString = AccountImageHelper.getAccountPictureUri(context, thisAccount);
- if (picUriString != null) {
- BitmapWorkerOptions.Builder optionBuilder =
- new BitmapWorkerOptions.Builder(context)
- .width(options.getWidth())
- .height(options.getHeight())
- .cacheFlag(options.getCacheFlag())
- .bitmapConfig(options.getBitmapConfig())
- .resource(Uri.parse(picUriString));
- return DrawableDownloader.getInstance(context)
- .loadBitmapBlocking(optionBuilder.build());
- }
- return null;
- }
- }
- return null;
- }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/RecycleBitmapPool.java b/car-apps-common/src/com/android/car/apps/common/RecycleBitmapPool.java
deleted file mode 100644
index 480ae00..0000000
--- a/car-apps-common/src/com/android/car/apps/common/RecycleBitmapPool.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import android.graphics.Bitmap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.lang.ref.SoftReference;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-
-
-/**
- * This class saves recycle bitmap as SoftReference, which is too vulnerable to
- * be garbage collected due to other part of application is re-allocating lots of
- * memory, we will lose all SoftReference in a GC run. We should maintain
- * certain amount of recycled bitmaps in memory, we may also need remove bitmap from LRUCache
- * if we are not able to get a recycled bitmap here.
- *
- * @hide
- */
-public class RecycleBitmapPool {
-
- private static final String TAG = "RecycleBitmapPool";
- private static final boolean DEBUG = false;
- // allow reuse bitmap with larger bytes, set to 0 to disable different byte size
- private static final int LARGER_BITMAP_ALLOWED_REUSE = 0;
- private static final boolean LARGER_BITMAP_ALLOWED = LARGER_BITMAP_ALLOWED_REUSE > 0;
-
- private static Method sGetAllocationByteCount;
-
- static {
- try {
- // KLP or later
- sGetAllocationByteCount = Bitmap.class.getMethod("getAllocationByteCount");
- } catch (NoSuchMethodException e) {
- }
- }
-
- private final SparseArray<ArrayList<SoftReference<Bitmap>>> mRecycled8888 =
- new SparseArray<ArrayList<SoftReference<Bitmap>>>();
-
- public RecycleBitmapPool() {
- }
-
- public static int getSize(Bitmap bitmap) {
- if (sGetAllocationByteCount != null) {
- try {
- return (Integer) sGetAllocationByteCount.invoke(bitmap);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "getAllocationByteCount() failed", e);
- } catch (IllegalAccessException e) {
- Log.e(TAG, "getAllocationByteCount() failed", e);
- } catch (InvocationTargetException e) {
- Log.e(TAG, "getAllocationByteCount() failed", e);
- }
- sGetAllocationByteCount = null;
- }
- return bitmap.getByteCount();
- }
-
- private static int getSize(int width, int height) {
- if (width >= 2048 || height >= 2048) {
- return 0;
- }
- return width * height * 4;
- }
-
- public void addRecycledBitmap(Bitmap bitmap) {
- if (bitmap.isRecycled()) {
- return;
- }
- Bitmap.Config config = bitmap.getConfig();
- if (config != Bitmap.Config.ARGB_8888) {
- return;
- }
- int key = getSize(bitmap);
- if (key == 0) {
- return;
- }
- synchronized (mRecycled8888) {
- ArrayList<SoftReference<Bitmap>> list = mRecycled8888.get(key);
- if (list == null) {
- list = new ArrayList<SoftReference<Bitmap>>();
- mRecycled8888.put(key, list);
- }
- list.add(new SoftReference<Bitmap>(bitmap));
- if (DEBUG) {
- Log.d(TAG, list.size() + " add bitmap " + bitmap.getWidth() + " "
- + bitmap.getHeight());
- }
- }
- }
-
- public Bitmap getRecycledBitmap(int width, int height) {
- int key = getSize(width, height);
- if (key == 0) {
- return null;
- }
- synchronized (mRecycled8888) {
- // for the new version with getAllocationByteCount(), we allow larger size
- // to be reused for the bitmap, otherwise we just looks for same size
- Bitmap bitmap = getRecycledBitmap(mRecycled8888.get(key));
- if (sGetAllocationByteCount == null || bitmap != null) {
- return bitmap;
- }
- if (LARGER_BITMAP_ALLOWED) {
- for (int i = 0, c = mRecycled8888.size(); i < c; i++) {
- int k = mRecycled8888.keyAt(i);
- if (k > key && k <= key * LARGER_BITMAP_ALLOWED_REUSE) {
- bitmap = getRecycledBitmap(mRecycled8888.valueAt(i));
- if (bitmap != null) {
- return bitmap;
- }
- }
- }
- }
- }
- if (DEBUG) {
- Log.d(TAG, "not avaialbe for " + width + "," + height);
- }
- return null;
- }
-
- private static Bitmap getRecycledBitmap(ArrayList<SoftReference<Bitmap>> list) {
- if (list != null && !list.isEmpty()) {
- while (!list.isEmpty()) {
- SoftReference<Bitmap> ref = list.remove(list.size() - 1);
- Bitmap bitmap = ref.get();
- if (bitmap != null && !bitmap.isRecycled()) {
- if (DEBUG) {
- Log.d(TAG, "reuse " + bitmap.getWidth() + " " + bitmap.getHeight());
- }
- return bitmap;
- } else {
- if (DEBUG) {
- Log.d(TAG, " we lost SoftReference to bitmap");
- }
- }
- }
- }
- return null;
- }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/RefcountBitmapDrawable.java b/car-apps-common/src/com/android/car/apps/common/RefcountBitmapDrawable.java
deleted file mode 100644
index 01a4bb1..0000000
--- a/car-apps-common/src/com/android/car/apps/common/RefcountBitmapDrawable.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.car.apps.common;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-
-/**
- * RefcountBitmapDrawable class
- * @hide
- */
-public class RefcountBitmapDrawable extends BitmapDrawable {
-
- private RefcountObject<Bitmap> mRefcountObject;
-
- /**
- * create initial drawable, this will not increase the refcount
- */
- public RefcountBitmapDrawable(Resources res, RefcountObject<Bitmap> bitmap) {
- super(res, bitmap.getObject());
- mRefcountObject = bitmap;
- }
-
- /**
- * create the drawable from existing drawable, will not increase refcount
- */
- public RefcountBitmapDrawable(Resources res, RefcountBitmapDrawable drawable) {
- this(res, drawable.getRefcountObject());
- }
-
- public RefcountObject<Bitmap> getRefcountObject() {
- return mRefcountObject;
- }
-}