From f5a0609baf19f46141ff676a37fb6f44cb5ff602 Mon Sep 17 00:00:00 2001 From: Ibraheem Zaman Date: Tue, 27 Oct 2015 17:23:22 +0500 Subject: [PATCH 1/2] Fix and enhance IconDrawable This commit adds lots of enhancements and fixes to IconDrawable: - Adds spin animation functionality. - Constant state has been changed to provide the correct semantics, instead of a dummy implementation just to work around bugs. - Handle the case where the width of the icon is not the same as it's height by returning the correct intrinsic width, and changing the drawing logic to always fit the icon within it's bounds. - Adds support for color state lists. - Adds support for tint, and sets the default to implement the half translucency on disabled state, and removed the custom logic to do it by changing the alpha. - Modulates the existing alpha from the color instead of replacing it. - Removes the changing of the bounds upon size change, as that should only be done by the view. - Adds a public method to get the icon. - Adds missing implementations of base methods. Note that because we need to be able to generate the drawable without a Context from the constant state, the methods that resolved resources (i.e. colors, dimensions) now have to take a Context as a parameter. --- .../mobile/discussion/DiscussionUtils.java | 12 +- .../third_party/iconify/IconDrawable.java | 512 ++++++++++++++---- .../mobile/third_party/iconify/IconView.java | 56 +- .../edx/mobile/view/CourseBaseActivity.java | 16 +- .../CourseDiscussionPostsThreadFragment.java | 11 +- .../view/CourseDiscussionTopicsFragment.java | 8 +- .../mobile/view/EditUserProfileFragment.java | 7 +- .../mobile/view/FormFieldSelectFragment.java | 8 +- .../edx/mobile/view/UserProfileFragment.java | 6 +- .../view/adapters/CourseOutlineAdapter.java | 15 +- .../adapters/DiscussionCommentsAdapter.java | 8 +- .../DiscussionPostsSpinnerAdapter.java | 4 +- .../adapters/DiscussionReportViewHolder.java | 2 +- .../DiscussionSocialLayoutViewHolder.java | 14 +- 14 files changed, 507 insertions(+), 172 deletions(-) diff --git a/VideoLocker/src/main/java/org/edx/mobile/discussion/DiscussionUtils.java b/VideoLocker/src/main/java/org/edx/mobile/discussion/DiscussionUtils.java index a02693247d..89a4861331 100644 --- a/VideoLocker/src/main/java/org/edx/mobile/discussion/DiscussionUtils.java +++ b/VideoLocker/src/main/java/org/edx/mobile/discussion/DiscussionUtils.java @@ -1,5 +1,6 @@ package org.edx.mobile.discussion; +import android.content.Context; import android.support.annotation.StringRes; import android.support.v4.widget.TextViewCompat; import android.view.View; @@ -26,12 +27,13 @@ public static void setStateOnTopicClosed(boolean isTopicClosed, TextView textVie @StringRes int negativeTextResId, ViewGroup creationLayout, View.OnClickListener listener) { + Context context = textView.getContext(); if (isTopicClosed) { textView.setText(negativeTextResId); TextViewCompat.setCompoundDrawablesRelative(textView, - new IconDrawable(textView.getContext(), Iconify.IconValue.fa_lock) - .sizeRes(R.dimen.icon_view_standard_width_height) - .colorRes(R.color.edx_grayscale_neutral_white_t), + new IconDrawable(context, Iconify.IconValue.fa_lock) + .sizeRes(context, R.dimen.icon_view_standard_width_height) + .colorRes(context, R.color.edx_grayscale_neutral_white_t), null, null, null ); creationLayout.setOnClickListener(null); @@ -39,8 +41,8 @@ public static void setStateOnTopicClosed(boolean isTopicClosed, TextView textVie textView.setText(positiveTextResId); TextViewCompat.setCompoundDrawablesRelative(textView, new IconDrawable(textView.getContext(), Iconify.IconValue.fa_plus_circle) - .sizeRes(R.dimen.icon_view_standard_width_height) - .colorRes(R.color.edx_grayscale_neutral_white_t), + .sizeRes(context, R.dimen.icon_view_standard_width_height) + .colorRes(context, R.color.edx_grayscale_neutral_white_t), null, null, null ); creationLayout.setOnClickListener(listener); diff --git a/VideoLocker/src/main/java/org/edx/mobile/third_party/iconify/IconDrawable.java b/VideoLocker/src/main/java/org/edx/mobile/third_party/iconify/IconDrawable.java index 19caa5ac39..a6223349ca 100644 --- a/VideoLocker/src/main/java/org/edx/mobile/third_party/iconify/IconDrawable.java +++ b/VideoLocker/src/main/java/org/edx/mobile/third_party/iconify/IconDrawable.java @@ -23,24 +23,39 @@ import android.annotation.TargetApi; import android.content.Context; +import android.content.res.ColorStateList; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; +import android.graphics.Outline; import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; +import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.SystemClock; +import android.support.annotation.ColorInt; +import android.support.annotation.ColorRes; +import android.support.annotation.DimenRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.text.TextPaint; +import android.util.StateSet; import android.view.View; +import org.edx.mobile.third_party.iconify.Iconify.IconValue; + import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; -import static android.os.Build.VERSION_CODES.KITKAT; -import static java.lang.String.valueOf; + +import static android.os.Build.VERSION_CODES.LOLLIPOP; import static org.edx.mobile.third_party.iconify.Utils.convertDpToPx; /** * Embed an icon into a Drawable that can be used as TextView icons, or ActionBar icons. - *

*

  *     new IconDrawable(context, IconValue.icon_star)
  *           .colorRes(R.color.white)
@@ -50,47 +65,68 @@
  * that is given to him. Note that in an ActionBar, if you don't
  * set the size explicitly it uses 0, so please use actionBarSize().
  */
-public class IconDrawable extends Drawable {
-
-    public static final int ANDROID_ACTIONBAR_ICON_SIZE_DP = 24;
-
-    private final Context context;
-
-    private final Iconify.IconValue icon;
-
-    private TextPaint paint;
-
-    private int size = -1;
-
-    private int alpha = 255;
-
-    private boolean autoMirrored;
+public final class IconDrawable extends Drawable implements Animatable {
+    static final int DEFAULT_COLOR = Color.BLACK;
+    // Set the default tint to make it half translucent on disabled state.
+    private static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.MULTIPLY;
+    private static final ColorStateList DEFAULT_TINT = new ColorStateList(
+            new int[][] { { -android.R.attr.state_enabled }, StateSet.WILD_CARD },
+            new int[] { 0x80FFFFFF, 0xFFFFFFFF }
+    );
+    private static final int ROTATION_DURATION = 2000;
+    private static final int ANDROID_ACTIONBAR_ICON_SIZE_DP = 24;
+    private static final Rect TEMP_DRAW_BOUNDS = new Rect();
+
+    @NonNull
+    private IconState iconState;
+    private final TextPaint paint;
+    private int color;
+    private ColorFilter tintFilter;
+    private int tintColor;
+    private long rotationStartTime = -1;
+    private boolean mMutated;
+    private final String text;
+    private final Rect drawBounds = new Rect();
+    private float centerX, centerY;
 
     /**
      * Create an IconDrawable.
      * @param context Your activity or application context.
      * @param icon    The icon you want this drawable to display.
      */
-    public IconDrawable(Context context, Iconify.IconValue icon) {
-        this.context = context;
-        this.icon = icon;
-        paint = new TextPaint();
+    public IconDrawable(@NonNull Context context, @NonNull IconValue icon) {
+        this(context, new IconState(icon));
+    }
+
+    private IconDrawable(@NonNull IconState state) {
+        this(null, state);
+    }
+
+    private IconDrawable(Context context, @NonNull IconState state) {
+        iconState = state;
+        paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
         paint.setTypeface(Iconify.getTypeface(context));
-        paint.setStyle(Paint.Style.FILL);
+        paint.setStyle(state.style);
         paint.setTextAlign(Paint.Align.CENTER);
         paint.setUnderlineText(false);
-        paint.setColor(Color.BLACK);
-        paint.setAntiAlias(true);
-        // Default to enable auto-mirroring
-        setAutoMirrored(true);
+        color = state.colorStateList.getColorForState(StateSet.WILD_CARD, DEFAULT_COLOR);
+        paint.setColor(color);
+        updateTintFilter();
+        setModulatedAlpha();
+        paint.setDither(iconState.dither);
+        text = String.valueOf(iconState.icon.character());
+        if (SDK_INT < LOLLIPOP && iconState.bounds != null) {
+            setBounds(iconState.bounds);
+        }
     }
 
     /**
      * Set the size of this icon to the standard Android ActionBar.
      * @return The current IconDrawable for chaining.
      */
-    public IconDrawable actionBarSize() {
-        return sizeDp(ANDROID_ACTIONBAR_ICON_SIZE_DP);
+    @NonNull
+    public IconDrawable actionBarSize(@NonNull Context context) {
+        return sizeDp(context, ANDROID_ACTIONBAR_ICON_SIZE_DP);
     }
 
     /**
@@ -98,7 +134,8 @@ public IconDrawable actionBarSize() {
      * @param dimenRes The dimension resource.
      * @return The current IconDrawable for chaining.
      */
-    public IconDrawable sizeRes(int dimenRes) {
+    @NonNull
+    public IconDrawable sizeRes(@NonNull Context context, @DimenRes int dimenRes) {
         return sizePx(context.getResources().getDimensionPixelSize(dimenRes));
     }
 
@@ -107,7 +144,8 @@ public IconDrawable sizeRes(int dimenRes) {
      * @param size The size in density-independent pixels (dp).
      * @return The current IconDrawable for chaining.
      */
-    public IconDrawable sizeDp(int size) {
+    @NonNull
+    public IconDrawable sizeDp(@NonNull Context context, int size) {
         return sizePx(convertDpToPx(context, size));
     }
 
@@ -116,10 +154,12 @@ public IconDrawable sizeDp(int size) {
      * @param size The size in pixels (px).
      * @return The current IconDrawable for chaining.
      */
+    @NonNull
     public IconDrawable sizePx(int size) {
-        this.size = size;
-        setBounds(0, 0, size, size);
-        invalidateSelf();
+        iconState.height = size;
+        paint.setTextSize(size);
+        paint.getTextBounds(text, 0, 1, TEMP_DRAW_BOUNDS);
+        iconState.width = TEMP_DRAW_BOUNDS.width();
         return this;
     }
 
@@ -128,9 +168,24 @@ public IconDrawable sizePx(int size) {
      * @param color The color, usually from android.graphics.Color or 0xFF012345.
      * @return The current IconDrawable for chaining.
      */
-    public IconDrawable color(int color) {
-        paint.setColor(color);
-        invalidateSelf();
+    @NonNull
+    public IconDrawable color(@ColorInt int color) {
+        return color(ColorStateList.valueOf(color));
+    }
+
+    /**
+     * Set the color of the drawable.
+     * @param colorStateList The color state list.
+     * @return The current IconDrawable for chaining.
+     */
+    @NonNull
+    public IconDrawable color(@NonNull ColorStateList colorStateList) {
+        if (colorStateList != iconState.colorStateList) {
+            iconState.colorStateList = colorStateList;
+            color = iconState.colorStateList.getColorForState(StateSet.WILD_CARD, DEFAULT_COLOR);
+            paint.setColor(color);
+            invalidateSelf();
+        }
         return this;
     }
 
@@ -139,10 +194,12 @@ public IconDrawable color(int color) {
      * @param colorRes The color resource, from your R file.
      * @return The current IconDrawable for chaining.
      */
-    public IconDrawable colorRes(int colorRes) {
-        paint.setColor(context.getResources().getColor(colorRes));
-        invalidateSelf();
-        return this;
+    @NonNull
+    public IconDrawable colorRes(@NonNull Context context, @ColorRes int colorRes) {
+        // Since we have an @ColorRes annotation on the colorRes parameter,
+        // we can be sure that we will get a non-null ColorStateList.
+        //noinspection ConstantConditions
+        return color(context.getResources().getColorStateList(colorRes));
     }
 
     /**
@@ -150,9 +207,20 @@ public IconDrawable colorRes(int colorRes) {
      * @param alpha The alpha, between 0 (transparent) and 255 (opaque).
      * @return The current IconDrawable for chaining.
      */
+    @NonNull
     public IconDrawable alpha(int alpha) {
         setAlpha(alpha);
-        invalidateSelf();
+        return this;
+    }
+
+    /**
+     * Start a spinning animation on this drawable. Call {@link #stop()}
+     * to stop it.
+     * @return The current IconDrawable for chaining.
+     */
+    @NonNull
+    public IconDrawable rotate() {
+        start();
         return this;
     }
 
@@ -160,151 +228,367 @@ public IconDrawable alpha(int alpha) {
      * Returns the icon to be displayed
      * @return The icon
      */
-    public final Iconify.IconValue getIcon() {
-        return icon;
+    public final IconValue getIcon() {
+        return iconState.icon;
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return size;
+        return iconState.height;
     }
 
     @Override
     public int getIntrinsicWidth() {
-        return size;
+        return iconState.width;
     }
 
     @Override
-    public void draw(Canvas canvas) {
-        Rect bounds = getBounds();
-        int height = bounds.height();
+    protected void onBoundsChange(@NonNull Rect bounds) {
+        final int width = bounds.width();
+        final int height = bounds.height();
         paint.setTextSize(height);
-        Rect textBounds = new Rect();
-        String textValue = valueOf(icon.character);
-        paint.getTextBounds(textValue, 0, 1, textBounds);
-        int textHeight = textBounds.height();
-        float textBottom = bounds.top + (height - textHeight) / 2f + textHeight - textBounds.bottom;
+        paint.getTextBounds(text, 0, 1, drawBounds);
+        paint.setTextSize(Math.min(height, (int) Math.ceil(
+                width * (height / (float) drawBounds.width()))));
+        paint.getTextBounds(text, 0, 1, drawBounds);
+        drawBounds.offsetTo(bounds.left + (width - drawBounds.width()) / 2,
+                bounds.top + (height - drawBounds.height()) / 2 - drawBounds.bottom);
+        centerX = bounds.exactCenterX();
+        centerY = bounds.exactCenterY();
+    }
+
+    @Override
+    @NonNull
+    public Rect getDirtyBounds() {
+        return drawBounds;
+    }
+
+    @Override
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public void getOutline(@NonNull Outline outline) {
+        outline.setRect(drawBounds);
+    }
+
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+        canvas.save();
         final boolean needMirroring = needMirroring();
         if (needMirroring) {
-            canvas.save();
-            // Mirror the icon
-            canvas.translate(bounds.width(), 0);
+            canvas.translate(getBounds().width(), 0);
             canvas.scale(-1.0f, 1.0f);
         }
-        canvas.drawText(textValue, bounds.exactCenterX(), textBottom, paint);
-        if (needMirroring) {
-            canvas.restore();
+        if (iconState.rotating) {
+            long currentTime = SystemClock.uptimeMillis();
+            if (rotationStartTime < 0) {
+                rotationStartTime = currentTime;
+            } else {
+                float rotation = (currentTime - rotationStartTime) /
+                        (float) ROTATION_DURATION * 360f;
+                canvas.rotate(rotation, centerX, centerY);
+            }
+            if (isVisible()) {
+                invalidateSelf();
+            }
         }
+        canvas.drawText(text, centerX, drawBounds.bottom, paint);
+        canvas.restore();
     }
 
     @Override
     public boolean isStateful() {
-        return true;
+        return iconState.colorStateList.isStateful() ||
+                (iconState.tint != null && iconState.tint.isStateful());
     }
 
     @Override
-    public void setAlpha(int alpha) {
-        this.alpha = alpha;
-        paint.setAlpha(alpha);
+    protected boolean onStateChange(@NonNull int[] state) {
+        boolean changed = false;
+
+        int newColor = iconState.colorStateList.getColorForState(state, DEFAULT_COLOR);
+        if (newColor != color) {
+            color = newColor;
+            paint.setColor(color);
+            setModulatedAlpha();
+            changed = true;
+        }
+
+        if (tintFilter != null) {
+            // If tintFilter is not null, then it's guaranteed that tint and tintMode
+            // are not null as well, so suppress any warnings otherwise.
+            //noinspection ConstantConditions
+            int newTintColor = iconState.tint.getColorForState(state, Color.TRANSPARENT);
+            if (newTintColor != tintColor) {
+                tintColor = newTintColor;
+                //noinspection ConstantConditions
+                tintFilter = new PorterDuffColorFilter(tintColor, iconState.tintMode);
+                if (iconState.colorFilter == null) {
+                    paint.setColorFilter(tintFilter);
+                    changed = true;
+                }
+            }
+        }
+
+        return changed;
     }
 
     @Override
-    public void setColorFilter(ColorFilter cf) {
-        paint.setColorFilter(cf);
+    public void setAlpha(int alpha) {
+        if (alpha != iconState.alpha) {
+            iconState.alpha = alpha;
+            setModulatedAlpha();
+            invalidateSelf();
+        }
+    }
+
+    private void setModulatedAlpha() {
+        paint.setAlpha(((color >> 24) * iconState.alpha) / 255);
     }
 
     @Override
-    public void clearColorFilter() {
-        paint.setColorFilter(null);
+    public int getAlpha() {
+        return iconState.alpha;
     }
 
     @Override
     public int getOpacity() {
-        return this.alpha;
+        int baseAlpha = color >> 24;
+        if (baseAlpha == 255 && iconState.alpha == 255) return PixelFormat.OPAQUE;
+        if (baseAlpha == 0 || iconState.alpha == 0) return PixelFormat.TRANSPARENT;
+        return PixelFormat.OPAQUE;
+    }
+
+    @Override
+    public void setDither(boolean dither) {
+        if (dither != iconState.dither) {
+            iconState.dither = dither;
+            paint.setDither(dither);
+            invalidateSelf();
+        }
+    }
+
+    @Override
+    public void setColorFilter(@Nullable ColorFilter cf) {
+        if (cf != iconState.colorFilter) {
+            iconState.colorFilter = cf;
+            paint.setColorFilter(cf);
+            invalidateSelf();
+        }
+    }
+
+    @Override
+    @Nullable
+    public ColorFilter getColorFilter() {
+        return iconState.colorFilter;
+    }
+
+    @Override
+    public void setTintList(@Nullable ColorStateList tint) {
+        if (tint != iconState.tint) {
+            iconState.tint = tint;
+            updateTintFilter();
+            invalidateSelf();
+        }
+    }
+
+    @Override
+    public void setTintMode(@NonNull PorterDuff.Mode tintMode) {
+        if (tintMode != iconState.tintMode) {
+            iconState.tintMode = tintMode;
+            updateTintFilter();
+            invalidateSelf();
+        }
+    }
+
+    private void updateTintFilter() {
+        if (iconState.tint == null || iconState.tintMode == null) {
+            if (tintFilter == null) {
+                return;
+            }
+            tintColor = 0;
+            tintFilter = null;
+        } else {
+            tintColor = iconState.tint.getColorForState(getState(), Color.TRANSPARENT);
+            tintFilter = new PorterDuffColorFilter(tintColor, iconState.tintMode);
+        }
+        if (iconState.colorFilter == null) {
+            paint.setColorFilter(tintFilter);
+            invalidateSelf();
+        }
     }
 
     /**
      * Sets paint style.
      * @param style to be applied
      */
-    public void setStyle(Paint.Style style) {
-        paint.setStyle(style);
+    public void setStyle(@NonNull Paint.Style style) {
+        if (style != iconState.style) {
+            iconState.style = style;
+            paint.setStyle(style);
+            invalidateSelf();
+        }
     }
 
     @Override
     public void setAutoMirrored(boolean mirrored) {
-        if (SDK_INT >= JELLY_BEAN_MR1 && icon.supportsRtl && autoMirrored != mirrored) {
-            autoMirrored = mirrored;
+        if (SDK_INT >= JELLY_BEAN_MR1 && iconState.icon.supportsRtl &&
+                iconState.autoMirrored != mirrored) {
+            iconState.autoMirrored = mirrored;
             invalidateSelf();
         }
     }
 
     @Override
     public final boolean isAutoMirrored() {
-        return autoMirrored;
+        return iconState.autoMirrored;
     }
 
-    @TargetApi(KITKAT)
+    // Since the auto-mirrored state is only set to true the SDK version
+    // supports it, we don't need an explicit check for it before calling
+    // the getLayoutDirection() methods.
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
     private boolean needMirroring() {
         if (isAutoMirrored()) {
-            // Since getLayoutDirection() is hidden, we will try to
-            // get the layout direction from the View, which we will
-            // attempt to get from the Callback. As the
-            // setLayoutDirection() method is also hidden, we can
-            // safely rely on the behaviour of the platform Views
-            // to provide a correct replacement for the hidden method.
+            // TODO: Uncomment this one we start compiling against Marshmallow
+            /*if (SDK_INT >= M) {
+                return getLayoutDirection() == LayoutDirection.RTL;
+            }*/
+            // Since getLayoutDirection() is hidden prior to Marshmallow, we will
+            // try to get the layout direction from the View, which we will assume
+            // is set as the callback. As the setLayoutDirection() method is also
+            // hidden, we can safely rely on the behaviour of the platform Views to
+            // provide a correct replacement for the hidden method.
             Callback callback = getCallback();
             if (callback instanceof View) {
-                View view = (View) callback;
-                if (SDK_INT < KITKAT || view.isLayoutDirectionResolved()) {
-                    return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
-                }
+                return ((View) callback).getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
             }
         }
         return false;
     }
 
-    // Although there is no shared state associated with IconDrawable, we
-    // need to provide a non-null ConstantState in order to make it work
-    // with LayerDrawable, which uses it to create a new instance of it's
-    // children when mutated, without checking if they support it. This
-    // bug has been fixed in Marshmallow. We work around it by providing
-    // a fake ConstantState which is actually bound to the IconDrawable
-    // instance.
-    private IconState state;
+    @Override
+    public void start() {
+        if (!iconState.rotating) {
+            iconState.rotating = true;
+            invalidateSelf();
+        }
+    }
+
+    @Override
+    public void stop() {
+        if (iconState.rotating) {
+            iconState.rotating = false;
+        }
+    }
+
+    @Override
+    public boolean isRunning() {
+        return iconState.rotating;
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        final boolean changed = super.setVisible(visible, restart);
+        if (iconState.rotating) {
+            if (changed) {
+                if (visible) {
+                    invalidateSelf();
+                }
+            } else {
+                if (restart && visible) {
+                    rotationStartTime = -1;
+                }
+            }
+        }
+        return changed;
+    }
+
+    @Override
+    public int getChangingConfigurations() {
+        return iconState.changingConfigurations;
+    }
+
+    @Override
+    public void setChangingConfigurations(int configs) {
+        iconState.changingConfigurations = configs;
+    }
 
+    // Implementing shared state despite being a third-party implementation
+    // in order to work around bugs in the framework and support library:
+    // http://b.android.com/191754
+    // https://github.com/JoanZapata/android-iconify/issues/93
     @Override
     public ConstantState getConstantState() {
-        if (state == null) {
-            state = new IconState();
+        // The bounds level need to be copied here to work around a bug in
+        // LayerDrawable where it doesn't copy the bounds and level in it's
+        // children when mutated or cloned. This bug has been fixed in
+        // Lollipop. The layout direction was not copied as well in Jelly
+        // Bean MR 1, but we're ignoring it for the moment as it's not
+        // exposed in the SDK prior to Marshmallow. If it ever becomes an
+        // issue though, then we'll need to handle that as well.
+        iconState.bounds = getBounds();
+        return iconState;
+    }
+
+    @Override
+    public Drawable mutate() {
+        if (!mMutated && super.mutate() == this) {
+            iconState = new IconState(iconState);
+            mMutated = true;
         }
-        return state;
+        return this;
     }
 
-    protected class IconState extends ConstantState {
+    private static class IconState extends ConstantState {
+        @NonNull
+        final IconValue icon;
+        int height = -1, width = -1;
+        @NonNull
+        ColorStateList colorStateList = ColorStateList.valueOf(DEFAULT_COLOR);
+        int alpha = 255;
+        boolean dither;
+        @Nullable
+        ColorFilter colorFilter;
+        @Nullable
+        ColorStateList tint = DEFAULT_TINT;
+        @Nullable
+        PorterDuff.Mode tintMode = DEFAULT_TINT_MODE;
+        @NonNull
+        Paint.Style style = Paint.Style.FILL;
+        boolean rotating;
+        boolean autoMirrored;
+        int changingConfigurations;
+        @Nullable
+        Rect bounds;
+
+        IconState(@NonNull IconValue icon) {
+            this.icon = icon;
+            autoMirrored = SDK_INT >= JELLY_BEAN_MR1 && icon.supportsRtl;
+        }
+
+        IconState(IconState state) {
+            icon = state.icon;
+            height = state.height;
+            width = state.width;
+            colorStateList = state.colorStateList;
+            alpha = state.alpha;
+            dither = state.dither;
+            colorFilter = state.colorFilter;
+            tint = state.tint;
+            tintMode = state.tintMode;
+            style = state.style;
+            rotating = state.rotating;
+            autoMirrored = state.autoMirrored;
+            changingConfigurations = state.changingConfigurations;
+        }
+
         @Override
         public Drawable newDrawable() {
-            IconDrawable iconDrawable = new IconDrawable(context, icon);
-            iconDrawable.sizePx(size);
-            iconDrawable.color(paint.getColor());
-            iconDrawable.setAlpha(getAlpha());
-            iconDrawable.setColorFilter(paint.getColorFilter());
-            iconDrawable.setStyle(paint.getStyle());
-            iconDrawable.setAutoMirrored(isAutoMirrored());
-            iconDrawable.setChangingConfigurations(getChangingConfigurations());
-            // The bounds and level needs to be copied here to work around a bug
-            // in LayerDrawable where it doesn't initialize these properties in
-            // it's children when mutated or cloned. This bug has been fixed in
-            // Lollipop.
-            iconDrawable.setBounds(getBounds());
-            iconDrawable.setLevel(getLevel());
-            return iconDrawable;
+            return new IconDrawable(this);
         }
 
         @Override
         public int getChangingConfigurations() {
-            return IconDrawable.this.getChangingConfigurations();
+            return changingConfigurations;
         }
     }
-
 }
\ No newline at end of file
diff --git a/VideoLocker/src/main/java/org/edx/mobile/third_party/iconify/IconView.java b/VideoLocker/src/main/java/org/edx/mobile/third_party/iconify/IconView.java
index 39a8a5801d..dfbdebe5b8 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/third_party/iconify/IconView.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/third_party/iconify/IconView.java
@@ -1,9 +1,13 @@
 package org.edx.mobile.third_party.iconify;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.ColorRes;
+import android.support.annotation.NonNull;
 import android.util.AttributeSet;
 import android.widget.ImageView;
 
@@ -11,21 +15,25 @@
 
 public class IconView extends ImageView {
 
-    private int color;
+    @NonNull
+    private ColorStateList colorStateList = ColorStateList.valueOf(IconDrawable.DEFAULT_COLOR);
 
-    public IconView(Context context) {
+    public IconView(@NonNull Context context) {
         super(context);
     }
 
-    public IconView(Context context, AttributeSet attrs) {
+    public IconView(@NonNull Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
-    public IconView(Context context, AttributeSet attrs, int defStyleAttr) {
+    public IconView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.IconView, defStyleAttr, 0);
-        color = a.getColor(R.styleable.IconView_iconColor, Color.BLACK);
+        ColorStateList colorStateList = a.getColorStateList(R.styleable.IconView_iconColor);
+        if (colorStateList != null) {
+            this.colorStateList = colorStateList;
+        }
         if (a.hasValue(R.styleable.IconView_iconName)) {
             setIcon(Iconify.IconValue.getFromHashCode(
                     a.getInt(R.styleable.IconView_iconName, -1)));
@@ -45,20 +53,50 @@ public final Iconify.IconValue getIcon() {
         return null;
     }
 
-    public void setIconColor(int iconColor) {
-        color = iconColor;
+    public void setIconColor(@ColorInt int color) {
+        setIconColor(ColorStateList.valueOf(color));
+    }
+
+    public void setIconColor(@NonNull ColorStateList colorStateList) {
+        this.colorStateList = colorStateList;
         Drawable drawable = getDrawable();
         if (drawable instanceof IconDrawable) {
-            ((IconDrawable) drawable).color(color);
+            ((IconDrawable) drawable).color(colorStateList);
         }
     }
 
+    public void setIconColorResource(@ColorRes int colorResId) {
+        // Since we have an @ColorRes annotation on the colorRes parameter,
+        // we can be sure that we will get a non-null ColorStateList.
+        //noinspection ConstantConditions
+        setIconColor(getContext().getResources().getColorStateList(colorResId));
+    }
+
     @Override
     public void setImageDrawable(Drawable drawable) {
         if (drawable instanceof IconDrawable && drawable != getDrawable()) {
-            ((IconDrawable) drawable).color(color);
+            ((IconDrawable) drawable).color(colorStateList);
         }
         super.setImageDrawable(drawable);
     }
 
+    public void setRotating(boolean rotate) {
+        setRotation(rotate, false);
+    }
+
+    public void setRotation(boolean rotate, boolean restart) {
+        Drawable drawable = getDrawable();
+        if (drawable instanceof IconDrawable) {
+            IconDrawable iconDrawable = (IconDrawable) drawable;
+            if (rotate) {
+                iconDrawable.start();
+            } else {
+                iconDrawable.stop();
+            }
+            if (restart && getVisibility() == VISIBLE) {
+                iconDrawable.setVisible(true, true);
+            }
+        }
+    }
+
 }
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/CourseBaseActivity.java b/VideoLocker/src/main/java/org/edx/mobile/view/CourseBaseActivity.java
index 54e2b1adcf..66ac7af360 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/CourseBaseActivity.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/CourseBaseActivity.java
@@ -91,7 +91,7 @@ protected void onCreate(Bundle arg0) {
     protected void initialize(Bundle arg){
 
         setApplyPrevTransitionOnRestart(true);
-        ((IconView)findViewById(R.id.video_download_indicator)).setIconColor(getResources().getColor(R.color.edx_brand_primary_light));
+        ((IconView)findViewById(R.id.video_download_indicator)).setIconColorResource(R.color.edx_brand_primary_light);
         findViewById(R.id.download_in_progress_button).setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -224,18 +224,18 @@ public boolean onPrepareOptionsMenu(Menu menu) {
         if( menu.findItem(R.id.action_share_on_web) != null)
             menu.findItem(R.id.action_share_on_web).setIcon(
                 new IconDrawable(this, Iconify.IconValue.fa_share_square_o)
-                    .actionBarSize().colorRes(R.color.edx_white));
+                    .actionBarSize(this).colorRes(this, R.color.edx_white));
         PrefManager.UserPrefManager userPrefManager = new PrefManager.UserPrefManager(this);
 
         if (  menu.findItem(R.id.action_change_mode) != null ) {
             if (userPrefManager.isUserPrefVideoModel()) {
                 menu.findItem(R.id.action_change_mode).setIcon(
                     new IconDrawable(this, Iconify.IconValue.fa_list)
-                        .actionBarSize().colorRes(R.color.edx_white));
+                        .actionBarSize(this).colorRes(this, R.color.edx_white));
             } else {
                 menu.findItem(R.id.action_change_mode).setIcon(
                     new IconDrawable(this, Iconify.IconValue.fa_film)
-                        .actionBarSize().colorRes(R.color.edx_white));
+                        .actionBarSize(this).colorRes(this, R.color.edx_white));
             }
         }
         return true;
@@ -274,12 +274,12 @@ public void changeMode(){
         // Setting checked states
         if (userPrefManager.isUserPrefVideoModel()) {
             videoOnlyItem.setChecked(true);
-            videoOnlyIcon.colorRes(R.color.cyan_4);
-            fullCourseIcon.colorRes(R.color.black);
+            videoOnlyIcon.colorRes(this, R.color.cyan_4);
+            fullCourseIcon.colorRes(this, R.color.black);
         } else {
             fullCourseItem.setChecked(true);
-            fullCourseIcon.colorRes(R.color.cyan_4);
-            videoOnlyIcon.colorRes(R.color.black);
+            fullCourseIcon.colorRes(this, R.color.cyan_4);
+            videoOnlyIcon.colorRes(this, R.color.black);
         }
 
         //registering popup with OnMenuItemClickListener
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/CourseDiscussionPostsThreadFragment.java b/VideoLocker/src/main/java/org/edx/mobile/view/CourseDiscussionPostsThreadFragment.java
index ee2ac0b1f5..0edf358d43 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/CourseDiscussionPostsThreadFragment.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/CourseDiscussionPostsThreadFragment.java
@@ -83,10 +83,11 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
         createNewPostTextView.setText(R.string.discussion_post_create_new_post);
+        Context context = getActivity();
         TextViewCompat.setCompoundDrawablesRelative(createNewPostTextView,
-                new IconDrawable(getActivity(), Iconify.IconValue.fa_plus_circle)
-                        .sizeRes(R.dimen.icon_view_standard_width_height)
-                        .colorRes(R.color.edx_grayscale_neutral_white_t),
+                new IconDrawable(context, Iconify.IconValue.fa_plus_circle)
+                        .sizeRes(context, R.dimen.icon_view_standard_width_height)
+                        .colorRes(context, R.color.edx_grayscale_neutral_white_t),
                 null, null, null
         );
         createNewPostLayout.setOnClickListener(new View.OnClickListener() {
@@ -111,9 +112,9 @@ public Drawable createIcon() {
                         Context context = getActivity();
                         LayerDrawable layeredIcon = new LayerDrawable(new Drawable[]{
                                 new IconDrawable(context, Iconify.IconValue.fa_long_arrow_up)
-                                        .colorRes(R.color.edx_brand_primary_base),
+                                        .colorRes(context, R.color.edx_brand_primary_base),
                                 new IconDrawable(context, Iconify.IconValue.fa_long_arrow_down)
-                                        .colorRes(R.color.edx_brand_primary_base)
+                                        .colorRes(context, R.color.edx_brand_primary_base)
                         });
                         Resources resources = context.getResources();
                         final int width = resources.getDimensionPixelSize(
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/CourseDiscussionTopicsFragment.java b/VideoLocker/src/main/java/org/edx/mobile/view/CourseDiscussionTopicsFragment.java
index 11e803a692..baa8e7bbd5 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/CourseDiscussionTopicsFragment.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/CourseDiscussionTopicsFragment.java
@@ -1,5 +1,6 @@
 package org.edx.mobile.view;
 
+import android.content.Context;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.v4.widget.TextViewCompat;
@@ -82,10 +83,11 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
         {
             final TextView header = (TextView) inflater.inflate(R.layout.row_discussion_topic, discussionTopicsListView, false);
             header.setText(R.string.forum_post_i_am_following);
+            Context context = getActivity();
             TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(header,
-                    new IconDrawable(getActivity(), Iconify.IconValue.fa_star)
-                            .colorRes(R.color.edx_grayscale_neutral_dark)
-                            .sizeRes(R.dimen.edx_base),
+                    new IconDrawable(context, Iconify.IconValue.fa_star)
+                            .colorRes(context, R.color.edx_grayscale_neutral_dark)
+                            .sizeRes(context, R.dimen.edx_base),
                     null, null, null);
             final DiscussionTopic discussionTopic = new DiscussionTopic();
             discussionTopic.setIdentifier(DiscussionTopic.FOLLOWING_TOPICS_ID);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/EditUserProfileFragment.java b/VideoLocker/src/main/java/org/edx/mobile/view/EditUserProfileFragment.java
index 98f56a2b95..fbdcf9116e 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/EditUserProfileFragment.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/EditUserProfileFragment.java
@@ -1,6 +1,7 @@
 package org.edx.mobile.view;
 
 import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -449,7 +450,11 @@ private static TextView createField(@NonNull LayoutInflater inflater, @NonNull V
             put("label", formattedLabel);
             put("value", formattedValue);
         }}));
-        TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, null, null, new IconDrawable(parent.getContext(), Iconify.IconValue.fa_angle_right).colorRes(R.color.edx_grayscale_neutral_light).sizeDp(24), null);
+        Context context = parent.getContext();
+        TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(
+                textView, null, null, new IconDrawable(context, Iconify.IconValue.fa_angle_right)
+                        .colorRes(context, R.color.edx_grayscale_neutral_light)
+                        .sizeDp(context, 24), null);
         if (readOnly) {
             textView.setEnabled(false);
             textView.setBackgroundColor(textView.getResources().getColor(R.color.edx_grayscale_neutral_x_light));
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/FormFieldSelectFragment.java b/VideoLocker/src/main/java/org/edx/mobile/view/FormFieldSelectFragment.java
index 3a42bdcaf5..1a3aa4fa77 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/FormFieldSelectFragment.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/FormFieldSelectFragment.java
@@ -1,6 +1,7 @@
 package org.edx.mobile.view;
 
 import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
@@ -131,10 +132,11 @@ private static void addDetectedValueHeader(@NonNull ListView listView, @StringRe
             labelValueSpan.setSpan(new ForegroundColorSpan(listView.getResources().getColor(R.color.edx_grayscale_neutral_dark)), 0, labelValueSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             textView.setText(ResourceUtil.getFormattedString(listView.getContext().getResources(), labelRes, labelKey, labelValueSpan));
         }
+        Context context = textView.getContext();
         TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(textView,
-                new IconDrawable(textView.getContext(), icon)
-                        .sizeRes(R.dimen.edx_base)
-                        .colorRes(R.color.edx_grayscale_neutral_light)
+                new IconDrawable(context, icon)
+                        .sizeRes(context, R.dimen.edx_base)
+                        .colorRes(context, R.color.edx_grayscale_neutral_light)
                 , null, null, null);
         listView.addHeaderView(textView, new FormOption(labelValue, value), true);
     }
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/UserProfileFragment.java b/VideoLocker/src/main/java/org/edx/mobile/view/UserProfileFragment.java
index 80c236ec64..77bc73df2e 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/UserProfileFragment.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/UserProfileFragment.java
@@ -1,5 +1,6 @@
 package org.edx.mobile.view;
 
+import android.content.Context;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
@@ -83,9 +84,10 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         super.onCreateOptionsMenu(menu, inflater);
         if (isViewingOwnProfile) {
             inflater.inflate(R.menu.edit_profile, menu);
+            Context context = getActivity();
             menu.findItem(R.id.edit_profile).setIcon(
-                    new IconDrawable(getActivity(), Iconify.IconValue.fa_pencil)
-                            .actionBarSize().colorRes(R.color.edx_white));
+                    new IconDrawable(context, Iconify.IconValue.fa_pencil)
+                            .actionBarSize(context).colorRes(context, R.color.edx_white));
         }
     }
 
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/CourseOutlineAdapter.java b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/CourseOutlineAdapter.java
index a708dcbfb3..f02f4afbbc 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/CourseOutlineAdapter.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/CourseOutlineAdapter.java
@@ -223,7 +223,7 @@ private  View getRowViewForLeaf(int position, View convertView, ViewGroup parent
         if ( !unit.isMultiDevice() && unit.getType() != BlockType.VIDEO){
             viewHolder.bulkDownload.setVisibility(View.INVISIBLE);
             viewHolder.rowType.setIcon(Iconify.IconValue.fa_laptop);
-            viewHolder.rowType.setIconColor(context.getResources().getColor(R.color.edx_grayscale_neutral_base));
+            viewHolder.rowType.setIconColorResource(R.color.edx_grayscale_neutral_base);
         } else if (row.component instanceof VideoBlockModel){
             updateUIForVideo(position, convertView, viewHolder, row);
         } else {
@@ -252,9 +252,9 @@ private void checkAccessStatus(final ViewHolder viewHolder, final CourseComponen
             @Override
             public void onResult(Boolean accessed) {
                 if (accessed) {
-                    viewHolder.rowType.setIconColor(context.getResources().getColor(R.color.edx_grayscale_neutral_base));
+                    viewHolder.rowType.setIconColorResource(R.color.edx_grayscale_neutral_base);
                 } else {
-                    viewHolder.rowType.setIconColor(context.getResources().getColor(R.color.edx_brand_primary_base));
+                    viewHolder.rowType.setIconColorResource(R.color.edx_brand_primary_base);
                 }
             }
 
@@ -295,9 +295,9 @@ private void updateUIForVideo(int position, View convertView, final ViewHolder v
                 @Override
                 public void onResult(DownloadEntry.WatchedState result) {
                     if(result != null && result == DownloadEntry.WatchedState.WATCHED) {
-                        viewHolder.rowType.setIconColor(context.getResources().getColor(R.color.edx_grayscale_neutral_base));
+                        viewHolder.rowType.setIconColorResource(R.color.edx_grayscale_neutral_base);
                     } else {
-                        viewHolder.rowType.setIconColor(context.getResources().getColor(R.color.edx_brand_primary_base));
+                        viewHolder.rowType.setIconColorResource(R.color.edx_brand_primary_base);
                     }
                 }
                 @Override
@@ -470,13 +470,12 @@ public ViewHolder getTag(View convertView) {
                 .findViewById(R.id.row_subtitle);
         holder.rowSubtitleIcon = (IconView) convertView
                 .findViewById(R.id.row_subtitle_icon);
-        holder.rowSubtitleIcon.setIconColor(context.getResources().getColor(R.color.edx_grayscale_neutral_light));
+        holder.rowSubtitleIcon.setIconColorResource(R.color.edx_grayscale_neutral_light);
         holder.noOfVideos = (TextView) convertView
                 .findViewById(R.id.no_of_videos);
         holder.bulkDownload = (IconView) convertView
                 .findViewById(R.id.bulk_download);
-        holder.bulkDownload.setIconColor(context.getResources().getColor(
-                R.color.edx_grayscale_neutral_base));
+        holder.bulkDownload.setIconColorResource(R.color.edx_grayscale_neutral_base);
         holder.numOfVideoAndDownloadArea = (LinearLayout) convertView
                 .findViewById(R.id.bulk_download_layout);
         holder.rowSubtitlePanel =convertView.findViewById(R.id.row_subtitle_panel);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionCommentsAdapter.java b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionCommentsAdapter.java
index 67d17f529e..aa9df22e9c 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionCommentsAdapter.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionCommentsAdapter.java
@@ -57,7 +57,9 @@ public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
             final int childrenSize = discussionComment.getChildren().size();
             holder.discussionCommentCountReportTextView.setText(context.getResources().
                     getQuantityString(R.plurals.number_responses_or_comments_comments_label, childrenSize, childrenSize));
-            iconDrawable = new IconDrawable(context, Iconify.IconValue.fa_comment).sizeRes(R.dimen.edx_xxx_small).colorRes(R.color.edx_grayscale_neutral_base);
+            iconDrawable = new IconDrawable(context, Iconify.IconValue.fa_comment)
+                    .sizeRes(context, R.dimen.edx_xxx_small)
+                    .colorRes(context, R.color.edx_grayscale_neutral_base);
             holder.discussionCommentCountReportTextView.setOnClickListener(null);
             holder.discussionCommentCountReportTextView.setClickable(false);
 
@@ -74,8 +76,8 @@ public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
             }
 
             iconDrawable = new IconDrawable(context, Iconify.IconValue.fa_flag)
-                    .sizeRes(R.dimen.edx_xxx_small)
-                    .colorRes(discussionComment.isAbuseFlagged() ? R.color.edx_brand_primary_base : R.color.edx_grayscale_neutral_dark);
+                    .sizeRes(context, R.dimen.edx_xxx_small)
+                    .colorRes(context, discussionComment.isAbuseFlagged() ? R.color.edx_brand_primary_base : R.color.edx_grayscale_neutral_dark);
             holder.discussionCommentCountReportTextView.setText(discussionComment.isAbuseFlagged() ? context.getString(R.string.discussion_responses_reported_label) : context.getString(R.string.discussion_responses_report_label));
             holder.discussionCommentCountReportTextView.setTextColor(context.getResources().getColor(R.color.edx_grayscale_neutral_dark));
 
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionPostsSpinnerAdapter.java b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionPostsSpinnerAdapter.java
index 7c32086820..bc72aa49ba 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionPostsSpinnerAdapter.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionPostsSpinnerAdapter.java
@@ -46,8 +46,8 @@ private static class IconDrawableFactoryImpl implements IconDrawableFactory {
         @NonNull
         public IconDrawable createIcon() {
             return new IconDrawable(context, iconValue)
-                    .sizeRes(R.dimen.icon_view_standard_width_height)
-                    .colorRes(R.color.edx_brand_primary_base);
+                    .sizeRes(context, R.dimen.icon_view_standard_width_height)
+                    .colorRes(context, R.color.edx_brand_primary_base);
         }
     }
 
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionReportViewHolder.java b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionReportViewHolder.java
index 1eb6c2420f..df707eedbc 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionReportViewHolder.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/DiscussionReportViewHolder.java
@@ -29,6 +29,6 @@ public void setReported(boolean isReported) {
         reportTextView.setText(reportTextView.getResources().getString(reportStringResId));
 
         int iconColor = isReported ? R.color.edx_brand_primary_base : R.color.edx_grayscale_neutral_base;
-        reportIconView.setIconColor(reportIconView.getResources().getColor(iconColor));
+        reportIconView.setIconColorResource(iconColor);
     }
 }
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/view_holders/DiscussionSocialLayoutViewHolder.java b/VideoLocker/src/main/java/org/edx/mobile/view/view_holders/DiscussionSocialLayoutViewHolder.java
index 0c85352e13..2262f15ca4 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/view_holders/DiscussionSocialLayoutViewHolder.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/view_holders/DiscussionSocialLayoutViewHolder.java
@@ -42,26 +42,24 @@ public DiscussionSocialLayoutViewHolder(View itemView) {
     public void setDiscussionThread(final DiscussionThread discussionThread) {
         threadVoteTextView.setText(ResourceUtil.getFormattedStringForQuantity(
                 threadVoteTextView.getResources(), R.plurals.discussion_responses_action_bar_vote_text, discussionThread.getVoteCount()));
-        threadVoteIconView.setIconColor(discussionThread.isVoted() ?
-                threadVoteIconView.getResources().getColor(R.color.edx_brand_primary_base) :
-                threadVoteIconView.getResources().getColor(R.color.edx_grayscale_neutral_base));
+        threadVoteIconView.setIconColorResource(discussionThread.isVoted() ?
+                R.color.edx_brand_primary_base : R.color.edx_grayscale_neutral_base);
 
         threadFollowContainer.setVisibility(View.VISIBLE);
 
         if (discussionThread.isFollowing()) {
             threadFollowTextView.setText(R.string.forum_unfollow);
-            threadFollowIconView.setIconColor(threadFollowIconView.getResources().getColor(R.color.edx_brand_primary_base));
+            threadFollowIconView.setIconColorResource(R.color.edx_brand_primary_base);
         } else {
             threadFollowTextView.setText(R.string.forum_follow);
-            threadFollowIconView.setIconColor(threadFollowIconView.getResources().getColor(R.color.edx_grayscale_neutral_base));
+            threadFollowIconView.setIconColorResource(R.color.edx_grayscale_neutral_base);
         }
     }
 
     public void setDiscussionResponse(final DiscussionComment discussionResponse) {
         threadVoteTextView.setText(ResourceUtil.getFormattedStringForQuantity(
                 threadVoteTextView.getResources(), R.plurals.discussion_responses_action_bar_vote_text, discussionResponse.getVoteCount()));
-        threadVoteIconView.setIconColor(discussionResponse.isVoted() ?
-                threadVoteIconView.getResources().getColor(R.color.edx_brand_primary_base) :
-                threadVoteIconView.getResources().getColor(R.color.edx_grayscale_neutral_base));
+        threadVoteIconView.setIconColorResource(discussionResponse.isVoted() ?
+                R.color.edx_brand_primary_base : R.color.edx_grayscale_neutral_base);
     }
 }

From a125a3e8fb098ea733330ffa24ae50e4dac0461f Mon Sep 17 00:00:00 2001
From: Mian Khalid 
Date: Fri, 30 Oct 2015 20:23:57 +0500
Subject: [PATCH 2/2] Add spinners to video download cells in outline view

- Removed downloading videos header
- Removed useless continous-calls of list refresh on sub-section screen
  while downloading a video
- webOnly type for VideoUnits case handled on section and sub-section screens
- Removed various tests related to downloading videos header
---
 .../res/layout/activity_course_base.xml       |  60 +-
 .../edx/mobile/base/MyVideosBaseFragment.java |  20 -
 .../org/edx/mobile/event/DownloadEvent.java   |  22 -
 .../org/edx/mobile/module/db/IDatabase.java   | 336 +++++++----
 .../module/db/impl/IDatabaseBaseImpl.java     |  41 +-
 .../mobile/module/db/impl/IDatabaseImpl.java  | 554 +++++++++++-------
 .../download/DownloadCompleteReceiver.java    |  14 -
 .../edx/mobile/module/prefs/PrefManager.java  |   1 -
 .../edx/mobile/module/storage/Storage.java    |  12 +-
 .../edx/mobile/player/PlayerController.java   |   4 +-
 .../mobile/services/VideoDownloadHelper.java  |   2 +-
 .../java/org/edx/mobile/util/NetworkUtil.java |  27 +
 .../edx/mobile/view/CourseBaseActivity.java   |  47 --
 .../mobile/view/CourseOutlineActivity.java    |   5 +-
 .../mobile/view/CourseOutlineFragment.java    |  32 +-
 .../mobile/view/CourseVideoListActivity.java  |  81 +--
 .../edx/mobile/view/MyVideosTabActivity.java  |  23 +-
 .../view/adapters/CourseOutlineAdapter.java   | 215 ++++---
 .../mobile/view/CourseBaseActivityTest.java   |  46 --
 .../view/CourseOutlineActivityTest.java       |  42 --
 .../CourseUnitNavigationActivityTest.java     |  10 -
 21 files changed, 741 insertions(+), 853 deletions(-)
 delete mode 100644 VideoLocker/src/main/java/org/edx/mobile/event/DownloadEvent.java

diff --git a/VideoLocker/res/layout/activity_course_base.xml b/VideoLocker/res/layout/activity_course_base.xml
index 3781a6c11d..bdc3b8743d 100755
--- a/VideoLocker/res/layout/activity_course_base.xml
+++ b/VideoLocker/res/layout/activity_course_base.xml
@@ -1,12 +1,10 @@
-
+    android:splitMotionEvents="false">
 
     
             
 
-            
-
-                
-
-                    
-
-                    
-
-
-                    
-
-                
-
-                
-            
-
              callback);
-    
-    
+
+
     /**
      * Returns all dmid's which are currently being downloaded for logged in user
      * This method is used for showing progress in the DownloadModule
-     * @return 
+     *
+     * @return
      */
     public List getAllDownloadingVideosDmidList(DataCallback> callback);
-    
-    
+
+
     /**
-     * Mark all videos as course deactivated for logged in user 
+     * Mark all videos as course deactivated for logged in user
      */
     public Integer updateAllVideosAsDeactivated(DataCallback callback);
-    
+
     /**
      * Mark all videos with enrollment id as course activated for logged in user
+     *
      * @param enrollmentId
      * @return The number of rows affected
      */
-    public Integer updateVideosActivatedForCourse(String enrollmentId, DataCallback callback);
-    
+    public Integer updateVideosActivatedForCourse(String enrollmentId, DataCallback
+            callback);
+
     /**
      * Returns all Deactivated videos for logged in user
+     *
      * @param callback
      */
     public List getAllDeactivatedVideos(DataCallback> callback);
-    
-    
+
+
     /**
-     * Mark the Video as online and reset the filepath and dmid for logged in user  
-     * @param videoId  - IVideoModel object
+     * Mark the Video as online and reset the filepath and dmid for logged in user
+     *
+     * @param videoId - IVideoModel object
      */
     public Integer updateVideoAsOnlineByVideoId(String videoId, DataCallback callback);
-    
-    
+
+
     /**
      * Returns count of Videos with passed DMID for logged in user
+     *
      * @param callback
      */
     public Integer getVideoCountBydmId(long dmId, DataCallback callback);
-    
-    
+
+
     /**
-     * Returns true if Video is downloaded in Chapter for logged in user 
+     * Returns true if Video is downloaded in Chapter for logged in user
+     *
      * @param enrollmentId - course which has the chapter
      * @param chapter
      */
-    public Boolean isVideoDownloadedInChapter(String enrollmentId, 
-            String chapter, DataCallback callback);
-    
+    public Boolean isVideoDownloadedInChapter(String enrollmentId,
+                                              String chapter, DataCallback callback);
+
     /**
-     * Returns number of videos marked as downloading/downloaded in Chapter for logged in user 
+     * Returns number of videos marked as downloading/downloaded in Chapter for logged in user
+     *
      * @param enrollmentId - course which has the chapter
      * @param chapter
      * @return - Number of videos not online
      */
-    public Integer getVideosCountByChapter(String enrollmentId, 
-            String chapter, DataCallback callback);
+    public Integer getVideosCountByChapter(String enrollmentId,
+                                           String chapter, DataCallback callback);
 
     /**
      * Return number of videos marked as web_view_only inChapter for logged in user
+     *
      * @param enrollmentId
      * @param chapter
      * @param callback
@@ -100,284 +109,369 @@ public Integer getWebOnlyVideosCountByChapter(String enrollmentId, String chapte
 
     /**
      * Returns true if any video downloading is in progress for chapter
+     *
      * @param enrollmentId - course which has the chapter
      * @param chapter
      * @return - Number of Downloaded videos
      */
-    public Boolean isVideoDownloadingInChapter(String enrollmentId, 
-            String chapter, DataCallback callback);
-    
-    
+    public Boolean isVideoDownloadingInChapter(String enrollmentId,
+                                               String chapter, DataCallback callback);
+
+
     /**
-     * Returns dmId's of all downloading videos for given Chapter of logged in user 
+     * Returns dmId's of all downloading videos for given Chapter of logged in user
+     *
      * @param enrollmentId - course which has the chapter
      * @param chapter
      */
-    public List getDownloadingVideoDmIdsForChapter(String enrollmentId, String chapter, 
-            DataCallback> callback);
-    
-    
+    public List getDownloadingVideoDmIdsForChapter(String enrollmentId, String chapter,
+                                                         DataCallback> callback);
+
+
     /**
      * Returns true if any video downloading is in progress for Section
+     *
      * @param enrollmentId - course which has the chapter
      * @param chapter
      * @param section
      */
     public Boolean isVideoDownloadingInSection(String enrollmentId, String chapter,
-            String section, DataCallback callback);
-    
-    
+                                               String section, DataCallback callback);
+
     /**
-     * Returns dmId's of all downloading videos for given section of logged in user 
-     * @param enrollmentId - course which has the chapter
-     * @param chapter
-     * @param section
-     */
-    public List getDownloadingVideoDmIdsForSection(String enrollmentId, String chapter, 
-            String section, final DataCallback> callback);
-    
-    
+     * Returns {@link android.app.DownloadManager} IDs of all downloading videos in a given section.
+     *
+     * @param enrollmentId course which has the chapter
+     * @param chapter      the chapter
+     * @param section      the section inside chapter
+     * @param callback     callback to return results to
+     * @return If the callback is null, returns an array containing the IDs for the downloading
+     * videos, or an empty array if there are no videos downloading in the section. Otherwise,
+     * returns null.
+     */
+    public long[] getDownloadingVideoDmIdsForSection(String enrollmentId, String chapter,
+                                                     String section, final
+                                                     DataCallback> callback);
+
     /**
-     * Returns number of videos marked as downloading/downloaded in Section for logged in user 
+     * Returns the count of downloading videos for given section
+     *
+     * @param enrollmentId course which has the chapter
+     * @param chapter      the chapter
+     * @param section      the section inside chapter
+     * @param callback     callback to return results to
+     * @return Count of downloading videos for a given section
+     */
+    public int getDownloadingVideosCountForSection(String enrollmentId, String chapter,
+                                                   String section, final DataCallback
+                                                           callback);
+
+    /**
+     * Returns number of videos marked as downloading/downloaded in Section for logged in user
+     *
      * @param enrollmentId - course which has the chapter
      * @param chapter
      * @param section
      */
-    public Integer getVideosCountBySection(String enrollmentId, String chapter, 
-            String section, DataCallback callback);
+    public Integer getVideosCountBySection(String enrollmentId, String chapter,
+                                           String section, DataCallback callback);
 
     /**
      * Returns true if Video is downloaded in Section for logged in user
      */
     public Boolean isVideoDownloadedInSection(String enrollmentId,
-                                              String chapter, String section, DataCallback callback);
+                                              String chapter, String section,
+                                              DataCallback callback);
+
+    /**
+     * Returns dmId's of all downloaded videos for given section of logged in user
+     *
+     * @param enrollmentId course which has the chapter
+     * @param chapter      the chapter
+     * @param section      the section inside chapter
+     * @param callback     callback to return results to
+     * @return If the callback is null, returns an array containing the IDs for the downloaded
+     * videos, or an empty array if there are no videos downloaded in the section. Otherwise,
+     * returns null.
+     */
+    public long[] getDownloadedVideoDmIdsForSection(String enrollmentId, String chapter,
+                                                    String section, final
+                                                    DataCallback> callback);
+
+    /**
+     * Returns the count of downloaded videos for given section
+     *
+     * @param enrollmentId course which has the chapter
+     * @param chapter      the chapter
+     * @param section      the section inside chapter
+     * @param callback     callback to return results to
+     * @return Count of downloaded videos for a given section
+     */
+    public int getDownloadedVideosCountForSection(String enrollmentId, String chapter,
+                                                  String section, final DataCallback
+                                                          callback);
+
     /**
      * get number of videos marked as webOnly
+     *
      * @param enrollmentId
      * @param chapter
      * @param section
      * @param callback
      * @return
      */
-    public Integer getWebOnlyVideosCountBySection(String enrollmentId, String chapter, String section,
+    public Integer getWebOnlyVideosCountBySection(String enrollmentId, String chapter, String
+            section,
                                                   final DataCallback callback);
 
     /**
-     * Update a Video's watched state 
-     * @param videoId  - Id of video for which status needs to change
-     * @param state - Status flag to be set for changing Video watched state
+     * Update a Video's watched state
+     *
+     * @param videoId - Id of video for which status needs to change
+     * @param state   - Status flag to be set for changing Video watched state
      */
     public Integer updateVideoWatchedState(String videoId, WatchedState state,
-            DataCallback callback);
-    
-    
+                                           DataCallback callback);
+
+
     /**
-     * Update a Video's last watched time 
-     * @param videoId  - Id of video for which status needs to change
-     * @param offset - Last Played offset 
+     * Update a Video's last watched time
+     *
+     * @param videoId - Id of video for which status needs to change
+     * @param offset  - Last Played offset
      */
     public Integer updateVideoLastPlayedOffset(String videoId, int offset,
-            DataCallback callback);
-    
-    
+                                               DataCallback callback);
+
+
     /**
-     * Insert Download Entry in the database 
-     * @param de  - IVideoModel object
+     * Insert Download Entry in the database
+     *
+     * @param de       - IVideoModel object
      * @param callback
      * @return - the row ID of the newly inserted row, or -1 if an error occurred
      */
     public Long addVideoData(VideoModel de, DataCallback callback);
-    
+
     /**
      * Returns VideoEntry for the passed VideoId
+     *
      * @param videoId
      * @param callback
      */
     public VideoModel getVideoEntryByVideoId(String videoId, DataCallback callback);
-    
+
     /**
-     * Returns {@link org.edx.mobile.model.VideoModel} which is downloaded or download is in progress for given videoUrl.
+     * Returns {@link org.edx.mobile.model.VideoModel} which is downloaded or download is in
+     * progress for given videoUrl.
+     *
      * @param videoUrl
      * @param callback
      * @return
      */
     VideoModel getVideoByVideoUrl(String videoUrl, DataCallback callback);
-    
-    
+
+
     /**
-     * Marks given Video as online and sets dmid to -1 so that this video is identified as NOT_DOWNLAODED.
-     * File path for this video is made empty so as to avoid access to non-existing file. 
+     * Marks given Video as online and sets dmid to -1 so that this video is identified as
+     * NOT_DOWNLAODED.
+     * File path for this video is made empty so as to avoid access to non-existing file.
      * NOTE: If there are multiple videos with same URL that are marked as Downloaded,
      * Only the reference should be removed and not the downloaded file
-     * @param de  - IVideoModel object
+     *
+     * @param de       - IVideoModel object
      * @param callback
      * @return - the row ID of the newly inserted row, or -1 if an error occurred
      */
     Integer deleteVideoByVideoId(VideoModel de, DataCallback callback);
-    
-    
+
+
     /**
      * Returns if a IVideoModel with the same video URL is downloaded
      * This method is used to display the progress if video is already downloaded
+     *
      * @param url
      */
     public Boolean isVideoFilePresentByUrl(String url, DataCallback callback);
-    
-    
+
+
     /**
      * This method updates info for Videos with the same URL and have been enqueued for downloading
+     *
      * @param model
      * @param callback
      */
     public Integer updateDownloadingVideoInfoByVideoId(VideoModel model,
-            DataCallback callback);
-    
+                                                       DataCallback callback);
+
     /**
      * This method marks the Video as Downloading when enqueued for Download
+     *
      * @param model
      * @param callback
      */
     public Integer updateAsDownloadingByVideoId(VideoModel model,
-            DataCallback callback);
-    
+                                                DataCallback callback);
+
     /**
      * Returns list of All VideoEntries which are currently being downloaded
+     *
      * @return
      */
     public List getListOfOngoingDownloads(DataCallback> callback);
-    
-    
+
+
     /**
-     * Returns no of Videos which have been completely 
+     * Returns no of Videos which have been completely
      * downloaded and marked as Downloaded in the DB
+     *
      * @return - count of Videos downloaded
      */
     public Integer getVideosDownloadedCount(DataCallback callback);
-    
+
     /**
-     * Returns Count of number of Downloaded Videos in the Course by Course ID 
+     * Returns Count of number of Downloaded Videos in the Course by Course ID
+     *
      * @param courseId
      * @param callback
      */
     public Integer getDownloadedVideoCountByCourse(String courseId, DataCallback callback);
-    
-    
+
+
     /**
-     * Returns Downloaded Videos in the Course by Course ID 
+     * Returns Downloaded Videos in the Course by Course ID
+     *
      * @param courseId
      * @param callback
      */
     public List getDownloadedVideoListForCourse(String courseId,
-            DataCallback> callback);
-    
-    
+                                                            DataCallback>
+                                                                    callback);
+
+
     /**
-     * Returns Size in bytes of Downloaded Videos in the Course by Course ID 
+     * Returns Size in bytes of Downloaded Videos in the Course by Course ID
+     *
      * @param courseId
      * @param callback
      */
     public Long getDownloadedVideosSizeByCourse(String courseId, DataCallback callback);
-    
+
     /**
-     * Returns IVideoModel object if entry exists with Video status set as 
+     * Returns IVideoModel object if entry exists with Video status set as
      * downloaded with the given URL
      */
     public VideoModel getIVideoModelByVideoUrl(String videoUrl,
-            DataCallback callback);
-    
-    
+                                               DataCallback callback);
+
+
     /**
-     * Return true if IVideoModel for associated dmId is present in db. Do not use username 
+     * Return true if IVideoModel for associated dmId is present in db. Do not use username
      * as this function is to check if the dmid is of VideoLocker or other application
+     *
      * @param dmId
      * @return
      */
     public Boolean isDmIdExists(long dmId, DataCallback callback);
-    
+
     /**
-     * Marks the download as complete for the given dmid. 
-     * NOTE - This should be done irrespective of username as if the user is 
+     * Marks the download as complete for the given dmid.
+     * NOTE - This should be done irrespective of username as if the user is
      * logged out and download is in progress, it should update download complete in the db.
+     *
      * @param dmId
      * @return
      */
-    public Integer updateDownloadCompleteInfoByDmId(long dmId, 
-            VideoModel de, DataCallback callback);
+    public Integer updateDownloadCompleteInfoByDmId(long dmId,
+                                                    VideoModel de, DataCallback callback);
 
     /**
      * Returns list of all videos from the database.
+     *
      * @return
      */
     List getAllVideos(String username, DataCallback> DataCallback);
 
     /**
      * Removes all records of given username from the datbase.
+     *
      * @param username
      */
     void clearDataByUser(String username);
 
     /**
      * This method gives the WatchedState stored in the DB for VideoID
+     *
      * @param videoId
      * @param dataCallback
      */
     WatchedState getWatchedStateForVideoId(String videoId,
-            DataCallback dataCallback);
+                                           DataCallback dataCallback);
 
     /**
      * Returns count of videos which have given URL as their video URL.
+     *
      * @param videoUrl
      * @param callback
      * @return
      */
     Integer getVideoCountByVideoUrl(String videoUrl, DataCallback callback);
-    
+
     /**
      * Returns count of videos which have given URL as their video URL.
+     *
      * @param dmId
      * @param callback
      * @return
      */
     VideoModel getDownloadEntryByDmId(long dmId, DataCallback callback);
-    
+
     /**
      * This function is used to getting all sorted Downloads based on Download date
      */
     public List getSortedDownloadsByDownloadedDateForCourseId(String courseId,
-            DataCallback> callback);
-    
+                                                                          DataCallback> callback);
+
     /**
      * This method gives the WatchedState stored in the DB for VideoID
+     *
      * @param videoId
      * @param dataCallback
      */
     DownloadedState getDownloadedStateForVideoId(String videoId,
-            DataCallback dataCallback);
+                                                 DataCallback dataCallback);
 
     /**
-     * Return true if any Video is marked as Downloading for the courseId in the database for logged in user
+     * Return true if any Video is marked as Downloading for the courseId in the database for
+     * logged in user
      * Used to handle reloading of Section listing
+     *
      * @return boolean flag if download is in progress
      */
     public Boolean isAnyVideoDownloadingInCourse(DataCallback callback, String courseId);
 
     /**
-     * Return true if any Video is marked as Downloading for a section in the database for logged in user
+     * Return true if any Video is marked as Downloading for a section in the database for logged
+     * in user
      * Used to handle reloading of subsection listing
+     *
      * @return boolean flag if download is in progress
      */
-    public Boolean isAnyVideoDownloadingInSection(DataCallback callback, String courseId, String section);
+    public Boolean isAnyVideoDownloadingInSection(DataCallback callback, String
+            courseId, String section);
 
     /**
-     * Return true if any Video is marked as Downloading for a subsection in the database for logged in user
+     * Return true if any Video is marked as Downloading for a subsection in the database for
+     * logged in user
      * Used to handle reloading of Video listing
+     *
      * @return boolean flag if download is in progress
      */
-    public Boolean isAnyVideoDownloadingInSubSection(DataCallback callback, String courseId,
+    public Boolean isAnyVideoDownloadingInSubSection(DataCallback callback, String
+            courseId,
                                                      String section, String subSection);
 
     /**
-     *
      * @param userName
      */
     public void setUserName(String userName);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/module/db/impl/IDatabaseBaseImpl.java b/VideoLocker/src/main/java/org/edx/mobile/module/db/impl/IDatabaseBaseImpl.java
index 50c0c91b10..bde11f03c8 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/module/db/impl/IDatabaseBaseImpl.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/module/db/impl/IDatabaseBaseImpl.java
@@ -9,17 +9,17 @@
 
 class IDatabaseBaseImpl implements Runnable {
 
+    protected static final Logger logger = new Logger(IDatabaseBaseImpl.class.getName());
+    protected Context context;
     private DbHelper helper;
     private Queue> opQueue = new LinkedList>();
     private boolean isQueueProcessing = false;
-    protected static final Logger logger = new Logger(IDatabaseBaseImpl.class.getName());
-    protected Context context;
 
     public IDatabaseBaseImpl(Context context) {
         this.context = context;
         helper = new DbHelper(context);
     }
-    
+
     @Override
     public void run() {
         if (isQueueProcessing) {
@@ -27,37 +27,38 @@ public void run() {
             // this will NOT allow multiple threads to process operation queue
             return;
         }
-        
+
         do {
             // mark queue being processed
             isQueueProcessing = true;
-            
+
             IDbOperation op = getNextQueuedOperation();
-            
+
             if (op == null) {
                 break;
             }
 
             // perform the datbase operation
-            execute(op); 
-        } while(true);
-        
+            execute(op);
+        } while (true);
+
         // mark queue not being processed
         isQueueProcessing = false;
-       // logger.debug("All database operations completed, queue is empty");
+        // logger.debug("All database operations completed, queue is empty");
     }
-    
+
     /**
      * Executes given database operation. This is a blocking call.
      * Returns result of the operation.
+     *
      * @param op
-     * @return 
+     * @return
      */
     private synchronized  T execute(IDbOperation op) {
         // perform this database operation
         synchronized (helper) {
             T result = (T) op.requestExecute(helper.getDatabase());
-            
+
             return result;
         }
     }
@@ -65,8 +66,9 @@ private synchronized  T execute(IDbOperation op) {
     /**
      * Enqueues given database operation to the operation queue and starts processing the queue,
      * if not already started.
-     * Operation is executed in a queue in background thread if callback is provided for the operation and this method returns null. 
+     * Operation is executed in a queue in background thread if callback is provided for the operation and this method returns null.
      * Otherwise this is a blocking call and returns result object.
+     *
      * @param operation
      */
     public synchronized  T enqueue(IDbOperation operation) {
@@ -74,20 +76,21 @@ public synchronized  T enqueue(IDbOperation operation) {
         if (operation.getCallback() == null) {
             return execute(operation);
         }
-        
+
         // add non-blocking operations to the queue and process in sequence 
         synchronized (opQueue) {
             opQueue.add(operation);
         }
-        
+
         // start processing the queue as we have a database operation to be processed
         new Thread(this).start();
-        
+
         return null;
     }
-    
+
     /**
      * Returns and removes the next operation from the operation queue.
+     *
      * @return
      */
     private IDbOperation getNextQueuedOperation() {
@@ -95,7 +98,7 @@ private IDbOperation getNextQueuedOperation() {
             if (opQueue.isEmpty()) {
                 return null;
             }
-            
+
             return opQueue.remove();
         }
     }
diff --git a/VideoLocker/src/main/java/org/edx/mobile/module/db/impl/IDatabaseImpl.java b/VideoLocker/src/main/java/org/edx/mobile/module/db/impl/IDatabaseImpl.java
index 193e40a199..0b4682e630 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/module/db/impl/IDatabaseImpl.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/module/db/impl/IDatabaseImpl.java
@@ -6,6 +6,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
+import org.apache.commons.lang.ArrayUtils;
 import org.edx.mobile.model.VideoModel;
 import org.edx.mobile.model.api.ProfileModel;
 import org.edx.mobile.model.db.DownloadEntry.DownloadedState;
@@ -23,13 +24,13 @@ public class IDatabaseImpl extends IDatabaseBaseImpl implements IDatabase {
     private String username;
 
     @Inject
-    public IDatabaseImpl( Context context ) {
+    public IDatabaseImpl(Context context) {
         super(context);
 
     }
 
-    private String username(){
-        if ( username == null ) {
+    private String username() {
+        if (username == null) {
             UserPrefs userprefs = new UserPrefs(context);
             if (userprefs != null) {
                 ProfileModel profile = userprefs.getProfile();
@@ -43,18 +44,21 @@ private String username(){
 
     @Override
     public Boolean isAnyVideoDownloading(final DataCallback callback) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.USERNAME + "=? AND "+ DbStructure.Column.DOWNLOADED + "=?", 
-                new String[] { username(), String.valueOf(DownloadedState.DOWNLOADING.ordinal()) }, null);
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.USERNAME + "=? AND " + DbStructure.Column.DOWNLOADED + "=?",
+                new String[]{username(), String.valueOf(DownloadedState.DOWNLOADING.ordinal())},
+                null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public List getAllDownloadingVideosDmidList(final DataCallback> callback){
-        DbOperationGetColumn op = new DbOperationGetColumn(true,DbStructure.Table.DOWNLOADS, new String[]{DbStructure.Column.DM_ID},
+    public List getAllDownloadingVideosDmidList(final DataCallback> callback) {
+        DbOperationGetColumn op = new DbOperationGetColumn(true, DbStructure.Table
+                .DOWNLOADS, new String[]{DbStructure.Column.DM_ID},
                 DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?",
-                new String[] {String.valueOf(DownloadedState.DOWNLOADING.ordinal()), username()}, null, Long.class);
+                new String[]{String.valueOf(DownloadedState.DOWNLOADING.ordinal()), username()},
+                null, Long.class);
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -65,20 +69,21 @@ public Integer updateAllVideosAsDeactivated(final DataCallback callback
         values.put(DbStructure.Column.IS_COURSE_ACTIVE, false);
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.USERNAME + "=?", new String[] {username()});
+                DbStructure.Column.USERNAME + "=?", new String[]{username()});
         op.setCallback(callback);
         return enqueue(op);
     }
 
 
     @Override
-    public Integer updateVideosActivatedForCourse(String enrollmentId, final DataCallback callback) {
+    public Integer updateVideosActivatedForCourse(String enrollmentId, final
+    DataCallback callback) {
         ContentValues values = new ContentValues();
         values.put(DbStructure.Column.IS_COURSE_ACTIVE, true);
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.EID + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] {enrollmentId, username()});
+                DbStructure.Column.EID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{enrollmentId, username()});
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -86,23 +91,25 @@ public Integer updateVideosActivatedForCourse(String enrollmentId, final DataCal
 
     @Override
     public List getAllDeactivatedVideos(final DataCallback> callback) {
-        DbOperationGetVideos op = new DbOperationGetVideos(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.IS_COURSE_ACTIVE + "=? AND "+ DbStructure.Column.USERNAME + "=? " , 
-                new String[] { "0", username()}, null);
+        DbOperationGetVideos op = new DbOperationGetVideos(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.IS_COURSE_ACTIVE + "=? AND " + DbStructure.Column.USERNAME +
+                        "=? ",
+                new String[]{"0", username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public Integer updateVideoAsOnlineByVideoId(String videoId, final DataCallback callback) {
+    public Integer updateVideoAsOnlineByVideoId(String videoId, final DataCallback
+            callback) {
         ContentValues values = new ContentValues();
         values.put(DbStructure.Column.DM_ID, 0);
         values.put(DbStructure.Column.FILEPATH, "");
         values.put(DbStructure.Column.DOWNLOADED, DownloadedState.ONLINE.ordinal());
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] {videoId, username()});
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoId, username()});
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -110,157 +117,236 @@ public Integer updateVideoAsOnlineByVideoId(String videoId, final DataCallback callback) {
-        DbOperationGetCount op = new DbOperationGetCount(false,DbStructure.Table.DOWNLOADS, 
-                new String[] {DbStructure.Column.VIDEO_ID}, 
-                DbStructure.Column.DM_ID + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] { String.valueOf(dmId), username() }, null);
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.DM_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{String.valueOf(dmId), username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public Boolean isVideoDownloadedInChapter(String enrollmentId,
-            String chapter, final DataCallback callback) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, 
-                new String[] {DbStructure.Column.VIDEO_ID}, 
-                DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND " 
-                        + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?",
-                        new String[] { chapter, enrollmentId, 
-                String.valueOf(DownloadedState.DOWNLOADED.ordinal()),username()}, null);
+                                              String chapter, final DataCallback
+                                                      callback) {
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME
+                        + "=?",
+                new String[]{chapter, enrollmentId,
+                        String.valueOf(DownloadedState.DOWNLOADED.ordinal()), username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
 
     @Override
-    public Integer getVideosCountByChapter(String enrollmentId, String chapter, 
-            final DataCallback callback) {
-        DbOperationGetCount op = new DbOperationGetCount(false,DbStructure.Table.DOWNLOADS, 
-                new String[] {DbStructure.Column.VIDEO_ID}, 
-                DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND " 
-                        + DbStructure.Column.DOWNLOADED + "!=? AND " + DbStructure.Column.USERNAME + "=?",
-                        new String[] { chapter, enrollmentId, 
-                String.valueOf(DownloadedState.ONLINE.ordinal()),username()}, null);
+    public Integer getVideosCountByChapter(String enrollmentId, String chapter,
+                                           final DataCallback callback) {
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.DOWNLOADED + "!=? AND " + DbStructure.Column
+                        .USERNAME + "=?",
+                new String[]{chapter, enrollmentId,
+                        String.valueOf(DownloadedState.ONLINE.ordinal()), username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public Integer getWebOnlyVideosCountByChapter(String enrollmentId, String chapter,
-                                           final DataCallback callback) {
-        DbOperationGetCount op = new DbOperationGetCount(false,DbStructure.Table.DOWNLOADS,
-                new String[] {DbStructure.Column.VIDEO_ID},
+                                                  final DataCallback callback) {
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
                 DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND "
-                        + DbStructure.Column.VIDEO_FOR_WEB_ONLY + "==1 AND " + DbStructure.Column.USERNAME + "=?",
-                new String[] { chapter, enrollmentId, username()}, null);
+                        + DbStructure.Column.VIDEO_FOR_WEB_ONLY + "==1 AND " + DbStructure.Column
+                        .USERNAME + "=?",
+                new String[]{chapter, enrollmentId, username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public Boolean isVideoDownloadingInChapter(String enrollmentId,
-            String chapter, final DataCallback callback) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, 
-                new String[] {DbStructure.Column.VIDEO_ID}, 
-                DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND " 
-                        + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?",
-                        new String[] { chapter, enrollmentId, 
-                String.valueOf(DownloadedState.DOWNLOADING.ordinal()),username()}, null);
+                                               String chapter, final DataCallback
+                                                       callback) {
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME
+                        + "=?",
+                new String[]{chapter, enrollmentId,
+                        String.valueOf(DownloadedState.DOWNLOADING.ordinal()), username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public List getDownloadingVideoDmIdsForChapter(String enrollmentId,
-            String chapter, final DataCallback> callback) {
-        DbOperationGetColumn op = new DbOperationGetColumn(true,DbStructure.Table.DOWNLOADS, 
+                                                         String chapter, final
+                                                         DataCallback> callback) {
+        DbOperationGetColumn op = new DbOperationGetColumn(true, DbStructure.Table
+                .DOWNLOADS,
                 new String[]{DbStructure.Column.DM_ID},
-                DbStructure.Column.DOWNLOADED + "=? AND "+ DbStructure.Column.EID + "=? AND " 
-                        + DbStructure.Column.CHAPTER + "=? AND "+ DbStructure.Column.USERNAME + "=?",
-                        new String[] {String.valueOf(DownloadedState.DOWNLOADING.ordinal()), 
-                enrollmentId, chapter,username()}, null, Long.class);
+                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.USERNAME +
+                        "=?",
+                new String[]{String.valueOf(DownloadedState.DOWNLOADING.ordinal()),
+                        enrollmentId, chapter, username()}, null, Long.class);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public Boolean isVideoDownloadingInSection(String enrollmentId,
-            String chapter, String section, final DataCallback callback) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, 
-                new String[] {DbStructure.Column.VIDEO_ID}, 
-                DbStructure.Column.SECTION + "=? AND " + DbStructure.Column.CHAPTER + "=? AND " 
-                        + DbStructure.Column.EID + "=? AND "+ DbStructure.Column.DOWNLOADED + "=? AND "
+                                               String chapter, String section, final
+                                               DataCallback callback) {
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.SECTION + "=? AND " + DbStructure.Column.CHAPTER + "=? AND "
+                        + DbStructure.Column.EID + "=? AND " + DbStructure.Column.DOWNLOADED +
+                        "=? AND "
                         + DbStructure.Column.USERNAME + "=?",
-                        new String[] {section, chapter, enrollmentId, 
-                String.valueOf(DownloadedState.DOWNLOADING.ordinal()),username()}, null);
+                new String[]{section, chapter, enrollmentId,
+                        String.valueOf(DownloadedState.DOWNLOADING.ordinal()), username()}, null);
         op.setCallback(callback);
         return enqueue(op);
 
     }
 
     @Override
-    public List getDownloadingVideoDmIdsForSection(String enrollmentId, String chapter, 
-            String section , final DataCallback> callback ) {
-        DbOperationGetColumn op = new DbOperationGetColumn(true,DbStructure.Table.DOWNLOADS, 
+    public long[] getDownloadingVideoDmIdsForSection(String enrollmentId, String chapter,
+                                                     String section, final
+                                                     DataCallback> callback) {
+        DbOperationGetColumn op = new DbOperationGetColumn(true, DbStructure.Table
+                .DOWNLOADS,
                 new String[]{DbStructure.Column.DM_ID},
-                DbStructure.Column.DOWNLOADED + "=? AND "+ DbStructure.Column.EID + "=? AND " 
+                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.EID + "=? AND "
                         + DbStructure.Column.CHAPTER + "=? AND "
                         + DbStructure.Column.SECTION + "=? AND "
                         + DbStructure.Column.USERNAME + "=?",
-                        new String[] {String.valueOf(DownloadedState.DOWNLOADING.ordinal()), 
-                enrollmentId, chapter, section, username()}, null, Long.class);
+                new String[]{String.valueOf(DownloadedState.DOWNLOADING.ordinal()),
+                        enrollmentId, chapter, section, username()}, null, Long.class);
         op.setCallback(callback);
-        return enqueue(op);
+        List downloadingList = enqueue(op);
+        if (callback != null) {
+            return null;
+        } else {
+            return ArrayUtils.toPrimitive(downloadingList.toArray(new Long[downloadingList.size()]));
+        }
     }
 
+    @Override
+    public int getDownloadingVideosCountForSection(String enrollmentId, String chapter,
+                                                   String section, final DataCallback
+                                                           callback) {
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.DM_ID},
+                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.CHAPTER + "=? AND "
+                        + DbStructure.Column.SECTION + "=? AND "
+                        + DbStructure.Column.USERNAME + "=?",
+                new String[]{String.valueOf(DownloadedState.DOWNLOADING.ordinal()),
+                        enrollmentId, chapter, section, username()}, null);
+        op.setCallback(callback);
+        return enqueue(op);
+    }
 
     @Override
     public Boolean isVideoDownloadedInSection(String enrollmentId,
-                                              String chapter, String section, final DataCallback callback) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS,
-            new String[] {DbStructure.Column.VIDEO_ID},
-            DbStructure.Column.SECTION + "=? AND " + DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND "
-                + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?",
-            new String[] { section, chapter, enrollmentId,
-                String.valueOf(DownloadedState.DOWNLOADED.ordinal()),username()}, null);
+                                              String chapter, String section, final
+                                              DataCallback callback) {
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.SECTION + "=? AND " + DbStructure.Column.CHAPTER + "=? AND " +
+                        DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME
+                        + "=?",
+                new String[]{section, chapter, enrollmentId,
+                        String.valueOf(DownloadedState.DOWNLOADED.ordinal()), username()}, null);
+        op.setCallback(callback);
+        return enqueue(op);
+    }
+
+    @Override
+    public long[] getDownloadedVideoDmIdsForSection(String enrollmentId, String chapter,
+                                                    String section, final
+                                                    DataCallback> callback) {
+        DbOperationGetColumn op = new DbOperationGetColumn(true, DbStructure.Table
+                .DOWNLOADS,
+                new String[]{DbStructure.Column.DM_ID},
+                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.CHAPTER + "=? AND "
+                        + DbStructure.Column.SECTION + "=? AND "
+                        + DbStructure.Column.USERNAME + "=?",
+                new String[]{String.valueOf(DownloadedState.DOWNLOADED.ordinal()),
+                        enrollmentId, chapter, section, username()}, null, Long.class);
+        op.setCallback(callback);
+        List downloadedList = enqueue(op);
+        if (callback != null) {
+            return null;
+        } else {
+            return ArrayUtils.toPrimitive(downloadedList.toArray(new Long[downloadedList.size()]));
+        }
+    }
+
+    @Override
+    public int getDownloadedVideosCountForSection(String enrollmentId, String chapter,
+                                                  String section, final DataCallback
+                                                          callback) {
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.DM_ID},
+                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.CHAPTER + "=? AND "
+                        + DbStructure.Column.SECTION + "=? AND "
+                        + DbStructure.Column.USERNAME + "=?",
+                new String[]{String.valueOf(DownloadedState.DOWNLOADED.ordinal()),
+                        enrollmentId, chapter, section, username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public Integer getVideosCountBySection(String enrollmentId, String chapter,
-            String section, final DataCallback callback) {
-        DbOperationGetCount op = new DbOperationGetCount(false,DbStructure.Table.DOWNLOADS, 
-                new String[] {DbStructure.Column.VIDEO_ID}, 
-                DbStructure.Column.SECTION + "=? AND "+DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND " 
-                        + DbStructure.Column.DOWNLOADED + "!=? AND " + DbStructure.Column.USERNAME + "=?",
-                        new String[] { section, chapter, enrollmentId, 
-                String.valueOf(DownloadedState.ONLINE.ordinal()),username()}, null);
+                                           String section, final DataCallback callback) {
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.SECTION + "=? AND " + DbStructure.Column.CHAPTER + "=? AND " +
+                        DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.DOWNLOADED + "!=? AND " + DbStructure.Column
+                        .USERNAME + "=?",
+                new String[]{section, chapter, enrollmentId,
+                        String.valueOf(DownloadedState.ONLINE.ordinal()), username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public Integer getWebOnlyVideosCountBySection(String enrollmentId, String chapter, String section,
+    public Integer getWebOnlyVideosCountBySection(String enrollmentId, String chapter, String
+            section,
                                                   final DataCallback callback) {
-        DbOperationGetCount op = new DbOperationGetCount(false,DbStructure.Table.DOWNLOADS,
-            new String[] {DbStructure.Column.VIDEO_ID},
-            DbStructure.Column.SECTION + "=? AND "+DbStructure.Column.CHAPTER + "=? AND " + DbStructure.Column.EID + "=? AND "
-                + DbStructure.Column.VIDEO_FOR_WEB_ONLY + "==1 AND " + DbStructure.Column.USERNAME + "=?",
-            new String[] { section, chapter, enrollmentId, username()}, null);
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.SECTION + "=? AND " + DbStructure.Column.CHAPTER + "=? AND " +
+                        DbStructure.Column.EID + "=? AND "
+                        + DbStructure.Column.VIDEO_FOR_WEB_ONLY + "==1 AND " + DbStructure.Column
+                        .USERNAME + "=?",
+                new String[]{section, chapter, enrollmentId, username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public Integer updateVideoWatchedState(String videoId, WatchedState status, 
-            final DataCallback callback) {
+    public Integer updateVideoWatchedState(String videoId, WatchedState status,
+                                           final DataCallback callback) {
         ContentValues values = new ContentValues();
         values.put(DbStructure.Column.WATCHED, status.ordinal());
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] {videoId, username()});
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoId, username()});
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -268,13 +354,13 @@ public Integer updateVideoWatchedState(String videoId, WatchedState status,
 
     @Override
     public Integer updateVideoLastPlayedOffset(String videoId, int offset,
-            final DataCallback callback) {
+                                               final DataCallback callback) {
         ContentValues values = new ContentValues();
         values.put(DbStructure.Column.LAST_PLAYED_OFFSET, offset);
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] {videoId, username()});
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoId, username()});
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -310,7 +396,7 @@ public Long addVideoData(final VideoModel de, final DataCallback callback)
             op.setCallback(callback);
             return enqueue(op);
         } else {
-            if(callback!=null){
+            if (callback != null) {
                 callback.sendResult(0L);
             }
             logger.warn("Not inserting, this seems a duplicate record");
@@ -322,24 +408,27 @@ public Long addVideoData(final VideoModel de, final DataCallback callback)
 
     /**
      * Returns download entry for given video id.
+     *
      * @param videoId
      * @return
      */
-    public VideoModel getVideoEntryByVideoId(String videoId, final DataCallback callback) {
-        DbOperationGetVideo op = new DbOperationGetVideo(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.VIDEO_ID + "=? AND "+ DbStructure.Column.USERNAME + "=?" , 
-                new String[] { videoId, username()}, null);
+    public VideoModel getVideoEntryByVideoId(String videoId, final DataCallback
+            callback) {
+        DbOperationGetVideo op = new DbOperationGetVideo(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoId, username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public VideoModel getVideoByVideoUrl(String videoUrl,
-            DataCallback callback) {
-        DbOperationGetVideo op = new DbOperationGetVideo(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.URL + "=? AND "+DbStructure.Column.DOWNLOADED + "!=? AND "
-                + DbStructure.Column.USERNAME + "=?" ,
-                new String[] { videoUrl, String.valueOf(DownloadedState.ONLINE.ordinal()), username()}, null);
+                                         DataCallback callback) {
+        DbOperationGetVideo op = new DbOperationGetVideo(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.URL + "=? AND " + DbStructure.Column.DOWNLOADED + "!=? AND "
+                        + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoUrl, String.valueOf(DownloadedState.ONLINE.ordinal()), username
+                        ()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -352,8 +441,8 @@ public Integer deleteVideoByVideoId(VideoModel video, DataCallback call
         values.put(DbStructure.Column.FILEPATH, "");
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] { video.getVideoId(), username()});
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{video.getVideoId(), username()});
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -361,18 +450,18 @@ public Integer deleteVideoByVideoId(VideoModel video, DataCallback call
 
     @Override
     public Boolean isVideoFilePresentByUrl(String videoUrl, final DataCallback callback) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.URL + "=? AND "+ DbStructure.Column.DOWNLOADED + "=? AND " 
-                        + DbStructure.Column.USERNAME + "=?", 
-                        new String[] { videoUrl,String.valueOf(DownloadedState.DOWNLOADED.ordinal()),
-                username()}, null);
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.URL + "=? AND " + DbStructure.Column.DOWNLOADED + "=? AND "
+                        + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoUrl, String.valueOf(DownloadedState.DOWNLOADED.ordinal()),
+                        username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public Integer updateDownloadingVideoInfoByVideoId(VideoModel model,
-            DataCallback callback) {
+                                                       DataCallback callback) {
         ContentValues values = new ContentValues();
         values.put(DbStructure.Column.DM_ID, model.getDmId());
         values.put(DbStructure.Column.DOWNLOADED, model.getDownloadedStateOrdinal());
@@ -382,8 +471,8 @@ public Integer updateDownloadingVideoInfoByVideoId(VideoModel model,
         values.put(DbStructure.Column.IS_COURSE_ACTIVE, model.isCourseActive());
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] { model.getVideoId(),username()});
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{model.getVideoId(), username()});
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -391,23 +480,25 @@ public Integer updateDownloadingVideoInfoByVideoId(VideoModel model,
 
     @Override
     public Integer updateAsDownloadingByVideoId(VideoModel model,
-            DataCallback callback) {
+                                                DataCallback callback) {
         ContentValues values = new ContentValues();
         values.put(DbStructure.Column.DM_ID, model.getDmId());
         values.put(DbStructure.Column.DOWNLOADED, DownloadedState.DOWNLOADING.ordinal());
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] { model.getVideoId(),username()});
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{model.getVideoId(), username()});
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public List getListOfOngoingDownloads(final DataCallback> callback) {
-        DbOperationGetVideos op = new DbOperationGetVideos(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] {String.valueOf(DownloadedState.DOWNLOADING.ordinal()), username()}, null);
+    public List getListOfOngoingDownloads(final DataCallback>
+                                                              callback) {
+        DbOperationGetVideos op = new DbOperationGetVideos(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{String.valueOf(DownloadedState.DOWNLOADING.ordinal()), username()},
+                null);
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -415,21 +506,25 @@ public List getListOfOngoingDownloads(final DataCallback callback) {
-        DbOperationGetCount op = new DbOperationGetCount(false,DbStructure.Table.DOWNLOADS, 
-                null, 
-                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] {String.valueOf(DownloadedState.DOWNLOADED.ordinal()), username()}, null);
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                null,
+                DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{String.valueOf(DownloadedState.DOWNLOADED.ordinal()), username()},
+                null);
         op.setCallback(callback);
         return enqueue(op);
 
     }
 
     @Override
-    public Integer getDownloadedVideoCountByCourse(String courseId, final DataCallback callback){
-        DbOperationGetCount op = new DbOperationGetCount(true,DbStructure.Table.DOWNLOADS, 
-                new String[] {DbStructure.Column.VIDEO_ID}, 
-                DbStructure.Column.EID + "=? AND " + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?",
-                new String[] { courseId, String.valueOf(DownloadedState.DOWNLOADED.ordinal()), username() },
+    public Integer getDownloadedVideoCountByCourse(String courseId, final DataCallback
+            callback) {
+        DbOperationGetCount op = new DbOperationGetCount(true, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.EID + "=? AND " + DbStructure.Column.DOWNLOADED + "=? AND " +
+                        DbStructure.Column.USERNAME + "=?",
+                new String[]{courseId, String.valueOf(DownloadedState.DOWNLOADED.ordinal()),
+                        username()},
                 null);
         op.setCallback(callback);
         return enqueue(op);
@@ -437,26 +532,29 @@ public Integer getDownloadedVideoCountByCourse(String courseId, final DataCallba
 
 
     @Override
-    public List getDownloadedVideoListForCourse(String courseId, final DataCallback> callback){
-        DbOperationGetVideos op = new DbOperationGetVideos(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.EID + "=? AND " + DbStructure.Column.DOWNLOADED + "=? AND " 
-                        + DbStructure.Column.USERNAME + "=?", 
-                        new String[] {courseId, String.valueOf(DownloadedState.DOWNLOADED.ordinal()),
-                username()}, null);
+    public List getDownloadedVideoListForCourse(String courseId, final
+    DataCallback> callback) {
+        DbOperationGetVideos op = new DbOperationGetVideos(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.EID + "=? AND " + DbStructure.Column.DOWNLOADED + "=? AND "
+                        + DbStructure.Column.USERNAME + "=?",
+                new String[]{courseId, String.valueOf(DownloadedState.DOWNLOADED.ordinal()),
+                        username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public Long getDownloadedVideosSizeByCourse(String courseId, final DataCallback callback){
+    public Long getDownloadedVideosSizeByCourse(String courseId, final DataCallback
+            callback) {
         String sqlQuery = "SELECT SUM(" + DbStructure.Column.SIZE + ") FROM "
-                + DbStructure.Table.DOWNLOADS + " WHERE " 
+                + DbStructure.Table.DOWNLOADS + " WHERE "
                 + DbStructure.Column.EID + "=? AND "
-                + DbStructure.Column.USERNAME + "=? AND " 
+                + DbStructure.Column.USERNAME + "=? AND "
                 + DbStructure.Column.DOWNLOADED + "=?";
         DbOperationSingleValueByRawQuery op = new DbOperationSingleValueByRawQuery(
                 sqlQuery,
-                new String[] { courseId, username(), String.valueOf(DownloadedState.DOWNLOADED.ordinal()) }, 
+                new String[]{courseId, username(), String.valueOf(DownloadedState.DOWNLOADED
+                        .ordinal())},
                 Long.class);
         op.setCallback(callback);
         return enqueue(op);
@@ -465,39 +563,40 @@ public Long getDownloadedVideosSizeByCourse(String courseId, final DataCallback<
 
     @Override
     public List getSortedDownloadsByDownloadedDateForCourseId(String courseId,
-            DataCallback> callback) {
-        DbOperationGetVideos op = new DbOperationGetVideos(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.EID + "=? AND " + DbStructure.Column.DOWNLOADED + "=? AND " 
-                        + DbStructure.Column.USERNAME + "=?", 
-                        new String[] { courseId, String.valueOf(
-                                DownloadedState.DOWNLOADED.ordinal()), username() }, 
-                                DbStructure.Column.DOWNLOADED_ON + " DESC");
+                                                                          DataCallback> callback) {
+        DbOperationGetVideos op = new DbOperationGetVideos(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.EID + "=? AND " + DbStructure.Column.DOWNLOADED + "=? AND "
+                        + DbStructure.Column.USERNAME + "=?",
+                new String[]{courseId, String.valueOf(
+                        DownloadedState.DOWNLOADED.ordinal()), username()},
+                DbStructure.Column.DOWNLOADED_ON + " DESC");
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public VideoModel getIVideoModelByVideoUrl(String videoUrl,
-            final DataCallback callback) {
-        DbOperationGetVideo op = new DbOperationGetVideo(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.URL + "=? AND "+ DbStructure.Column.USERNAME + "=?" , 
-                new String[] { videoUrl, username()}, null);
+                                               final DataCallback callback) {
+        DbOperationGetVideo op = new DbOperationGetVideo(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.URL + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoUrl, username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public Boolean isDmIdExists(long dmId, final DataCallback callback) {
-        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.USERNAME + "=? AND "+ DbStructure.Column.DM_ID + "=?", 
-                new String[] { username(), String.valueOf(dmId) }, null);
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.USERNAME + "=? AND " + DbStructure.Column.DM_ID + "=?",
+                new String[]{username(), String.valueOf(dmId)}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public Integer updateDownloadCompleteInfoByDmId(long dmId, 
-            VideoModel model, DataCallback callback) {
+    public Integer updateDownloadCompleteInfoByDmId(long dmId,
+                                                    VideoModel model, DataCallback
+                                                            callback) {
         ContentValues values = new ContentValues();
         values.put(DbStructure.Column.SIZE, model.getSize());
         values.put(DbStructure.Column.DURATION, model.getDuration());
@@ -510,26 +609,27 @@ public Integer updateDownloadCompleteInfoByDmId(long dmId,
         values.put(DbStructure.Column.DOWNLOADED_ON, model.getDownloadedOn());
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.DOWNLOADS, values,
-                DbStructure.Column.DM_ID + "=? AND " + DbStructure.Column.DOWNLOADED + "!=?", 
-                new String[] { String.valueOf(dmId), 
-                String.valueOf(DownloadedState.ONLINE.ordinal())});
+                DbStructure.Column.DM_ID + "=? AND " + DbStructure.Column.DOWNLOADED + "!=?",
+                new String[]{String.valueOf(dmId),
+                        String.valueOf(DownloadedState.ONLINE.ordinal())});
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public List getAllVideos(String username, final DataCallback> callback) {
-        DbOperationGetVideos op = new DbOperationGetVideos(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.USERNAME + "=?", new String[] { username() }, null);
+    public List getAllVideos(String username, final DataCallback>
+            callback) {
+        DbOperationGetVideos op = new DbOperationGetVideos(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.USERNAME + "=?", new String[]{username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public void clearDataByUser(String username) {
-        DbOperationDelete op = new DbOperationDelete(DbStructure.Table.DOWNLOADS, 
-                DbStructure.Column.USERNAME + "=?", 
-                new String[] { username() } );
+        DbOperationDelete op = new DbOperationDelete(DbStructure.Table.DOWNLOADS,
+                DbStructure.Column.USERNAME + "=?",
+                new String[]{username()});
         enqueue(op);
     }
 
@@ -541,17 +641,18 @@ public void release() {
 
     @Override
     public WatchedState getWatchedStateForVideoId(String videoId,
-            final DataCallback dataCallback) {
-        DbOperationGetColumn op = new DbOperationGetColumn(false,DbStructure.Table.DOWNLOADS, 
-                new String[] { DbStructure.Column.WATCHED }, 
-                DbStructure.Column.VIDEO_ID + "=? AND "+ DbStructure.Column.USERNAME + "=?" , 
-                new String[] { videoId, username()}, null, Integer.class);
+                                                  final DataCallback dataCallback) {
+        DbOperationGetColumn op = new DbOperationGetColumn(false, DbStructure
+                .Table.DOWNLOADS,
+                new String[]{DbStructure.Column.WATCHED},
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoId, username()}, null, Integer.class);
         op.setCallback(new DataCallback>() {
             @Override
             public void onResult(List ordinals) {
-                if(ordinals!=null && !ordinals.isEmpty()){
+                if (ordinals != null && !ordinals.isEmpty()) {
                     dataCallback.sendResult(WatchedState.values()[ordinals.get(0)]);
-                }else{
+                } else {
                     dataCallback.sendResult(WatchedState.UNWATCHED);
                 }
             }
@@ -566,20 +667,20 @@ public void onFail(Exception ex) {
 
     @Override
     public Integer getVideoCountByVideoUrl(String videoUrl, DataCallback callback) {
-        DbOperationGetCount op = new DbOperationGetCount(false,DbStructure.Table.DOWNLOADS, 
-                new String[] {DbStructure.Column.VIDEO_ID}, 
-                DbStructure.Column.URL + "=? AND " + DbStructure.Column.USERNAME + "=?", 
-                new String[] { videoUrl, username() }, null);
+        DbOperationGetCount op = new DbOperationGetCount(false, DbStructure.Table.DOWNLOADS,
+                new String[]{DbStructure.Column.VIDEO_ID},
+                DbStructure.Column.URL + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoUrl, username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
     public VideoModel getDownloadEntryByDmId(long dmId,
-            DataCallback callback) {
-        DbOperationGetVideo op = new DbOperationGetVideo(false,DbStructure.Table.DOWNLOADS, null, 
-                DbStructure.Column.DM_ID + "=? AND "+ DbStructure.Column.DOWNLOADED + "=?" , 
-                new String[] { String.valueOf(dmId), String.valueOf(DownloadedState
+                                             DataCallback callback) {
+        DbOperationGetVideo op = new DbOperationGetVideo(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.DM_ID + "=? AND " + DbStructure.Column.DOWNLOADED + "=?",
+                new String[]{String.valueOf(dmId), String.valueOf(DownloadedState
                         .DOWNLOADING.ordinal())}, null);
         op.setCallback(callback);
         return enqueue(op);
@@ -591,26 +692,30 @@ public Boolean isVideoDownloadingByVideoId(String videoId,
         DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, 
                 new String[] {DbStructure.Column.VIDEO_ID}, 
                 DbStructure.Column.VIDEO_ID + "=? "
-                        + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME + "=?",
-                        new String[] { videoId, String.valueOf(DownloadedState.DOWNLOADING.ordinal())
+                        + DbStructure.Column.DOWNLOADED + "=? AND " + DbStructure.Column.USERNAME
+                         + "=?",
+                        new String[] { videoId, String.valueOf(DownloadedState.DOWNLOADING
+                        .ordinal())
                 ,username()}, null);
         op.setCallback(callback);
         return enqueue(op);
     }*/
-    
+
     @Override
     public DownloadedState getDownloadedStateForVideoId(String videoId,
-            final DataCallback dataCallback) {
-        DbOperationGetColumn op = new DbOperationGetColumn(false,DbStructure.Table.DOWNLOADS, 
-                new String[] { DbStructure.Column.DOWNLOADED }, 
-                DbStructure.Column.VIDEO_ID + "=? AND "+ DbStructure.Column.USERNAME + "=?" , 
-                new String[] { videoId, username()}, null, Integer.class);
+                                                        final DataCallback
+                                                                dataCallback) {
+        DbOperationGetColumn op = new DbOperationGetColumn(false, DbStructure
+                .Table.DOWNLOADS,
+                new String[]{DbStructure.Column.DOWNLOADED},
+                DbStructure.Column.VIDEO_ID + "=? AND " + DbStructure.Column.USERNAME + "=?",
+                new String[]{videoId, username()}, null, Integer.class);
         op.setCallback(new DataCallback>() {
             @Override
             public void onResult(List ordinals) {
-                if(ordinals!=null && !ordinals.isEmpty()){
+                if (ordinals != null && !ordinals.isEmpty()) {
                     dataCallback.sendResult(DownloadedState.values()[ordinals.get(0)]);
-                }else{
+                } else {
                     dataCallback.sendResult(DownloadedState.ONLINE);
                 }
             }
@@ -624,39 +729,47 @@ public void onFail(Exception ex) {
     }
 
     @Override
-    public Boolean isAnyVideoDownloadingInCourse(final DataCallback callback, String courseId) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, null,
-                DbStructure.Column.EID + "=? AND "+ DbStructure.Column.USERNAME + "=? AND "
+    public Boolean isAnyVideoDownloadingInCourse(final DataCallback callback, String
+            courseId) {
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.EID + "=? AND " + DbStructure.Column.USERNAME + "=? AND "
                         + DbStructure.Column.DOWNLOADED + "=?",
-                new String[] {courseId, username(), String.valueOf(DownloadedState.DOWNLOADING.ordinal()) }, null);
+                new String[]{courseId, username(), String.valueOf(DownloadedState.DOWNLOADING
+                        .ordinal())}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public Boolean isAnyVideoDownloadingInSection(final DataCallback callback, String courseId, String section) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, null,
-                DbStructure.Column.EID + "=? AND "+ DbStructure.Column.CHAPTER + "=? AND "+
-                DbStructure.Column.USERNAME + "=? AND "+ DbStructure.Column.DOWNLOADED + "=?",
-                new String[] {courseId, section, username(), String.valueOf(DownloadedState.DOWNLOADING.ordinal()) }, null);
+    public Boolean isAnyVideoDownloadingInSection(final DataCallback callback, String
+            courseId, String section) {
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.EID + "=? AND " + DbStructure.Column.CHAPTER + "=? AND " +
+                        DbStructure.Column.USERNAME + "=? AND " + DbStructure.Column.DOWNLOADED +
+                        "=?",
+                new String[]{courseId, section, username(), String.valueOf(DownloadedState
+                        .DOWNLOADING.ordinal())}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public Boolean isAnyVideoDownloadingInSubSection(final DataCallback callback, String courseId,
+    public Boolean isAnyVideoDownloadingInSubSection(final DataCallback callback, String
+            courseId,
                                                      String section, String subSection) {
-        DbOperationExists op = new DbOperationExists(false,DbStructure.Table.DOWNLOADS, null,
-                DbStructure.Column.EID + "=? AND "+ DbStructure.Column.CHAPTER + "=? AND "+
-                        DbStructure.Column.SECTION + "=? AND "+ DbStructure.Column.USERNAME + "=? AND "+
+        DbOperationExists op = new DbOperationExists(false, DbStructure.Table.DOWNLOADS, null,
+                DbStructure.Column.EID + "=? AND " + DbStructure.Column.CHAPTER + "=? AND " +
+                        DbStructure.Column.SECTION + "=? AND " + DbStructure.Column.USERNAME +
+                        "=? AND " +
                         DbStructure.Column.DOWNLOADED + "=?",
-                new String[] {courseId, section, subSection, username(), String.valueOf(DownloadedState.DOWNLOADING.ordinal()) }, null);
+                new String[]{courseId, section, subSection, username(), String.valueOf
+                        (DownloadedState.DOWNLOADING.ordinal())}, null);
         op.setCallback(callback);
         return enqueue(op);
     }
 
     @Override
-    public void setUserName(String userName){
+    public void setUserName(String userName) {
         this.username = userName;
     }
 
@@ -664,13 +777,15 @@ public void setUserName(String userName){
     /**
      * update assessment unit access record
      */
-    public synchronized Integer updateAccess(DataCallback callback, String unitId, boolean visited){
+    public synchronized Integer updateAccess(DataCallback callback, String unitId,
+                                             boolean visited) {
         ContentValues values = new ContentValues();
         values.put(DbStructure.Column.ASSESSMENT_TB_UNIT_WATCHED, visited);
 
         DbOperationUpdate op = new DbOperationUpdate(DbStructure.Table.ASSESSMENT, values,
-            DbStructure.Column.ASSESSMENT_TB_UNIT_ID + "=? AND " + DbStructure.Column.ASSESSMENT_TB_USERNAME + "=?",
-            new String[] {unitId, username()});
+                DbStructure.Column.ASSESSMENT_TB_UNIT_ID + "=? AND " + DbStructure.Column
+                        .ASSESSMENT_TB_USERNAME + "=?",
+                new String[]{unitId, username()});
         op.setCallback(callback);
         return enqueue(op);
     }
@@ -678,17 +793,20 @@ public synchronized Integer updateAccess(DataCallback callback, String
     /**
      * get assessment unit access status
      */
-    public synchronized boolean isUnitAccessed(final DataCallback callback, String unitId){
-        DbOperationGetColumn op = new DbOperationGetColumn(false,DbStructure.Table.ASSESSMENT,
-            new String[] { DbStructure.Column.ASSESSMENT_TB_UNIT_WATCHED },
-            DbStructure.Column.ASSESSMENT_TB_UNIT_ID + "=? AND "+ DbStructure.Column.ASSESSMENT_TB_USERNAME + "=?" ,
-            new String[] { unitId, username()}, null, Boolean.class);
-        if( callback != null ) {
+    public synchronized boolean isUnitAccessed(final DataCallback callback, String
+            unitId) {
+        DbOperationGetColumn op = new DbOperationGetColumn(false, DbStructure
+                .Table.ASSESSMENT,
+                new String[]{DbStructure.Column.ASSESSMENT_TB_UNIT_WATCHED},
+                DbStructure.Column.ASSESSMENT_TB_UNIT_ID + "=? AND " + DbStructure.Column
+                        .ASSESSMENT_TB_USERNAME + "=?",
+                new String[]{unitId, username()}, null, Boolean.class);
+        if (callback != null) {
             op.setCallback(new DataCallback>() {
                 @Override
                 public void onResult(List ordinals) {
                     if (ordinals != null && !ordinals.isEmpty()) {
-                        callback.sendResult( ordinals.get(0));
+                        callback.sendResult(ordinals.get(0));
                     } else {
                         //if no record, it also means not accessed before.
                         callback.sendResult(false);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/module/download/DownloadCompleteReceiver.java b/VideoLocker/src/main/java/org/edx/mobile/module/download/DownloadCompleteReceiver.java
index cde8bbd938..190414ff3c 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/module/download/DownloadCompleteReceiver.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/module/download/DownloadCompleteReceiver.java
@@ -7,7 +7,6 @@
 import com.google.inject.Inject;
 
 import org.edx.mobile.core.IEdxEnvironment;
-import org.edx.mobile.event.DownloadEvent;
 import org.edx.mobile.logger.Logger;
 import org.edx.mobile.model.VideoModel;
 import org.edx.mobile.model.db.DownloadEntry;
@@ -16,7 +15,6 @@
 import org.edx.mobile.module.db.DataCallback;
 import org.edx.mobile.module.prefs.PrefManager;
 
-import de.greenrobot.event.EventBus;
 import roboguice.receiver.RoboBroadcastReceiver;
 
 public class DownloadCompleteReceiver extends RoboBroadcastReceiver {
@@ -54,18 +52,6 @@ public void onResult(VideoModel result) {
                                 ISegment segIO = environment.getSegment();
                                 segIO.trackDownloadComplete(download.videoId, download.eid, 
                                         download.lmsUrl);
-
-                                // update count of downloaded videos
-                                // store user's data in his own preference file, so as to keep it unique
-                                PrefManager p = new PrefManager(context, download.username);
-                                long count = p.getLong(PrefManager.Key.COUNT_OF_VIDEOS_DOWNLOADED);
-                                if (count < 0) {
-                                    count = 0;
-                                }
-                                count ++;
-                                p.put(PrefManager.Key.COUNT_OF_VIDEOS_DOWNLOADED, count);
-
-                                EventBus.getDefault().post(new DownloadEvent(DownloadEvent.DownloadStatus.COMPLETED));
                             }
                         }
 
diff --git a/VideoLocker/src/main/java/org/edx/mobile/module/prefs/PrefManager.java b/VideoLocker/src/main/java/org/edx/mobile/module/prefs/PrefManager.java
index 2b519ba3df..74a6b86ec2 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/module/prefs/PrefManager.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/module/prefs/PrefManager.java
@@ -339,7 +339,6 @@ public static final class Key {
         public static final String AUTH_TOKEN_SOCIAL_COOKIE = "social_auth_cookie";
         public static final String DOWNLOAD_ONLY_ON_WIFI = "download_only_on_wifi";
         public static final String DOWNLOAD_OFF_WIFI_SHOW_DIALOG_FLAG = "download_off_wifi_dialog_flag";
-        public static final String COUNT_OF_VIDEOS_DOWNLOADED = "count_videos_downloaded";
         public static final String TRANSCRIPT_LANGUAGE = "transcript_language";
         public static final String ALLOW_SOCIAL_FEATURES = "allow_social_features";
         public static final String LAST_ACCESS_MODIFICATION_TIME = "last_access_modification_time";
diff --git a/VideoLocker/src/main/java/org/edx/mobile/module/storage/Storage.java b/VideoLocker/src/main/java/org/edx/mobile/module/storage/Storage.java
index 40110775eb..22b9afb1ee 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/module/storage/Storage.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/module/storage/Storage.java
@@ -219,19 +219,15 @@ public void onFail(Exception ex) {
     @Override
     public void getAverageDownloadProgressInSection(String enrollmentId,
             String chapter, String section, DataCallback callback) {
-        List dmidList = db.getDownloadingVideoDmIdsForSection(enrollmentId, chapter, section, null);
-        if (dmidList == null || dmidList.isEmpty()) {
-            callback.onResult(Integer.valueOf(0));
+        long[] dmidArray = db.getDownloadingVideoDmIdsForSection(enrollmentId, chapter, section, null);
+        if (dmidArray == null || dmidArray.length == 0) {
+            callback.onResult(0);
             return;
         }
 
         try {
-            long[] dmidArray = new long[dmidList.size()];
-            for (int i=0; i< dmidList.size(); i++) {
-                dmidArray[i] = dmidList.get(i);
-            }
             int progress = dm.getAverageProgressForDownloads(dmidArray);
-            callback.sendResult(Integer.valueOf(progress));
+            callback.sendResult((int)progress);
         } catch(Exception ex) {
             logger.error(ex);
             callback.sendException(ex);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/player/PlayerController.java b/VideoLocker/src/main/java/org/edx/mobile/player/PlayerController.java
index b648e6326c..65f85a5a3d 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/player/PlayerController.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/player/PlayerController.java
@@ -534,12 +534,12 @@ public void updatePausePlay() {
         }
         if (mPlayer.isPlaying()) {
             mPauseButton.setImageDrawable(new IconDrawable(getContext(), Iconify.IconValue.fa_pause)
-                    .colorRes(R.color.edx_grayscale_neutral_white_t));
+                    .colorRes(getContext(), R.color.edx_grayscale_neutral_white_t));
             mPauseButton.setContentDescription(getContext().getResources()
                     .getString(R.string.video_player_pause));
         } else {
             mPauseButton.setImageDrawable(new IconDrawable(getContext(), Iconify.IconValue.fa_play)
-                    .colorRes(R.color.edx_grayscale_neutral_white_t));
+                    .colorRes(getContext(),R.color.edx_grayscale_neutral_white_t));
             mPauseButton.setContentDescription(getContext().getResources()
                     .getString(R.string.video_player_play));
         }
diff --git a/VideoLocker/src/main/java/org/edx/mobile/services/VideoDownloadHelper.java b/VideoLocker/src/main/java/org/edx/mobile/services/VideoDownloadHelper.java
index b8d491d0be..cf82cc4924 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/services/VideoDownloadHelper.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/services/VideoDownloadHelper.java
@@ -30,7 +30,7 @@
  */
 @Singleton
 public class VideoDownloadHelper {
-    public static interface DownloadManagerCallback{
+    public interface DownloadManagerCallback{
         void onDownloadSuccess(Long result);
         void onDownloadFailure();
         void showProgressDialog(int numDownloads);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/util/NetworkUtil.java b/VideoLocker/src/main/java/org/edx/mobile/util/NetworkUtil.java
index 3cd82653db..51b0859513 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/util/NetworkUtil.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/util/NetworkUtil.java
@@ -8,7 +8,10 @@
 import android.net.wifi.WifiManager;
 import android.telephony.TelephonyManager;
 
+import org.edx.mobile.R;
+import org.edx.mobile.base.BaseFragmentActivity;
 import org.edx.mobile.logger.Logger;
+import org.edx.mobile.module.prefs.PrefManager;
 
 import java.net.InetAddress;
 import java.net.NetworkInterface;
@@ -168,4 +171,28 @@ public static boolean isSocialFeatureFlagEnabled(Context context, Config config)
         return isSocialEnabled && (NetworkUtil.isConnectedWifi(context) || !NetworkUtil.isOnSocialDisabledNetwork(context, config));
 
     }
+
+    /**
+     * Verify that there is an active network connection on which downloading is allowed. If
+     * there is no such connection, then an appropriate message is displayed.
+     *
+     * @param activity Delegate of type {@link BaseFragmentActivity} to show proper error messages
+     * @return If downloads can be performed, returns true; else returns false.
+     */
+
+    public static boolean verifyDownloadPossible(BaseFragmentActivity activity) {
+        if (new PrefManager(activity, PrefManager.Pref.WIFI).getBoolean(PrefManager.Key
+                .DOWNLOAD_ONLY_ON_WIFI, true)) {
+            if (!isConnectedWifi(activity)) {
+                activity.showInfoMessage(activity.getString(R.string.wifi_off_message));
+                return false;
+            }
+        } else {
+            if (AppConstants.offline_flag) {
+                activity.showInfoMessage(activity.getString(R.string.network_not_connected));
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/CourseBaseActivity.java b/VideoLocker/src/main/java/org/edx/mobile/view/CourseBaseActivity.java
index 66ac7af360..4fafb294c3 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/CourseBaseActivity.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/CourseBaseActivity.java
@@ -15,14 +15,12 @@
 
 import org.edx.mobile.R;
 import org.edx.mobile.base.BaseFragmentActivity;
-import org.edx.mobile.event.DownloadEvent;
 import org.edx.mobile.model.api.EnrolledCoursesResponse;
 import org.edx.mobile.model.course.CourseComponent;
 import org.edx.mobile.module.prefs.PrefManager;
 import org.edx.mobile.services.CourseManager;
 import org.edx.mobile.task.GetCourseStructureTask;
 import org.edx.mobile.third_party.iconify.IconDrawable;
-import org.edx.mobile.third_party.iconify.IconView;
 import org.edx.mobile.third_party.iconify.Iconify;
 import org.edx.mobile.util.AppConstants;
 import org.edx.mobile.util.BrowserUtil;
@@ -31,7 +29,6 @@
 import org.edx.mobile.view.common.TaskProcessCallback;
 import org.edx.mobile.view.custom.popup.menu.PopupMenu;
 
-import de.greenrobot.event.EventBus;
 import roboguice.inject.ContentView;
 import roboguice.inject.InjectView;
 
@@ -51,12 +48,6 @@ public abstract  class CourseBaseActivity  extends BaseFragmentActivity implemen
     @InjectView(R.id.last_access_bar)
     View lastAccessBar;
 
-    @InjectView(R.id.download_in_progress_bar)
-    View downloadProgressBar;
-
-    @InjectView(R.id.video_download_indicator)
-    IconView downloadIndicator;
-
     @InjectView(R.id.progress_spinner)
     ProgressBar progressWheel;
 
@@ -68,8 +59,6 @@ public abstract  class CourseBaseActivity  extends BaseFragmentActivity implemen
 
     private GetCourseStructureTask getHierarchyTask;
 
-    private boolean isDestroyed;
-
     protected abstract String getUrlForWebView();
 
     protected abstract void onLoadData();
@@ -89,17 +78,7 @@ protected void onCreate(Bundle arg0) {
     }
 
     protected void initialize(Bundle arg){
-
         setApplyPrevTransitionOnRestart(true);
-        ((IconView)findViewById(R.id.video_download_indicator)).setIconColorResource(R.color.edx_brand_primary_light);
-        findViewById(R.id.download_in_progress_button).setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                environment.getRouter().showDownloads(CourseBaseActivity.this);
-            }
-        });
-
-
         if (!(NetworkUtil.isConnected(this))) {
             AppConstants.offline_flag = true;
             invalidateOptionsMenu();
@@ -112,18 +91,8 @@ public void onClick(View v) {
     protected void onResume() {
         super.onResume();
         invalidateOptionsMenu();
-        if ( !EventBus.getDefault().isRegistered(this) )
-            EventBus.getDefault().register(this);
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        if ( EventBus.getDefault().isRegistered(this) )
-            EventBus.getDefault().unregister(this);
     }
 
-
     @Override
     protected void onDestroy() {
         super.onDestroy();
@@ -131,10 +100,8 @@ protected void onDestroy() {
             getHierarchyTask.cancel(true);
             getHierarchyTask = null;
         }
-        isDestroyed = true;
     }
 
-
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
@@ -184,14 +151,6 @@ protected void onPostCreate(Bundle savedInstanceState) {
         }
     }
 
-    /**
-     * callback for EventBus
-     * https://github.com/greenrobot/EventBus
-     */
-    public void onEvent(DownloadEvent event) {
-        setVisibilityForDownloadProgressView(true);
-    }
-
     @Override
     protected void onOnline() {
         offlineBar.setVisibility(View.GONE);
@@ -369,12 +328,6 @@ private void hideLoadingProgress(){
         }
     }
 
-
-    protected void setVisibilityForDownloadProgressView(boolean show){
-        if ( downloadProgressBar != null )
-            downloadProgressBar.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
     protected void hideLastAccessedView(View v) {
         try{
             lastAccessBar.setVisibility(View.GONE);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/CourseOutlineActivity.java b/VideoLocker/src/main/java/org/edx/mobile/view/CourseOutlineActivity.java
index e2fc750d76..4148241855 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/CourseOutlineActivity.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/CourseOutlineActivity.java
@@ -102,8 +102,9 @@ protected void onPostCreate(Bundle savedInstanceState) {
 
     @Override
     public void updateListUI() {
-        if( fragment != null )
+        if( fragment != null ) {
             fragment.reloadList();
-        fragment.updateMessageView(null);
+            fragment.updateMessageView(null);
+        }
     }
 }
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/CourseOutlineFragment.java b/VideoLocker/src/main/java/org/edx/mobile/view/CourseOutlineFragment.java
index f90f5d4f9d..6e933c7be2 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/CourseOutlineFragment.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/CourseOutlineFragment.java
@@ -3,7 +3,6 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.v4.app.FragmentActivity;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -141,34 +140,39 @@ public void updateMessageView(View view){
         }
     }
 
-    private void initializeAdapter(){
+    private void initializeAdapter() {
         if (adapter == null) {
             // creating adapter just once
-            adapter = new CourseOutlineAdapter(getActivity(), environment.getDatabase(), environment.getStorage(), new CourseOutlineAdapter.DownloadListener() {
+            adapter = new CourseOutlineAdapter(getActivity(), environment.getDatabase(),
+                    environment.getStorage(), new CourseOutlineAdapter.DownloadListener() {
                 @Override
                 public void download(List models) {
-                    downloadManager.downloadVideos(
-                            (List) models, (FragmentActivity) getActivity(), (VideoDownloadHelper.DownloadManagerCallback) getActivity());
-
+                    CourseOutlineActivity activity = (CourseOutlineActivity) getActivity();
+                    if (NetworkUtil.verifyDownloadPossible(activity)) {
+                        downloadManager.downloadVideos(models, getActivity(),
+                                (VideoDownloadHelper.DownloadManagerCallback) getActivity());
+                    }
                 }
 
                 @Override
                 public void download(DownloadEntry videoData) {
-                    downloadManager.downloadVideo(
-                            videoData, (FragmentActivity) getActivity(), (VideoDownloadHelper.DownloadManagerCallback) getActivity());
+                    CourseOutlineActivity activity = (CourseOutlineActivity) getActivity();
+                    if (NetworkUtil.verifyDownloadPossible(activity)) {
+                        downloadManager.downloadVideo(videoData, activity, activity);
+                    }
+                }
+
+                @Override
+                public void viewDownloadsStatus() {
+                    environment.getRouter().showDownloads(getActivity());
                 }
             });
         }
 
-        if (!(NetworkUtil.isConnected(getActivity()))) {
-            AppConstants.offline_flag = true;
-        } else {
-            AppConstants.offline_flag = false;
-        }
+        AppConstants.offline_flag = !NetworkUtil.isConnected(getActivity());
     }
 
 
-
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/CourseVideoListActivity.java b/VideoLocker/src/main/java/org/edx/mobile/view/CourseVideoListActivity.java
index 1979056a80..21c4cd892f 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/CourseVideoListActivity.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/CourseVideoListActivity.java
@@ -5,10 +5,7 @@
 import android.os.SystemClock;
 import android.view.Menu;
 import android.view.View;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
 
-import org.edx.mobile.R;
 import org.edx.mobile.base.MainApplication;
 import org.edx.mobile.logger.Logger;
 import org.edx.mobile.model.course.BlockPath;
@@ -122,94 +119,24 @@ protected void modeChanged(){
     }
 
     @Override
-    protected void updateDownloadProgress(final int progressPercent){
-
-        mHandler.postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                if (progressPercent < 100) {
-                    downloadProgressBar.setVisibility(View.VISIBLE);
-                    mHandler.removeCallbacks(mHideRunnable);
-                    if (downloadIndicator.getAnimation() == null) {
-                        downloadIndicator.setVisibility(View.VISIBLE);
-                        Animation animation = AnimationUtils.loadAnimation(CourseVideoListActivity.this, R.anim.rotate);
-                        downloadIndicator.startAnimation(animation);
-                    }
-                } else { //progressPercent == 100
-                    downloadIndicator.clearAnimation();
-                    downloadIndicator.setVisibility(View.INVISIBLE);
-                    mHandler.postDelayed(mHideRunnable, getResources().getInteger(R.integer.message_delay));
-                }
-            }
-        }, 500);
-    }
+    protected void updateDownloadProgress(final int progressPercent) {}
 
     @Override
-    protected void setVisibilityForDownloadProgressView(boolean show){
-         boolean visible = downloadProgressBar.getVisibility() == View.VISIBLE;
-        if (visible == show )
-            return; //do nothing
-
-        if ( show ){
-            //TODO - we pass a value less than 100 to indicate it is downloading.
-            updateDownloadProgress(0);
-        } else {
-            updateDownloadProgress(100);
-        }
-    }
+    public void showProgressDialog(int numDownloads) {}
 
     @Override
     public void onDownloadSuccess(Long result) {
-        try {
-            updateListUI();
-        }catch(Exception e){
-            logger.error(e);
-        }
+        updateListUI();
     }
 
     @Override
     public void onDownloadFailure() {
-    }
-
-    @Override
-    public void showProgressDialog(int numDownloads) {
-        setVisibilityForDownloadProgressView(true);
+        updateListUI();
     }
 
     @Override
     public abstract  void updateListUI();
 
-
-    private Runnable mHideRunnable = new Runnable() {
-        @Override
-        public void run() {
-            downloadProgressBar.setVisibility(  View.GONE );
-        }
-    };
-
-    //TODO - legacy code use one minute tick loop to sync some UI status, like
-    //total download progress. this is a simple approach, but may not be the
-    //best one.
-    protected void onTick() {
-        // this is a per second callback
-        try {
-                if(AppConstants.offline_flag){
-                    setVisibilityForDownloadProgressView(false);
-                }else{
-                    if(environment.getDatabase()!=null){
-                        boolean downloading = environment.getDatabase().isAnyVideoDownloading(null);
-                        if(!downloading){
-                            setVisibilityForDownloadProgressView(false);
-                        }else{
-                            environment.getStorage().getAverageDownloadProgress(averageProgressCallback);
-                        }
-                    }   //store not null check
-                }
-            }  catch(Exception ex) {
-            logger.error(ex);
-        }
-    }
-
     protected boolean isOnCourseOutline(){
         if (courseComponentId == null) return true;
         CourseComponent outlineComp = courseManager.getComponentById(
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/MyVideosTabActivity.java b/VideoLocker/src/main/java/org/edx/mobile/view/MyVideosTabActivity.java
index 3e5aaa751c..33e8a600cc 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/MyVideosTabActivity.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/MyVideosTabActivity.java
@@ -19,9 +19,7 @@
 
 import org.edx.mobile.R;
 import org.edx.mobile.logger.Logger;
-import org.edx.mobile.model.api.ProfileModel;
 import org.edx.mobile.module.analytics.ISegment;
-import org.edx.mobile.module.prefs.PrefManager;
 import org.edx.mobile.player.PlayerActivity;
 import org.edx.mobile.player.VideoListFragment.VideoListCallback;
 import org.edx.mobile.util.AppConstants;
@@ -78,13 +76,8 @@ protected void onStart() {
             setTitle(getString(R.string.label_my_videos));
         }
 
-        try{
-            if(recentVideosFragment!=null){
-                recentVideosFragment.setCallback(this);
-            }
-            clearDownloadCount();
-        }catch(Exception ex){
-            logger.error(ex);
+        if (recentVideosFragment != null) {
+            recentVideosFragment.setCallback(this);
         }
     }
 
@@ -153,18 +146,6 @@ protected void restore(Bundle savedInstanceState) {
         }
     }
 
-    private void clearDownloadCount() {
-        try{
-            PrefManager p = new PrefManager(this, PrefManager.Pref.LOGIN);
-            // user specific data is stored in his own file
-            ProfileModel profile = p.getCurrentUserProfile();
-            p = new PrefManager(this, profile.username);
-            p.put(PrefManager.Key.COUNT_OF_VIDEOS_DOWNLOADED, 0);
-        }catch(Exception e){
-            logger.error(e);
-        }
-    }
-
     private void initializeTab() {
         try{
             mTabHost = (TabHost) findViewById(android.R.id.tabhost);
diff --git a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/CourseOutlineAdapter.java b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/CourseOutlineAdapter.java
index f02f4afbbc..73192db60d 100644
--- a/VideoLocker/src/main/java/org/edx/mobile/view/adapters/CourseOutlineAdapter.java
+++ b/VideoLocker/src/main/java/org/edx/mobile/view/adapters/CourseOutlineAdapter.java
@@ -12,7 +12,6 @@
 
 import org.edx.mobile.R;
 import org.edx.mobile.base.MainApplication;
-import org.edx.mobile.event.DownloadEvent;
 import org.edx.mobile.logger.Logger;
 import org.edx.mobile.model.course.BlockPath;
 import org.edx.mobile.model.course.BlockType;
@@ -21,21 +20,17 @@
 import org.edx.mobile.model.course.IBlock;
 import org.edx.mobile.model.course.VideoBlockModel;
 import org.edx.mobile.model.db.DownloadEntry;
-import org.edx.mobile.model.download.NativeDownloadModel;
 import org.edx.mobile.module.db.DataCallback;
 import org.edx.mobile.module.db.IDatabase;
 import org.edx.mobile.module.prefs.PrefManager;
 import org.edx.mobile.module.storage.IStorage;
 import org.edx.mobile.third_party.iconify.IconView;
 import org.edx.mobile.third_party.iconify.Iconify;
-import org.edx.mobile.util.AppConstants;
 import org.edx.mobile.view.custom.ETextView;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import de.greenrobot.event.EventBus;
-
 /**
  * Used for pinned behavior.
  */
@@ -46,6 +41,7 @@ public class CourseOutlineAdapter extends BaseAdapter{
     public interface DownloadListener {
         void download(List models);
         void download(DownloadEntry videoData);
+        void viewDownloadsStatus();
     }
 
     private CourseComponent rootComponent;
@@ -110,7 +106,8 @@ public final View getView(int position, View convertView, ViewGroup parent) {
 
         int type = getItemViewType(position);
 
-        if (convertView == null) {
+        // FIXME: Re-enable row recycling in favor of better DB communication [MA-1640]
+        //if (convertView == null) {
             switch (type) {
                 case SectionRow.ITEM: {
                     convertView = mInflater.inflate(R.layout.row_course_outline_list, parent, false);
@@ -124,7 +121,7 @@ public final View getView(int position, View convertView, ViewGroup parent) {
                     break;
                 }
             }
-        }
+        //}
 
         switch (type) {
             case SectionRow.ITEM:
@@ -175,7 +172,7 @@ public void setData(CourseComponent component){
 
     public void reloadData(){
         if (  this.rootComponent != null )
-            setData(this.rootComponent);
+             setData(this.rootComponent);
     }
 
     public View getRowView(int position, View convertView, ViewGroup parent) {
@@ -278,85 +275,63 @@ private void updateUIForVideo(int position, View convertView, final ViewHolder v
         viewHolder.rowSubtitle.setVisibility(View.VISIBLE);
         viewHolder.rowSubtitle.setText(videoData.getDurationReadable());
 
-        if (videoData.downloaded == DownloadEntry.DownloadedState.DOWNLOADING) {
-
-            NativeDownloadModel downloadModel = storage.
-                getNativeDownlaod(videoData.dmId);
-            if(downloadModel!=null){
-                int percent = downloadModel.getPercent();
-                if(percent>=0 && percent < 100){
-                    EventBus.getDefault().post(new DownloadEvent(DownloadEvent.DownloadStatus.STARTED));
-                }
-            }
-        }
-
         dbStore.getWatchedStateForVideoId(videoData.videoId,
-            new DataCallback(true) {
-                @Override
-                public void onResult(DownloadEntry.WatchedState result) {
-                    if(result != null && result == DownloadEntry.WatchedState.WATCHED) {
-                        viewHolder.rowType.setIconColorResource(R.color.edx_grayscale_neutral_base);
-                    } else {
-                        viewHolder.rowType.setIconColorResource(R.color.edx_brand_primary_base);
-                    }
-                }
-                @Override
-                public void onFail(Exception ex) {
-                    logger.error(ex);
-                }
-            });
-
-        dbStore.getDownloadedStateForVideoId(videoData.videoId,
-                new DataCallback(true) {
+                new DataCallback(true) {
                     @Override
-                    public void onResult(DownloadEntry.DownloadedState result) {
-                        DownloadEntry.DownloadedState ds = result;
-                        if (ds == null || ds == DownloadEntry.DownloadedState.ONLINE) {
-                            // not yet downloaded
-                            viewHolder.bulkDownload.setVisibility(View.VISIBLE);
-                            viewHolder.numOfVideoAndDownloadArea.setOnClickListener(new View.OnClickListener() {
-                                @Override
-                                public void onClick(View v) {
-                                    EventBus.getDefault().post(new DownloadEvent(DownloadEvent.DownloadStatus.STARTED));
-                                    logger.debug("Download Button Clicked");
-                                    //notifyDataSetChanged();
-                                    mDownloadListener.download(videoData);
-                                }
-                            });
-                        } else if (ds == DownloadEntry.DownloadedState.DOWNLOADING) {
-                            // may be download in progress
-                            EventBus.getDefault().post(new DownloadEvent(DownloadEvent.DownloadStatus.STARTED));
-                            viewHolder.bulkDownload.setVisibility(View.GONE);
-                            storage.getDownloadProgressByDmid(videoData.dmId, new DataCallback(true) {
-                                @Override
-                                public void onResult(Integer result) {
-                                    if (result >= 0 && result < 100) {
-                                        EventBus.getDefault().post(new DownloadEvent(DownloadEvent.DownloadStatus.STARTED));
-                                    } else if (result == 100) {
-                                        EventBus.getDefault().post(new DownloadEvent(DownloadEvent.DownloadStatus.COMPLETED));
-                                    }
-                                }
-
-                                @Override
-                                public void onFail(Exception ex) {
-                                    logger.error(ex);
-                                    viewHolder.bulkDownload.setVisibility(View.VISIBLE);
-                                }
-                            });
-                        } else if (ds == DownloadEntry.DownloadedState.DOWNLOADED) {
-                            // downloaded
-                            viewHolder.bulkDownload.setVisibility(View.GONE);
+                    public void onResult(DownloadEntry.WatchedState result) {
+                        if (result != null && result == DownloadEntry.WatchedState.WATCHED) {
+                            viewHolder.rowType.setIconColorResource(R.color.edx_grayscale_neutral_base);
+                        } else {
+                            viewHolder.rowType.setIconColorResource(R.color.edx_brand_primary_base);
                         }
-
                     }
 
                     @Override
                     public void onFail(Exception ex) {
                         logger.error(ex);
-                        viewHolder.bulkDownload.setVisibility(View.VISIBLE);
                     }
                 });
 
+        if (videoData.isVideoForWebOnly()) {
+            viewHolder.numOfVideoAndDownloadArea.setVisibility(View.GONE);
+        }
+        else {
+            viewHolder.numOfVideoAndDownloadArea.setVisibility(View.VISIBLE);
+            dbStore.getDownloadedStateForVideoId(videoData.videoId,
+                    new DataCallback(true) {
+                        @Override
+                        public void onResult(DownloadEntry.DownloadedState state) {
+                            if (state == null || state == DownloadEntry.DownloadedState.ONLINE) {
+                                // not yet downloaded
+                                setRowStateOnDownload(viewHolder, DownloadEntry.DownloadedState.ONLINE,
+                                        new View.OnClickListener() {
+                                            @Override
+                                            public void onClick(View v) {
+                                                mDownloadListener.download(videoData);
+                                            }
+                                        });
+                            } else if (state == DownloadEntry.DownloadedState.DOWNLOADING) {
+                                // may be download in progress
+                                setRowStateOnDownload(viewHolder, DownloadEntry.DownloadedState.DOWNLOADING,
+                                        new View.OnClickListener() {
+                                            @Override
+                                            public void onClick(View v) {
+                                                mDownloadListener.viewDownloadsStatus();
+                                            }
+                                        });
+                            } else if (state == DownloadEntry.DownloadedState.DOWNLOADED) {
+                                setRowStateOnDownload(viewHolder, DownloadEntry.DownloadedState.DOWNLOADED, null);
+                            }
+                        }
+
+                        @Override
+                        public void onFail(Exception ex) {
+                            logger.error(ex);
+                            viewHolder.bulkDownload.setVisibility(View.VISIBLE);
+                        }
+                    });
+        }
+
     }
 
     private  View getRowViewForContainer(int position, View convertView, ViewGroup parent, final SectionRow row) {
@@ -379,52 +354,75 @@ private  View getRowViewForContainer(int position, View convertView, ViewGroup p
             holder.rowSubtitle.setText(component.getFormat());
         }
 
-        //support video download for video type
-        final int totalCount = component.getBlockCount().videoCount;
-        if (totalCount == 0 ){
+        // support video download for video type excluding the ones only viewable on web
+        int webOnlyCount = dbStore.getWebOnlyVideosCountBySection(courseId, chapterId, sequentialId, null);
+        final int totalDownloadableVideos = component.getBlockCount().videoCount - webOnlyCount;
+        if (totalDownloadableVideos == 0 ){
             holder.numOfVideoAndDownloadArea.setVisibility(View.GONE);
         } else {
+            holder.bulkDownload.setVisibility(View.VISIBLE);
             holder.noOfVideos.setVisibility(View.VISIBLE);
-            holder.noOfVideos.setText("" + totalCount);
-
-            if (  row.numOfVideoNotDownloaded == 0 ){
-                holder.bulkDownload.setVisibility(View.GONE);
+            holder.noOfVideos.setText("" + totalDownloadableVideos);
+
+            Integer downloadedCount = dbStore.getDownloadedVideosCountForSection(courseId, chapterId, sequentialId, null);
+
+            if (downloadedCount == totalDownloadableVideos) {
+                holder.noOfVideos.setVisibility(View.VISIBLE);
+                setRowStateOnDownload(holder, DownloadEntry.DownloadedState.DOWNLOADED, null);
+            } else if (dbStore.getDownloadingVideosCountForSection(courseId, chapterId, sequentialId, null)
+                    + downloadedCount == totalDownloadableVideos) {
+                holder.noOfVideos.setVisibility(View.GONE);
+                setRowStateOnDownload(holder, DownloadEntry.DownloadedState.DOWNLOADING
+                    , new View.OnClickListener() {
+                            @Override
+                            public void onClick(View downloadView) {
+                                mDownloadListener.viewDownloadsStatus();
+                            }
+                        });
             } else {
-                int inProcessCount = dbStore.getVideosCountBySection(courseId, chapterId, sequentialId, null);
-                int webOnlyCount = dbStore.getWebOnlyVideosCountBySection(courseId, chapterId, sequentialId, null);
-                row.numOfVideoNotDownloaded = totalCount - inProcessCount - webOnlyCount;
-                if (row.numOfVideoNotDownloaded > 0) {
-                    holder.bulkDownload.setVisibility(View.VISIBLE);
-                    holder.numOfVideoAndDownloadArea
-                        .setOnClickListener(new View.OnClickListener() {
+                holder.noOfVideos.setVisibility(View.VISIBLE);
+                setRowStateOnDownload(holder, DownloadEntry.DownloadedState.ONLINE
+                    , new View.OnClickListener() {
                             @Override
                             public void onClick(View downloadView) {
                                 mDownloadListener.download(component.getVideos());
                             }
                         });
-                } else {
-                    holder.bulkDownload.setVisibility(View.GONE);
-                }
-            }
-        }
-
-        if (AppConstants.offline_flag) {
-            holder.numOfVideoAndDownloadArea.setVisibility(View.GONE);
-            boolean isVideoDownloaded = dbStore.isVideoDownloadedInSection
-                (courseId, chapterId, sequentialId, null);
-            if(isVideoDownloaded)
-            {
-                //TODO - any UI update
-            }else{
-                //TODO - any UI update
             }
-        } else {
-           //TODO - any UI update?
         }
 
         return convertView;
     }
 
+    /**
+     * Makes various changes to the row based on a video element's download status
+     *
+     * @param row      ViewHolder of the row view
+     * @param state    current state of video download
+     * @param listener the listener to attach to the video download button
+     */
+    private void setRowStateOnDownload(ViewHolder row, DownloadEntry.DownloadedState state
+            , View.OnClickListener listener) {
+        switch (state) {
+            case DOWNLOADING:
+                row.bulkDownload.setIcon(Iconify.IconValue.fa_spinner);
+                row.bulkDownload.setRotating(true);
+                row.bulkDownload.setIconColorResource(R.color.edx_brand_primary_base);
+                break;
+            case DOWNLOADED:
+                row.bulkDownload.setIcon(Iconify.IconValue.fa_check);
+                row.bulkDownload.setRotating(false);
+                row.bulkDownload.setIconColorResource(R.color.edx_grayscale_neutral_base);
+                break;
+            case ONLINE:
+                row.bulkDownload.setIcon(Iconify.IconValue.fa_arrow_down);
+                row.bulkDownload.setRotating(false);
+                row.bulkDownload.setIconColorResource(R.color.edx_grayscale_neutral_base);
+                break;
+        }
+        row.numOfVideoAndDownloadArea.setOnClickListener(listener);
+    }
+
     public  View getHeaderView(int position, View convertView, ViewGroup parent){
         final SectionRow row = this.getItem(position);
         TextView titleView = (TextView)convertView.findViewById(R.id.row_header);
@@ -509,9 +507,6 @@ public static class SectionRow {
         public final boolean topComponent;
         public final CourseComponent component;
 
-        //field to cache the temp value
-        public int numOfVideoNotDownloaded = -1;
-
         public SectionRow(int type, CourseComponent component) {
             this(type, false, component);
         }
diff --git a/VideoLocker/src/test/java/org/edx/mobile/view/CourseBaseActivityTest.java b/VideoLocker/src/test/java/org/edx/mobile/view/CourseBaseActivityTest.java
index 2525b5ad90..0d0b6da45f 100644
--- a/VideoLocker/src/test/java/org/edx/mobile/view/CourseBaseActivityTest.java
+++ b/VideoLocker/src/test/java/org/edx/mobile/view/CourseBaseActivityTest.java
@@ -8,11 +8,9 @@
 import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
 import android.widget.ProgressBar;
 
 import org.edx.mobile.R;
-import org.edx.mobile.event.DownloadEvent;
 import org.edx.mobile.http.OkHttpUtil;
 import org.edx.mobile.model.api.EnrolledCoursesResponse;
 import org.edx.mobile.model.course.CourseComponent;
@@ -25,11 +23,8 @@
 import org.robolectric.shadows.ShadowActivity;
 import org.robolectric.util.ActivityController;
 
-import de.greenrobot.event.EventBus;
-
 import static org.assertj.android.api.Assertions.assertThat;
 import static org.junit.Assert.*;
-import static org.junit.Assume.*;
 
 public abstract class CourseBaseActivityTest extends BaseFragmentActivityTest {
     /**
@@ -100,10 +95,6 @@ public void initializeTest() {
         controller.create();
         assertNotNull(activity.findViewById(R.id.offline_bar));
         assertNotNull(activity.findViewById(R.id.last_access_bar));
-        assertNotNull(activity.findViewById(R.id.video_download_indicator));
-        View downloadInProgressButton =
-                activity.findViewById(R.id.download_in_progress_button);
-        assertNotNull(downloadInProgressButton);
         DrawerLayout drawerLayout = (DrawerLayout)
                 activity.findViewById(R.id.drawer_layout);
         if (drawerLayout != null) {
@@ -114,43 +105,6 @@ public void initializeTest() {
         }
 
         controller.postCreate(null).resume().postResume().visible();
-        // Is there any way to test options menu invalidation?
-        assertTrue(downloadInProgressButton.performClick());
-        assertNextStartedActivity(activity, DownloadListActivity.class);
-    }
-
-    /**
-     * Testing functionality upon receiving a DownloadEvent
-     */
-    @Test
-    @Ignore // Hangs indefinitely. Fixed in https://github.com/robolectric/robolectric/pull/2017
-    public void downloadEventTest() {
-        CourseBaseActivity activity =
-                Robolectric.buildActivity(getActivityClass())
-                        .withIntent(getIntent()).setup().get();
-        View downloadProgressBar =
-                activity.findViewById(R.id.download_in_progress_bar);
-        assumeNotNull(downloadProgressBar);
-        assertThat(downloadProgressBar).isNotVisible();
-        EventBus eventBus = EventBus.getDefault();
-        eventBus.post(new DownloadEvent(DownloadEvent.DownloadStatus.STARTED));
-        assertDownloadProgressBarVisible(activity.getWindow().getDecorView(),
-                downloadProgressBar);
-    }
-
-    /**
-     * Method for asserting the functionality of
-     * {@link CourseBaseActivity#setVisibilityForDownloadProgressView} which
-     * is called upon receiving a {@link DownloadEvent}. The base
-     * implementation just makes the download progress bar visible
-     * immediately, but this behaviour may be overridden in subclasses.
-     *
-     * @param rootView The root View for finding Views by id
-     * @param downloadProgressBar The download progress bar View
-     */
-    protected void assertDownloadProgressBarVisible(
-            View rootView, View downloadProgressBar) {
-        assertThat(downloadProgressBar).isVisible();
     }
 
     /**
diff --git a/VideoLocker/src/test/java/org/edx/mobile/view/CourseOutlineActivityTest.java b/VideoLocker/src/test/java/org/edx/mobile/view/CourseOutlineActivityTest.java
index 8cfd866728..ce13bbf02a 100644
--- a/VideoLocker/src/test/java/org/edx/mobile/view/CourseOutlineActivityTest.java
+++ b/VideoLocker/src/test/java/org/edx/mobile/view/CourseOutlineActivityTest.java
@@ -5,12 +5,9 @@
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
 import android.view.View;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
 import android.widget.ListView;
 
 import org.edx.mobile.R;
-import org.edx.mobile.event.DownloadEvent;
 import org.edx.mobile.http.OkHttpUtil;
 import org.edx.mobile.model.api.EnrolledCoursesResponse;
 import org.edx.mobile.model.course.BlockPath;
@@ -18,15 +15,12 @@
 import org.edx.mobile.model.course.CourseComponent;
 import org.edx.mobile.model.course.IBlock;
 import org.edx.mobile.module.prefs.PrefManager;
-import org.edx.mobile.third_party.iconify.IconView;
 import org.junit.Test;
 import org.junit.runners.Parameterized.Parameters;
 import org.robolectric.Robolectric;
 import org.robolectric.Shadows;
 import org.robolectric.shadows.ShadowActivity;
-import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.ActivityController;
-import org.robolectric.util.Scheduler;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -295,40 +289,4 @@ private void clickRow(ActivityController contro
         listView.performItemClick(listView.getChildAt(rowIndex),
                 rowIndex, listView.getItemIdAtPosition(rowIndex));
     }
-
-    /**
-     * Method for asserting the functionality of
-     * {@link CourseBaseActivity#setVisibilityForDownloadProgressView} which
-     * is called upon receiving a {@link DownloadEvent}. This overrides the
-     * base implementation, as {@link CourseVideoListActivity} performs a
-     * delayed callback with a more detailed implementation.
-     *
-     * @param rootView The root View for finding Views by id
-     * @param downloadProgressBar The download progress bar View
-     */
-    @Override
-    protected void assertDownloadProgressBarVisible(
-            View rootView, View downloadProgressBar) {
-        View downloadIndicatorView = rootView.findViewById(
-                R.id.video_download_indicator);
-        assertNotNull(downloadIndicatorView);
-        assertThat(downloadIndicatorView).isInstanceOf(IconView.class);
-        boolean indicatorHadAnimation =
-                downloadIndicatorView.getAnimation() != null;
-
-        // The animation is started from a delayed callback, so the
-        // foreground scheduler needs to be advanced to it.
-        Scheduler foregroundScheduler = ShadowApplication.getInstance()
-                .getForegroundThreadScheduler();
-        foregroundScheduler.advanceToNextPostedRunnable();
-        assertThat(downloadProgressBar).isVisible();
-        if (!indicatorHadAnimation) {
-            assertThat(downloadIndicatorView).isVisible();
-            Animation animation = downloadIndicatorView.getAnimation();
-            assertNotNull(animation);
-            assertThat(animation.getStartTime())
-                    .isLessThanOrEqualTo(AnimationUtils.currentAnimationTimeMillis());
-            assertThat(animation).hasStartOffset(0);
-        }
-    }
 }
diff --git a/VideoLocker/src/test/java/org/edx/mobile/view/CourseUnitNavigationActivityTest.java b/VideoLocker/src/test/java/org/edx/mobile/view/CourseUnitNavigationActivityTest.java
index f491af18f2..3ee5e39cf1 100644
--- a/VideoLocker/src/test/java/org/edx/mobile/view/CourseUnitNavigationActivityTest.java
+++ b/VideoLocker/src/test/java/org/edx/mobile/view/CourseUnitNavigationActivityTest.java
@@ -20,7 +20,6 @@
 import org.edx.mobile.model.course.VideoBlockModel;
 import org.edx.mobile.module.prefs.PrefManager;
 import org.edx.mobile.view.custom.DisableableViewPager;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
@@ -368,13 +367,4 @@ public void orientationChangeTest() {
                 activity.getResources().getConfiguration().orientation);
         assertOrientationSetup(activity);
     }
-
-    /**
-     * Ignoring functionality testing upon receiving a DownloadEvent, as
-     * {@link CourseUnitNavigationActivity} also overrides and ignores it
-     */
-    @Override
-    @Ignore
-    @Test
-    public void downloadEventTest() {}
 }