Remove bitmapfun code sample (it has moved to samples framework).

Change-Id: I70fc6437815001c7b98174cfe2e29e1244c55e75
diff --git a/samples/training/bitmapfun/BitmapFun/build.gradle b/samples/training/bitmapfun/BitmapFun/build.gradle
deleted file mode 100644
index c978231..0000000
--- a/samples/training/bitmapfun/BitmapFun/build.gradle
+++ /dev/null
@@ -1,27 +0,0 @@
-buildscript {
-    repositories {
-        mavenCentral()
-    }
-    dependencies {
-        classpath 'com.android.tools.build:gradle:0.6.+'
-    }
-}
-apply plugin: 'android'
-
-repositories {
-    mavenCentral()
-}
-
-android {
-    compileSdkVersion 19
-    buildToolsVersion "19.0.0"
-
-    defaultConfig {
-        minSdkVersion 7
-        targetSdkVersion 19
-    }
-}
-
-dependencies {
-    compile 'com.android.support:support-v4:19.0.+'
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/AndroidManifest.xml b/samples/training/bitmapfun/BitmapFun/src/main/AndroidManifest.xml
deleted file mode 100644
index 9ca5cf5..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.example.android.bitmapfun"
-    android:versionCode="1"
-    android:versionName="1.0" >
-
-    <uses-sdk
-        android:minSdkVersion="7"
-        android:targetSdkVersion="19" />
-
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-
-    <application
-        android:description="@string/app_description"
-        android:hardwareAccelerated="true"
-        android:icon="@drawable/ic_launcher"
-        android:label="@string/app_name"
-        android:allowBackup="false">
-        <activity
-            android:name=".ui.ImageDetailActivity"
-            android:label="@string/app_name"
-            android:parentActivityName=".ui.ImageGridActivity"
-            android:theme="@style/AppTheme.FullScreen" >
-            <meta-data android:name="android.support.PARENT_ACTIVITY"
-                       android:value=".ui.ImageGridActivity" />
-        </activity>
-        <activity
-            android:name=".ui.ImageGridActivity"
-            android:label="@string/app_name"
-            android:theme="@style/AppTheme" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/provider/Images.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/provider/Images.java
deleted file mode 100644
index fcf4496..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/provider/Images.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.provider;
-
-/**
- * Some simple test data to use for this sample app.
- */
-public class Images {
-
-    /**
-     * This are PicasaWeb URLs and could potentially change. Ideally the PicasaWeb API should be
-     * used to fetch the URLs.
-     *
-     * Credit to Romain Guy for the photos:
-     * http://www.curious-creature.org/
-     * https://plus.google.com/109538161516040592207/about
-     * http://www.flickr.com/photos/romainguy
-     */
-    public final static String[] imageUrls = new String[] {
-            "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg",
-            "https://lh4.googleusercontent.com/--dq8niRp7W4/URquVgmXvgI/AAAAAAAAAbs/-gnuLQfNnBA/s1024/A%252520Song%252520of%252520Ice%252520and%252520Fire.jpg",
-            "https://lh5.googleusercontent.com/-7qZeDtRKFKc/URquWZT1gOI/AAAAAAAAAbs/hqWgteyNXsg/s1024/Another%252520Rockaway%252520Sunset.jpg",
-            "https://lh3.googleusercontent.com/--L0Km39l5J8/URquXHGcdNI/AAAAAAAAAbs/3ZrSJNrSomQ/s1024/Antelope%252520Butte.jpg",
-            "https://lh6.googleusercontent.com/-8HO-4vIFnlw/URquZnsFgtI/AAAAAAAAAbs/WT8jViTF7vw/s1024/Antelope%252520Hallway.jpg",
-            "https://lh4.googleusercontent.com/-WIuWgVcU3Qw/URqubRVcj4I/AAAAAAAAAbs/YvbwgGjwdIQ/s1024/Antelope%252520Walls.jpg",
-            "https://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpg",
-            "https://lh3.googleusercontent.com/-s-AFpvgSeew/URquc6dF-JI/AAAAAAAAAbs/Mt3xNGRUd68/s1024/Backlit%252520Cloud.jpg",
-            "https://lh5.googleusercontent.com/-bvmif9a9YOQ/URquea3heHI/AAAAAAAAAbs/rcr6wyeQtAo/s1024/Bee%252520and%252520Flower.jpg",
-            "https://lh5.googleusercontent.com/-n7mdm7I7FGs/URqueT_BT-I/AAAAAAAAAbs/9MYmXlmpSAo/s1024/Bonzai%252520Rock%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-4CN4X4t0M1k/URqufPozWzI/AAAAAAAAAbs/8wK41lg1KPs/s1024/Caterpillar.jpg",
-            "https://lh3.googleusercontent.com/-rrFnVC8xQEg/URqufdrLBaI/AAAAAAAAAbs/s69WYy_fl1E/s1024/Chess.jpg",
-            "https://lh5.googleusercontent.com/-WVpRptWH8Yw/URqugh-QmDI/AAAAAAAAAbs/E-MgBgtlUWU/s1024/Chihuly.jpg",
-            "https://lh5.googleusercontent.com/-0BDXkYmckbo/URquhKFW84I/AAAAAAAAAbs/ogQtHCTk2JQ/s1024/Closed%252520Door.jpg",
-            "https://lh3.googleusercontent.com/-PyggXXZRykM/URquh-kVvoI/AAAAAAAAAbs/hFtDwhtrHHQ/s1024/Colorado%252520River%252520Sunset.jpg",
-            "https://lh3.googleusercontent.com/-ZAs4dNZtALc/URquikvOCWI/AAAAAAAAAbs/DXz4h3dll1Y/s1024/Colors%252520of%252520Autumn.jpg",
-            "https://lh4.googleusercontent.com/-GztnWEIiMz8/URqukVCU7bI/AAAAAAAAAbs/jo2Hjv6MZ6M/s1024/Countryside.jpg",
-            "https://lh4.googleusercontent.com/-bEg9EZ9QoiM/URquklz3FGI/AAAAAAAAAbs/UUuv8Ac2BaE/s1024/Death%252520Valley%252520-%252520Dunes.jpg",
-            "https://lh6.googleusercontent.com/-ijQJ8W68tEE/URqulGkvFEI/AAAAAAAAAbs/zPXvIwi_rFw/s1024/Delicate%252520Arch.jpg",
-            "https://lh5.googleusercontent.com/-Oh8mMy2ieng/URqullDwehI/AAAAAAAAAbs/TbdeEfsaIZY/s1024/Despair.jpg",
-            "https://lh5.googleusercontent.com/-gl0y4UiAOlk/URqumC_KjBI/AAAAAAAAAbs/PM1eT7dn4oo/s1024/Eagle%252520Fall%252520Sunrise.jpg",
-            "https://lh3.googleusercontent.com/-hYYHd2_vXPQ/URqumtJa9eI/AAAAAAAAAbs/wAalXVkbSh0/s1024/Electric%252520Storm.jpg",
-            "https://lh5.googleusercontent.com/-PyY_yiyjPTo/URqunUOhHFI/AAAAAAAAAbs/azZoULNuJXc/s1024/False%252520Kiva.jpg",
-            "https://lh6.googleusercontent.com/-PYvLVdvXywk/URqunwd8hfI/AAAAAAAAAbs/qiMwgkFvf6I/s1024/Fitzgerald%252520Streaks.jpg",
-            "https://lh4.googleusercontent.com/-KIR_UobIIqY/URquoCZ9SlI/AAAAAAAAAbs/Y4d4q8sXu4c/s1024/Foggy%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-9lzOk_OWZH0/URquoo4xYoI/AAAAAAAAAbs/AwgzHtNVCwU/s1024/Frantic.jpg",
-            "https://lh3.googleusercontent.com/-0X3JNaKaz48/URqupH78wpI/AAAAAAAAAbs/lHXxu_zbH8s/s1024/Golden%252520Gate%252520Afternoon.jpg",
-            "https://lh6.googleusercontent.com/-95sb5ag7ABc/URqupl95RDI/AAAAAAAAAbs/g73R20iVTRA/s1024/Golden%252520Gate%252520Fog.jpg",
-            "https://lh3.googleusercontent.com/-JB9v6rtgHhk/URqup21F-zI/AAAAAAAAAbs/64Fb8qMZWXk/s1024/Golden%252520Grass.jpg",
-            "https://lh4.googleusercontent.com/-EIBGfnuLtII/URquqVHwaRI/AAAAAAAAAbs/FA4McV2u8VE/s1024/Grand%252520Teton.jpg",
-            "https://lh4.googleusercontent.com/-WoMxZvmN9nY/URquq1v2AoI/AAAAAAAAAbs/grj5uMhL6NA/s1024/Grass%252520Closeup.jpg",
-            "https://lh3.googleusercontent.com/-6hZiEHXx64Q/URqurxvNdqI/AAAAAAAAAbs/kWMXM3o5OVI/s1024/Green%252520Grass.jpg",
-            "https://lh5.googleusercontent.com/-6LVb9OXtQ60/URquteBFuKI/AAAAAAAAAbs/4F4kRgecwFs/s1024/Hanging%252520Leaf.jpg",
-            "https://lh4.googleusercontent.com/-zAvf__52ONk/URqutT_IuxI/AAAAAAAAAbs/D_bcuc0thoU/s1024/Highway%2525201.jpg",
-            "https://lh6.googleusercontent.com/-H4SrUg615rA/URquuL27fXI/AAAAAAAAAbs/4aEqJfiMsOU/s1024/Horseshoe%252520Bend%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-JhFi4fb_Pqw/URquuX-QXbI/AAAAAAAAAbs/IXpYUxuweYM/s1024/Horseshoe%252520Bend.jpg",
-            "https://lh5.googleusercontent.com/-UGgssvFRJ7g/URquueyJzGI/AAAAAAAAAbs/yYIBlLT0toM/s1024/Into%252520the%252520Blue.jpg",
-            "https://lh3.googleusercontent.com/-CH7KoupI7uI/URquu0FF__I/AAAAAAAAAbs/R7GDmI7v_G0/s1024/Jelly%252520Fish%2525202.jpg",
-            "https://lh4.googleusercontent.com/-pwuuw6yhg8U/URquvPxR3FI/AAAAAAAAAbs/VNGk6f-tsGE/s1024/Jelly%252520Fish%2525203.jpg",
-            "https://lh5.googleusercontent.com/-GoUQVw1fnFw/URquv6xbC0I/AAAAAAAAAbs/zEUVTQQ43Zc/s1024/Kauai.jpg",
-            "https://lh6.googleusercontent.com/-8QdYYQEpYjw/URquwvdh88I/AAAAAAAAAbs/cktDy-ysfHo/s1024/Kyoto%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-vPeekyDjOE0/URquwzJ28qI/AAAAAAAAAbs/qxcyXULsZrg/s1024/Lake%252520Tahoe%252520Colors.jpg",
-            "https://lh4.googleusercontent.com/-xBPxWpD4yxU/URquxWHk8AI/AAAAAAAAAbs/ARDPeDYPiMY/s1024/Lava%252520from%252520the%252520Sky.jpg",
-            "https://lh3.googleusercontent.com/-897VXrJB6RE/URquxxxd-5I/AAAAAAAAAbs/j-Cz4T4YvIw/s1024/Leica%25252050mm%252520Summilux.jpg",
-            "https://lh5.googleusercontent.com/-qSJ4D4iXzGo/URquyDWiJ1I/AAAAAAAAAbs/k2pBXeWehOA/s1024/Leica%25252050mm%252520Summilux.jpg",
-            "https://lh6.googleusercontent.com/-dwlPg83vzLg/URquylTVuFI/AAAAAAAAAbs/G6SyQ8b4YsI/s1024/Leica%252520M8%252520%252528Front%252529.jpg",
-            "https://lh3.googleusercontent.com/-R3_EYAyJvfk/URquzQBv8eI/AAAAAAAAAbs/b9xhpUM3pEI/s1024/Light%252520to%252520Sand.jpg",
-            "https://lh3.googleusercontent.com/-fHY5h67QPi0/URqu0Cp4J1I/AAAAAAAAAbs/0lG6m94Z6vM/s1024/Little%252520Bit%252520of%252520Paradise.jpg",
-            "https://lh5.googleusercontent.com/-TzF_LwrCnRM/URqu0RddPOI/AAAAAAAAAbs/gaj2dLiuX0s/s1024/Lone%252520Pine%252520Sunset.jpg",
-            "https://lh3.googleusercontent.com/-4HdpJ4_DXU4/URqu046dJ9I/AAAAAAAAAbs/eBOodtk2_uk/s1024/Lonely%252520Rock.jpg",
-            "https://lh6.googleusercontent.com/-erbF--z-W4s/URqu1ajSLkI/AAAAAAAAAbs/xjDCDO1INzM/s1024/Longue%252520Vue.jpg",
-            "https://lh6.googleusercontent.com/-0CXJRdJaqvc/URqu1opNZNI/AAAAAAAAAbs/PFB2oPUU7Lk/s1024/Look%252520Me%252520in%252520the%252520Eye.jpg",
-            "https://lh3.googleusercontent.com/-D_5lNxnDN6g/URqu2Tk7HVI/AAAAAAAAAbs/p0ddca9W__Y/s1024/Lost%252520in%252520a%252520Field.jpg",
-            "https://lh6.googleusercontent.com/-flsqwMrIk2Q/URqu24PcmjI/AAAAAAAAAbs/5ocIH85XofM/s1024/Marshall%252520Beach%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-Y4lgryEVTmU/URqu28kG3gI/AAAAAAAAAbs/OjXpekqtbJ4/s1024/Mono%252520Lake%252520Blue.jpg",
-            "https://lh4.googleusercontent.com/-AaHAJPmcGYA/URqu3PIldHI/AAAAAAAAAbs/lcTqk1SIcRs/s1024/Monument%252520Valley%252520Overlook.jpg",
-            "https://lh4.googleusercontent.com/-vKxfdQ83dQA/URqu31Yq_BI/AAAAAAAAAbs/OUoGk_2AyfM/s1024/Moving%252520Rock.jpg",
-            "https://lh5.googleusercontent.com/-CG62QiPpWXg/URqu4ia4vRI/AAAAAAAAAbs/0YOdqLAlcAc/s1024/Napali%252520Coast.jpg",
-            "https://lh6.googleusercontent.com/-wdGrP5PMmJQ/URqu5PZvn7I/AAAAAAAAAbs/m0abEcdPXe4/s1024/One%252520Wheel.jpg",
-            "https://lh6.googleusercontent.com/-6WS5DoCGuOA/URqu5qx1UgI/AAAAAAAAAbs/giMw2ixPvrY/s1024/Open%252520Sky.jpg",
-            "https://lh6.googleusercontent.com/-u8EHKj8G8GQ/URqu55sM6yI/AAAAAAAAAbs/lIXX_GlTdmI/s1024/Orange%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-74Z5qj4bTDE/URqu6LSrJrI/AAAAAAAAAbs/XzmVkw90szQ/s1024/Orchid.jpg",
-            "https://lh6.googleusercontent.com/-lEQE4h6TePE/URqu6t_lSkI/AAAAAAAAAbs/zvGYKOea_qY/s1024/Over%252520there.jpg",
-            "https://lh5.googleusercontent.com/-cauH-53JH2M/URqu66v_USI/AAAAAAAAAbs/EucwwqclfKQ/s1024/Plumes.jpg",
-            "https://lh3.googleusercontent.com/-eDLT2jHDoy4/URqu7axzkAI/AAAAAAAAAbs/iVZE-xJ7lZs/s1024/Rainbokeh.jpg",
-            "https://lh5.googleusercontent.com/-j1NLqEFIyco/URqu8L1CGcI/AAAAAAAAAbs/aqZkgX66zlI/s1024/Rainbow.jpg",
-            "https://lh5.googleusercontent.com/-DRnqmK0t4VU/URqu8XYN9yI/AAAAAAAAAbs/LgvF_592WLU/s1024/Rice%252520Fields.jpg",
-            "https://lh3.googleusercontent.com/-hwh1v3EOGcQ/URqu8qOaKwI/AAAAAAAAAbs/IljRJRnbJGw/s1024/Rockaway%252520Fire%252520Sky.jpg",
-            "https://lh5.googleusercontent.com/-wjV6FQk7tlk/URqu9jCQ8sI/AAAAAAAAAbs/RyYUpdo-c9o/s1024/Rockaway%252520Flow.jpg",
-            "https://lh6.googleusercontent.com/-6cAXNfo7D20/URqu-BdzgPI/AAAAAAAAAbs/OmsYllzJqwo/s1024/Rockaway%252520Sunset%252520Sky.jpg",
-            "https://lh3.googleusercontent.com/-sl8fpGPS-RE/URqu_BOkfgI/AAAAAAAAAbs/Dg2Fv-JxOeg/s1024/Russian%252520Ridge%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-gVtY36mMBIg/URqu_q91lkI/AAAAAAAAAbs/3CiFMBcy5MA/s1024/Rust%252520Knot.jpg",
-            "https://lh6.googleusercontent.com/-GHeImuHqJBE/URqu_FKfVLI/AAAAAAAAAbs/axuEJeqam7Q/s1024/Sailing%252520Stones.jpg",
-            "https://lh3.googleusercontent.com/-hBbYZjTOwGc/URqu_ycpIrI/AAAAAAAAAbs/nAdJUXnGJYE/s1024/Seahorse.jpg",
-            "https://lh3.googleusercontent.com/-Iwi6-i6IexY/URqvAYZHsVI/AAAAAAAAAbs/5ETWl4qXsFE/s1024/Shinjuku%252520Street.jpg",
-            "https://lh6.googleusercontent.com/-amhnySTM_MY/URqvAlb5KoI/AAAAAAAAAbs/pFCFgzlKsn0/s1024/Sierra%252520Heavens.jpg",
-            "https://lh5.googleusercontent.com/-dJgjepFrYSo/URqvBVJZrAI/AAAAAAAAAbs/v-F5QWpYO6s/s1024/Sierra%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-Z4zGiC5nWdc/URqvBdEwivI/AAAAAAAAAbs/ZRZR1VJ84QA/s1024/Sin%252520Lights.jpg",
-            "https://lh4.googleusercontent.com/-_0cYiWW8ccY/URqvBz3iM4I/AAAAAAAAAbs/9N_Wq8MhLTY/s1024/Starry%252520Lake.jpg",
-            "https://lh3.googleusercontent.com/-A9LMoRyuQUA/URqvCYx_JoI/AAAAAAAAAbs/s7sde1Bz9cI/s1024/Starry%252520Night.jpg",
-            "https://lh3.googleusercontent.com/-KtLJ3k858eY/URqvC_2h_bI/AAAAAAAAAbs/zzEBImwDA_g/s1024/Stream.jpg",
-            "https://lh5.googleusercontent.com/-dFB7Lad6RcA/URqvDUftwWI/AAAAAAAAAbs/BrhoUtXTN7o/s1024/Strip%252520Sunset.jpg",
-            "https://lh5.googleusercontent.com/-at6apgFiN20/URqvDyffUZI/AAAAAAAAAbs/clABCx171bE/s1024/Sunset%252520Hills.jpg",
-            "https://lh4.googleusercontent.com/-7-EHhtQthII/URqvEYTk4vI/AAAAAAAAAbs/QSJZoB3YjVg/s1024/Tenaya%252520Lake%2525202.jpg",
-            "https://lh6.googleusercontent.com/-8MrjV_a-Pok/URqvFC5repI/AAAAAAAAAbs/9inKTg9fbCE/s1024/Tenaya%252520Lake.jpg",
-            "https://lh5.googleusercontent.com/-B1HW-z4zwao/URqvFWYRwUI/AAAAAAAAAbs/8Peli53Bs8I/s1024/The%252520Cave%252520BW.jpg",
-            "https://lh3.googleusercontent.com/-PO4E-xZKAnQ/URqvGRqjYkI/AAAAAAAAAbs/42nyADFsXag/s1024/The%252520Fisherman.jpg",
-            "https://lh4.googleusercontent.com/-iLyZlzfdy7s/URqvG0YScdI/AAAAAAAAAbs/1J9eDKmkXtk/s1024/The%252520Night%252520is%252520Coming.jpg",
-            "https://lh6.googleusercontent.com/-G-k7YkkUco0/URqvHhah6fI/AAAAAAAAAbs/_taQQG7t0vo/s1024/The%252520Road.jpg",
-            "https://lh6.googleusercontent.com/-h-ALJt7kSus/URqvIThqYfI/AAAAAAAAAbs/ejiv35olWS8/s1024/Tokyo%252520Heights.jpg",
-            "https://lh5.googleusercontent.com/-Hy9k-TbS7xg/URqvIjQMOxI/AAAAAAAAAbs/RSpmmOATSkg/s1024/Tokyo%252520Highway.jpg",
-            "https://lh6.googleusercontent.com/-83oOvMb4OZs/URqvJL0T7lI/AAAAAAAAAbs/c5TECZ6RONM/s1024/Tokyo%252520Smog.jpg",
-            "https://lh3.googleusercontent.com/-FB-jfgREEfI/URqvJI3EXAI/AAAAAAAAAbs/XfyweiRF4v8/s1024/Tufa%252520at%252520Night.jpg",
-            "https://lh4.googleusercontent.com/-vngKD5Z1U8w/URqvJUCEgPI/AAAAAAAAAbs/ulxCMVcU6EU/s1024/Valley%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-DOz5I2E2oMQ/URqvKMND1kI/AAAAAAAAAbs/Iqf0IsInleo/s1024/Windmill%252520Sunrise.jpg",
-            "https://lh5.googleusercontent.com/-biyiyWcJ9MU/URqvKculiAI/AAAAAAAAAbs/jyPsCplJOpE/s1024/Windmill.jpg",
-            "https://lh4.googleusercontent.com/-PDT167_xRdA/URqvK36mLcI/AAAAAAAAAbs/oi2ik9QseMI/s1024/Windmills.jpg",
-            "https://lh5.googleusercontent.com/-kI_QdYx7VlU/URqvLXCB6gI/AAAAAAAAAbs/N31vlZ6u89o/s1024/Yet%252520Another%252520Rockaway%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-e9NHZ5k5MSs/URqvMIBZjtI/AAAAAAAAAbs/1fV810rDNfQ/s1024/Yosemite%252520Tree.jpg",
-    };
-
-    /**
-     * This are PicasaWeb thumbnail URLs and could potentially change. Ideally the PicasaWeb API
-     * should be used to fetch the URLs.
-     *
-     * Credit to Romain Guy for the photos:
-     * http://www.curious-creature.org/
-     * https://plus.google.com/109538161516040592207/about
-     * http://www.flickr.com/photos/romainguy
-     */
-    public final static String[] imageThumbUrls = new String[] {
-            "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s240-c/A%252520Photographer.jpg",
-            "https://lh4.googleusercontent.com/--dq8niRp7W4/URquVgmXvgI/AAAAAAAAAbs/-gnuLQfNnBA/s240-c/A%252520Song%252520of%252520Ice%252520and%252520Fire.jpg",
-            "https://lh5.googleusercontent.com/-7qZeDtRKFKc/URquWZT1gOI/AAAAAAAAAbs/hqWgteyNXsg/s240-c/Another%252520Rockaway%252520Sunset.jpg",
-            "https://lh3.googleusercontent.com/--L0Km39l5J8/URquXHGcdNI/AAAAAAAAAbs/3ZrSJNrSomQ/s240-c/Antelope%252520Butte.jpg",
-            "https://lh6.googleusercontent.com/-8HO-4vIFnlw/URquZnsFgtI/AAAAAAAAAbs/WT8jViTF7vw/s240-c/Antelope%252520Hallway.jpg",
-            "https://lh4.googleusercontent.com/-WIuWgVcU3Qw/URqubRVcj4I/AAAAAAAAAbs/YvbwgGjwdIQ/s240-c/Antelope%252520Walls.jpg",
-            "https://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s240-c/Apre%2525CC%252580s%252520la%252520Pluie.jpg",
-            "https://lh3.googleusercontent.com/-s-AFpvgSeew/URquc6dF-JI/AAAAAAAAAbs/Mt3xNGRUd68/s240-c/Backlit%252520Cloud.jpg",
-            "https://lh5.googleusercontent.com/-bvmif9a9YOQ/URquea3heHI/AAAAAAAAAbs/rcr6wyeQtAo/s240-c/Bee%252520and%252520Flower.jpg",
-            "https://lh5.googleusercontent.com/-n7mdm7I7FGs/URqueT_BT-I/AAAAAAAAAbs/9MYmXlmpSAo/s240-c/Bonzai%252520Rock%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-4CN4X4t0M1k/URqufPozWzI/AAAAAAAAAbs/8wK41lg1KPs/s240-c/Caterpillar.jpg",
-            "https://lh3.googleusercontent.com/-rrFnVC8xQEg/URqufdrLBaI/AAAAAAAAAbs/s69WYy_fl1E/s240-c/Chess.jpg",
-            "https://lh5.googleusercontent.com/-WVpRptWH8Yw/URqugh-QmDI/AAAAAAAAAbs/E-MgBgtlUWU/s240-c/Chihuly.jpg",
-            "https://lh5.googleusercontent.com/-0BDXkYmckbo/URquhKFW84I/AAAAAAAAAbs/ogQtHCTk2JQ/s240-c/Closed%252520Door.jpg",
-            "https://lh3.googleusercontent.com/-PyggXXZRykM/URquh-kVvoI/AAAAAAAAAbs/hFtDwhtrHHQ/s240-c/Colorado%252520River%252520Sunset.jpg",
-            "https://lh3.googleusercontent.com/-ZAs4dNZtALc/URquikvOCWI/AAAAAAAAAbs/DXz4h3dll1Y/s240-c/Colors%252520of%252520Autumn.jpg",
-            "https://lh4.googleusercontent.com/-GztnWEIiMz8/URqukVCU7bI/AAAAAAAAAbs/jo2Hjv6MZ6M/s240-c/Countryside.jpg",
-            "https://lh4.googleusercontent.com/-bEg9EZ9QoiM/URquklz3FGI/AAAAAAAAAbs/UUuv8Ac2BaE/s240-c/Death%252520Valley%252520-%252520Dunes.jpg",
-            "https://lh6.googleusercontent.com/-ijQJ8W68tEE/URqulGkvFEI/AAAAAAAAAbs/zPXvIwi_rFw/s240-c/Delicate%252520Arch.jpg",
-            "https://lh5.googleusercontent.com/-Oh8mMy2ieng/URqullDwehI/AAAAAAAAAbs/TbdeEfsaIZY/s240-c/Despair.jpg",
-            "https://lh5.googleusercontent.com/-gl0y4UiAOlk/URqumC_KjBI/AAAAAAAAAbs/PM1eT7dn4oo/s240-c/Eagle%252520Fall%252520Sunrise.jpg",
-            "https://lh3.googleusercontent.com/-hYYHd2_vXPQ/URqumtJa9eI/AAAAAAAAAbs/wAalXVkbSh0/s240-c/Electric%252520Storm.jpg",
-            "https://lh5.googleusercontent.com/-PyY_yiyjPTo/URqunUOhHFI/AAAAAAAAAbs/azZoULNuJXc/s240-c/False%252520Kiva.jpg",
-            "https://lh6.googleusercontent.com/-PYvLVdvXywk/URqunwd8hfI/AAAAAAAAAbs/qiMwgkFvf6I/s240-c/Fitzgerald%252520Streaks.jpg",
-            "https://lh4.googleusercontent.com/-KIR_UobIIqY/URquoCZ9SlI/AAAAAAAAAbs/Y4d4q8sXu4c/s240-c/Foggy%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-9lzOk_OWZH0/URquoo4xYoI/AAAAAAAAAbs/AwgzHtNVCwU/s240-c/Frantic.jpg",
-            "https://lh3.googleusercontent.com/-0X3JNaKaz48/URqupH78wpI/AAAAAAAAAbs/lHXxu_zbH8s/s240-c/Golden%252520Gate%252520Afternoon.jpg",
-            "https://lh6.googleusercontent.com/-95sb5ag7ABc/URqupl95RDI/AAAAAAAAAbs/g73R20iVTRA/s240-c/Golden%252520Gate%252520Fog.jpg",
-            "https://lh3.googleusercontent.com/-JB9v6rtgHhk/URqup21F-zI/AAAAAAAAAbs/64Fb8qMZWXk/s240-c/Golden%252520Grass.jpg",
-            "https://lh4.googleusercontent.com/-EIBGfnuLtII/URquqVHwaRI/AAAAAAAAAbs/FA4McV2u8VE/s240-c/Grand%252520Teton.jpg",
-            "https://lh4.googleusercontent.com/-WoMxZvmN9nY/URquq1v2AoI/AAAAAAAAAbs/grj5uMhL6NA/s240-c/Grass%252520Closeup.jpg",
-            "https://lh3.googleusercontent.com/-6hZiEHXx64Q/URqurxvNdqI/AAAAAAAAAbs/kWMXM3o5OVI/s240-c/Green%252520Grass.jpg",
-            "https://lh5.googleusercontent.com/-6LVb9OXtQ60/URquteBFuKI/AAAAAAAAAbs/4F4kRgecwFs/s240-c/Hanging%252520Leaf.jpg",
-            "https://lh4.googleusercontent.com/-zAvf__52ONk/URqutT_IuxI/AAAAAAAAAbs/D_bcuc0thoU/s240-c/Highway%2525201.jpg",
-            "https://lh6.googleusercontent.com/-H4SrUg615rA/URquuL27fXI/AAAAAAAAAbs/4aEqJfiMsOU/s240-c/Horseshoe%252520Bend%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-JhFi4fb_Pqw/URquuX-QXbI/AAAAAAAAAbs/IXpYUxuweYM/s240-c/Horseshoe%252520Bend.jpg",
-            "https://lh5.googleusercontent.com/-UGgssvFRJ7g/URquueyJzGI/AAAAAAAAAbs/yYIBlLT0toM/s240-c/Into%252520the%252520Blue.jpg",
-            "https://lh3.googleusercontent.com/-CH7KoupI7uI/URquu0FF__I/AAAAAAAAAbs/R7GDmI7v_G0/s240-c/Jelly%252520Fish%2525202.jpg",
-            "https://lh4.googleusercontent.com/-pwuuw6yhg8U/URquvPxR3FI/AAAAAAAAAbs/VNGk6f-tsGE/s240-c/Jelly%252520Fish%2525203.jpg",
-            "https://lh5.googleusercontent.com/-GoUQVw1fnFw/URquv6xbC0I/AAAAAAAAAbs/zEUVTQQ43Zc/s240-c/Kauai.jpg",
-            "https://lh6.googleusercontent.com/-8QdYYQEpYjw/URquwvdh88I/AAAAAAAAAbs/cktDy-ysfHo/s240-c/Kyoto%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-vPeekyDjOE0/URquwzJ28qI/AAAAAAAAAbs/qxcyXULsZrg/s240-c/Lake%252520Tahoe%252520Colors.jpg",
-            "https://lh4.googleusercontent.com/-xBPxWpD4yxU/URquxWHk8AI/AAAAAAAAAbs/ARDPeDYPiMY/s240-c/Lava%252520from%252520the%252520Sky.jpg",
-            "https://lh3.googleusercontent.com/-897VXrJB6RE/URquxxxd-5I/AAAAAAAAAbs/j-Cz4T4YvIw/s240-c/Leica%25252050mm%252520Summilux.jpg",
-            "https://lh5.googleusercontent.com/-qSJ4D4iXzGo/URquyDWiJ1I/AAAAAAAAAbs/k2pBXeWehOA/s240-c/Leica%25252050mm%252520Summilux.jpg",
-            "https://lh6.googleusercontent.com/-dwlPg83vzLg/URquylTVuFI/AAAAAAAAAbs/G6SyQ8b4YsI/s240-c/Leica%252520M8%252520%252528Front%252529.jpg",
-            "https://lh3.googleusercontent.com/-R3_EYAyJvfk/URquzQBv8eI/AAAAAAAAAbs/b9xhpUM3pEI/s240-c/Light%252520to%252520Sand.jpg",
-            "https://lh3.googleusercontent.com/-fHY5h67QPi0/URqu0Cp4J1I/AAAAAAAAAbs/0lG6m94Z6vM/s240-c/Little%252520Bit%252520of%252520Paradise.jpg",
-            "https://lh5.googleusercontent.com/-TzF_LwrCnRM/URqu0RddPOI/AAAAAAAAAbs/gaj2dLiuX0s/s240-c/Lone%252520Pine%252520Sunset.jpg",
-            "https://lh3.googleusercontent.com/-4HdpJ4_DXU4/URqu046dJ9I/AAAAAAAAAbs/eBOodtk2_uk/s240-c/Lonely%252520Rock.jpg",
-            "https://lh6.googleusercontent.com/-erbF--z-W4s/URqu1ajSLkI/AAAAAAAAAbs/xjDCDO1INzM/s240-c/Longue%252520Vue.jpg",
-            "https://lh6.googleusercontent.com/-0CXJRdJaqvc/URqu1opNZNI/AAAAAAAAAbs/PFB2oPUU7Lk/s240-c/Look%252520Me%252520in%252520the%252520Eye.jpg",
-            "https://lh3.googleusercontent.com/-D_5lNxnDN6g/URqu2Tk7HVI/AAAAAAAAAbs/p0ddca9W__Y/s240-c/Lost%252520in%252520a%252520Field.jpg",
-            "https://lh6.googleusercontent.com/-flsqwMrIk2Q/URqu24PcmjI/AAAAAAAAAbs/5ocIH85XofM/s240-c/Marshall%252520Beach%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-Y4lgryEVTmU/URqu28kG3gI/AAAAAAAAAbs/OjXpekqtbJ4/s240-c/Mono%252520Lake%252520Blue.jpg",
-            "https://lh4.googleusercontent.com/-AaHAJPmcGYA/URqu3PIldHI/AAAAAAAAAbs/lcTqk1SIcRs/s240-c/Monument%252520Valley%252520Overlook.jpg",
-            "https://lh4.googleusercontent.com/-vKxfdQ83dQA/URqu31Yq_BI/AAAAAAAAAbs/OUoGk_2AyfM/s240-c/Moving%252520Rock.jpg",
-            "https://lh5.googleusercontent.com/-CG62QiPpWXg/URqu4ia4vRI/AAAAAAAAAbs/0YOdqLAlcAc/s240-c/Napali%252520Coast.jpg",
-            "https://lh6.googleusercontent.com/-wdGrP5PMmJQ/URqu5PZvn7I/AAAAAAAAAbs/m0abEcdPXe4/s240-c/One%252520Wheel.jpg",
-            "https://lh6.googleusercontent.com/-6WS5DoCGuOA/URqu5qx1UgI/AAAAAAAAAbs/giMw2ixPvrY/s240-c/Open%252520Sky.jpg",
-            "https://lh6.googleusercontent.com/-u8EHKj8G8GQ/URqu55sM6yI/AAAAAAAAAbs/lIXX_GlTdmI/s240-c/Orange%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-74Z5qj4bTDE/URqu6LSrJrI/AAAAAAAAAbs/XzmVkw90szQ/s240-c/Orchid.jpg",
-            "https://lh6.googleusercontent.com/-lEQE4h6TePE/URqu6t_lSkI/AAAAAAAAAbs/zvGYKOea_qY/s240-c/Over%252520there.jpg",
-            "https://lh5.googleusercontent.com/-cauH-53JH2M/URqu66v_USI/AAAAAAAAAbs/EucwwqclfKQ/s240-c/Plumes.jpg",
-            "https://lh3.googleusercontent.com/-eDLT2jHDoy4/URqu7axzkAI/AAAAAAAAAbs/iVZE-xJ7lZs/s240-c/Rainbokeh.jpg",
-            "https://lh5.googleusercontent.com/-j1NLqEFIyco/URqu8L1CGcI/AAAAAAAAAbs/aqZkgX66zlI/s240-c/Rainbow.jpg",
-            "https://lh5.googleusercontent.com/-DRnqmK0t4VU/URqu8XYN9yI/AAAAAAAAAbs/LgvF_592WLU/s240-c/Rice%252520Fields.jpg",
-            "https://lh3.googleusercontent.com/-hwh1v3EOGcQ/URqu8qOaKwI/AAAAAAAAAbs/IljRJRnbJGw/s240-c/Rockaway%252520Fire%252520Sky.jpg",
-            "https://lh5.googleusercontent.com/-wjV6FQk7tlk/URqu9jCQ8sI/AAAAAAAAAbs/RyYUpdo-c9o/s240-c/Rockaway%252520Flow.jpg",
-            "https://lh6.googleusercontent.com/-6cAXNfo7D20/URqu-BdzgPI/AAAAAAAAAbs/OmsYllzJqwo/s240-c/Rockaway%252520Sunset%252520Sky.jpg",
-            "https://lh3.googleusercontent.com/-sl8fpGPS-RE/URqu_BOkfgI/AAAAAAAAAbs/Dg2Fv-JxOeg/s240-c/Russian%252520Ridge%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-gVtY36mMBIg/URqu_q91lkI/AAAAAAAAAbs/3CiFMBcy5MA/s240-c/Rust%252520Knot.jpg",
-            "https://lh6.googleusercontent.com/-GHeImuHqJBE/URqu_FKfVLI/AAAAAAAAAbs/axuEJeqam7Q/s240-c/Sailing%252520Stones.jpg",
-            "https://lh3.googleusercontent.com/-hBbYZjTOwGc/URqu_ycpIrI/AAAAAAAAAbs/nAdJUXnGJYE/s240-c/Seahorse.jpg",
-            "https://lh3.googleusercontent.com/-Iwi6-i6IexY/URqvAYZHsVI/AAAAAAAAAbs/5ETWl4qXsFE/s240-c/Shinjuku%252520Street.jpg",
-            "https://lh6.googleusercontent.com/-amhnySTM_MY/URqvAlb5KoI/AAAAAAAAAbs/pFCFgzlKsn0/s240-c/Sierra%252520Heavens.jpg",
-            "https://lh5.googleusercontent.com/-dJgjepFrYSo/URqvBVJZrAI/AAAAAAAAAbs/v-F5QWpYO6s/s240-c/Sierra%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-Z4zGiC5nWdc/URqvBdEwivI/AAAAAAAAAbs/ZRZR1VJ84QA/s240-c/Sin%252520Lights.jpg",
-            "https://lh4.googleusercontent.com/-_0cYiWW8ccY/URqvBz3iM4I/AAAAAAAAAbs/9N_Wq8MhLTY/s240-c/Starry%252520Lake.jpg",
-            "https://lh3.googleusercontent.com/-A9LMoRyuQUA/URqvCYx_JoI/AAAAAAAAAbs/s7sde1Bz9cI/s240-c/Starry%252520Night.jpg",
-            "https://lh3.googleusercontent.com/-KtLJ3k858eY/URqvC_2h_bI/AAAAAAAAAbs/zzEBImwDA_g/s240-c/Stream.jpg",
-            "https://lh5.googleusercontent.com/-dFB7Lad6RcA/URqvDUftwWI/AAAAAAAAAbs/BrhoUtXTN7o/s240-c/Strip%252520Sunset.jpg",
-            "https://lh5.googleusercontent.com/-at6apgFiN20/URqvDyffUZI/AAAAAAAAAbs/clABCx171bE/s240-c/Sunset%252520Hills.jpg",
-            "https://lh4.googleusercontent.com/-7-EHhtQthII/URqvEYTk4vI/AAAAAAAAAbs/QSJZoB3YjVg/s240-c/Tenaya%252520Lake%2525202.jpg",
-            "https://lh6.googleusercontent.com/-8MrjV_a-Pok/URqvFC5repI/AAAAAAAAAbs/9inKTg9fbCE/s240-c/Tenaya%252520Lake.jpg",
-            "https://lh5.googleusercontent.com/-B1HW-z4zwao/URqvFWYRwUI/AAAAAAAAAbs/8Peli53Bs8I/s240-c/The%252520Cave%252520BW.jpg",
-            "https://lh3.googleusercontent.com/-PO4E-xZKAnQ/URqvGRqjYkI/AAAAAAAAAbs/42nyADFsXag/s240-c/The%252520Fisherman.jpg",
-            "https://lh4.googleusercontent.com/-iLyZlzfdy7s/URqvG0YScdI/AAAAAAAAAbs/1J9eDKmkXtk/s240-c/The%252520Night%252520is%252520Coming.jpg",
-            "https://lh6.googleusercontent.com/-G-k7YkkUco0/URqvHhah6fI/AAAAAAAAAbs/_taQQG7t0vo/s240-c/The%252520Road.jpg",
-            "https://lh6.googleusercontent.com/-h-ALJt7kSus/URqvIThqYfI/AAAAAAAAAbs/ejiv35olWS8/s240-c/Tokyo%252520Heights.jpg",
-            "https://lh5.googleusercontent.com/-Hy9k-TbS7xg/URqvIjQMOxI/AAAAAAAAAbs/RSpmmOATSkg/s240-c/Tokyo%252520Highway.jpg",
-            "https://lh6.googleusercontent.com/-83oOvMb4OZs/URqvJL0T7lI/AAAAAAAAAbs/c5TECZ6RONM/s240-c/Tokyo%252520Smog.jpg",
-            "https://lh3.googleusercontent.com/-FB-jfgREEfI/URqvJI3EXAI/AAAAAAAAAbs/XfyweiRF4v8/s240-c/Tufa%252520at%252520Night.jpg",
-            "https://lh4.googleusercontent.com/-vngKD5Z1U8w/URqvJUCEgPI/AAAAAAAAAbs/ulxCMVcU6EU/s240-c/Valley%252520Sunset.jpg",
-            "https://lh6.googleusercontent.com/-DOz5I2E2oMQ/URqvKMND1kI/AAAAAAAAAbs/Iqf0IsInleo/s240-c/Windmill%252520Sunrise.jpg",
-            "https://lh5.googleusercontent.com/-biyiyWcJ9MU/URqvKculiAI/AAAAAAAAAbs/jyPsCplJOpE/s240-c/Windmill.jpg",
-            "https://lh4.googleusercontent.com/-PDT167_xRdA/URqvK36mLcI/AAAAAAAAAbs/oi2ik9QseMI/s240-c/Windmills.jpg",
-            "https://lh5.googleusercontent.com/-kI_QdYx7VlU/URqvLXCB6gI/AAAAAAAAAbs/N31vlZ6u89o/s240-c/Yet%252520Another%252520Rockaway%252520Sunset.jpg",
-            "https://lh4.googleusercontent.com/-e9NHZ5k5MSs/URqvMIBZjtI/AAAAAAAAAbs/1fV810rDNfQ/s240-c/Yosemite%252520Tree.jpg",
-    };
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageDetailActivity.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageDetailActivity.java
deleted file mode 100644
index 05d7b03..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageDetailActivity.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.ui;
-
-import android.annotation.TargetApi;
-import android.app.ActionBar;
-import android.os.Build.VERSION_CODES;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentStatePagerAdapter;
-import android.support.v4.app.NavUtils;
-import android.support.v4.view.ViewPager;
-import android.util.DisplayMetrics;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.WindowManager.LayoutParams;
-import android.widget.Toast;
-
-import com.example.android.bitmapfun.BuildConfig;
-import com.example.android.bitmapfun.R;
-import com.example.android.bitmapfun.provider.Images;
-import com.example.android.bitmapfun.util.ImageCache;
-import com.example.android.bitmapfun.util.ImageFetcher;
-import com.example.android.bitmapfun.util.Utils;
-
-public class ImageDetailActivity extends FragmentActivity implements OnClickListener {
-    private static final String IMAGE_CACHE_DIR = "images";
-    public static final String EXTRA_IMAGE = "extra_image";
-
-    private ImagePagerAdapter mAdapter;
-    private ImageFetcher mImageFetcher;
-    private ViewPager mPager;
-
-    @TargetApi(VERSION_CODES.HONEYCOMB)
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        if (BuildConfig.DEBUG) {
-            Utils.enableStrictMode();
-        }
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.image_detail_pager);
-
-        // Fetch screen height and width, to use as our max size when loading images as this
-        // activity runs full screen
-        final DisplayMetrics displayMetrics = new DisplayMetrics();
-        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
-        final int height = displayMetrics.heightPixels;
-        final int width = displayMetrics.widthPixels;
-
-        // For this sample we'll use half of the longest width to resize our images. As the
-        // image scaling ensures the image is larger than this, we should be left with a
-        // resolution that is appropriate for both portrait and landscape. For best image quality
-        // we shouldn't divide by 2, but this will use more memory and require a larger memory
-        // cache.
-        final int longest = (height > width ? height : width) / 2;
-
-        ImageCache.ImageCacheParams cacheParams =
-                new ImageCache.ImageCacheParams(this, IMAGE_CACHE_DIR);
-        cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 25% of app memory
-
-        // The ImageFetcher takes care of loading images into our ImageView children asynchronously
-        mImageFetcher = new ImageFetcher(this, longest);
-        mImageFetcher.addImageCache(getSupportFragmentManager(), cacheParams);
-        mImageFetcher.setImageFadeIn(false);
-
-        // Set up ViewPager and backing adapter
-        mAdapter = new ImagePagerAdapter(getSupportFragmentManager(), Images.imageUrls.length);
-        mPager = (ViewPager) findViewById(R.id.pager);
-        mPager.setAdapter(mAdapter);
-        mPager.setPageMargin((int) getResources().getDimension(R.dimen.image_detail_pager_margin));
-        mPager.setOffscreenPageLimit(2);
-
-        // Set up activity to go full screen
-        getWindow().addFlags(LayoutParams.FLAG_FULLSCREEN);
-
-        // Enable some additional newer visibility and ActionBar features to create a more
-        // immersive photo viewing experience
-        if (Utils.hasHoneycomb()) {
-            final ActionBar actionBar = getActionBar();
-
-            // Hide title text and set home as up
-            actionBar.setDisplayShowTitleEnabled(false);
-            actionBar.setDisplayHomeAsUpEnabled(true);
-
-            // Hide and show the ActionBar as the visibility changes
-            mPager.setOnSystemUiVisibilityChangeListener(
-                    new View.OnSystemUiVisibilityChangeListener() {
-                        @Override
-                        public void onSystemUiVisibilityChange(int vis) {
-                            if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
-                                actionBar.hide();
-                            } else {
-                                actionBar.show();
-                            }
-                        }
-                    });
-
-            // Start low profile mode and hide ActionBar
-            mPager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
-            actionBar.hide();
-        }
-
-        // Set the current item based on the extra passed in to this activity
-        final int extraCurrentItem = getIntent().getIntExtra(EXTRA_IMAGE, -1);
-        if (extraCurrentItem != -1) {
-            mPager.setCurrentItem(extraCurrentItem);
-        }
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mImageFetcher.setExitTasksEarly(false);
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mImageFetcher.setExitTasksEarly(true);
-        mImageFetcher.flushCache();
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        mImageFetcher.closeCache();
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case android.R.id.home:
-                NavUtils.navigateUpFromSameTask(this);
-                return true;
-            case R.id.clear_cache:
-                mImageFetcher.clearCache();
-                Toast.makeText(
-                        this, R.string.clear_cache_complete_toast,Toast.LENGTH_SHORT).show();
-                return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.main_menu, menu);
-        return true;
-    }
-
-    /**
-     * Called by the ViewPager child fragments to load images via the one ImageFetcher
-     */
-    public ImageFetcher getImageFetcher() {
-        return mImageFetcher;
-    }
-
-    /**
-     * The main adapter that backs the ViewPager. A subclass of FragmentStatePagerAdapter as there
-     * could be a large number of items in the ViewPager and we don't want to retain them all in
-     * memory at once but create/destroy them on the fly.
-     */
-    private class ImagePagerAdapter extends FragmentStatePagerAdapter {
-        private final int mSize;
-
-        public ImagePagerAdapter(FragmentManager fm, int size) {
-            super(fm);
-            mSize = size;
-        }
-
-        @Override
-        public int getCount() {
-            return mSize;
-        }
-
-        @Override
-        public Fragment getItem(int position) {
-            return ImageDetailFragment.newInstance(Images.imageUrls[position]);
-        }
-    }
-
-    /**
-     * Set on the ImageView in the ViewPager children fragments, to enable/disable low profile mode
-     * when the ImageView is touched.
-     */
-    @TargetApi(VERSION_CODES.HONEYCOMB)
-    @Override
-    public void onClick(View v) {
-        final int vis = mPager.getSystemUiVisibility();
-        if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
-            mPager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
-        } else {
-            mPager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
-        }
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageDetailFragment.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageDetailFragment.java
deleted file mode 100644
index 9fff8a0..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageDetailFragment.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.ui;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-
-import com.example.android.bitmapfun.R;
-import com.example.android.bitmapfun.util.ImageFetcher;
-import com.example.android.bitmapfun.util.ImageWorker;
-import com.example.android.bitmapfun.util.Utils;
-
-/**
- * This fragment will populate the children of the ViewPager from {@link ImageDetailActivity}.
- */
-public class ImageDetailFragment extends Fragment {
-    private static final String IMAGE_DATA_EXTRA = "extra_image_data";
-    private String mImageUrl;
-    private ImageView mImageView;
-    private ImageFetcher mImageFetcher;
-
-    /**
-     * Factory method to generate a new instance of the fragment given an image number.
-     *
-     * @param imageUrl The image url to load
-     * @return A new instance of ImageDetailFragment with imageNum extras
-     */
-    public static ImageDetailFragment newInstance(String imageUrl) {
-        final ImageDetailFragment f = new ImageDetailFragment();
-
-        final Bundle args = new Bundle();
-        args.putString(IMAGE_DATA_EXTRA, imageUrl);
-        f.setArguments(args);
-
-        return f;
-    }
-
-    /**
-     * Empty constructor as per the Fragment documentation
-     */
-    public ImageDetailFragment() {}
-
-    /**
-     * Populate image using a url from extras, use the convenience factory method
-     * {@link ImageDetailFragment#newInstance(String)} to create this fragment.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mImageUrl = getArguments() != null ? getArguments().getString(IMAGE_DATA_EXTRA) : null;
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        // Inflate and locate the main ImageView
-        final View v = inflater.inflate(R.layout.image_detail_fragment, container, false);
-        mImageView = (ImageView) v.findViewById(R.id.imageView);
-        return v;
-    }
-
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-
-        // Use the parent activity to load the image asynchronously into the ImageView (so a single
-        // cache can be used over all pages in the ViewPager
-        if (ImageDetailActivity.class.isInstance(getActivity())) {
-            mImageFetcher = ((ImageDetailActivity) getActivity()).getImageFetcher();
-            mImageFetcher.loadImage(mImageUrl, mImageView);
-        }
-
-        // Pass clicks on the ImageView to the parent activity to handle
-        if (OnClickListener.class.isInstance(getActivity()) && Utils.hasHoneycomb()) {
-            mImageView.setOnClickListener((OnClickListener) getActivity());
-        }
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        if (mImageView != null) {
-            // Cancel any pending image work
-            ImageWorker.cancelWork(mImageView);
-            mImageView.setImageDrawable(null);
-        }
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageGridActivity.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageGridActivity.java
deleted file mode 100644
index e7c7d1c..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageGridActivity.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.ui;
-
-import android.os.Bundle;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentTransaction;
-
-import com.example.android.bitmapfun.BuildConfig;
-import com.example.android.bitmapfun.util.Utils;
-
-/**
- * Simple FragmentActivity to hold the main {@link ImageGridFragment} and not much else.
- */
-public class ImageGridActivity extends FragmentActivity {
-    private static final String TAG = "ImageGridActivity";
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        if (BuildConfig.DEBUG) {
-            Utils.enableStrictMode();
-        }
-        super.onCreate(savedInstanceState);
-
-        if (getSupportFragmentManager().findFragmentByTag(TAG) == null) {
-            final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
-            ft.add(android.R.id.content, new ImageGridFragment(), TAG);
-            ft.commit();
-        }
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageGridFragment.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageGridFragment.java
deleted file mode 100644
index ba4581a..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/ImageGridFragment.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.ui;
-
-import android.annotation.TargetApi;
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build.VERSION_CODES;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewTreeObserver;
-import android.widget.AbsListView;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import com.example.android.bitmapfun.BuildConfig;
-import com.example.android.bitmapfun.R;
-import com.example.android.bitmapfun.provider.Images;
-import com.example.android.bitmapfun.util.ImageCache.ImageCacheParams;
-import com.example.android.bitmapfun.util.ImageFetcher;
-import com.example.android.bitmapfun.util.Utils;
-
-/**
- * The main fragment that powers the ImageGridActivity screen. Fairly straight forward GridView
- * implementation with the key addition being the ImageWorker class w/ImageCache to load children
- * asynchronously, keeping the UI nice and smooth and caching thumbnails for quick retrieval. The
- * cache is retained over configuration changes like orientation change so the images are populated
- * quickly if, for example, the user rotates the device.
- */
-public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener {
-    private static final String TAG = "ImageGridFragment";
-    private static final String IMAGE_CACHE_DIR = "thumbs";
-
-    private int mImageThumbSize;
-    private int mImageThumbSpacing;
-    private ImageAdapter mAdapter;
-    private ImageFetcher mImageFetcher;
-
-    /**
-     * Empty constructor as per the Fragment documentation
-     */
-    public ImageGridFragment() {}
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setHasOptionsMenu(true);
-
-        mImageThumbSize = getResources().getDimensionPixelSize(R.dimen.image_thumbnail_size);
-        mImageThumbSpacing = getResources().getDimensionPixelSize(R.dimen.image_thumbnail_spacing);
-
-        mAdapter = new ImageAdapter(getActivity());
-
-        ImageCacheParams cacheParams = new ImageCacheParams(getActivity(), IMAGE_CACHE_DIR);
-
-        cacheParams.setMemCacheSizePercent(0.25f); // Set memory cache to 25% of app memory
-
-        // The ImageFetcher takes care of loading images into our ImageView children asynchronously
-        mImageFetcher = new ImageFetcher(getActivity(), mImageThumbSize);
-        mImageFetcher.setLoadingImage(R.drawable.empty_photo);
-        mImageFetcher.addImageCache(getActivity().getSupportFragmentManager(), cacheParams);
-    }
-
-    @Override
-    public View onCreateView(
-            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-
-        final View v = inflater.inflate(R.layout.image_grid_fragment, container, false);
-        final GridView mGridView = (GridView) v.findViewById(R.id.gridView);
-        mGridView.setAdapter(mAdapter);
-        mGridView.setOnItemClickListener(this);
-        mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {
-            @Override
-            public void onScrollStateChanged(AbsListView absListView, int scrollState) {
-                // Pause fetcher to ensure smoother scrolling when flinging
-                if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
-                    // Before Honeycomb pause image loading on scroll to help with performance
-                    if (!Utils.hasHoneycomb()) {
-                        mImageFetcher.setPauseWork(true);
-                    }
-                } else {
-                    mImageFetcher.setPauseWork(false);
-                }
-            }
-
-            @Override
-            public void onScroll(AbsListView absListView, int firstVisibleItem,
-                    int visibleItemCount, int totalItemCount) {
-            }
-        });
-
-        // This listener is used to get the final width of the GridView and then calculate the
-        // number of columns and the width of each column. The width of each column is variable
-        // as the GridView has stretchMode=columnWidth. The column width is used to set the height
-        // of each view so we get nice square thumbnails.
-        mGridView.getViewTreeObserver().addOnGlobalLayoutListener(
-                new ViewTreeObserver.OnGlobalLayoutListener() {
-                    @Override
-                    public void onGlobalLayout() {
-                        if (mAdapter.getNumColumns() == 0) {
-                            final int numColumns = (int) Math.floor(
-                                    mGridView.getWidth() / (mImageThumbSize + mImageThumbSpacing));
-                            if (numColumns > 0) {
-                                final int columnWidth =
-                                        (mGridView.getWidth() / numColumns) - mImageThumbSpacing;
-                                mAdapter.setNumColumns(numColumns);
-                                mAdapter.setItemHeight(columnWidth);
-                                if (BuildConfig.DEBUG) {
-                                    Log.d(TAG, "onCreateView - numColumns set to " + numColumns);
-                                }
-                                if (Utils.hasJellyBean()) {
-                                    mGridView.getViewTreeObserver()
-                                            .removeOnGlobalLayoutListener(this);
-                                } else {
-                                    mGridView.getViewTreeObserver()
-                                            .removeGlobalOnLayoutListener(this);
-                                }
-                            }
-                        }
-                    }
-                });
-
-        return v;
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mImageFetcher.setExitTasksEarly(false);
-        mAdapter.notifyDataSetChanged();
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mImageFetcher.setPauseWork(false);
-        mImageFetcher.setExitTasksEarly(true);
-        mImageFetcher.flushCache();
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        mImageFetcher.closeCache();
-    }
-
-    @TargetApi(VERSION_CODES.JELLY_BEAN)
-    @Override
-    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
-        final Intent i = new Intent(getActivity(), ImageDetailActivity.class);
-        i.putExtra(ImageDetailActivity.EXTRA_IMAGE, (int) id);
-        if (Utils.hasJellyBean()) {
-            // makeThumbnailScaleUpAnimation() looks kind of ugly here as the loading spinner may
-            // show plus the thumbnail image in GridView is cropped. so using
-            // makeScaleUpAnimation() instead.
-            ActivityOptions options =
-                    ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight());
-            getActivity().startActivity(i, options.toBundle());
-        } else {
-            startActivity(i);
-        }
-    }
-
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        inflater.inflate(R.menu.main_menu, menu);
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case R.id.clear_cache:
-                mImageFetcher.clearCache();
-                Toast.makeText(getActivity(), R.string.clear_cache_complete_toast,
-                        Toast.LENGTH_SHORT).show();
-                return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-    /**
-     * The main adapter that backs the GridView. This is fairly standard except the number of
-     * columns in the GridView is used to create a fake top row of empty views as we use a
-     * transparent ActionBar and don't want the real top row of images to start off covered by it.
-     */
-    private class ImageAdapter extends BaseAdapter {
-
-        private final Context mContext;
-        private int mItemHeight = 0;
-        private int mNumColumns = 0;
-        private int mActionBarHeight = 0;
-        private GridView.LayoutParams mImageViewLayoutParams;
-
-        public ImageAdapter(Context context) {
-            super();
-            mContext = context;
-            mImageViewLayoutParams = new GridView.LayoutParams(
-                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
-            // Calculate ActionBar height
-            TypedValue tv = new TypedValue();
-            if (context.getTheme().resolveAttribute(
-                    android.R.attr.actionBarSize, tv, true)) {
-                mActionBarHeight = TypedValue.complexToDimensionPixelSize(
-                        tv.data, context.getResources().getDisplayMetrics());
-            }
-        }
-
-        @Override
-        public int getCount() {
-            // If columns have yet to be determined, return no items
-            if (getNumColumns() == 0) {
-                return 0;
-            }
-
-            // Size + number of columns for top empty row
-            return Images.imageThumbUrls.length + mNumColumns;
-        }
-
-        @Override
-        public Object getItem(int position) {
-            return position < mNumColumns ?
-                    null : Images.imageThumbUrls[position - mNumColumns];
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position < mNumColumns ? 0 : position - mNumColumns;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            // Two types of views, the normal ImageView and the top row of empty views
-            return 2;
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            return (position < mNumColumns) ? 1 : 0;
-        }
-
-        @Override
-        public boolean hasStableIds() {
-            return true;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup container) {
-            // First check if this is the top row
-            if (position < mNumColumns) {
-                if (convertView == null) {
-                    convertView = new View(mContext);
-                }
-                // Set empty view with height of ActionBar
-                convertView.setLayoutParams(new AbsListView.LayoutParams(
-                        ViewGroup.LayoutParams.MATCH_PARENT, mActionBarHeight));
-                return convertView;
-            }
-
-            // Now handle the main ImageView thumbnails
-            ImageView imageView;
-            if (convertView == null) { // if it's not recycled, instantiate and initialize
-                imageView = new RecyclingImageView(mContext);
-                imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
-                imageView.setLayoutParams(mImageViewLayoutParams);
-            } else { // Otherwise re-use the converted view
-                imageView = (ImageView) convertView;
-            }
-
-            // Check the height matches our calculated column width
-            if (imageView.getLayoutParams().height != mItemHeight) {
-                imageView.setLayoutParams(mImageViewLayoutParams);
-            }
-
-            // Finally load the image asynchronously into the ImageView, this also takes care of
-            // setting a placeholder image while the background thread runs
-            mImageFetcher.loadImage(Images.imageThumbUrls[position - mNumColumns], imageView);
-            return imageView;
-        }
-
-        /**
-         * Sets the item height. Useful for when we know the column width so the height can be set
-         * to match.
-         *
-         * @param height
-         */
-        public void setItemHeight(int height) {
-            if (height == mItemHeight) {
-                return;
-            }
-            mItemHeight = height;
-            mImageViewLayoutParams =
-                    new GridView.LayoutParams(LayoutParams.MATCH_PARENT, mItemHeight);
-            mImageFetcher.setImageSize(height);
-            notifyDataSetChanged();
-        }
-
-        public void setNumColumns(int numColumns) {
-            mNumColumns = numColumns;
-        }
-
-        public int getNumColumns() {
-            return mNumColumns;
-        }
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/RecyclingImageView.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/RecyclingImageView.java
deleted file mode 100644
index 1bcc014..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/ui/RecyclingImageView.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2013 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.example.android.bitmapfun.ui;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import com.example.android.bitmapfun.util.RecyclingBitmapDrawable;
-
-/**
- * Sub-class of ImageView which automatically notifies the drawable when it is
- * being displayed.
- */
-public class RecyclingImageView extends ImageView {
-
-    public RecyclingImageView(Context context) {
-        super(context);
-    }
-
-    public RecyclingImageView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    /**
-     * @see android.widget.ImageView#onDetachedFromWindow()
-     */
-    @Override
-    protected void onDetachedFromWindow() {
-        // This has been detached from Window, so clear the drawable
-        setImageDrawable(null);
-
-        super.onDetachedFromWindow();
-    }
-
-    /**
-     * @see android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)
-     */
-    @Override
-    public void setImageDrawable(Drawable drawable) {
-        // Keep hold of previous Drawable
-        final Drawable previousDrawable = getDrawable();
-
-        // Call super to set new Drawable
-        super.setImageDrawable(drawable);
-
-        // Notify new Drawable that it is being displayed
-        notifyDrawable(drawable, true);
-
-        // Notify old Drawable so it is no longer being displayed
-        notifyDrawable(previousDrawable, false);
-    }
-
-    /**
-     * Notifies the drawable that it's displayed state has changed.
-     *
-     * @param drawable
-     * @param isDisplayed
-     */
-    private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
-        if (drawable instanceof RecyclingBitmapDrawable) {
-            // The drawable is a CountingBitmapDrawable, so notify it
-            ((RecyclingBitmapDrawable) drawable).setIsDisplayed(isDisplayed);
-        } else if (drawable instanceof LayerDrawable) {
-            // The drawable is a LayerDrawable, so recurse on each layer
-            LayerDrawable layerDrawable = (LayerDrawable) drawable;
-            for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
-                notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
-            }
-        }
-    }
-
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/AsyncTask.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/AsyncTask.java
deleted file mode 100644
index 018ce1a..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/AsyncTask.java
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- * Copyright (C) 2008 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.example.android.bitmapfun.util;
-
-import android.annotation.TargetApi;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Process;
-
-import java.util.ArrayDeque;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * *************************************
- * Copied from JB release framework:
- * https://android.googlesource.com/platform/frameworks/base/+/jb-release/core/java/android/os/AsyncTask.java
- *
- * so that threading behavior on all OS versions is the same and we can tweak behavior by using
- * executeOnExecutor() if needed.
- *
- * There are 3 changes in this copy of AsyncTask:
- *    -pre-HC a single thread executor is used for serial operation
- *    (Executors.newSingleThreadExecutor) and is the default
- *    -the default THREAD_POOL_EXECUTOR was changed to use DiscardOldestPolicy
- *    -a new fixed thread pool called DUAL_THREAD_EXECUTOR was added
- * *************************************
- *
- * <p>AsyncTask enables proper and easy use of the UI thread. This class allows to
- * perform background operations and publish results on the UI thread without
- * having to manipulate threads and/or handlers.</p>
- *
- * <p>AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler}
- * and does not constitute a generic threading framework. AsyncTasks should ideally be
- * used for short operations (a few seconds at the most.) If you need to keep threads
- * running for long periods of time, it is highly recommended you use the various APIs
- * provided by the <code>java.util.concurrent</code> pacakge such as {@link Executor},
- * {@link ThreadPoolExecutor} and {@link FutureTask}.</p>
- *
- * <p>An asynchronous task is defined by a computation that runs on a background thread and
- * whose result is published on the UI thread. An asynchronous task is defined by 3 generic
- * types, called <code>Params</code>, <code>Progress</code> and <code>Result</code>,
- * and 4 steps, called <code>onPreExecute</code>, <code>doInBackground</code>,
- * <code>onProgressUpdate</code> and <code>onPostExecute</code>.</p>
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using tasks and threads, read the
- * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
- * Threads</a> developer guide.</p>
- * </div>
- *
- * <h2>Usage</h2>
- * <p>AsyncTask must be subclassed to be used. The subclass will override at least
- * one method ({@link #doInBackground}), and most often will override a
- * second one ({@link #onPostExecute}.)</p>
- *
- * <p>Here is an example of subclassing:</p>
- * <pre class="prettyprint">
- * private class DownloadFilesTask extends AsyncTask&lt;URL, Integer, Long&gt; {
- *     protected Long doInBackground(URL... urls) {
- *         int count = urls.length;
- *         long totalSize = 0;
- *         for (int i = 0; i < count; i++) {
- *             totalSize += Downloader.downloadFile(urls[i]);
- *             publishProgress((int) ((i / (float) count) * 100));
- *             // Escape early if cancel() is called
- *             if (isCancelled()) break;
- *         }
- *         return totalSize;
- *     }
- *
- *     protected void onProgressUpdate(Integer... progress) {
- *         setProgressPercent(progress[0]);
- *     }
- *
- *     protected void onPostExecute(Long result) {
- *         showDialog("Downloaded " + result + " bytes");
- *     }
- * }
- * </pre>
- *
- * <p>Once created, a task is executed very simply:</p>
- * <pre class="prettyprint">
- * new DownloadFilesTask().execute(url1, url2, url3);
- * </pre>
- *
- * <h2>AsyncTask's generic types</h2>
- * <p>The three types used by an asynchronous task are the following:</p>
- * <ol>
- *     <li><code>Params</code>, the type of the parameters sent to the task upon
- *     execution.</li>
- *     <li><code>Progress</code>, the type of the progress units published during
- *     the background computation.</li>
- *     <li><code>Result</code>, the type of the result of the background
- *     computation.</li>
- * </ol>
- * <p>Not all types are always used by an asynchronous task. To mark a type as unused,
- * simply use the type {@link Void}:</p>
- * <pre>
- * private class MyTask extends AsyncTask&lt;Void, Void, Void&gt; { ... }
- * </pre>
- *
- * <h2>The 4 steps</h2>
- * <p>When an asynchronous task is executed, the task goes through 4 steps:</p>
- * <ol>
- *     <li>{@link #onPreExecute()}, invoked on the UI thread immediately after the task
- *     is executed. This step is normally used to setup the task, for instance by
- *     showing a progress bar in the user interface.</li>
- *     <li>{@link #doInBackground}, invoked on the background thread
- *     immediately after {@link #onPreExecute()} finishes executing. This step is used
- *     to perform background computation that can take a long time. The parameters
- *     of the asynchronous task are passed to this step. The result of the computation must
- *     be returned by this step and will be passed back to the last step. This step
- *     can also use {@link #publishProgress} to publish one or more units
- *     of progress. These values are published on the UI thread, in the
- *     {@link #onProgressUpdate} step.</li>
- *     <li>{@link #onProgressUpdate}, invoked on the UI thread after a
- *     call to {@link #publishProgress}. The timing of the execution is
- *     undefined. This method is used to display any form of progress in the user
- *     interface while the background computation is still executing. For instance,
- *     it can be used to animate a progress bar or show logs in a text field.</li>
- *     <li>{@link #onPostExecute}, invoked on the UI thread after the background
- *     computation finishes. The result of the background computation is passed to
- *     this step as a parameter.</li>
- * </ol>
- *
- * <h2>Cancelling a task</h2>
- * <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking
- * this method will cause subsequent calls to {@link #isCancelled()} to return true.
- * After invoking this method, {@link #onCancelled(Object)}, instead of
- * {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])}
- * returns. To ensure that a task is cancelled as quickly as possible, you should always
- * check the return value of {@link #isCancelled()} periodically from
- * {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p>
- *
- * <h2>Threading rules</h2>
- * <p>There are a few threading rules that must be followed for this class to
- * work properly:</p>
- * <ul>
- *     <li>The AsyncTask class must be loaded on the UI thread. This is done
- *     automatically as of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}.</li>
- *     <li>The task instance must be created on the UI thread.</li>
- *     <li>{@link #execute} must be invoked on the UI thread.</li>
- *     <li>Do not call {@link #onPreExecute()}, {@link #onPostExecute},
- *     {@link #doInBackground}, {@link #onProgressUpdate} manually.</li>
- *     <li>The task can be executed only once (an exception will be thrown if
- *     a second execution is attempted.)</li>
- * </ul>
- *
- * <h2>Memory observability</h2>
- * <p>AsyncTask guarantees that all callback calls are synchronized in such a way that the following
- * operations are safe without explicit synchronizations.</p>
- * <ul>
- *     <li>Set member fields in the constructor or {@link #onPreExecute}, and refer to them
- *     in {@link #doInBackground}.
- *     <li>Set member fields in {@link #doInBackground}, and refer to them in
- *     {@link #onProgressUpdate} and {@link #onPostExecute}.
- * </ul>
- *
- * <h2>Order of execution</h2>
- * <p>When first introduced, AsyncTasks were executed serially on a single background
- * thread. Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
- * to a pool of threads allowing multiple tasks to operate in parallel. Starting with
- * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are executed on a single
- * thread to avoid common application errors caused by parallel execution.</p>
- * <p>If you truly want parallel execution, you can invoke
- * {@link #executeOnExecutor(java.util.concurrent.Executor, Object[])} with
- * {@link #THREAD_POOL_EXECUTOR}.</p>
- */
-public abstract class AsyncTask<Params, Progress, Result> {
-    private static final String LOG_TAG = "AsyncTask";
-
-    private static final int CORE_POOL_SIZE = 5;
-    private static final int MAXIMUM_POOL_SIZE = 128;
-    private static final int KEEP_ALIVE = 1;
-
-    private static final ThreadFactory  sThreadFactory = new ThreadFactory() {
-        private final AtomicInteger mCount = new AtomicInteger(1);
-
-        public Thread newThread(Runnable r) {
-            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
-        }
-    };
-
-    private static final BlockingQueue<Runnable> sPoolWorkQueue =
-            new LinkedBlockingQueue<Runnable>(10);
-
-    /**
-     * An {@link Executor} that can be used to execute tasks in parallel.
-     */
-    public static final Executor THREAD_POOL_EXECUTOR
-            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
-            TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory,
-            new ThreadPoolExecutor.DiscardOldestPolicy());
-
-    /**
-     * An {@link Executor} that executes tasks one at a time in serial
-     * order.  This serialization is global to a particular process.
-     */
-    public static final Executor SERIAL_EXECUTOR = Utils.hasHoneycomb() ? new SerialExecutor() :
-            Executors.newSingleThreadExecutor(sThreadFactory);
-
-    public static final Executor DUAL_THREAD_EXECUTOR =
-            Executors.newFixedThreadPool(2, sThreadFactory);
-
-    private static final int MESSAGE_POST_RESULT = 0x1;
-    private static final int MESSAGE_POST_PROGRESS = 0x2;
-
-    private static final InternalHandler sHandler = new InternalHandler();
-
-    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
-    private final WorkerRunnable<Params, Result> mWorker;
-    private final FutureTask<Result> mFuture;
-
-    private volatile Status mStatus = Status.PENDING;
-
-    private final AtomicBoolean mCancelled = new AtomicBoolean();
-    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
-
-    @TargetApi(11)
-    private static class SerialExecutor implements Executor {
-        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
-        Runnable mActive;
-
-        public synchronized void execute(final Runnable r) {
-            mTasks.offer(new Runnable() {
-                public void run() {
-                    try {
-                        r.run();
-                    } finally {
-                        scheduleNext();
-                    }
-                }
-            });
-            if (mActive == null) {
-                scheduleNext();
-            }
-        }
-
-        protected synchronized void scheduleNext() {
-            if ((mActive = mTasks.poll()) != null) {
-                THREAD_POOL_EXECUTOR.execute(mActive);
-            }
-        }
-    }
-
-    /**
-     * Indicates the current status of the task. Each status will be set only once
-     * during the lifetime of a task.
-     */
-    public enum Status {
-        /**
-         * Indicates that the task has not been executed yet.
-         */
-        PENDING,
-        /**
-         * Indicates that the task is running.
-         */
-        RUNNING,
-        /**
-         * Indicates that {@link AsyncTask#onPostExecute} has finished.
-         */
-        FINISHED,
-    }
-
-    /** @hide Used to force static handler to be created. */
-    public static void init() {
-        sHandler.getLooper();
-    }
-
-    /** @hide */
-    public static void setDefaultExecutor(Executor exec) {
-        sDefaultExecutor = exec;
-    }
-
-    /**
-     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
-     */
-    public AsyncTask() {
-        mWorker = new WorkerRunnable<Params, Result>() {
-            public Result call() throws Exception {
-                mTaskInvoked.set(true);
-
-                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-                //noinspection unchecked
-                return postResult(doInBackground(mParams));
-            }
-        };
-
-        mFuture = new FutureTask<Result>(mWorker) {
-            @Override
-            protected void done() {
-                try {
-                    postResultIfNotInvoked(get());
-                } catch (InterruptedException e) {
-                    android.util.Log.w(LOG_TAG, e);
-                } catch (ExecutionException e) {
-                    throw new RuntimeException("An error occured while executing doInBackground()",
-                            e.getCause());
-                } catch (CancellationException e) {
-                    postResultIfNotInvoked(null);
-                }
-            }
-        };
-    }
-
-    private void postResultIfNotInvoked(Result result) {
-        final boolean wasTaskInvoked = mTaskInvoked.get();
-        if (!wasTaskInvoked) {
-            postResult(result);
-        }
-    }
-
-    private Result postResult(Result result) {
-        @SuppressWarnings("unchecked")
-        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
-                new AsyncTaskResult<Result>(this, result));
-        message.sendToTarget();
-        return result;
-    }
-
-    /**
-     * Returns the current status of this task.
-     *
-     * @return The current status.
-     */
-    public final Status getStatus() {
-        return mStatus;
-    }
-
-    /**
-     * Override this method to perform a computation on a background thread. The
-     * specified parameters are the parameters passed to {@link #execute}
-     * by the caller of this task.
-     *
-     * This method can call {@link #publishProgress} to publish updates
-     * on the UI thread.
-     *
-     * @param params The parameters of the task.
-     *
-     * @return A result, defined by the subclass of this task.
-     *
-     * @see #onPreExecute()
-     * @see #onPostExecute
-     * @see #publishProgress
-     */
-    protected abstract Result doInBackground(Params... params);
-
-    /**
-     * Runs on the UI thread before {@link #doInBackground}.
-     *
-     * @see #onPostExecute
-     * @see #doInBackground
-     */
-    protected void onPreExecute() {
-    }
-
-    /**
-     * <p>Runs on the UI thread after {@link #doInBackground}. The
-     * specified result is the value returned by {@link #doInBackground}.</p>
-     *
-     * <p>This method won't be invoked if the task was cancelled.</p>
-     *
-     * @param result The result of the operation computed by {@link #doInBackground}.
-     *
-     * @see #onPreExecute
-     * @see #doInBackground
-     * @see #onCancelled(Object)
-     */
-    @SuppressWarnings({"UnusedDeclaration"})
-    protected void onPostExecute(Result result) {
-    }
-
-    /**
-     * Runs on the UI thread after {@link #publishProgress} is invoked.
-     * The specified values are the values passed to {@link #publishProgress}.
-     *
-     * @param values The values indicating progress.
-     *
-     * @see #publishProgress
-     * @see #doInBackground
-     */
-    @SuppressWarnings({"UnusedDeclaration"})
-    protected void onProgressUpdate(Progress... values) {
-    }
-
-    /**
-     * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
-     * {@link #doInBackground(Object[])} has finished.</p>
-     *
-     * <p>The default implementation simply invokes {@link #onCancelled()} and
-     * ignores the result. If you write your own implementation, do not call
-     * <code>super.onCancelled(result)</code>.</p>
-     *
-     * @param result The result, if any, computed in
-     *               {@link #doInBackground(Object[])}, can be null
-     *
-     * @see #cancel(boolean)
-     * @see #isCancelled()
-     */
-    @SuppressWarnings({"UnusedParameters"})
-    protected void onCancelled(Result result) {
-        onCancelled();
-    }
-
-    /**
-     * <p>Applications should preferably override {@link #onCancelled(Object)}.
-     * This method is invoked by the default implementation of
-     * {@link #onCancelled(Object)}.</p>
-     *
-     * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
-     * {@link #doInBackground(Object[])} has finished.</p>
-     *
-     * @see #onCancelled(Object)
-     * @see #cancel(boolean)
-     * @see #isCancelled()
-     */
-    protected void onCancelled() {
-    }
-
-    /**
-     * Returns <tt>true</tt> if this task was cancelled before it completed
-     * normally. If you are calling {@link #cancel(boolean)} on the task,
-     * the value returned by this method should be checked periodically from
-     * {@link #doInBackground(Object[])} to end the task as soon as possible.
-     *
-     * @return <tt>true</tt> if task was cancelled before it completed
-     *
-     * @see #cancel(boolean)
-     */
-    public final boolean isCancelled() {
-        return mCancelled.get();
-    }
-
-    /**
-     * <p>Attempts to cancel execution of this task.  This attempt will
-     * fail if the task has already completed, already been cancelled,
-     * or could not be cancelled for some other reason. If successful,
-     * and this task has not started when <tt>cancel</tt> is called,
-     * this task should never run. If the task has already started,
-     * then the <tt>mayInterruptIfRunning</tt> parameter determines
-     * whether the thread executing this task should be interrupted in
-     * an attempt to stop the task.</p>
-     *
-     * <p>Calling this method will result in {@link #onCancelled(Object)} being
-     * invoked on the UI thread after {@link #doInBackground(Object[])}
-     * returns. Calling this method guarantees that {@link #onPostExecute(Object)}
-     * is never invoked. After invoking this method, you should check the
-     * value returned by {@link #isCancelled()} periodically from
-     * {@link #doInBackground(Object[])} to finish the task as early as
-     * possible.</p>
-     *
-     * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
-     *        task should be interrupted; otherwise, in-progress tasks are allowed
-     *        to complete.
-     *
-     * @return <tt>false</tt> if the task could not be cancelled,
-     *         typically because it has already completed normally;
-     *         <tt>true</tt> otherwise
-     *
-     * @see #isCancelled()
-     * @see #onCancelled(Object)
-     */
-    public final boolean cancel(boolean mayInterruptIfRunning) {
-        mCancelled.set(true);
-        return mFuture.cancel(mayInterruptIfRunning);
-    }
-
-    /**
-     * Waits if necessary for the computation to complete, and then
-     * retrieves its result.
-     *
-     * @return The computed result.
-     *
-     * @throws CancellationException If the computation was cancelled.
-     * @throws ExecutionException If the computation threw an exception.
-     * @throws InterruptedException If the current thread was interrupted
-     *         while waiting.
-     */
-    public final Result get() throws InterruptedException, ExecutionException {
-        return mFuture.get();
-    }
-
-    /**
-     * Waits if necessary for at most the given time for the computation
-     * to complete, and then retrieves its result.
-     *
-     * @param timeout Time to wait before cancelling the operation.
-     * @param unit The time unit for the timeout.
-     *
-     * @return The computed result.
-     *
-     * @throws CancellationException If the computation was cancelled.
-     * @throws ExecutionException If the computation threw an exception.
-     * @throws InterruptedException If the current thread was interrupted
-     *         while waiting.
-     * @throws TimeoutException If the wait timed out.
-     */
-    public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
-            ExecutionException, TimeoutException {
-        return mFuture.get(timeout, unit);
-    }
-
-    /**
-     * Executes the task with the specified parameters. The task returns
-     * itself (this) so that the caller can keep a reference to it.
-     *
-     * <p>Note: this function schedules the task on a queue for a single background
-     * thread or pool of threads depending on the platform version.  When first
-     * introduced, AsyncTasks were executed serially on a single background thread.
-     * Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
-     * to a pool of threads allowing multiple tasks to operate in parallel. Starting
-     * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being
-     * executed on a single thread to avoid common application errors caused
-     * by parallel execution.  If you truly want parallel execution, you can use
-     * the {@link #executeOnExecutor} version of this method
-     * with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings
-     * on its use.
-     *
-     * <p>This method must be invoked on the UI thread.
-     *
-     * @param params The parameters of the task.
-     *
-     * @return This instance of AsyncTask.
-     *
-     * @throws IllegalStateException If {@link #getStatus()} returns either
-     *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
-     *
-     * @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
-     * @see #execute(Runnable)
-     */
-    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
-        return executeOnExecutor(sDefaultExecutor, params);
-    }
-
-    /**
-     * Executes the task with the specified parameters. The task returns
-     * itself (this) so that the caller can keep a reference to it.
-     *
-     * <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to
-     * allow multiple tasks to run in parallel on a pool of threads managed by
-     * AsyncTask, however you can also use your own {@link Executor} for custom
-     * behavior.
-     *
-     * <p><em>Warning:</em> Allowing multiple tasks to run in parallel from
-     * a thread pool is generally <em>not</em> what one wants, because the order
-     * of their operation is not defined.  For example, if these tasks are used
-     * to modify any state in common (such as writing a file due to a button click),
-     * there are no guarantees on the order of the modifications.
-     * Without careful work it is possible in rare cases for the newer version
-     * of the data to be over-written by an older one, leading to obscure data
-     * loss and stability issues.  Such changes are best
-     * executed in serial; to guarantee such work is serialized regardless of
-     * platform version you can use this function with {@link #SERIAL_EXECUTOR}.
-     *
-     * <p>This method must be invoked on the UI thread.
-     *
-     * @param exec The executor to use.  {@link #THREAD_POOL_EXECUTOR} is available as a
-     *              convenient process-wide thread pool for tasks that are loosely coupled.
-     * @param params The parameters of the task.
-     *
-     * @return This instance of AsyncTask.
-     *
-     * @throws IllegalStateException If {@link #getStatus()} returns either
-     *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
-     *
-     * @see #execute(Object[])
-     */
-    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
-            Params... params) {
-        if (mStatus != Status.PENDING) {
-            switch (mStatus) {
-                case RUNNING:
-                    throw new IllegalStateException("Cannot execute task:"
-                            + " the task is already running.");
-                case FINISHED:
-                    throw new IllegalStateException("Cannot execute task:"
-                            + " the task has already been executed "
-                            + "(a task can be executed only once)");
-            }
-        }
-
-        mStatus = Status.RUNNING;
-
-        onPreExecute();
-
-        mWorker.mParams = params;
-        exec.execute(mFuture);
-
-        return this;
-    }
-
-    /**
-     * Convenience version of {@link #execute(Object...)} for use with
-     * a simple Runnable object. See {@link #execute(Object[])} for more
-     * information on the order of execution.
-     *
-     * @see #execute(Object[])
-     * @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
-     */
-    public static void execute(Runnable runnable) {
-        sDefaultExecutor.execute(runnable);
-    }
-
-    /**
-     * This method can be invoked from {@link #doInBackground} to
-     * publish updates on the UI thread while the background computation is
-     * still running. Each call to this method will trigger the execution of
-     * {@link #onProgressUpdate} on the UI thread.
-     *
-     * {@link #onProgressUpdate} will note be called if the task has been
-     * canceled.
-     *
-     * @param values The progress values to update the UI with.
-     *
-     * @see #onProgressUpdate
-     * @see #doInBackground
-     */
-    protected final void publishProgress(Progress... values) {
-        if (!isCancelled()) {
-            sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
-                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
-        }
-    }
-
-    private void finish(Result result) {
-        if (isCancelled()) {
-            onCancelled(result);
-        } else {
-            onPostExecute(result);
-        }
-        mStatus = Status.FINISHED;
-    }
-
-    private static class InternalHandler extends Handler {
-        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
-        @Override
-        public void handleMessage(Message msg) {
-            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
-            switch (msg.what) {
-                case MESSAGE_POST_RESULT:
-                    // There is only one result
-                    result.mTask.finish(result.mData[0]);
-                    break;
-                case MESSAGE_POST_PROGRESS:
-                    result.mTask.onProgressUpdate(result.mData);
-                    break;
-            }
-        }
-    }
-
-    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
-        Params[] mParams;
-    }
-
-    @SuppressWarnings({"RawUseOfParameterizedType"})
-    private static class AsyncTaskResult<Data> {
-        final AsyncTask mTask;
-        final Data[] mData;
-
-        AsyncTaskResult(AsyncTask task, Data... data) {
-            mTask = task;
-            mData = data;
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/DiskLruCache.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/DiskLruCache.java
deleted file mode 100644
index 26cdbd7..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/DiskLruCache.java
+++ /dev/null
@@ -1,953 +0,0 @@
-/*
- * Copyright (C) 2011 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.example.android.bitmapfun.util;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedWriter;
-import java.io.Closeable;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.lang.reflect.Array;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- ******************************************************************************
- * Taken from the JB source code, can be found in:
- * libcore/luni/src/main/java/libcore/io/DiskLruCache.java
- * or direct link:
- * https://android.googlesource.com/platform/libcore/+/android-4.1.1_r1/luni/src/main/java/libcore/io/DiskLruCache.java
- ******************************************************************************
- *
- * A cache that uses a bounded amount of space on a filesystem. Each cache
- * entry has a string key and a fixed number of values. Values are byte
- * sequences, accessible as streams or files. Each value must be between {@code
- * 0} and {@code Integer.MAX_VALUE} bytes in length.
- *
- * <p>The cache stores its data in a directory on the filesystem. This
- * directory must be exclusive to the cache; the cache may delete or overwrite
- * files from its directory. It is an error for multiple processes to use the
- * same cache directory at the same time.
- *
- * <p>This cache limits the number of bytes that it will store on the
- * filesystem. When the number of stored bytes exceeds the limit, the cache will
- * remove entries in the background until the limit is satisfied. The limit is
- * not strict: the cache may temporarily exceed it while waiting for files to be
- * deleted. The limit does not include filesystem overhead or the cache
- * journal so space-sensitive applications should set a conservative limit.
- *
- * <p>Clients call {@link #edit} to create or update the values of an entry. An
- * entry may have only one editor at one time; if a value is not available to be
- * edited then {@link #edit} will return null.
- * <ul>
- *     <li>When an entry is being <strong>created</strong> it is necessary to
- *         supply a full set of values; the empty value should be used as a
- *         placeholder if necessary.
- *     <li>When an entry is being <strong>edited</strong>, it is not necessary
- *         to supply data for every value; values default to their previous
- *         value.
- * </ul>
- * Every {@link #edit} call must be matched by a call to {@link Editor#commit}
- * or {@link Editor#abort}. Committing is atomic: a read observes the full set
- * of values as they were before or after the commit, but never a mix of values.
- *
- * <p>Clients call {@link #get} to read a snapshot of an entry. The read will
- * observe the value at the time that {@link #get} was called. Updates and
- * removals after the call do not impact ongoing reads.
- *
- * <p>This class is tolerant of some I/O errors. If files are missing from the
- * filesystem, the corresponding entries will be dropped from the cache. If
- * an error occurs while writing a cache value, the edit will fail silently.
- * Callers should handle other problems by catching {@code IOException} and
- * responding appropriately.
- */
-public final class DiskLruCache implements Closeable {
-    static final String JOURNAL_FILE = "journal";
-    static final String JOURNAL_FILE_TMP = "journal.tmp";
-    static final String MAGIC = "libcore.io.DiskLruCache";
-    static final String VERSION_1 = "1";
-    static final long ANY_SEQUENCE_NUMBER = -1;
-    private static final String CLEAN = "CLEAN";
-    private static final String DIRTY = "DIRTY";
-    private static final String REMOVE = "REMOVE";
-    private static final String READ = "READ";
-
-    private static final Charset UTF_8 = Charset.forName("UTF-8");
-    private static final int IO_BUFFER_SIZE = 8 * 1024;
-
-    /*
-     * This cache uses a journal file named "journal". A typical journal file
-     * looks like this:
-     *     libcore.io.DiskLruCache
-     *     1
-     *     100
-     *     2
-     *
-     *     CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
-     *     DIRTY 335c4c6028171cfddfbaae1a9c313c52
-     *     CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
-     *     REMOVE 335c4c6028171cfddfbaae1a9c313c52
-     *     DIRTY 1ab96a171faeeee38496d8b330771a7a
-     *     CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
-     *     READ 335c4c6028171cfddfbaae1a9c313c52
-     *     READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
-     *
-     * The first five lines of the journal form its header. They are the
-     * constant string "libcore.io.DiskLruCache", the disk cache's version,
-     * the application's version, the value count, and a blank line.
-     *
-     * Each of the subsequent lines in the file is a record of the state of a
-     * cache entry. Each line contains space-separated values: a state, a key,
-     * and optional state-specific values.
-     *   o DIRTY lines track that an entry is actively being created or updated.
-     *     Every successful DIRTY action should be followed by a CLEAN or REMOVE
-     *     action. DIRTY lines without a matching CLEAN or REMOVE indicate that
-     *     temporary files may need to be deleted.
-     *   o CLEAN lines track a cache entry that has been successfully published
-     *     and may be read. A publish line is followed by the lengths of each of
-     *     its values.
-     *   o READ lines track accesses for LRU.
-     *   o REMOVE lines track entries that have been deleted.
-     *
-     * The journal file is appended to as cache operations occur. The journal may
-     * occasionally be compacted by dropping redundant lines. A temporary file named
-     * "journal.tmp" will be used during compaction; that file should be deleted if
-     * it exists when the cache is opened.
-     */
-
-    private final File directory;
-    private final File journalFile;
-    private final File journalFileTmp;
-    private final int appVersion;
-    private final long maxSize;
-    private final int valueCount;
-    private long size = 0;
-    private Writer journalWriter;
-    private final LinkedHashMap<String, Entry> lruEntries
-            = new LinkedHashMap<String, Entry>(0, 0.75f, true);
-    private int redundantOpCount;
-
-    /**
-     * To differentiate between old and current snapshots, each entry is given
-     * a sequence number each time an edit is committed. A snapshot is stale if
-     * its sequence number is not equal to its entry's sequence number.
-     */
-    private long nextSequenceNumber = 0;
-
-    /* From java.util.Arrays */
-    @SuppressWarnings("unchecked")
-    private static <T> T[] copyOfRange(T[] original, int start, int end) {
-        final int originalLength = original.length; // For exception priority compatibility.
-        if (start > end) {
-            throw new IllegalArgumentException();
-        }
-        if (start < 0 || start > originalLength) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        final int resultLength = end - start;
-        final int copyLength = Math.min(resultLength, originalLength - start);
-        final T[] result = (T[]) Array
-                .newInstance(original.getClass().getComponentType(), resultLength);
-        System.arraycopy(original, start, result, 0, copyLength);
-        return result;
-    }
-
-    /**
-     * Returns the remainder of 'reader' as a string, closing it when done.
-     */
-    public static String readFully(Reader reader) throws IOException {
-        try {
-            StringWriter writer = new StringWriter();
-            char[] buffer = new char[1024];
-            int count;
-            while ((count = reader.read(buffer)) != -1) {
-                writer.write(buffer, 0, count);
-            }
-            return writer.toString();
-        } finally {
-            reader.close();
-        }
-    }
-
-    /**
-     * Returns the ASCII characters up to but not including the next "\r\n", or
-     * "\n".
-     *
-     * @throws java.io.EOFException if the stream is exhausted before the next newline
-     *     character.
-     */
-    public static String readAsciiLine(InputStream in) throws IOException {
-        // TODO: support UTF-8 here instead
-
-        StringBuilder result = new StringBuilder(80);
-        while (true) {
-            int c = in.read();
-            if (c == -1) {
-                throw new EOFException();
-            } else if (c == '\n') {
-                break;
-            }
-
-            result.append((char) c);
-        }
-        int length = result.length();
-        if (length > 0 && result.charAt(length - 1) == '\r') {
-            result.setLength(length - 1);
-        }
-        return result.toString();
-    }
-
-    /**
-     * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
-     */
-    public static void closeQuietly(Closeable closeable) {
-        if (closeable != null) {
-            try {
-                closeable.close();
-            } catch (RuntimeException rethrown) {
-                throw rethrown;
-            } catch (Exception ignored) {
-            }
-        }
-    }
-
-    /**
-     * Recursively delete everything in {@code dir}.
-     */
-    // TODO: this should specify paths as Strings rather than as Files
-    public static void deleteContents(File dir) throws IOException {
-        File[] files = dir.listFiles();
-        if (files == null) {
-            throw new IllegalArgumentException("not a directory: " + dir);
-        }
-        for (File file : files) {
-            if (file.isDirectory()) {
-                deleteContents(file);
-            }
-            if (!file.delete()) {
-                throw new IOException("failed to delete file: " + file);
-            }
-        }
-    }
-
-    /** This cache uses a single background thread to evict entries. */
-    private final ExecutorService executorService = new ThreadPoolExecutor(0, 1,
-            60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
-    private final Callable<Void> cleanupCallable = new Callable<Void>() {
-        @Override public Void call() throws Exception {
-            synchronized (DiskLruCache.this) {
-                if (journalWriter == null) {
-                    return null; // closed
-                }
-                trimToSize();
-                if (journalRebuildRequired()) {
-                    rebuildJournal();
-                    redundantOpCount = 0;
-                }
-            }
-            return null;
-        }
-    };
-
-    private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
-        this.directory = directory;
-        this.appVersion = appVersion;
-        this.journalFile = new File(directory, JOURNAL_FILE);
-        this.journalFileTmp = new File(directory, JOURNAL_FILE_TMP);
-        this.valueCount = valueCount;
-        this.maxSize = maxSize;
-    }
-
-    /**
-     * Opens the cache in {@code directory}, creating a cache if none exists
-     * there.
-     *
-     * @param directory a writable directory
-     * @param appVersion
-     * @param valueCount the number of values per cache entry. Must be positive.
-     * @param maxSize the maximum number of bytes this cache should use to store
-     * @throws IOException if reading or writing the cache directory fails
-     */
-    public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
-            throws IOException {
-        if (maxSize <= 0) {
-            throw new IllegalArgumentException("maxSize <= 0");
-        }
-        if (valueCount <= 0) {
-            throw new IllegalArgumentException("valueCount <= 0");
-        }
-
-        // prefer to pick up where we left off
-        DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
-        if (cache.journalFile.exists()) {
-            try {
-                cache.readJournal();
-                cache.processJournal();
-                cache.journalWriter = new BufferedWriter(new FileWriter(cache.journalFile, true),
-                        IO_BUFFER_SIZE);
-                return cache;
-            } catch (IOException journalIsCorrupt) {
-//                System.logW("DiskLruCache " + directory + " is corrupt: "
-//                        + journalIsCorrupt.getMessage() + ", removing");
-                cache.delete();
-            }
-        }
-
-        // create a new empty cache
-        directory.mkdirs();
-        cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
-        cache.rebuildJournal();
-        return cache;
-    }
-
-    private void readJournal() throws IOException {
-        InputStream in = new BufferedInputStream(new FileInputStream(journalFile), IO_BUFFER_SIZE);
-        try {
-            String magic = readAsciiLine(in);
-            String version = readAsciiLine(in);
-            String appVersionString = readAsciiLine(in);
-            String valueCountString = readAsciiLine(in);
-            String blank = readAsciiLine(in);
-            if (!MAGIC.equals(magic)
-                    || !VERSION_1.equals(version)
-                    || !Integer.toString(appVersion).equals(appVersionString)
-                    || !Integer.toString(valueCount).equals(valueCountString)
-                    || !"".equals(blank)) {
-                throw new IOException("unexpected journal header: ["
-                        + magic + ", " + version + ", " + valueCountString + ", " + blank + "]");
-            }
-
-            while (true) {
-                try {
-                    readJournalLine(readAsciiLine(in));
-                } catch (EOFException endOfJournal) {
-                    break;
-                }
-            }
-        } finally {
-            closeQuietly(in);
-        }
-    }
-
-    private void readJournalLine(String line) throws IOException {
-        String[] parts = line.split(" ");
-        if (parts.length < 2) {
-            throw new IOException("unexpected journal line: " + line);
-        }
-
-        String key = parts[1];
-        if (parts[0].equals(REMOVE) && parts.length == 2) {
-            lruEntries.remove(key);
-            return;
-        }
-
-        Entry entry = lruEntries.get(key);
-        if (entry == null) {
-            entry = new Entry(key);
-            lruEntries.put(key, entry);
-        }
-
-        if (parts[0].equals(CLEAN) && parts.length == 2 + valueCount) {
-            entry.readable = true;
-            entry.currentEditor = null;
-            entry.setLengths(copyOfRange(parts, 2, parts.length));
-        } else if (parts[0].equals(DIRTY) && parts.length == 2) {
-            entry.currentEditor = new Editor(entry);
-        } else if (parts[0].equals(READ) && parts.length == 2) {
-            // this work was already done by calling lruEntries.get()
-        } else {
-            throw new IOException("unexpected journal line: " + line);
-        }
-    }
-
-    /**
-     * Computes the initial size and collects garbage as a part of opening the
-     * cache. Dirty entries are assumed to be inconsistent and will be deleted.
-     */
-    private void processJournal() throws IOException {
-        deleteIfExists(journalFileTmp);
-        for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) {
-            Entry entry = i.next();
-            if (entry.currentEditor == null) {
-                for (int t = 0; t < valueCount; t++) {
-                    size += entry.lengths[t];
-                }
-            } else {
-                entry.currentEditor = null;
-                for (int t = 0; t < valueCount; t++) {
-                    deleteIfExists(entry.getCleanFile(t));
-                    deleteIfExists(entry.getDirtyFile(t));
-                }
-                i.remove();
-            }
-        }
-    }
-
-    /**
-     * Creates a new journal that omits redundant information. This replaces the
-     * current journal if it exists.
-     */
-    private synchronized void rebuildJournal() throws IOException {
-        if (journalWriter != null) {
-            journalWriter.close();
-        }
-
-        Writer writer = new BufferedWriter(new FileWriter(journalFileTmp), IO_BUFFER_SIZE);
-        writer.write(MAGIC);
-        writer.write("\n");
-        writer.write(VERSION_1);
-        writer.write("\n");
-        writer.write(Integer.toString(appVersion));
-        writer.write("\n");
-        writer.write(Integer.toString(valueCount));
-        writer.write("\n");
-        writer.write("\n");
-
-        for (Entry entry : lruEntries.values()) {
-            if (entry.currentEditor != null) {
-                writer.write(DIRTY + ' ' + entry.key + '\n');
-            } else {
-                writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
-            }
-        }
-
-        writer.close();
-        journalFileTmp.renameTo(journalFile);
-        journalWriter = new BufferedWriter(new FileWriter(journalFile, true), IO_BUFFER_SIZE);
-    }
-
-    private static void deleteIfExists(File file) throws IOException {
-//        try {
-//            Libcore.os.remove(file.getPath());
-//        } catch (ErrnoException errnoException) {
-//            if (errnoException.errno != OsConstants.ENOENT) {
-//                throw errnoException.rethrowAsIOException();
-//            }
-//        }
-        if (file.exists() && !file.delete()) {
-            throw new IOException();
-        }
-    }
-
-    /**
-     * Returns a snapshot of the entry named {@code key}, or null if it doesn't
-     * exist is not currently readable. If a value is returned, it is moved to
-     * the head of the LRU queue.
-     */
-    public synchronized Snapshot get(String key) throws IOException {
-        checkNotClosed();
-        validateKey(key);
-        Entry entry = lruEntries.get(key);
-        if (entry == null) {
-            return null;
-        }
-
-        if (!entry.readable) {
-            return null;
-        }
-
-        /*
-         * Open all streams eagerly to guarantee that we see a single published
-         * snapshot. If we opened streams lazily then the streams could come
-         * from different edits.
-         */
-        InputStream[] ins = new InputStream[valueCount];
-        try {
-            for (int i = 0; i < valueCount; i++) {
-                ins[i] = new FileInputStream(entry.getCleanFile(i));
-            }
-        } catch (FileNotFoundException e) {
-            // a file must have been deleted manually!
-            return null;
-        }
-
-        redundantOpCount++;
-        journalWriter.append(READ + ' ' + key + '\n');
-        if (journalRebuildRequired()) {
-            executorService.submit(cleanupCallable);
-        }
-
-        return new Snapshot(key, entry.sequenceNumber, ins);
-    }
-
-    /**
-     * Returns an editor for the entry named {@code key}, or null if another
-     * edit is in progress.
-     */
-    public Editor edit(String key) throws IOException {
-        return edit(key, ANY_SEQUENCE_NUMBER);
-    }
-
-    private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {
-        checkNotClosed();
-        validateKey(key);
-        Entry entry = lruEntries.get(key);
-        if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER
-                && (entry == null || entry.sequenceNumber != expectedSequenceNumber)) {
-            return null; // snapshot is stale
-        }
-        if (entry == null) {
-            entry = new Entry(key);
-            lruEntries.put(key, entry);
-        } else if (entry.currentEditor != null) {
-            return null; // another edit is in progress
-        }
-
-        Editor editor = new Editor(entry);
-        entry.currentEditor = editor;
-
-        // flush the journal before creating files to prevent file leaks
-        journalWriter.write(DIRTY + ' ' + key + '\n');
-        journalWriter.flush();
-        return editor;
-    }
-
-    /**
-     * Returns the directory where this cache stores its data.
-     */
-    public File getDirectory() {
-        return directory;
-    }
-
-    /**
-     * Returns the maximum number of bytes that this cache should use to store
-     * its data.
-     */
-    public long maxSize() {
-        return maxSize;
-    }
-
-    /**
-     * Returns the number of bytes currently being used to store the values in
-     * this cache. This may be greater than the max size if a background
-     * deletion is pending.
-     */
-    public synchronized long size() {
-        return size;
-    }
-
-    private synchronized void completeEdit(Editor editor, boolean success) throws IOException {
-        Entry entry = editor.entry;
-        if (entry.currentEditor != editor) {
-            throw new IllegalStateException();
-        }
-
-        // if this edit is creating the entry for the first time, every index must have a value
-        if (success && !entry.readable) {
-            for (int i = 0; i < valueCount; i++) {
-                if (!entry.getDirtyFile(i).exists()) {
-                    editor.abort();
-                    throw new IllegalStateException("edit didn't create file " + i);
-                }
-            }
-        }
-
-        for (int i = 0; i < valueCount; i++) {
-            File dirty = entry.getDirtyFile(i);
-            if (success) {
-                if (dirty.exists()) {
-                    File clean = entry.getCleanFile(i);
-                    dirty.renameTo(clean);
-                    long oldLength = entry.lengths[i];
-                    long newLength = clean.length();
-                    entry.lengths[i] = newLength;
-                    size = size - oldLength + newLength;
-                }
-            } else {
-                deleteIfExists(dirty);
-            }
-        }
-
-        redundantOpCount++;
-        entry.currentEditor = null;
-        if (entry.readable | success) {
-            entry.readable = true;
-            journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
-            if (success) {
-                entry.sequenceNumber = nextSequenceNumber++;
-            }
-        } else {
-            lruEntries.remove(entry.key);
-            journalWriter.write(REMOVE + ' ' + entry.key + '\n');
-        }
-
-        if (size > maxSize || journalRebuildRequired()) {
-            executorService.submit(cleanupCallable);
-        }
-    }
-
-    /**
-     * We only rebuild the journal when it will halve the size of the journal
-     * and eliminate at least 2000 ops.
-     */
-    private boolean journalRebuildRequired() {
-        final int REDUNDANT_OP_COMPACT_THRESHOLD = 2000;
-        return redundantOpCount >= REDUNDANT_OP_COMPACT_THRESHOLD
-                && redundantOpCount >= lruEntries.size();
-    }
-
-    /**
-     * Drops the entry for {@code key} if it exists and can be removed. Entries
-     * actively being edited cannot be removed.
-     *
-     * @return true if an entry was removed.
-     */
-    public synchronized boolean remove(String key) throws IOException {
-        checkNotClosed();
-        validateKey(key);
-        Entry entry = lruEntries.get(key);
-        if (entry == null || entry.currentEditor != null) {
-            return false;
-        }
-
-        for (int i = 0; i < valueCount; i++) {
-            File file = entry.getCleanFile(i);
-            if (!file.delete()) {
-                throw new IOException("failed to delete " + file);
-            }
-            size -= entry.lengths[i];
-            entry.lengths[i] = 0;
-        }
-
-        redundantOpCount++;
-        journalWriter.append(REMOVE + ' ' + key + '\n');
-        lruEntries.remove(key);
-
-        if (journalRebuildRequired()) {
-            executorService.submit(cleanupCallable);
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns true if this cache has been closed.
-     */
-    public boolean isClosed() {
-        return journalWriter == null;
-    }
-
-    private void checkNotClosed() {
-        if (journalWriter == null) {
-            throw new IllegalStateException("cache is closed");
-        }
-    }
-
-    /**
-     * Force buffered operations to the filesystem.
-     */
-    public synchronized void flush() throws IOException {
-        checkNotClosed();
-        trimToSize();
-        journalWriter.flush();
-    }
-
-    /**
-     * Closes this cache. Stored values will remain on the filesystem.
-     */
-    public synchronized void close() throws IOException {
-        if (journalWriter == null) {
-            return; // already closed
-        }
-        for (Entry entry : new ArrayList<Entry>(lruEntries.values())) {
-            if (entry.currentEditor != null) {
-                entry.currentEditor.abort();
-            }
-        }
-        trimToSize();
-        journalWriter.close();
-        journalWriter = null;
-    }
-
-    private void trimToSize() throws IOException {
-        while (size > maxSize) {
-//            Map.Entry<String, Entry> toEvict = lruEntries.eldest();
-            final Map.Entry<String, Entry> toEvict = lruEntries.entrySet().iterator().next();
-            remove(toEvict.getKey());
-        }
-    }
-
-    /**
-     * Closes the cache and deletes all of its stored values. This will delete
-     * all files in the cache directory including files that weren't created by
-     * the cache.
-     */
-    public void delete() throws IOException {
-        close();
-        deleteContents(directory);
-    }
-
-    private void validateKey(String key) {
-        if (key.contains(" ") || key.contains("\n") || key.contains("\r")) {
-            throw new IllegalArgumentException(
-                    "keys must not contain spaces or newlines: \"" + key + "\"");
-        }
-    }
-
-    private static String inputStreamToString(InputStream in) throws IOException {
-        return readFully(new InputStreamReader(in, UTF_8));
-    }
-
-    /**
-     * A snapshot of the values for an entry.
-     */
-    public final class Snapshot implements Closeable {
-        private final String key;
-        private final long sequenceNumber;
-        private final InputStream[] ins;
-
-        private Snapshot(String key, long sequenceNumber, InputStream[] ins) {
-            this.key = key;
-            this.sequenceNumber = sequenceNumber;
-            this.ins = ins;
-        }
-
-        /**
-         * Returns an editor for this snapshot's entry, or null if either the
-         * entry has changed since this snapshot was created or if another edit
-         * is in progress.
-         */
-        public Editor edit() throws IOException {
-            return DiskLruCache.this.edit(key, sequenceNumber);
-        }
-
-        /**
-         * Returns the unbuffered stream with the value for {@code index}.
-         */
-        public InputStream getInputStream(int index) {
-            return ins[index];
-        }
-
-        /**
-         * Returns the string value for {@code index}.
-         */
-        public String getString(int index) throws IOException {
-            return inputStreamToString(getInputStream(index));
-        }
-
-        @Override public void close() {
-            for (InputStream in : ins) {
-                closeQuietly(in);
-            }
-        }
-    }
-
-    /**
-     * Edits the values for an entry.
-     */
-    public final class Editor {
-        private final Entry entry;
-        private boolean hasErrors;
-
-        private Editor(Entry entry) {
-            this.entry = entry;
-        }
-
-        /**
-         * Returns an unbuffered input stream to read the last committed value,
-         * or null if no value has been committed.
-         */
-        public InputStream newInputStream(int index) throws IOException {
-            synchronized (DiskLruCache.this) {
-                if (entry.currentEditor != this) {
-                    throw new IllegalStateException();
-                }
-                if (!entry.readable) {
-                    return null;
-                }
-                return new FileInputStream(entry.getCleanFile(index));
-            }
-        }
-
-        /**
-         * Returns the last committed value as a string, or null if no value
-         * has been committed.
-         */
-        public String getString(int index) throws IOException {
-            InputStream in = newInputStream(index);
-            return in != null ? inputStreamToString(in) : null;
-        }
-
-        /**
-         * Returns a new unbuffered output stream to write the value at
-         * {@code index}. If the underlying output stream encounters errors
-         * when writing to the filesystem, this edit will be aborted when
-         * {@link #commit} is called. The returned output stream does not throw
-         * IOExceptions.
-         */
-        public OutputStream newOutputStream(int index) throws IOException {
-            synchronized (DiskLruCache.this) {
-                if (entry.currentEditor != this) {
-                    throw new IllegalStateException();
-                }
-                return new FaultHidingOutputStream(new FileOutputStream(entry.getDirtyFile(index)));
-            }
-        }
-
-        /**
-         * Sets the value at {@code index} to {@code value}.
-         */
-        public void set(int index, String value) throws IOException {
-            Writer writer = null;
-            try {
-                writer = new OutputStreamWriter(newOutputStream(index), UTF_8);
-                writer.write(value);
-            } finally {
-                closeQuietly(writer);
-            }
-        }
-
-        /**
-         * Commits this edit so it is visible to readers.  This releases the
-         * edit lock so another edit may be started on the same key.
-         */
-        public void commit() throws IOException {
-            if (hasErrors) {
-                completeEdit(this, false);
-                remove(entry.key); // the previous entry is stale
-            } else {
-                completeEdit(this, true);
-            }
-        }
-
-        /**
-         * Aborts this edit. This releases the edit lock so another edit may be
-         * started on the same key.
-         */
-        public void abort() throws IOException {
-            completeEdit(this, false);
-        }
-
-        private class FaultHidingOutputStream extends FilterOutputStream {
-            private FaultHidingOutputStream(OutputStream out) {
-                super(out);
-            }
-
-            @Override public void write(int oneByte) {
-                try {
-                    out.write(oneByte);
-                } catch (IOException e) {
-                    hasErrors = true;
-                }
-            }
-
-            @Override public void write(byte[] buffer, int offset, int length) {
-                try {
-                    out.write(buffer, offset, length);
-                } catch (IOException e) {
-                    hasErrors = true;
-                }
-            }
-
-            @Override public void close() {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    hasErrors = true;
-                }
-            }
-
-            @Override public void flush() {
-                try {
-                    out.flush();
-                } catch (IOException e) {
-                    hasErrors = true;
-                }
-            }
-        }
-    }
-
-    private final class Entry {
-        private final String key;
-
-        /** Lengths of this entry's files. */
-        private final long[] lengths;
-
-        /** True if this entry has ever been published */
-        private boolean readable;
-
-        /** The ongoing edit or null if this entry is not being edited. */
-        private Editor currentEditor;
-
-        /** The sequence number of the most recently committed edit to this entry. */
-        private long sequenceNumber;
-
-        private Entry(String key) {
-            this.key = key;
-            this.lengths = new long[valueCount];
-        }
-
-        public String getLengths() throws IOException {
-            StringBuilder result = new StringBuilder();
-            for (long size : lengths) {
-                result.append(' ').append(size);
-            }
-            return result.toString();
-        }
-
-        /**
-         * Set lengths using decimal numbers like "10123".
-         */
-        private void setLengths(String[] strings) throws IOException {
-            if (strings.length != valueCount) {
-                throw invalidLengths(strings);
-            }
-
-            try {
-                for (int i = 0; i < strings.length; i++) {
-                    lengths[i] = Long.parseLong(strings[i]);
-                }
-            } catch (NumberFormatException e) {
-                throw invalidLengths(strings);
-            }
-        }
-
-        private IOException invalidLengths(String[] strings) throws IOException {
-            throw new IOException("unexpected journal line: " + Arrays.toString(strings));
-        }
-
-        public File getCleanFile(int i) {
-            return new File(directory, key + "." + i);
-        }
-
-        public File getDirtyFile(int i) {
-            return new File(directory, key + "." + i + ".tmp");
-        }
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageCache.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageCache.java
deleted file mode 100644
index 7021d2c..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageCache.java
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.util;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.os.Build.VERSION_CODES;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.StatFs;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.util.LruCache;
-import android.util.Log;
-
-import com.example.android.bitmapfun.BuildConfig;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.ref.SoftReference;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-/**
- * This class handles disk and memory caching of bitmaps in conjunction with the
- * {@link ImageWorker} class and its subclasses. Use
- * {@link ImageCache#getInstance(FragmentManager, ImageCacheParams)} to get an instance of this
- * class, although usually a cache should be added directly to an {@link ImageWorker} by calling
- * {@link ImageWorker#addImageCache(FragmentManager, ImageCacheParams)}.
- */
-public class ImageCache {
-    private static final String TAG = "ImageCache";
-
-    // Default memory cache size in kilobytes
-    private static final int DEFAULT_MEM_CACHE_SIZE = 1024 * 5; // 5MB
-
-    // Default disk cache size in bytes
-    private static final int DEFAULT_DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
-
-    // Compression settings when writing images to disk cache
-    private static final CompressFormat DEFAULT_COMPRESS_FORMAT = CompressFormat.JPEG;
-    private static final int DEFAULT_COMPRESS_QUALITY = 70;
-    private static final int DISK_CACHE_INDEX = 0;
-
-    // Constants to easily toggle various caches
-    private static final boolean DEFAULT_MEM_CACHE_ENABLED = true;
-    private static final boolean DEFAULT_DISK_CACHE_ENABLED = true;
-    private static final boolean DEFAULT_INIT_DISK_CACHE_ON_CREATE = false;
-
-    private DiskLruCache mDiskLruCache;
-    private LruCache<String, BitmapDrawable> mMemoryCache;
-    private ImageCacheParams mCacheParams;
-    private final Object mDiskCacheLock = new Object();
-    private boolean mDiskCacheStarting = true;
-
-    private Set<SoftReference<Bitmap>> mReusableBitmaps;
-
-    /**
-     * Create a new ImageCache object using the specified parameters. This should not be
-     * called directly by other classes, instead use
-     * {@link ImageCache#getInstance(FragmentManager, ImageCacheParams)} to fetch an ImageCache
-     * instance.
-     *
-     * @param cacheParams The cache parameters to use to initialize the cache
-     */
-    private ImageCache(ImageCacheParams cacheParams) {
-        init(cacheParams);
-    }
-
-    /**
-     * Return an {@link ImageCache} instance. A {@link RetainFragment} is used to retain the
-     * ImageCache object across configuration changes such as a change in device orientation.
-     *
-     * @param fragmentManager The fragment manager to use when dealing with the retained fragment.
-     * @param cacheParams The cache parameters to use if the ImageCache needs instantiation.
-     * @return An existing retained ImageCache object or a new one if one did not exist
-     */
-    public static ImageCache getInstance(
-            FragmentManager fragmentManager, ImageCacheParams cacheParams) {
-
-        // Search for, or create an instance of the non-UI RetainFragment
-        final RetainFragment mRetainFragment = findOrCreateRetainFragment(fragmentManager);
-
-        // See if we already have an ImageCache stored in RetainFragment
-        ImageCache imageCache = (ImageCache) mRetainFragment.getObject();
-
-        // No existing ImageCache, create one and store it in RetainFragment
-        if (imageCache == null) {
-            imageCache = new ImageCache(cacheParams);
-            mRetainFragment.setObject(imageCache);
-        }
-
-        return imageCache;
-    }
-
-    /**
-     * Initialize the cache, providing all parameters.
-     *
-     * @param cacheParams The cache parameters to initialize the cache
-     */
-    private void init(ImageCacheParams cacheParams) {
-        mCacheParams = cacheParams;
-
-        // Set up memory cache
-        if (mCacheParams.memoryCacheEnabled) {
-            if (BuildConfig.DEBUG) {
-                Log.d(TAG, "Memory cache created (size = " + mCacheParams.memCacheSize + ")");
-            }
-
-            // If we're running on Honeycomb or newer, create a set of reusable bitmaps that can be
-            // populated into the inBitmap field of BitmapFactory.Options. Note that the set is
-            // of SoftReferences which will actually not be very effective due to the garbage
-            // collector being aggressive clearing Soft/WeakReferences. A better approach
-            // would be to use a strongly references bitmaps, however this would require some
-            // balancing of memory usage between this set and the bitmap LruCache. It would also
-            // require knowledge of the expected size of the bitmaps. From Honeycomb to JellyBean
-            // the size would need to be precise, from KitKat onward the size would just need to
-            // be the upper bound (due to changes in how inBitmap can re-use bitmaps).
-            if (Utils.hasHoneycomb()) {
-                mReusableBitmaps =
-                        Collections.synchronizedSet(new HashSet<SoftReference<Bitmap>>());
-            }
-
-            mMemoryCache = new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) {
-
-                /**
-                 * Notify the removed entry that is no longer being cached
-                 */
-                @Override
-                protected void entryRemoved(boolean evicted, String key,
-                        BitmapDrawable oldValue, BitmapDrawable newValue) {
-                    if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {
-                        // The removed entry is a recycling drawable, so notify it 
-                        // that it has been removed from the memory cache
-                        ((RecyclingBitmapDrawable) oldValue).setIsCached(false);
-                    } else {
-                        // The removed entry is a standard BitmapDrawable
-
-                        if (Utils.hasHoneycomb()) {
-                            // We're running on Honeycomb or later, so add the bitmap
-                            // to a SoftReference set for possible use with inBitmap later
-                            mReusableBitmaps.add(new SoftReference<Bitmap>(oldValue.getBitmap()));
-                        }
-                    }
-                }
-
-                /**
-                 * Measure item size in kilobytes rather than units which is more practical
-                 * for a bitmap cache
-                 */
-                @Override
-                protected int sizeOf(String key, BitmapDrawable value) {
-                    final int bitmapSize = getBitmapSize(value) / 1024;
-                    return bitmapSize == 0 ? 1 : bitmapSize;
-                }
-            };
-        }
-
-        // By default the disk cache is not initialized here as it should be initialized
-        // on a separate thread due to disk access.
-        if (cacheParams.initDiskCacheOnCreate) {
-            // Set up disk cache
-            initDiskCache();
-        }
-    }
-
-    /**
-     * Initializes the disk cache.  Note that this includes disk access so this should not be
-     * executed on the main/UI thread. By default an ImageCache does not initialize the disk
-     * cache when it is created, instead you should call initDiskCache() to initialize it on a
-     * background thread.
-     */
-    public void initDiskCache() {
-        // Set up disk cache
-        synchronized (mDiskCacheLock) {
-            if (mDiskLruCache == null || mDiskLruCache.isClosed()) {
-                File diskCacheDir = mCacheParams.diskCacheDir;
-                if (mCacheParams.diskCacheEnabled && diskCacheDir != null) {
-                    if (!diskCacheDir.exists()) {
-                        diskCacheDir.mkdirs();
-                    }
-                    if (getUsableSpace(diskCacheDir) > mCacheParams.diskCacheSize) {
-                        try {
-                            mDiskLruCache = DiskLruCache.open(
-                                    diskCacheDir, 1, 1, mCacheParams.diskCacheSize);
-                            if (BuildConfig.DEBUG) {
-                                Log.d(TAG, "Disk cache initialized");
-                            }
-                        } catch (final IOException e) {
-                            mCacheParams.diskCacheDir = null;
-                            Log.e(TAG, "initDiskCache - " + e);
-                        }
-                    }
-                }
-            }
-            mDiskCacheStarting = false;
-            mDiskCacheLock.notifyAll();
-        }
-    }
-
-    /**
-     * Adds a bitmap to both memory and disk cache.
-     * @param data Unique identifier for the bitmap to store
-     * @param value The bitmap drawable to store
-     */
-    public void addBitmapToCache(String data, BitmapDrawable value) {
-        if (data == null || value == null) {
-            return;
-        }
-
-        // Add to memory cache
-        if (mMemoryCache != null) {
-            if (RecyclingBitmapDrawable.class.isInstance(value)) {
-                // The removed entry is a recycling drawable, so notify it 
-                // that it has been added into the memory cache
-                ((RecyclingBitmapDrawable) value).setIsCached(true);
-            }
-            mMemoryCache.put(data, value);
-        }
-
-        synchronized (mDiskCacheLock) {
-            // Add to disk cache
-            if (mDiskLruCache != null) {
-                final String key = hashKeyForDisk(data);
-                OutputStream out = null;
-                try {
-                    DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
-                    if (snapshot == null) {
-                        final DiskLruCache.Editor editor = mDiskLruCache.edit(key);
-                        if (editor != null) {
-                            out = editor.newOutputStream(DISK_CACHE_INDEX);
-                            value.getBitmap().compress(
-                                    mCacheParams.compressFormat, mCacheParams.compressQuality, out);
-                            editor.commit();
-                            out.close();
-                        }
-                    } else {
-                        snapshot.getInputStream(DISK_CACHE_INDEX).close();
-                    }
-                } catch (final IOException e) {
-                    Log.e(TAG, "addBitmapToCache - " + e);
-                } catch (Exception e) {
-                    Log.e(TAG, "addBitmapToCache - " + e);
-                } finally {
-                    try {
-                        if (out != null) {
-                            out.close();
-                        }
-                    } catch (IOException e) {}
-                }
-            }
-        }
-    }
-
-    /**
-     * Get from memory cache.
-     *
-     * @param data Unique identifier for which item to get
-     * @return The bitmap drawable if found in cache, null otherwise
-     */
-    public BitmapDrawable getBitmapFromMemCache(String data) {
-        BitmapDrawable memValue = null;
-
-        if (mMemoryCache != null) {
-            memValue = mMemoryCache.get(data);
-        }
-
-        if (BuildConfig.DEBUG && memValue != null) {
-            Log.d(TAG, "Memory cache hit");
-        }
-
-        return memValue;
-    }
-
-    /**
-     * Get from disk cache.
-     *
-     * @param data Unique identifier for which item to get
-     * @return The bitmap if found in cache, null otherwise
-     */
-    public Bitmap getBitmapFromDiskCache(String data) {
-        final String key = hashKeyForDisk(data);
-        Bitmap bitmap = null;
-
-        synchronized (mDiskCacheLock) {
-            while (mDiskCacheStarting) {
-                try {
-                    mDiskCacheLock.wait();
-                } catch (InterruptedException e) {}
-            }
-            if (mDiskLruCache != null) {
-                InputStream inputStream = null;
-                try {
-                    final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
-                    if (snapshot != null) {
-                        if (BuildConfig.DEBUG) {
-                            Log.d(TAG, "Disk cache hit");
-                        }
-                        inputStream = snapshot.getInputStream(DISK_CACHE_INDEX);
-                        if (inputStream != null) {
-                            FileDescriptor fd = ((FileInputStream) inputStream).getFD();
-
-                            // Decode bitmap, but we don't want to sample so give
-                            // MAX_VALUE as the target dimensions
-                            bitmap = ImageResizer.decodeSampledBitmapFromDescriptor(
-                                    fd, Integer.MAX_VALUE, Integer.MAX_VALUE, this);
-                        }
-                    }
-                } catch (final IOException e) {
-                    Log.e(TAG, "getBitmapFromDiskCache - " + e);
-                } finally {
-                    try {
-                        if (inputStream != null) {
-                            inputStream.close();
-                        }
-                    } catch (IOException e) {}
-                }
-            }
-            return bitmap;
-        }
-    }
-
-    /**
-     * @param options - BitmapFactory.Options with out* options populated
-     * @return Bitmap that case be used for inBitmap
-     */
-    protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {
-        Bitmap bitmap = null;
-
-        if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {
-            synchronized (mReusableBitmaps) {
-                final Iterator<SoftReference<Bitmap>> iterator = mReusableBitmaps.iterator();
-                Bitmap item;
-
-                while (iterator.hasNext()) {
-                    item = iterator.next().get();
-
-                    if (null != item && item.isMutable()) {
-                        // Check to see it the item can be used for inBitmap
-                        if (canUseForInBitmap(item, options)) {
-                            bitmap = item;
-
-                            // Remove from reusable set so it can't be used again
-                            iterator.remove();
-                            break;
-                        }
-                    } else {
-                        // Remove from the set if the reference has been cleared.
-                        iterator.remove();
-                    }
-                }
-            }
-        }
-
-        return bitmap;
-    }
-
-    /**
-     * Clears both the memory and disk cache associated with this ImageCache object. Note that
-     * this includes disk access so this should not be executed on the main/UI thread.
-     */
-    public void clearCache() {
-        if (mMemoryCache != null) {
-            mMemoryCache.evictAll();
-            if (BuildConfig.DEBUG) {
-                Log.d(TAG, "Memory cache cleared");
-            }
-        }
-
-        synchronized (mDiskCacheLock) {
-            mDiskCacheStarting = true;
-            if (mDiskLruCache != null && !mDiskLruCache.isClosed()) {
-                try {
-                    mDiskLruCache.delete();
-                    if (BuildConfig.DEBUG) {
-                        Log.d(TAG, "Disk cache cleared");
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "clearCache - " + e);
-                }
-                mDiskLruCache = null;
-                initDiskCache();
-            }
-        }
-    }
-
-    /**
-     * Flushes the disk cache associated with this ImageCache object. Note that this includes
-     * disk access so this should not be executed on the main/UI thread.
-     */
-    public void flush() {
-        synchronized (mDiskCacheLock) {
-            if (mDiskLruCache != null) {
-                try {
-                    mDiskLruCache.flush();
-                    if (BuildConfig.DEBUG) {
-                        Log.d(TAG, "Disk cache flushed");
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "flush - " + e);
-                }
-            }
-        }
-    }
-
-    /**
-     * Closes the disk cache associated with this ImageCache object. Note that this includes
-     * disk access so this should not be executed on the main/UI thread.
-     */
-    public void close() {
-        synchronized (mDiskCacheLock) {
-            if (mDiskLruCache != null) {
-                try {
-                    if (!mDiskLruCache.isClosed()) {
-                        mDiskLruCache.close();
-                        mDiskLruCache = null;
-                        if (BuildConfig.DEBUG) {
-                            Log.d(TAG, "Disk cache closed");
-                        }
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "close - " + e);
-                }
-            }
-        }
-    }
-
-    /**
-     * A holder class that contains cache parameters.
-     */
-    public static class ImageCacheParams {
-        public int memCacheSize = DEFAULT_MEM_CACHE_SIZE;
-        public int diskCacheSize = DEFAULT_DISK_CACHE_SIZE;
-        public File diskCacheDir;
-        public CompressFormat compressFormat = DEFAULT_COMPRESS_FORMAT;
-        public int compressQuality = DEFAULT_COMPRESS_QUALITY;
-        public boolean memoryCacheEnabled = DEFAULT_MEM_CACHE_ENABLED;
-        public boolean diskCacheEnabled = DEFAULT_DISK_CACHE_ENABLED;
-        public boolean initDiskCacheOnCreate = DEFAULT_INIT_DISK_CACHE_ON_CREATE;
-
-        /**
-         * Create a set of image cache parameters that can be provided to
-         * {@link ImageCache#getInstance(FragmentManager, ImageCacheParams)} or
-         * {@link ImageWorker#addImageCache(FragmentManager, ImageCacheParams)}.
-         * @param context A context to use.
-         * @param diskCacheDirectoryName A unique subdirectory name that will be appended to the
-         *                               application cache directory. Usually "cache" or "images"
-         *                               is sufficient.
-         */
-        public ImageCacheParams(Context context, String diskCacheDirectoryName) {
-            diskCacheDir = getDiskCacheDir(context, diskCacheDirectoryName);
-        }
-
-        /**
-         * Sets the memory cache size based on a percentage of the max available VM memory.
-         * Eg. setting percent to 0.2 would set the memory cache to one fifth of the available
-         * memory. Throws {@link IllegalArgumentException} if percent is < 0.01 or > .8.
-         * memCacheSize is stored in kilobytes instead of bytes as this will eventually be passed
-         * to construct a LruCache which takes an int in its constructor.
-         *
-         * This value should be chosen carefully based on a number of factors
-         * Refer to the corresponding Android Training class for more discussion:
-         * http://developer.android.com/training/displaying-bitmaps/
-         *
-         * @param percent Percent of available app memory to use to size memory cache
-         */
-        public void setMemCacheSizePercent(float percent) {
-            if (percent < 0.01f || percent > 0.8f) {
-                throw new IllegalArgumentException("setMemCacheSizePercent - percent must be "
-                        + "between 0.01 and 0.8 (inclusive)");
-            }
-            memCacheSize = Math.round(percent * Runtime.getRuntime().maxMemory() / 1024);
-        }
-    }
-
-    /**
-     * @param candidate - Bitmap to check
-     * @param targetOptions - Options that have the out* value populated
-     * @return true if <code>candidate</code> can be used for inBitmap re-use with
-     *      <code>targetOptions</code>
-     */
-    @TargetApi(VERSION_CODES.KITKAT)
-    private static boolean canUseForInBitmap(
-            Bitmap candidate, BitmapFactory.Options targetOptions) {
-
-        if (!Utils.hasKitKat()) {
-            // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1
-            return candidate.getWidth() == targetOptions.outWidth
-                    && candidate.getHeight() == targetOptions.outHeight
-                    && targetOptions.inSampleSize == 1;
-        }
-
-        // From Android 4.4 (KitKat) onward we can re-use if the byte size of the new bitmap
-        // is smaller than the reusable bitmap candidate allocation byte count.
-        int width = targetOptions.outWidth / targetOptions.inSampleSize;
-        int height = targetOptions.outHeight / targetOptions.inSampleSize;
-        int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
-        return byteCount <= candidate.getAllocationByteCount();
-    }
-
-    /**
-     * Return the byte usage per pixel of a bitmap based on its configuration.
-     * @param config The bitmap configuration.
-     * @return The byte usage per pixel.
-     */
-    private static int getBytesPerPixel(Config config) {
-        if (config == Config.ARGB_8888) {
-            return 4;
-        } else if (config == Config.RGB_565) {
-            return 2;
-        } else if (config == Config.ARGB_4444) {
-            return 2;
-        } else if (config == Config.ALPHA_8) {
-            return 1;
-        }
-        return 1;
-    }
-
-    /**
-     * Get a usable cache directory (external if available, internal otherwise).
-     *
-     * @param context The context to use
-     * @param uniqueName A unique directory name to append to the cache dir
-     * @return The cache dir
-     */
-    public static File getDiskCacheDir(Context context, String uniqueName) {
-        // Check if media is mounted or storage is built-in, if so, try and use external cache dir
-        // otherwise use internal cache dir
-        final String cachePath =
-                Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||
-                        !isExternalStorageRemovable() ? getExternalCacheDir(context).getPath() :
-                                context.getCacheDir().getPath();
-
-        return new File(cachePath + File.separator + uniqueName);
-    }
-
-    /**
-     * A hashing method that changes a string (like a URL) into a hash suitable for using as a
-     * disk filename.
-     */
-    public static String hashKeyForDisk(String key) {
-        String cacheKey;
-        try {
-            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
-            mDigest.update(key.getBytes());
-            cacheKey = bytesToHexString(mDigest.digest());
-        } catch (NoSuchAlgorithmException e) {
-            cacheKey = String.valueOf(key.hashCode());
-        }
-        return cacheKey;
-    }
-
-    private static String bytesToHexString(byte[] bytes) {
-        // http://stackoverflow.com/questions/332079
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < bytes.length; i++) {
-            String hex = Integer.toHexString(0xFF & bytes[i]);
-            if (hex.length() == 1) {
-                sb.append('0');
-            }
-            sb.append(hex);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Get the size in bytes of a bitmap in a BitmapDrawable. Note that from Android 4.4 (KitKat)
-     * onward this returns the allocated memory size of the bitmap which can be larger than the
-     * actual bitmap data byte count (in the case it was re-used).
-     *
-     * @param value
-     * @return size in bytes
-     */
-    @TargetApi(VERSION_CODES.KITKAT)
-    public static int getBitmapSize(BitmapDrawable value) {
-        Bitmap bitmap = value.getBitmap();
-
-        // From KitKat onward use getAllocationByteCount() as allocated bytes can potentially be
-        // larger than bitmap byte count.
-        if (Utils.hasKitKat()) {
-            return bitmap.getAllocationByteCount();
-        }
-
-        if (Utils.hasHoneycombMR1()) {
-            return bitmap.getByteCount();
-        }
-
-        // Pre HC-MR1
-        return bitmap.getRowBytes() * bitmap.getHeight();
-    }
-
-    /**
-     * Check if external storage is built-in or removable.
-     *
-     * @return True if external storage is removable (like an SD card), false
-     *         otherwise.
-     */
-    @TargetApi(VERSION_CODES.GINGERBREAD)
-    public static boolean isExternalStorageRemovable() {
-        if (Utils.hasGingerbread()) {
-            return Environment.isExternalStorageRemovable();
-        }
-        return true;
-    }
-
-    /**
-     * Get the external app cache directory.
-     *
-     * @param context The context to use
-     * @return The external cache dir
-     */
-    @TargetApi(VERSION_CODES.FROYO)
-    public static File getExternalCacheDir(Context context) {
-        if (Utils.hasFroyo()) {
-            return context.getExternalCacheDir();
-        }
-
-        // Before Froyo we need to construct the external cache dir ourselves
-        final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/";
-        return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir);
-    }
-
-    /**
-     * Check how much usable space is available at a given path.
-     *
-     * @param path The path to check
-     * @return The space available in bytes
-     */
-    @TargetApi(VERSION_CODES.GINGERBREAD)
-    public static long getUsableSpace(File path) {
-        if (Utils.hasGingerbread()) {
-            return path.getUsableSpace();
-        }
-        final StatFs stats = new StatFs(path.getPath());
-        return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
-    }
-
-    /**
-     * Locate an existing instance of this Fragment or if not found, create and
-     * add it using FragmentManager.
-     *
-     * @param fm The FragmentManager manager to use.
-     * @return The existing instance of the Fragment or the new instance if just
-     *         created.
-     */
-    private static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
-        // Check to see if we have retained the worker fragment.
-        RetainFragment mRetainFragment = (RetainFragment) fm.findFragmentByTag(TAG);
-
-        // If not retained (or first time running), we need to create and add it.
-        if (mRetainFragment == null) {
-            mRetainFragment = new RetainFragment();
-            fm.beginTransaction().add(mRetainFragment, TAG).commitAllowingStateLoss();
-        }
-
-        return mRetainFragment;
-    }
-
-    /**
-     * A simple non-UI Fragment that stores a single Object and is retained over configuration
-     * changes. It will be used to retain the ImageCache object.
-     */
-    public static class RetainFragment extends Fragment {
-        private Object mObject;
-
-        /**
-         * Empty constructor as per the Fragment documentation
-         */
-        public RetainFragment() {}
-
-        @Override
-        public void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-
-            // Make sure this Fragment is retained over a configuration change
-            setRetainInstance(true);
-        }
-
-        /**
-         * Store a single object in this Fragment.
-         *
-         * @param object The object to store
-         */
-        public void setObject(Object object) {
-            mObject = object;
-        }
-
-        /**
-         * Get the stored object.
-         *
-         * @return The stored object
-         */
-        public Object getObject() {
-            return mObject;
-        }
-    }
-
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageFetcher.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageFetcher.java
deleted file mode 100644
index 4c92d74..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageFetcher.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.util;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.Build;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.example.android.bitmapfun.BuildConfig;
-import com.example.android.bitmapfun.R;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-
-/**
- * A simple subclass of {@link ImageResizer} that fetches and resizes images fetched from a URL.
- */
-public class ImageFetcher extends ImageResizer {
-    private static final String TAG = "ImageFetcher";
-    private static final int HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10MB
-    private static final String HTTP_CACHE_DIR = "http";
-    private static final int IO_BUFFER_SIZE = 8 * 1024;
-
-    private DiskLruCache mHttpDiskCache;
-    private File mHttpCacheDir;
-    private boolean mHttpDiskCacheStarting = true;
-    private final Object mHttpDiskCacheLock = new Object();
-    private static final int DISK_CACHE_INDEX = 0;
-
-    /**
-     * Initialize providing a target image width and height for the processing images.
-     *
-     * @param context
-     * @param imageWidth
-     * @param imageHeight
-     */
-    public ImageFetcher(Context context, int imageWidth, int imageHeight) {
-        super(context, imageWidth, imageHeight);
-        init(context);
-    }
-
-    /**
-     * Initialize providing a single target image size (used for both width and height);
-     *
-     * @param context
-     * @param imageSize
-     */
-    public ImageFetcher(Context context, int imageSize) {
-        super(context, imageSize);
-        init(context);
-    }
-
-    private void init(Context context) {
-        checkConnection(context);
-        mHttpCacheDir = ImageCache.getDiskCacheDir(context, HTTP_CACHE_DIR);
-    }
-
-    @Override
-    protected void initDiskCacheInternal() {
-        super.initDiskCacheInternal();
-        initHttpDiskCache();
-    }
-
-    private void initHttpDiskCache() {
-        if (!mHttpCacheDir.exists()) {
-            mHttpCacheDir.mkdirs();
-        }
-        synchronized (mHttpDiskCacheLock) {
-            if (ImageCache.getUsableSpace(mHttpCacheDir) > HTTP_CACHE_SIZE) {
-                try {
-                    mHttpDiskCache = DiskLruCache.open(mHttpCacheDir, 1, 1, HTTP_CACHE_SIZE);
-                    if (BuildConfig.DEBUG) {
-                        Log.d(TAG, "HTTP cache initialized");
-                    }
-                } catch (IOException e) {
-                    mHttpDiskCache = null;
-                }
-            }
-            mHttpDiskCacheStarting = false;
-            mHttpDiskCacheLock.notifyAll();
-        }
-    }
-
-    @Override
-    protected void clearCacheInternal() {
-        super.clearCacheInternal();
-        synchronized (mHttpDiskCacheLock) {
-            if (mHttpDiskCache != null && !mHttpDiskCache.isClosed()) {
-                try {
-                    mHttpDiskCache.delete();
-                    if (BuildConfig.DEBUG) {
-                        Log.d(TAG, "HTTP cache cleared");
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "clearCacheInternal - " + e);
-                }
-                mHttpDiskCache = null;
-                mHttpDiskCacheStarting = true;
-                initHttpDiskCache();
-            }
-        }
-    }
-
-    @Override
-    protected void flushCacheInternal() {
-        super.flushCacheInternal();
-        synchronized (mHttpDiskCacheLock) {
-            if (mHttpDiskCache != null) {
-                try {
-                    mHttpDiskCache.flush();
-                    if (BuildConfig.DEBUG) {
-                        Log.d(TAG, "HTTP cache flushed");
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "flush - " + e);
-                }
-            }
-        }
-    }
-
-    @Override
-    protected void closeCacheInternal() {
-        super.closeCacheInternal();
-        synchronized (mHttpDiskCacheLock) {
-            if (mHttpDiskCache != null) {
-                try {
-                    if (!mHttpDiskCache.isClosed()) {
-                        mHttpDiskCache.close();
-                        mHttpDiskCache = null;
-                        if (BuildConfig.DEBUG) {
-                            Log.d(TAG, "HTTP cache closed");
-                        }
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "closeCacheInternal - " + e);
-                }
-            }
-        }
-    }
-
-    /**
-    * Simple network connection check.
-    *
-    * @param context
-    */
-    private void checkConnection(Context context) {
-        final ConnectivityManager cm =
-                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
-        if (networkInfo == null || !networkInfo.isConnectedOrConnecting()) {
-            Toast.makeText(context, R.string.no_network_connection_toast, Toast.LENGTH_LONG).show();
-            Log.e(TAG, "checkConnection - no connection found");
-        }
-    }
-
-    /**
-     * The main process method, which will be called by the ImageWorker in the AsyncTask background
-     * thread.
-     *
-     * @param data The data to load the bitmap, in this case, a regular http URL
-     * @return The downloaded and resized bitmap
-     */
-    private Bitmap processBitmap(String data) {
-        if (BuildConfig.DEBUG) {
-            Log.d(TAG, "processBitmap - " + data);
-        }
-
-        final String key = ImageCache.hashKeyForDisk(data);
-        FileDescriptor fileDescriptor = null;
-        FileInputStream fileInputStream = null;
-        DiskLruCache.Snapshot snapshot;
-        synchronized (mHttpDiskCacheLock) {
-            // Wait for disk cache to initialize
-            while (mHttpDiskCacheStarting) {
-                try {
-                    mHttpDiskCacheLock.wait();
-                } catch (InterruptedException e) {}
-            }
-
-            if (mHttpDiskCache != null) {
-                try {
-                    snapshot = mHttpDiskCache.get(key);
-                    if (snapshot == null) {
-                        if (BuildConfig.DEBUG) {
-                            Log.d(TAG, "processBitmap, not found in http cache, downloading...");
-                        }
-                        DiskLruCache.Editor editor = mHttpDiskCache.edit(key);
-                        if (editor != null) {
-                            if (downloadUrlToStream(data,
-                                    editor.newOutputStream(DISK_CACHE_INDEX))) {
-                                editor.commit();
-                            } else {
-                                editor.abort();
-                            }
-                        }
-                        snapshot = mHttpDiskCache.get(key);
-                    }
-                    if (snapshot != null) {
-                        fileInputStream =
-                                (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX);
-                        fileDescriptor = fileInputStream.getFD();
-                    }
-                } catch (IOException e) {
-                    Log.e(TAG, "processBitmap - " + e);
-                } catch (IllegalStateException e) {
-                    Log.e(TAG, "processBitmap - " + e);
-                } finally {
-                    if (fileDescriptor == null && fileInputStream != null) {
-                        try {
-                            fileInputStream.close();
-                        } catch (IOException e) {}
-                    }
-                }
-            }
-        }
-
-        Bitmap bitmap = null;
-        if (fileDescriptor != null) {
-            bitmap = decodeSampledBitmapFromDescriptor(fileDescriptor, mImageWidth,
-                    mImageHeight, getImageCache());
-        }
-        if (fileInputStream != null) {
-            try {
-                fileInputStream.close();
-            } catch (IOException e) {}
-        }
-        return bitmap;
-    }
-
-    @Override
-    protected Bitmap processBitmap(Object data) {
-        return processBitmap(String.valueOf(data));
-    }
-
-    /**
-     * Download a bitmap from a URL and write the content to an output stream.
-     *
-     * @param urlString The URL to fetch
-     * @return true if successful, false otherwise
-     */
-    public boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
-        disableConnectionReuseIfNecessary();
-        HttpURLConnection urlConnection = null;
-        BufferedOutputStream out = null;
-        BufferedInputStream in = null;
-
-        try {
-            final URL url = new URL(urlString);
-            urlConnection = (HttpURLConnection) url.openConnection();
-            in = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE);
-            out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE);
-
-            int b;
-            while ((b = in.read()) != -1) {
-                out.write(b);
-            }
-            return true;
-        } catch (final IOException e) {
-            Log.e(TAG, "Error in downloadBitmap - " + e);
-        } finally {
-            if (urlConnection != null) {
-                urlConnection.disconnect();
-            }
-            try {
-                if (out != null) {
-                    out.close();
-                }
-                if (in != null) {
-                    in.close();
-                }
-            } catch (final IOException e) {}
-        }
-        return false;
-    }
-
-    /**
-     * Workaround for bug pre-Froyo, see here for more info:
-     * http://android-developers.blogspot.com/2011/09/androids-http-clients.html
-     */
-    public static void disableConnectionReuseIfNecessary() {
-        // HTTP connection reuse which was buggy pre-froyo
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) {
-            System.setProperty("http.keepAlive", "false");
-        }
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageResizer.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageResizer.java
deleted file mode 100644
index e8ce4e1..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageResizer.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.util;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Build;
-import android.util.Log;
-
-import com.example.android.bitmapfun.BuildConfig;
-
-import java.io.FileDescriptor;
-
-/**
- * A simple subclass of {@link ImageWorker} that resizes images from resources given a target width
- * and height. Useful for when the input images might be too large to simply load directly into
- * memory.
- */
-public class ImageResizer extends ImageWorker {
-    private static final String TAG = "ImageResizer";
-    protected int mImageWidth;
-    protected int mImageHeight;
-
-    /**
-     * Initialize providing a single target image size (used for both width and height);
-     *
-     * @param context
-     * @param imageWidth
-     * @param imageHeight
-     */
-    public ImageResizer(Context context, int imageWidth, int imageHeight) {
-        super(context);
-        setImageSize(imageWidth, imageHeight);
-    }
-
-    /**
-     * Initialize providing a single target image size (used for both width and height);
-     *
-     * @param context
-     * @param imageSize
-     */
-    public ImageResizer(Context context, int imageSize) {
-        super(context);
-        setImageSize(imageSize);
-    }
-
-    /**
-     * Set the target image width and height.
-     *
-     * @param width
-     * @param height
-     */
-    public void setImageSize(int width, int height) {
-        mImageWidth = width;
-        mImageHeight = height;
-    }
-
-    /**
-     * Set the target image size (width and height will be the same).
-     *
-     * @param size
-     */
-    public void setImageSize(int size) {
-        setImageSize(size, size);
-    }
-
-    /**
-     * The main processing method. This happens in a background task. In this case we are just
-     * sampling down the bitmap and returning it from a resource.
-     *
-     * @param resId
-     * @return
-     */
-    private Bitmap processBitmap(int resId) {
-        if (BuildConfig.DEBUG) {
-            Log.d(TAG, "processBitmap - " + resId);
-        }
-        return decodeSampledBitmapFromResource(mResources, resId, mImageWidth,
-                mImageHeight, getImageCache());
-    }
-
-    @Override
-    protected Bitmap processBitmap(Object data) {
-        return processBitmap(Integer.parseInt(String.valueOf(data)));
-    }
-
-    /**
-     * Decode and sample down a bitmap from resources to the requested width and height.
-     *
-     * @param res The resources object containing the image data
-     * @param resId The resource id of the image data
-     * @param reqWidth The requested width of the resulting bitmap
-     * @param reqHeight The requested height of the resulting bitmap
-     * @param cache The ImageCache used to find candidate bitmaps for use with inBitmap
-     * @return A bitmap sampled down from the original with the same aspect ratio and dimensions
-     *         that are equal to or greater than the requested width and height
-     */
-    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
-            int reqWidth, int reqHeight, ImageCache cache) {
-
-        // First decode with inJustDecodeBounds=true to check dimensions
-        final BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inJustDecodeBounds = true;
-        BitmapFactory.decodeResource(res, resId, options);
-
-        // Calculate inSampleSize
-        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
-
-        // If we're running on Honeycomb or newer, try to use inBitmap
-        if (Utils.hasHoneycomb()) {
-            addInBitmapOptions(options, cache);
-        }
-
-        // Decode bitmap with inSampleSize set
-        options.inJustDecodeBounds = false;
-        return BitmapFactory.decodeResource(res, resId, options);
-    }
-
-    /**
-     * Decode and sample down a bitmap from a file to the requested width and height.
-     *
-     * @param filename The full path of the file to decode
-     * @param reqWidth The requested width of the resulting bitmap
-     * @param reqHeight The requested height of the resulting bitmap
-     * @param cache The ImageCache used to find candidate bitmaps for use with inBitmap
-     * @return A bitmap sampled down from the original with the same aspect ratio and dimensions
-     *         that are equal to or greater than the requested width and height
-     */
-    public static Bitmap decodeSampledBitmapFromFile(String filename,
-            int reqWidth, int reqHeight, ImageCache cache) {
-
-        // First decode with inJustDecodeBounds=true to check dimensions
-        final BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inJustDecodeBounds = true;
-        BitmapFactory.decodeFile(filename, options);
-
-        // Calculate inSampleSize
-        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
-
-        // If we're running on Honeycomb or newer, try to use inBitmap
-        if (Utils.hasHoneycomb()) {
-            addInBitmapOptions(options, cache);
-        }
-
-        // Decode bitmap with inSampleSize set
-        options.inJustDecodeBounds = false;
-        return BitmapFactory.decodeFile(filename, options);
-    }
-
-    /**
-     * Decode and sample down a bitmap from a file input stream to the requested width and height.
-     *
-     * @param fileDescriptor The file descriptor to read from
-     * @param reqWidth The requested width of the resulting bitmap
-     * @param reqHeight The requested height of the resulting bitmap
-     * @param cache The ImageCache used to find candidate bitmaps for use with inBitmap
-     * @return A bitmap sampled down from the original with the same aspect ratio and dimensions
-     *         that are equal to or greater than the requested width and height
-     */
-    public static Bitmap decodeSampledBitmapFromDescriptor(
-            FileDescriptor fileDescriptor, int reqWidth, int reqHeight, ImageCache cache) {
-
-        // First decode with inJustDecodeBounds=true to check dimensions
-        final BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inJustDecodeBounds = true;
-        BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
-
-        // Calculate inSampleSize
-        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
-
-        // Decode bitmap with inSampleSize set
-        options.inJustDecodeBounds = false;
-
-        // If we're running on Honeycomb or newer, try to use inBitmap
-        if (Utils.hasHoneycomb()) {
-            addInBitmapOptions(options, cache);
-        }
-
-        return BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
-    }
-
-    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
-    private static void addInBitmapOptions(BitmapFactory.Options options, ImageCache cache) {
-        // inBitmap only works with mutable bitmaps so force the decoder to
-        // return mutable bitmaps.
-        options.inMutable = true;
-
-        if (cache != null) {
-            // Try and find a bitmap to use for inBitmap
-            Bitmap inBitmap = cache.getBitmapFromReusableSet(options);
-
-            if (inBitmap != null) {
-                options.inBitmap = inBitmap;
-            }
-        }
-    }
-
-    /**
-     * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding
-     * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates
-     * the closest inSampleSize that is a power of 2 and will result in the final decoded bitmap
-     * having a width and height equal to or larger than the requested width and height.
-     *
-     * @param options An options object with out* params already populated (run through a decode*
-     *            method with inJustDecodeBounds==true
-     * @param reqWidth The requested width of the resulting bitmap
-     * @param reqHeight The requested height of the resulting bitmap
-     * @return The value to be used for inSampleSize
-     */
-    public static int calculateInSampleSize(BitmapFactory.Options options,
-            int reqWidth, int reqHeight) {
-        // Raw height and width of image
-        final int height = options.outHeight;
-        final int width = options.outWidth;
-        int inSampleSize = 1;
-
-        if (height > reqHeight || width > reqWidth) {
-
-            final int halfHeight = height / 2;
-            final int halfWidth = width / 2;
-
-            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
-            // height and width larger than the requested height and width.
-            while ((halfHeight / inSampleSize) > reqHeight
-                    && (halfWidth / inSampleSize) > reqWidth) {
-                inSampleSize *= 2;
-            }
-
-            // This offers some additional logic in case the image has a strange
-            // aspect ratio. For example, a panorama may have a much larger
-            // width than height. In these cases the total pixels might still
-            // end up being too large to fit comfortably in memory, so we should
-            // be more aggressive with sample down the image (=larger inSampleSize).
-
-            long totalPixels = width * height / inSampleSize;
-
-            // Anything more than 2x the requested pixels we'll sample down further
-            final long totalReqPixelsCap = reqWidth * reqHeight * 2;
-
-            while (totalPixels > totalReqPixelsCap) {
-                inSampleSize *= 2;
-                totalPixels /= 2;
-            }
-        }
-        return inSampleSize;
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageWorker.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageWorker.java
deleted file mode 100644
index d260660..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/ImageWorker.java
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.util;
-
-import com.example.android.bitmapfun.BuildConfig;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.TransitionDrawable;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
-import android.util.Log;
-import android.widget.ImageView;
-
-import java.lang.ref.WeakReference;
-
-/**
- * This class wraps up completing some arbitrary long running work when loading a bitmap to an
- * ImageView. It handles things like using a memory and disk cache, running the work in a background
- * thread and setting a placeholder image.
- */
-public abstract class ImageWorker {
-    private static final String TAG = "ImageWorker";
-    private static final int FADE_IN_TIME = 200;
-
-    private ImageCache mImageCache;
-    private ImageCache.ImageCacheParams mImageCacheParams;
-    private Bitmap mLoadingBitmap;
-    private boolean mFadeInBitmap = true;
-    private boolean mExitTasksEarly = false;
-    protected boolean mPauseWork = false;
-    private final Object mPauseWorkLock = new Object();
-
-    protected Resources mResources;
-
-    private static final int MESSAGE_CLEAR = 0;
-    private static final int MESSAGE_INIT_DISK_CACHE = 1;
-    private static final int MESSAGE_FLUSH = 2;
-    private static final int MESSAGE_CLOSE = 3;
-
-    protected ImageWorker(Context context) {
-        mResources = context.getResources();
-    }
-
-    /**
-     * Load an image specified by the data parameter into an ImageView (override
-     * {@link ImageWorker#processBitmap(Object)} to define the processing logic). A memory and
-     * disk cache will be used if an {@link ImageCache} has been added using
-     * {@link ImageWorker#addImageCache(FragmentManager, ImageCache.ImageCacheParams)}. If the
-     * image is found in the memory cache, it is set immediately, otherwise an {@link AsyncTask}
-     * will be created to asynchronously load the bitmap.
-     *
-     * @param data The URL of the image to download.
-     * @param imageView The ImageView to bind the downloaded image to.
-     */
-    public void loadImage(Object data, ImageView imageView) {
-        if (data == null) {
-            return;
-        }
-
-        BitmapDrawable value = null;
-
-        if (mImageCache != null) {
-            value = mImageCache.getBitmapFromMemCache(String.valueOf(data));
-        }
-
-        if (value != null) {
-            // Bitmap found in memory cache
-            imageView.setImageDrawable(value);
-        } else if (cancelPotentialWork(data, imageView)) {
-            final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
-            final AsyncDrawable asyncDrawable =
-                    new AsyncDrawable(mResources, mLoadingBitmap, task);
-            imageView.setImageDrawable(asyncDrawable);
-
-            // NOTE: This uses a custom version of AsyncTask that has been pulled from the
-            // framework and slightly modified. Refer to the docs at the top of the class
-            // for more info on what was changed.
-            task.executeOnExecutor(AsyncTask.DUAL_THREAD_EXECUTOR, data);
-        }
-    }
-
-    /**
-     * Set placeholder bitmap that shows when the the background thread is running.
-     *
-     * @param bitmap
-     */
-    public void setLoadingImage(Bitmap bitmap) {
-        mLoadingBitmap = bitmap;
-    }
-
-    /**
-     * Set placeholder bitmap that shows when the the background thread is running.
-     *
-     * @param resId
-     */
-    public void setLoadingImage(int resId) {
-        mLoadingBitmap = BitmapFactory.decodeResource(mResources, resId);
-    }
-
-    /**
-     * Adds an {@link ImageCache} to this {@link ImageWorker} to handle disk and memory bitmap
-     * caching.
-     * @param fragmentManager
-     * @param cacheParams The cache parameters to use for the image cache.
-     */
-    public void addImageCache(FragmentManager fragmentManager,
-            ImageCache.ImageCacheParams cacheParams) {
-        mImageCacheParams = cacheParams;
-        mImageCache = ImageCache.getInstance(fragmentManager, mImageCacheParams);
-        new CacheAsyncTask().execute(MESSAGE_INIT_DISK_CACHE);
-    }
-
-    /**
-     * Adds an {@link ImageCache} to this {@link ImageWorker} to handle disk and memory bitmap
-     * caching.
-     * @param activity
-     * @param diskCacheDirectoryName See
-     * {@link ImageCache.ImageCacheParams#ImageCacheParams(Context, String)}.
-     */
-    public void addImageCache(FragmentActivity activity, String diskCacheDirectoryName) {
-        mImageCacheParams = new ImageCache.ImageCacheParams(activity, diskCacheDirectoryName);
-        mImageCache = ImageCache.getInstance(activity.getSupportFragmentManager(), mImageCacheParams);
-        new CacheAsyncTask().execute(MESSAGE_INIT_DISK_CACHE);
-    }
-
-    /**
-     * If set to true, the image will fade-in once it has been loaded by the background thread.
-     */
-    public void setImageFadeIn(boolean fadeIn) {
-        mFadeInBitmap = fadeIn;
-    }
-
-    public void setExitTasksEarly(boolean exitTasksEarly) {
-        mExitTasksEarly = exitTasksEarly;
-        setPauseWork(false);
-    }
-
-    /**
-     * Subclasses should override this to define any processing or work that must happen to produce
-     * the final bitmap. This will be executed in a background thread and be long running. For
-     * example, you could resize a large bitmap here, or pull down an image from the network.
-     *
-     * @param data The data to identify which image to process, as provided by
-     *            {@link ImageWorker#loadImage(Object, ImageView)}
-     * @return The processed bitmap
-     */
-    protected abstract Bitmap processBitmap(Object data);
-
-    /**
-     * @return The {@link ImageCache} object currently being used by this ImageWorker.
-     */
-    protected ImageCache getImageCache() {
-        return mImageCache;
-    }
-
-    /**
-     * Cancels any pending work attached to the provided ImageView.
-     * @param imageView
-     */
-    public static void cancelWork(ImageView imageView) {
-        final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
-        if (bitmapWorkerTask != null) {
-            bitmapWorkerTask.cancel(true);
-            if (BuildConfig.DEBUG) {
-                final Object bitmapData = bitmapWorkerTask.data;
-                Log.d(TAG, "cancelWork - cancelled work for " + bitmapData);
-            }
-        }
-    }
-
-    /**
-     * Returns true if the current work has been canceled or if there was no work in
-     * progress on this image view.
-     * Returns false if the work in progress deals with the same data. The work is not
-     * stopped in that case.
-     */
-    public static boolean cancelPotentialWork(Object data, ImageView imageView) {
-        final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
-
-        if (bitmapWorkerTask != null) {
-            final Object bitmapData = bitmapWorkerTask.data;
-            if (bitmapData == null || !bitmapData.equals(data)) {
-                bitmapWorkerTask.cancel(true);
-                if (BuildConfig.DEBUG) {
-                    Log.d(TAG, "cancelPotentialWork - cancelled work for " + data);
-                }
-            } else {
-                // The same work is already in progress.
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * @param imageView Any imageView
-     * @return Retrieve the currently active work task (if any) associated with this imageView.
-     * null if there is no such task.
-     */
-    private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
-        if (imageView != null) {
-            final Drawable drawable = imageView.getDrawable();
-            if (drawable instanceof AsyncDrawable) {
-                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
-                return asyncDrawable.getBitmapWorkerTask();
-            }
-        }
-        return null;
-    }
-
-    /**
-     * The actual AsyncTask that will asynchronously process the image.
-     */
-    private class BitmapWorkerTask extends AsyncTask<Object, Void, BitmapDrawable> {
-        private Object data;
-        private final WeakReference<ImageView> imageViewReference;
-
-        public BitmapWorkerTask(ImageView imageView) {
-            imageViewReference = new WeakReference<ImageView>(imageView);
-        }
-
-        /**
-         * Background processing.
-         */
-        @Override
-        protected BitmapDrawable doInBackground(Object... params) {
-            if (BuildConfig.DEBUG) {
-                Log.d(TAG, "doInBackground - starting work");
-            }
-
-            data = params[0];
-            final String dataString = String.valueOf(data);
-            Bitmap bitmap = null;
-            BitmapDrawable drawable = null;
-
-            // Wait here if work is paused and the task is not cancelled
-            synchronized (mPauseWorkLock) {
-                while (mPauseWork && !isCancelled()) {
-                    try {
-                        mPauseWorkLock.wait();
-                    } catch (InterruptedException e) {}
-                }
-            }
-
-            // If the image cache is available and this task has not been cancelled by another
-            // thread and the ImageView that was originally bound to this task is still bound back
-            // to this task and our "exit early" flag is not set then try and fetch the bitmap from
-            // the cache
-            if (mImageCache != null && !isCancelled() && getAttachedImageView() != null
-                    && !mExitTasksEarly) {
-                bitmap = mImageCache.getBitmapFromDiskCache(dataString);
-            }
-
-            // If the bitmap was not found in the cache and this task has not been cancelled by
-            // another thread and the ImageView that was originally bound to this task is still
-            // bound back to this task and our "exit early" flag is not set, then call the main
-            // process method (as implemented by a subclass)
-            if (bitmap == null && !isCancelled() && getAttachedImageView() != null
-                    && !mExitTasksEarly) {
-                bitmap = processBitmap(params[0]);
-            }
-
-            // If the bitmap was processed and the image cache is available, then add the processed
-            // bitmap to the cache for future use. Note we don't check if the task was cancelled
-            // here, if it was, and the thread is still running, we may as well add the processed
-            // bitmap to our cache as it might be used again in the future
-            if (bitmap != null) {
-                if (Utils.hasHoneycomb()) {
-                    // Running on Honeycomb or newer, so wrap in a standard BitmapDrawable
-                    drawable = new BitmapDrawable(mResources, bitmap);
-                } else {
-                    // Running on Gingerbread or older, so wrap in a RecyclingBitmapDrawable
-                    // which will recycle automagically
-                    drawable = new RecyclingBitmapDrawable(mResources, bitmap);
-                }
-
-                if (mImageCache != null) {
-                    mImageCache.addBitmapToCache(dataString, drawable);
-                }
-            }
-
-            if (BuildConfig.DEBUG) {
-                Log.d(TAG, "doInBackground - finished work");
-            }
-
-            return drawable;
-        }
-
-        /**
-         * Once the image is processed, associates it to the imageView
-         */
-        @Override
-        protected void onPostExecute(BitmapDrawable value) {
-            // if cancel was called on this task or the "exit early" flag is set then we're done
-            if (isCancelled() || mExitTasksEarly) {
-                value = null;
-            }
-
-            final ImageView imageView = getAttachedImageView();
-            if (value != null && imageView != null) {
-                if (BuildConfig.DEBUG) {
-                    Log.d(TAG, "onPostExecute - setting bitmap");
-                }
-                setImageDrawable(imageView, value);
-            }
-        }
-
-        @Override
-        protected void onCancelled(BitmapDrawable value) {
-            super.onCancelled(value);
-            synchronized (mPauseWorkLock) {
-                mPauseWorkLock.notifyAll();
-            }
-        }
-
-        /**
-         * Returns the ImageView associated with this task as long as the ImageView's task still
-         * points to this task as well. Returns null otherwise.
-         */
-        private ImageView getAttachedImageView() {
-            final ImageView imageView = imageViewReference.get();
-            final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
-
-            if (this == bitmapWorkerTask) {
-                return imageView;
-            }
-
-            return null;
-        }
-    }
-
-    /**
-     * A custom Drawable that will be attached to the imageView while the work is in progress.
-     * Contains a reference to the actual worker task, so that it can be stopped if a new binding is
-     * required, and makes sure that only the last started worker process can bind its result,
-     * independently of the finish order.
-     */
-    private static class AsyncDrawable extends BitmapDrawable {
-        private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
-
-        public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
-            super(res, bitmap);
-            bitmapWorkerTaskReference =
-                new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
-        }
-
-        public BitmapWorkerTask getBitmapWorkerTask() {
-            return bitmapWorkerTaskReference.get();
-        }
-    }
-
-    /**
-     * Called when the processing is complete and the final drawable should be 
-     * set on the ImageView.
-     *
-     * @param imageView
-     * @param drawable
-     */
-    private void setImageDrawable(ImageView imageView, Drawable drawable) {
-        if (mFadeInBitmap) {
-            // Transition drawable with a transparent drawable and the final drawable
-            final TransitionDrawable td =
-                    new TransitionDrawable(new Drawable[] {
-                            new ColorDrawable(android.R.color.transparent),
-                            drawable
-                    });
-            // Set background to loading bitmap
-            imageView.setBackgroundDrawable(
-                    new BitmapDrawable(mResources, mLoadingBitmap));
-
-            imageView.setImageDrawable(td);
-            td.startTransition(FADE_IN_TIME);
-        } else {
-            imageView.setImageDrawable(drawable);
-        }
-    }
-
-    /**
-     * Pause any ongoing background work. This can be used as a temporary
-     * measure to improve performance. For example background work could
-     * be paused when a ListView or GridView is being scrolled using a
-     * {@link android.widget.AbsListView.OnScrollListener} to keep
-     * scrolling smooth.
-     * <p>
-     * If work is paused, be sure setPauseWork(false) is called again
-     * before your fragment or activity is destroyed (for example during
-     * {@link android.app.Activity#onPause()}), or there is a risk the
-     * background thread will never finish.
-     */
-    public void setPauseWork(boolean pauseWork) {
-        synchronized (mPauseWorkLock) {
-            mPauseWork = pauseWork;
-            if (!mPauseWork) {
-                mPauseWorkLock.notifyAll();
-            }
-        }
-    }
-
-    protected class CacheAsyncTask extends AsyncTask<Object, Void, Void> {
-
-        @Override
-        protected Void doInBackground(Object... params) {
-            switch ((Integer)params[0]) {
-                case MESSAGE_CLEAR:
-                    clearCacheInternal();
-                    break;
-                case MESSAGE_INIT_DISK_CACHE:
-                    initDiskCacheInternal();
-                    break;
-                case MESSAGE_FLUSH:
-                    flushCacheInternal();
-                    break;
-                case MESSAGE_CLOSE:
-                    closeCacheInternal();
-                    break;
-            }
-            return null;
-        }
-    }
-
-    protected void initDiskCacheInternal() {
-        if (mImageCache != null) {
-            mImageCache.initDiskCache();
-        }
-    }
-
-    protected void clearCacheInternal() {
-        if (mImageCache != null) {
-            mImageCache.clearCache();
-        }
-    }
-
-    protected void flushCacheInternal() {
-        if (mImageCache != null) {
-            mImageCache.flush();
-        }
-    }
-
-    protected void closeCacheInternal() {
-        if (mImageCache != null) {
-            mImageCache.close();
-            mImageCache = null;
-        }
-    }
-
-    public void clearCache() {
-        new CacheAsyncTask().execute(MESSAGE_CLEAR);
-    }
-
-    public void flushCache() {
-        new CacheAsyncTask().execute(MESSAGE_FLUSH);
-    }
-
-    public void closeCache() {
-        new CacheAsyncTask().execute(MESSAGE_CLOSE);
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/RecyclingBitmapDrawable.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/RecyclingBitmapDrawable.java
deleted file mode 100644
index 2aae97f..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/RecyclingBitmapDrawable.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2013 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.example.android.bitmapfun.util;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.util.Log;
-
-import com.example.android.bitmapfun.BuildConfig;
-
-/**
- * A BitmapDrawable that keeps track of whether it is being displayed or cached.
- * When the drawable is no longer being displayed or cached,
- * {@link Bitmap#recycle() recycle()} will be called on this drawable's bitmap.
- */
-public class RecyclingBitmapDrawable extends BitmapDrawable {
-
-    static final String LOG_TAG = "CountingBitmapDrawable";
-
-    private int mCacheRefCount = 0;
-    private int mDisplayRefCount = 0;
-
-    private boolean mHasBeenDisplayed;
-
-    public RecyclingBitmapDrawable(Resources res, Bitmap bitmap) {
-        super(res, bitmap);
-    }
-
-    /**
-     * Notify the drawable that the displayed state has changed. Internally a
-     * count is kept so that the drawable knows when it is no longer being
-     * displayed.
-     *
-     * @param isDisplayed - Whether the drawable is being displayed or not
-     */
-    public void setIsDisplayed(boolean isDisplayed) {
-        synchronized (this) {
-            if (isDisplayed) {
-                mDisplayRefCount++;
-                mHasBeenDisplayed = true;
-            } else {
-                mDisplayRefCount--;
-            }
-        }
-
-        // Check to see if recycle() can be called
-        checkState();
-    }
-
-    /**
-     * Notify the drawable that the cache state has changed. Internally a count
-     * is kept so that the drawable knows when it is no longer being cached.
-     *
-     * @param isCached - Whether the drawable is being cached or not
-     */
-    public void setIsCached(boolean isCached) {
-        synchronized (this) {
-            if (isCached) {
-                mCacheRefCount++;
-            } else {
-                mCacheRefCount--;
-            }
-        }
-
-        // Check to see if recycle() can be called
-        checkState();
-    }
-
-    private synchronized void checkState() {
-        // If the drawable cache and display ref counts = 0, and this drawable
-        // has been displayed, then recycle
-        if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed
-                && hasValidBitmap()) {
-            if (BuildConfig.DEBUG) {
-                Log.d(LOG_TAG, "No longer being used or cached so recycling. "
-                        + toString());
-            }
-
-            getBitmap().recycle();
-        }
-    }
-
-    private synchronized boolean hasValidBitmap() {
-        Bitmap bitmap = getBitmap();
-        return bitmap != null && !bitmap.isRecycled();
-    }
-
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/Utils.java b/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/Utils.java
deleted file mode 100644
index 31dc342..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/java/com/example/android/bitmapfun/util/Utils.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2012 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.example.android.bitmapfun.util;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
-import android.os.StrictMode;
-
-import com.example.android.bitmapfun.ui.ImageDetailActivity;
-import com.example.android.bitmapfun.ui.ImageGridActivity;
-
-/**
- * Class containing some static utility methods.
- */
-public class Utils {
-    private Utils() {};
-
-
-    @TargetApi(VERSION_CODES.HONEYCOMB)
-    public static void enableStrictMode() {
-        if (Utils.hasGingerbread()) {
-            StrictMode.ThreadPolicy.Builder threadPolicyBuilder =
-                    new StrictMode.ThreadPolicy.Builder()
-                            .detectAll()
-                            .penaltyLog();
-            StrictMode.VmPolicy.Builder vmPolicyBuilder =
-                    new StrictMode.VmPolicy.Builder()
-                            .detectAll()
-                            .penaltyLog();
-
-            if (Utils.hasHoneycomb()) {
-                threadPolicyBuilder.penaltyFlashScreen();
-                vmPolicyBuilder
-                        .setClassInstanceLimit(ImageGridActivity.class, 1)
-                        .setClassInstanceLimit(ImageDetailActivity.class, 1);
-            }
-            StrictMode.setThreadPolicy(threadPolicyBuilder.build());
-            StrictMode.setVmPolicy(vmPolicyBuilder.build());
-        }
-    }
-
-    public static boolean hasFroyo() {
-        // Can use static final constants like FROYO, declared in later versions
-        // of the OS since they are inlined at compile time. This is guaranteed behavior.
-        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
-    }
-
-    public static boolean hasGingerbread() {
-        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
-    }
-
-    public static boolean hasHoneycomb() {
-        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
-    }
-
-    public static boolean hasHoneycombMR1() {
-        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1;
-    }
-
-    public static boolean hasJellyBean() {
-        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-    }
-
-    public static boolean hasKitKat() {
-        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
-    }
-}
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-hdpi/ic_launcher.png b/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644
index 75b3c97..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-ldpi/ic_launcher.png b/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-ldpi/ic_launcher.png
deleted file mode 100644
index 9923872..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-ldpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-mdpi/ic_launcher.png b/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644
index 0c9c11a..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-nodpi/empty_photo.png b/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-nodpi/empty_photo.png
deleted file mode 100644
index da1478a..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-nodpi/empty_photo.png
+++ /dev/null
Binary files differ
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-xhdpi/ic_launcher.png b/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index 7c5aeed..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-xxhdpi/ic_launcher.png b/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100644
index 91b0f96..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable/photogrid_list_selector.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/drawable/photogrid_list_selector.xml
deleted file mode 100644
index 19d8670..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/drawable/photogrid_list_selector.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-  Copyright (C) 2012 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="true">
-        <shape>
-            <solid android:color="@color/grid_state_pressed" />
-        </shape>
-    </item>
-    <item android:state_focused="true">
-        <shape>
-            <solid android:color="@color/grid_state_focused" />
-        </shape>
-    </item>
-    <item android:drawable="@android:color/transparent" />
-
-</selector>
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_detail_fragment.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_detail_fragment.xml
deleted file mode 100644
index 6940357..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_detail_fragment.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent" >
-
-    <ProgressBar
-        style="?android:attr/progressBarStyleLarge"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center" />
-
-    <com.example.android.bitmapfun.ui.RecyclingImageView
-        android:id="@+id/imageView"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
-        android:contentDescription="@string/imageview_description" />
-
-</FrameLayout>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_detail_pager.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_detail_pager.xml
deleted file mode 100644
index 877a26b..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_detail_pager.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/pager"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent" >
-
-</android.support.v4.view.ViewPager>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_grid_fragment.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_grid_fragment.xml
deleted file mode 100644
index e2034de..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/layout/image_grid_fragment.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<GridView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/gridView"
-    style="@style/PhotoGridLayout"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:columnWidth="@dimen/image_thumbnail_size"
-    android:horizontalSpacing="@dimen/image_thumbnail_spacing"
-    android:numColumns="auto_fit"
-    android:stretchMode="columnWidth"
-    android:verticalSpacing="@dimen/image_thumbnail_spacing" >
-
-</GridView>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/menu/main_menu.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/menu/main_menu.xml
deleted file mode 100644
index 35dad09..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/menu/main_menu.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <item
-        android:id="@+id/clear_cache"
-        android:icon="@android:drawable/ic_menu_delete"
-        android:showAsAction="never"
-        android:title="@string/clear_cache_menu"/>
-
-</menu>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/values-large/dimens.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/values-large/dimens.xml
deleted file mode 100644
index c681876..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/values-large/dimens.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<resources>
-
-    <dimen name="image_thumbnail_size">148dp</dimen>
-    <dimen name="image_thumbnail_spacing">2dp</dimen>
-
-</resources>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/values-v11/styles.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/values-v11/styles.xml
deleted file mode 100644
index 0c64526..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/values-v11/styles.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<resources>
-
-    <style name="AppTheme" parent="@android:style/Theme.Holo">
-        <item name="android:windowActionBarOverlay">true</item>
-        <item name="android:windowBackground">@android:color/black</item>
-        <item name="android:actionBarStyle">@style/TranslucentDarkActionBar</item>
-    </style>
-
-    <style name="AppTheme.FullScreen" />
-
-    <style name="TranslucentDarkActionBar" parent="@android:style/Widget.Holo.ActionBar">
-        <item name="android:background">#99000000</item>
-    </style>
-
-    <style name="PhotoGridLayout">
-        <item name="android:drawSelectorOnTop">true</item>
-    </style>
-
-</resources>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/values-xlarge/dimens.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/values-xlarge/dimens.xml
deleted file mode 100644
index 0f43977..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/values-xlarge/dimens.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<resources>
-
-    <dimen name="image_thumbnail_size">198dp</dimen>
-    <dimen name="image_thumbnail_spacing">2dp</dimen>
-
-</resources>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/values/colors.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/values/colors.xml
deleted file mode 100644
index 7e4a4fe..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<resources>
-
-    <color name="grid_state_pressed">#BB7dbcd3</color>
-    <color name="grid_state_focused">#777dbcd3</color>
-
-</resources>
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/values/dimens.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/values/dimens.xml
deleted file mode 100644
index 60d540f..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/values/dimens.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<resources>
-
-    <dimen name="image_thumbnail_size">100dp</dimen>
-    <dimen name="image_thumbnail_spacing">1dp</dimen>
-    <dimen name="image_detail_pager_margin">80dp</dimen>
-
-</resources>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/values/strings.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/values/strings.xml
deleted file mode 100644
index 8108c23..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<resources>
-
-    <string name="app_name">BitmapFun</string>
-    <string name="app_description">This is a sample application for the Android Training class
-        &quot;Displaying Bitmaps Efficiently&quot;
-        (http://developer.android.com/training/displaying-bitmaps/display-bitmap.html). It is not
-        designed to be a full reference application but to demonstrate the concepts discussed in
-        training course.</string>
-    <string name="clear_cache_menu">Clear Caches</string>
-    <string name="clear_cache_complete_toast">Caches have been cleared</string>
-    <string name="imageview_description">Image Thumbnail</string>
-    <string name="no_network_connection_toast">No network connection found</string>
-
-</resources>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/BitmapFun/src/main/res/values/styles.xml b/samples/training/bitmapfun/BitmapFun/src/main/res/values/styles.xml
deleted file mode 100644
index 0f1a018..0000000
--- a/samples/training/bitmapfun/BitmapFun/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2012 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.
--->
-
-<resources>
-
-    <style name="AppTheme" parent="android:Theme" />
-
-    <style name="AppTheme.FullScreen" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen" />
-
-    <style name="PhotoGridLayout">
-        <item name="android:drawSelectorOnTop">true</item>
-        <item name="android:listSelector">@drawable/photogrid_list_selector</item>
-    </style>
-
-</resources>
\ No newline at end of file
diff --git a/samples/training/bitmapfun/README b/samples/training/bitmapfun/README
deleted file mode 100644
index a0a192f..0000000
--- a/samples/training/bitmapfun/README
+++ /dev/null
@@ -1,8 +0,0 @@
-This is an Android Studio project:
-http://developer.android.com/sdk/installing/studio.html
-
-First copy local.properties.sample to local.properties and set your SDK path.
-
-Then import the project into Android Studio:
-File -> Import Project -> Choose Directory -> Import from external model ->
-    Gradle -> Use default gradle wrapper -> Finish
diff --git a/samples/training/bitmapfun/build.gradle b/samples/training/bitmapfun/build.gradle
deleted file mode 100644
index 495c503..0000000
--- a/samples/training/bitmapfun/build.gradle
+++ /dev/null
@@ -1 +0,0 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
diff --git a/samples/training/bitmapfun/local.properties.sample b/samples/training/bitmapfun/local.properties.sample
deleted file mode 100644
index 37317f4..0000000
--- a/samples/training/bitmapfun/local.properties.sample
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file should be copied to local.properties and path set to point
-# to your Android SDK.
-
-# Location of the SDK. This is only used by Gradle.
-# For customization when using a Version Control System, please read the
-# header note.
-sdk.dir=/usr/local/lib/android-sdk
\ No newline at end of file
diff --git a/samples/training/bitmapfun/settings.gradle b/samples/training/bitmapfun/settings.gradle
deleted file mode 100644
index 9f12781..0000000
--- a/samples/training/bitmapfun/settings.gradle
+++ /dev/null
@@ -1 +0,0 @@
-include ':BitmapFun'