1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.data;
18 
19 import android.support.annotation.Nullable;
20 import android.text.TextUtils;
21 import android.util.Log;
22 
23 import com.android.tv.data.api.Program;
24 import com.android.tv.data.api.Program.CriticScore;
25 import com.android.tv.dvr.data.RecordedProgram;
26 
27 import java.io.ByteArrayInputStream;
28 import java.io.ByteArrayOutputStream;
29 import java.io.IOException;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.util.List;
33 
34 /**
35  * A utility class to parse and store data from the {@link
36  * android.media.tv.TvContract.Programs#COLUMN_INTERNAL_PROVIDER_DATA} field in the {@link
37  * android.media.tv.TvContract.Programs}.
38  */
39 public final class InternalDataUtils {
40     private static final boolean DEBUG = false;
41     private static final String TAG = "InternalDataUtils";
42 
InternalDataUtils()43     private InternalDataUtils() {
44         // do nothing
45     }
46 
47     /**
48      * Deserializes a byte array into objects to be stored in the Program class.
49      *
50      * <p>Series ID and critic scores are loaded from the bytes.
51      *
52      * @param bytes the bytes to be deserialized
53      * @param builder the builder for the Program class
54      */
deserializeInternalProviderData(byte[] bytes, ProgramImpl.Builder builder)55     public static void deserializeInternalProviderData(byte[] bytes, ProgramImpl.Builder builder) {
56         if (bytes == null || bytes.length == 0) {
57             return;
58         }
59         try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
60             builder.setSeriesId((String) in.readObject());
61             builder.setCriticScores((List<CriticScore>) in.readObject());
62         } catch (NullPointerException e) {
63             Log.e(TAG, "no bytes to deserialize");
64         } catch (IOException e) {
65             Log.e(TAG, "Could not deserialize internal provider contents");
66         } catch (ClassNotFoundException e) {
67             Log.e(TAG, "class not found in internal provider contents");
68         }
69     }
70 
71     /**
72      * Convenience method for converting relevant data in Program class to a serialized blob type
73      * for storage in internal_provider_data field.
74      *
75      * @param program the program which contains the objects to be serialized
76      * @return serialized blob-type data
77      */
78     @Nullable
serializeInternalProviderData(Program program)79     public static byte[] serializeInternalProviderData(Program program) {
80         ByteArrayOutputStream bos = new ByteArrayOutputStream();
81         try (ObjectOutputStream out = new ObjectOutputStream(bos)) {
82             if (!TextUtils.isEmpty(program.getSeriesId()) || program.getCriticScores() != null) {
83                 out.writeObject(program.getSeriesId());
84                 out.writeObject(program.getCriticScores());
85                 return bos.toByteArray();
86             }
87         } catch (IOException e) {
88             Log.e(
89                     TAG,
90                     "Could not serialize internal provider contents for program: "
91                             + program.getTitle());
92         }
93         return null;
94     }
95 
96     /**
97      * Deserializes a byte array into objects to be stored in the RecordedProgram class.
98      *
99      * <p>Series ID is loaded from the bytes.
100      *
101      * @param bytes the bytes to be deserialized
102      * @param builder the builder for the RecordedProgram class
103      */
deserializeInternalProviderData( byte[] bytes, RecordedProgram.Builder builder)104     public static void deserializeInternalProviderData(
105             byte[] bytes, RecordedProgram.Builder builder) {
106         if (bytes == null || bytes.length == 0) {
107             return;
108         }
109         try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
110             builder.setSeriesId((String) in.readObject());
111         } catch (NullPointerException e) {
112             Log.e(TAG, "no bytes to deserialize");
113         } catch (IOException e) {
114             Log.e(TAG, "Could not deserialize internal provider contents");
115         } catch (ClassNotFoundException e) {
116             Log.e(TAG, "class not found in internal provider contents");
117         }
118     }
119 
120     /**
121      * Serializes relevant objects in {@link android.media.tv.TvContract.Programs} to byte array.
122      *
123      * @return the serialized byte array
124      */
serializeInternalProviderData(RecordedProgram program)125     public static byte[] serializeInternalProviderData(RecordedProgram program) {
126         ByteArrayOutputStream bos = new ByteArrayOutputStream();
127         try (ObjectOutputStream out = new ObjectOutputStream(bos)) {
128             if (!TextUtils.isEmpty(program.getSeriesId())) {
129                 out.writeObject(program.getSeriesId());
130                 return bos.toByteArray();
131             }
132         } catch (IOException e) {
133             Log.e(
134                     TAG,
135                     "Could not serialize internal provider contents for program: "
136                             + program.getTitle());
137         }
138         return null;
139     }
140 }
141