// Path: playerSDK/src/main/java/com/kaltura/playersdk/utils/Utilities.java
// public class Utilities {
// 
//     private static final String TAG = "Utilities";
// 
//     public static boolean doesPackageExist(String targetPackage, Context context){
//         List<ApplicationInfo> packages;
//         PackageManager pm;
//         pm = context.getPackageManager();
//         packages = pm.getInstalledApplications(0);
// 
//         for (ApplicationInfo packageInfo : packages) {
//             if(packageInfo.packageName.equals(targetPackage)){
//                 return true;
//             }
//         }
// 
//         return false;
//     }
// 
//     public static String readAssetToString(Context context, String asset) {
//         try {
//             InputStream assetStream = context.getAssets().open(asset);
//             return fullyReadInputStream(assetStream, 1024*1024).toString();
//         } catch (IOException e) {
//             LOGE(TAG, "Failed reading asset " + asset, e);
//             return null;
//         }
//     }
// 
//     @NonNull
//     public static ByteArrayOutputStream fullyReadInputStream(InputStream inputStream, int byteLimit) throws IOException {
//         ByteArrayOutputStream bos = new ByteArrayOutputStream();
//         byte data[] = new byte[1024];
//         int count;
//         
//         while ((count = inputStream.read(data)) != -1) {
//             int maxCount = byteLimit - bos.size();
//             if (count > maxCount) {
//                 bos.write(data, 0, maxCount);
//                 break;
//             } else {
//                 bos.write(data, 0, count);
//             }
//         }
//         bos.flush();
//         bos.close();
//         inputStream.close();
//         return bos;
//     }
// 
//     public static Uri stripLastUriPathSegment(Uri uri) {
//         String path = uri.getPath();
//         if (TextUtils.isEmpty(path)) {
//             return uri;
//         }
//         path = stripLastPathSegment(path);
//         return uri.buildUpon().path(path).clearQuery().fragment(null).build();
//     }
// 
//     public static String stripLastUriPathSegment(String uri) {
//         return stripLastUriPathSegment(Uri.parse(uri)).toString();
//     }
// 
//     @NonNull
//     public static String stripLastPathSegment(String path) {
//         path = path.substring(0, path.lastIndexOf('/', path.length() - 2));
//         return path;
//     }
// 
//     public static String loadStringFromURL(Uri url, int byteLimit) throws IOException {
//         HttpURLConnection conn = (HttpURLConnection) new URL(url.toString()).openConnection();
//         conn.setRequestMethod("GET");
//         conn.connect();
//         InputStream is = conn.getInputStream();
//         return fullyReadInputStream(is, byteLimit).toString();
//     }
// 
//     public static boolean isOnline(Context context) {
//         ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
//         NetworkInfo netInfo = conMgr.getActiveNetworkInfo();
//         return !(netInfo == null || !netInfo.isConnected() || !netInfo.isAvailable());
//     }
// 
//     public static void quietClose(Closeable... closeables) {
//         for (Closeable c : closeables) {
//             try {
//                 if (c != null) {
//                     c.close();
//                 }
//             } catch (Exception e) {
//                 LOGE(TAG, "Failed closing " + c);
//             }
//         }
//     }
// 
//     public static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException {
//         byte data[] = new byte[1024];
//         int count;
// 
//         while ((count = inputStream.read(data)) != -1) {
//             if (count > 0) {
//                 outputStream.write(data, 0, count);
//             }
//         }
//     }
//     
//     public static String optString(JSONObject jsonObject, String key) {
//         return jsonObject.isNull(key) ? null : jsonObject.optString(key);
//     }
// }
// 
// Path: playerSDK/src/main/java/com/kaltura/playersdk/helpers/KStringUtilities.java
// static public String md5(String string) {
//     return md5(string.getBytes());
// }


import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.webkit.WebResourceResponse;
import com.kaltura.playersdk.utils.Utilities;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import static com.kaltura.playersdk.helpers.KStringUtilities.md5;
import static com.kaltura.playersdk.utils.LogUtils.LOGD;
import static com.kaltura.playersdk.utils.LogUtils.LOGE;
                @Override
                public void streamClosed(long fileSize, String filePath) {
                    int trimLength = mCachePath.length();
                    String fileId = filePath.substring(trimLength);
                    mSQLHelper.updateFileSize(fileId, fileSize);
                    logCacheSaved(requestUrl, fileId);
                    deleteLessUsedFiles(fileSize);
                    connection.disconnect();
                }
            });
            return webResourceResponse(contentType, encoding, inputStream);
        } finally {
            // if inputStream wasn't created, streamClosed() will not get called and the connection may leak. 
            if (inputStream == null) {
                connection.disconnect();
            }
        }

    }

    @NonNull
    private static WebResourceResponse webResourceResponse(String contentType, String encoding, InputStream inputStream) {
        return new WebResourceResponse(contentType, encoding, inputStream);
    }

    @NonNull
    private String getCacheFileId(Uri requestUrl) {
        if (requestUrl.getFragment() != null) {
            String localContentId = getLocalContentId(requestUrl);
            if (!TextUtils.isEmpty(localContentId)) {
// Path: playerSDK/src/main/java/com/kaltura/playersdk/utils/Utilities.java
// public class Utilities {
// 
//     private static final String TAG = "Utilities";
// 
//     public static boolean doesPackageExist(String targetPackage, Context context){
//         List<ApplicationInfo> packages;
//         PackageManager pm;
//         pm = context.getPackageManager();
//         packages = pm.getInstalledApplications(0);
// 
//         for (ApplicationInfo packageInfo : packages) {
//             if(packageInfo.packageName.equals(targetPackage)){
//                 return true;
//             }
//         }
// 
//         return false;
//     }
// 
//     public static String readAssetToString(Context context, String asset) {
//         try {
//             InputStream assetStream = context.getAssets().open(asset);
//             return fullyReadInputStream(assetStream, 1024*1024).toString();
//         } catch (IOException e) {
//             LOGE(TAG, "Failed reading asset " + asset, e);
//             return null;
//         }
//     }
// 
//     @NonNull
//     public static ByteArrayOutputStream fullyReadInputStream(InputStream inputStream, int byteLimit) throws IOException {
//         ByteArrayOutputStream bos = new ByteArrayOutputStream();
//         byte data[] = new byte[1024];
//         int count;
//         
//         while ((count = inputStream.read(data)) != -1) {
//             int maxCount = byteLimit - bos.size();
//             if (count > maxCount) {
//                 bos.write(data, 0, maxCount);
//                 break;
//             } else {
//                 bos.write(data, 0, count);
//             }
//         }
//         bos.flush();
//         bos.close();
//         inputStream.close();
//         return bos;
//     }
// 
//     public static Uri stripLastUriPathSegment(Uri uri) {
//         String path = uri.getPath();
//         if (TextUtils.isEmpty(path)) {
//             return uri;
//         }
//         path = stripLastPathSegment(path);
//         return uri.buildUpon().path(path).clearQuery().fragment(null).build();
//     }
// 
//     public static String stripLastUriPathSegment(String uri) {
//         return stripLastUriPathSegment(Uri.parse(uri)).toString();
//     }
// 
//     @NonNull
//     public static String stripLastPathSegment(String path) {
//         path = path.substring(0, path.lastIndexOf('/', path.length() - 2));
//         return path;
//     }
// 
//     public static String loadStringFromURL(Uri url, int byteLimit) throws IOException {
//         HttpURLConnection conn = (HttpURLConnection) new URL(url.toString()).openConnection();
//         conn.setRequestMethod("GET");
//         conn.connect();
//         InputStream is = conn.getInputStream();
//         return fullyReadInputStream(is, byteLimit).toString();
//     }
// 
//     public static boolean isOnline(Context context) {
//         ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
//         NetworkInfo netInfo = conMgr.getActiveNetworkInfo();
//         return !(netInfo == null || !netInfo.isConnected() || !netInfo.isAvailable());
//     }
// 
//     public static void quietClose(Closeable... closeables) {
//         for (Closeable c : closeables) {
//             try {
//                 if (c != null) {
//                     c.close();
//                 }
//             } catch (Exception e) {
//                 LOGE(TAG, "Failed closing " + c);
//             }
//         }
//     }
// 
//     public static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException {
//         byte data[] = new byte[1024];
//         int count;
// 
//         while ((count = inputStream.read(data)) != -1) {
//             if (count > 0) {
//                 outputStream.write(data, 0, count);
//             }
//         }
//     }
//     
//     public static String optString(JSONObject jsonObject, String key) {
//         return jsonObject.isNull(key) ? null : jsonObject.optString(key);
//     }
// }
// 
// Path: playerSDK/src/main/java/com/kaltura/playersdk/helpers/KStringUtilities.java
// static public String md5(String string) {
//     return md5(string.getBytes());
// }


// Path: playerSDK/src/main/java/com/kaltura/playersdk/helpers/CacheManager.java
import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.webkit.WebResourceResponse;
import com.kaltura.playersdk.utils.Utilities;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import static com.kaltura.playersdk.helpers.KStringUtilities.md5;
import static com.kaltura.playersdk.utils.LogUtils.LOGD;
import static com.kaltura.playersdk.utils.LogUtils.LOGE;

                @Override
                public void streamClosed(long fileSize, String filePath) {
                    int trimLength = mCachePath.length();
                    String fileId = filePath.substring(trimLength);
                    mSQLHelper.updateFileSize(fileId, fileSize);
                    logCacheSaved(requestUrl, fileId);
                    deleteLessUsedFiles(fileSize);
                    connection.disconnect();
                }
            });
            return webResourceResponse(contentType, encoding, inputStream);
        } finally {
            // if inputStream wasn't created, streamClosed() will not get called and the connection may leak. 
            if (inputStream == null) {
                connection.disconnect();
            }
        }

    }

    @NonNull
    private static WebResourceResponse webResourceResponse(String contentType, String encoding, InputStream inputStream) {
        return new WebResourceResponse(contentType, encoding, inputStream);
    }

    @NonNull
    private String getCacheFileId(Uri requestUrl) {
        if (requestUrl.getFragment() != null) {
            String localContentId = getLocalContentId(requestUrl);
            if (!TextUtils.isEmpty(localContentId)) {
                return md5("contentId:" + localContentId);