author | Tellen Yu <tellen.yu@amlogic.com> | 2018-01-12 03:04:56 (GMT) |
---|---|---|
committer | Gerrit Code Review <gituser@scgit.amlogic.com> | 2018-01-12 03:04:56 (GMT) |
commit | 372a36029881be05b353e66db482ad59acacae63 (patch) | |
tree | 7a271edf24cf1b8f5a1c8cf43a1a03a1d501fae4 | |
parent | 3d73db380ddac871b5681143944d7494f19c35c8 (diff) | |
parent | c4c6ed9cc1d00327464814f330326b5bb5cf7298 (diff) | |
download | tv-372a36029881be05b353e66db482ad59acacae63.zip tv-372a36029881be05b353e66db482ad59acacae63.tar.gz tv-372a36029881be05b353e66db482ad59acacae63.tar.bz2 |
Merge "Merge remote-tracking branch 'remotes/amlogic/n-amlogic' into HEAD" into o-amlogic
-rw-r--r-- | core/java/com/droidlogic/app/tv/ChannelInfo.java | 129 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/DroidContentRatingsParser.java | 328 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/DroidLogicOverlayView.java | 15 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/DroidLogicTvInputService.java | 20 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/DroidLogicTvUtils.java | 91 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/EasEvent.java | 152 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/EasManager.java | 33 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/Program.java | 70 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/TVTime.java | 7 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/TvControlCommand.java | 19 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/TvControlManager.java | 291 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/TvDataBaseManager.java | 345 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/TvInputBaseSession.java | 24 | ||||
-rw-r--r-- | core/java/com/droidlogic/app/tv/TvStoreManager.java | 321 | ||||
-rw-r--r-- | libtvbinder/include/tvcmd.h | 20 |
15 files changed, 1767 insertions, 98 deletions
diff --git a/core/java/com/droidlogic/app/tv/ChannelInfo.java b/core/java/com/droidlogic/app/tv/ChannelInfo.java index a03fffc..9181277 100644 --- a/core/java/com/droidlogic/app/tv/ChannelInfo.java +++ b/core/java/com/droidlogic/app/tv/ChannelInfo.java @@ -30,6 +30,7 @@ public class ChannelInfo { Channels.COLUMN_VIDEO_FORMAT, Channels.COLUMN_INTERNAL_PROVIDER_DATA, Channels.COLUMN_BROWSABLE, + TvContract.Channels.COLUMN_LOCKED, COLUMN_LCN, COLUMN_LCN1, COLUMN_LCN2 @@ -59,6 +60,7 @@ public class ChannelInfo { public static final String KEY_AUDIO_LANGS = "audio_langs"; public static final String KEY_AUDIO_EXTS = "audio_exts"; public static final String KEY_AUDIO_TRACK_INDEX = "audio_track_index"; + public static final String KEY_AUDIO_OUTPUT_MODE = "audio_out_mode"; public static final String KEY_AUDIO_COMPENSATION = "audio_compensation"; public static final String KEY_AUDIO_CHANNEL = "audio_channel"; public static final String KEY_AUDIO_STD = "audio_std"; @@ -95,8 +97,12 @@ public class ChannelInfo { public static final String KEY_ACCESS_CONTROL = "access"; public static final String KEY_HIDDEN = "hidden"; public static final String KEY_HIDE_GUIDE = "hideGuide"; + public static final String KEY_VCT = "vct"; + public static final String KEY_EITV = "eitv"; public static final String EXTRA_CHANNEL_INFO = "extra_channel_info"; + public static final String KEY_CONTENT_RATINGS = "content_ratings"; + public static final String KEY_SIGNAL_TYPE = "signal_type"; public static final String LABEL_ATV = "ATV"; public static final String LABEL_DTV = "DTV"; @@ -136,6 +142,7 @@ public class ChannelInfo { private int mAudioTrackIndex; //-1:not select, -2:off, >=0:index private int mAudioCompensation; private int mAudioChannel; + private int mAudioOutPutMode;//-1:not set 0:mono 1:stereo 2:sap private int mPcrPid; @@ -176,6 +183,11 @@ public class ChannelInfo { private int mAccessControlled; private int mHidden; private int mHideGuide; + private String mVct; + private int[] mEitVersions; + + private String mContentRatings; + private String mSignalType; private ChannelInfo() {} @@ -272,9 +284,14 @@ public class ChannelInfo { builder.setVideoPid(Integer.parseInt(parsedMap.get(KEY_VIDEO_PID))); if (parsedMap.get(KEY_PCR_ID) != null) builder.setPcrPid(Integer.parseInt(parsedMap.get(KEY_PCR_ID))); - + if (parsedMap.get(KEY_CONTENT_RATINGS) != null) + builder.setContentRatings(DroidLogicTvUtils.TvString.fromString(parsedMap.get(KEY_CONTENT_RATINGS))); + if (parsedMap.get(KEY_SIGNAL_TYPE) != null) + builder.setSignalType(DroidLogicTvUtils.TvString.fromString(parsedMap.get(KEY_SIGNAL_TYPE))); if (parsedMap.get(KEY_AUDIO_TRACK_INDEX) != null) builder.setAudioTrackIndex(Integer.parseInt(parsedMap.get(KEY_AUDIO_TRACK_INDEX))); + if (parsedMap.get(KEY_AUDIO_OUTPUT_MODE) != null) + builder.setAudioOutPutMode(Integer.parseInt(parsedMap.get(KEY_AUDIO_OUTPUT_MODE))); if (parsedMap.get(KEY_AUDIO_COMPENSATION) != null) builder.setAudioCompensation(Integer.parseInt(parsedMap.get(KEY_AUDIO_COMPENSATION))); if (parsedMap.get(KEY_AUDIO_CHANNEL) != null) @@ -348,12 +365,28 @@ public class ChannelInfo { builder.setHidden(Integer.parseInt(parsedMap.get(KEY_HIDDEN))); if (parsedMap.get(KEY_HIDE_GUIDE) != null) builder.setHideGuide(Integer.parseInt(parsedMap.get(KEY_HIDE_GUIDE))); + if (parsedMap.get(KEY_VCT) != null) + builder.setVct(parsedMap.get(KEY_VCT)); + if (parsedMap.get(KEY_EITV) != null) { + String[] svs = parsedMap.get(KEY_EITV).replace("[", "").replace("]", "").split(","); + int vn = (svs[0].compareTo("null") == 0)? 0 : svs.length; + if (vn > 0) { + int[] vs = new int[vn]; + for (int i = 0; i < vn; i++) + vs[i] = Integer.parseInt(svs[i]); + builder.setEitVersions(vs); + } + } } index = cursor.getColumnIndex(Channels.COLUMN_BROWSABLE); if (index >= 0) builder.setBrowsable(cursor.getInt(index)==1 ? true : false); + index = cursor.getColumnIndex(Channels.COLUMN_LOCKED); + if (index >= 0) + builder.setLocked(cursor.getInt(index)==1 ? true : false); + index = cursor.getColumnIndex(COLUMN_LCN); if (index >= 0) builder.setLCN(cursor.getInt(index)); @@ -465,6 +498,10 @@ public class ChannelInfo { return mAudioTrackIndex; } + public int getAudioOutPutMode() { + return mAudioOutPutMode; + } + public int getAudioCompensation() { return mAudioCompensation; } @@ -481,6 +518,22 @@ public class ChannelInfo { return mFrequency; } + public String getContentRatings() { + return mContentRatings; + } + + public String getSignalType() { + return mSignalType; + } + + public void setSignalType(String signalType) { + mSignalType = signalType; + } + + public void setContentRatings(String contentRatings) { + mContentRatings = contentRatings; + } + public int getBandwidth() { return mBandwidth; } @@ -589,6 +642,14 @@ public class ChannelInfo { return mHideGuide; } + public String getVct() { + return mVct; + } + + public int[] getEitVersions() { + return mEitVersions; + } + public boolean isBrowsable() { return this.mBrowsable; } @@ -616,6 +677,10 @@ public class ChannelInfo { mType = type; } + public void setId(long value) { + mId = value; + } + public void setDisplayNumber(String number) { mDisplayNumber = number; mNumber = stringToInteger(number); @@ -673,6 +738,10 @@ public class ChannelInfo { mAudioTrackIndex = index; } + public void setAudioOutPutMode(int mode) { + mAudioOutPutMode = mode; + } + public void setAudioCompensation(int value) { mAudioCompensation = value; } @@ -689,6 +758,10 @@ public class ChannelInfo { mBrowsable = enable; } + public void setLocked(boolean enable) { + mLocked = enable; + } + public void setFavourite(boolean enable) { mIsFavourite = enable; } @@ -753,6 +826,10 @@ public class ChannelInfo { mLCN2 = lcn; } + public void setEitVersions(int[] versions) { + mEitVersions = versions; + } + public void copyFrom(ChannelInfo channel) { if (this == channel) return; @@ -799,11 +876,14 @@ public class ChannelInfo { mChannel.mAudioStd = -1; mChannel.mIsAutoStd = -1; mChannel.mAudioTrackIndex = -1; + mChannel.mAudioOutPutMode = -1; mChannel.mAudioCompensation = -1; mChannel.mAudioChannel = 0; mChannel.mPcrPid = -1; mChannel.mFrequency = -1; + mChannel.mContentRatings = ""; + mChannel.mSignalType = ""; mChannel.mBandwidth = -1; mChannel.mSymbolRate = -1; mChannel.mModulation = -1; @@ -838,6 +918,8 @@ public class ChannelInfo { mChannel.mAccessControlled = 0; mChannel.mHidden = 0; mChannel.mHideGuide = 0; + mChannel.mVct = null; + mChannel.mEitVersions = null; } public Builder setId(long id) { @@ -956,6 +1038,11 @@ public class ChannelInfo { return this; } + public Builder setAudioOutPutMode(int mode) { + mChannel.mAudioOutPutMode = mode; + return this; + } + public Builder setAudioCompensation(int c) { mChannel.mAudioCompensation = c; return this; @@ -976,6 +1063,16 @@ public class ChannelInfo { return this; } + public Builder setContentRatings(String contentRatings) { + mChannel.mContentRatings = contentRatings; + return this; + } + + public Builder setSignalType(String signalType) { + mChannel.mSignalType = signalType; + return this; + } + public Builder setBandwidth(int w) { mChannel.mBandwidth = w; return this; @@ -1121,6 +1218,16 @@ public class ChannelInfo { return this; } + public Builder setVct(String vct) { + mChannel.mVct = vct; + return this; + } + + public Builder setEitVersions(int[] versions) { + mChannel.mEitVersions = versions; + return this; + } + public ChannelInfo build() { return mChannel; } @@ -1179,6 +1286,17 @@ public class ChannelInfo { return (!mServiceType.equals(TvContract.Channels.SERVICE_TYPE_OTHER)); } + public boolean isSameChannel(ChannelInfo a) { + if (a == null) + return false; + + return a.getServiceId() == mServiceId + && a.getOriginalNetworkId() == mOriginalNetworkId + && a.getTransportStreamId() == mTransportStreamId + && a.getFrequency() == mFrequency + && TextUtils.equals(a.getDisplayName(), mDisplayName); + } + public void print () { Log.d(TAG, toString()); } @@ -1206,6 +1324,7 @@ public class ChannelInfo { "\n AudioStd = " + mAudioStd + "\n IsAutoStd = " + mIsAutoStd + "\n AudioTrackIndex = " + mAudioTrackIndex + + "\n mAudioOutPutMode = " + mAudioOutPutMode + "\n AudioCompensation = " + mAudioCompensation + "\n AudioChannel = " + mAudioChannel + "\n PcrPid = " + mPcrPid + @@ -1232,7 +1351,11 @@ public class ChannelInfo { "\n mSourceId = " + mSourceId + "\n AccessControled = " + mAccessControlled + "\n Hidden = " + mHidden + - "\n HideGuide = " + mHideGuide; + "\n HideGuide = " + mHideGuide + + "\n Ratings = " + mContentRatings + + "\n SignalType = " + mSignalType + + "\n vct = " + mVct + + "\n EitVers = " + Arrays.toString(mEitVersions); } public static class Subtitle { @@ -1259,6 +1382,8 @@ public class ChannelInfo { public static final int CC_CAPTION_SERVICE4 = 12; public static final int CC_CAPTION_SERVICE5 = 13; public static final int CC_CAPTION_SERVICE6 = 14; + /*xds vchip services*/ + public static final int CC_CAPTION_VCHIP_ONLY = 15; public int mType; public int mPid; diff --git a/core/java/com/droidlogic/app/tv/DroidContentRatingsParser.java b/core/java/com/droidlogic/app/tv/DroidContentRatingsParser.java new file mode 100644 index 0000000..50816d4 --- a/dev/null +++ b/core/java/com/droidlogic/app/tv/DroidContentRatingsParser.java @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.droidlogic.app.tv; + +import android.content.ContentUris; +import android.content.Context; +//import android.content.pm.PackageManager.NameNotFoundException; +//import android.content.res.Resources; +//import android.content.res.XmlResourceParser; +import android.media.tv.TvContentRatingSystemInfo; +//import android.net.Uri; +import android.util.Log; + +//import com.android.tv.parental.ContentRatingSystem.Order; +//import com.android.tv.parental.ContentRatingSystem.Rating; +//import com.android.tv.parental.ContentRatingSystem.SubRating; + +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.List; +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; + + +import android.content.Context; +import android.content.Intent; +//import android.media.tv.TvContentRating; +//import android.media.tv.TvInputManager; +//import android.os.Environment; +import android.os.Handler; +import android.os.UserHandle; +import android.text.TextUtils; +import android.util.AtomicFile; +import android.util.Xml; + +//import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.XmlUtils; + + +import libcore.io.IoUtils; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DroidContentRatingsParser { + private static final String TAG = "DroidContentRatingsParser"; + private static final boolean DEBUG = false; + + public static final String DOMAIN_RRT_RATINGS = "com.droidlogic.app.tv"; + public static final int FIXED_REGION_lEVEL_2 = 2; + + private static final String TAG_RATING_SYSTEM_DEFINITIONS = "rating-system-definitions"; + private static final String TAG_RATING_SYSTEM_DEFINITION = "rating-system-definition"; + private static final String TAG_RATING_DEFINITION = "rating-definition"; + + private static final String ATTR_STRING = "string"; + private static final String ATTR_ENABLED = "enabled"; + + private static final String ATTR_NAME = "name"; + private static final String ATTR_RATING = "rating"; + private static final String ATTR_COUNTRY = "country"; + private static final String ATTR_DIMENSION_ID = "dimension_id"; + private static final String ATTR_TITLE = "title"; + private static final String ATTR_DESCRIPTION = "description"; + private static final String ATTR_RADING_ID = "rating_id"; + + //private final Context mContext; + //private Resources mResources; + private String mXmlVersionCode; + private final Object mLock = new Object(); + + private AtomicFile mAtomicFile_t; + public DroidContentRatingsParser() { + //mContext = context; + File userDir = new File("/param");//Environment.getDataSystemDirectory(); + if (!userDir.exists()) { + if (!userDir.mkdirs()) { + throw new IllegalStateException("User dir cannot be created: " + userDir); + } + } + mAtomicFile_t = new AtomicFile(new File(userDir, "tv_rrt_define.xml")); + } + + public List<ContentRatingSystemT> load_t() { + //clearState(); + synchronized (mLock) { + final InputStream is; + Log.d(TAG, "==== start load_t===="); + try { + is = mAtomicFile_t.openRead(); + } catch (FileNotFoundException ex) { + Log.d(TAG, "==== load FileNotFoundException===="); + return null; + } + + XmlPullParser parser; + try { + parser = Xml.newPullParser(); + parser.setInput(new BufferedInputStream(is), StandardCharsets.UTF_8.name()); + return loadFromXml_t(parser); + } catch (IOException | XmlPullParserException ex) { + Log.w(TAG, "Failed to load tv input manager persistent store data.", ex); + //clearState(); + } finally { + IoUtils.closeQuietly(is); + } + return null; + } + } + private List<ContentRatingSystemT> loadFromXml_t(XmlPullParser parser) + throws IOException, XmlPullParserException { + List<ContentRatingSystemT> ratingSystems_t = new ArrayList<>(); + + XmlUtils.beginDocument(parser, TAG_RATING_SYSTEM_DEFINITIONS); + final int outerDepth = parser.getDepth(); + //Log.w(TAG, "loadFromXml_t,outerDepth:"+outerDepth); + while (XmlUtils.nextElementWithin(parser, outerDepth)) { + // Log.w(TAG, "-----name:"+parser.getName()); + if (parser.getName().equals(TAG_RATING_SYSTEM_DEFINITION)) { + ratingSystems_t.add(parseRatingSystemDefinition_t(parser)); + } + } + return ratingSystems_t; + } + private ContentRatingSystemT parseRatingSystemDefinition_t(XmlPullParser parser) + throws IOException, XmlPullParserException { + ContentRatingSystemT builder = new ContentRatingSystemT(); + //builder.setDomain(domain); + final int outerDepth = parser.getDepth(); + int i = 0; + //Log.w(TAG, " parseRatingSystemDefinition_t:"+outerDepth); + int attr_num = parser.getAttributeCount(); + // Log.w(TAG, " attr_num:"+attr_num); + + for (i = 0; i< attr_num; i++) { + String attr = parser.getAttributeName(i); + switch (attr) { + case ATTR_NAME: + //Log.w(TAG, " attr:"+attr+", value:"+parser.getAttributeValue(i)); + builder.setName(parser.getAttributeValue(i)); + break; + case ATTR_RATING: + //Log.w(TAG, " attr:"+attr+", value:"+parser.getAttributeValue(i)); + builder.setRegion(StringToInt(parser.getAttributeValue(i))); + break; + case ATTR_COUNTRY: + // Log.w(TAG, " attr:"+attr+", value:"+parser.getAttributeValue(i)); + builder.setCountry(parser.getAttributeValue(i)); + break; + case ATTR_DIMENSION_ID: + // Log.w(TAG, " attr:"+attr+", value:"+parser.getAttributeValue(i)); + break; + } + } + + + while (XmlUtils.nextElementWithin(parser, outerDepth)) { + i = 0; + // Log.w(TAG, " ---tag:"+parser.getName()+"i:"+i); + if (parser.getName().equals(TAG_RATING_DEFINITION)) { + builder.addRatingBuilder(parseRatingDefinition_t(parser)); + } + } + return builder; + } + + private int StringToInt(String value) { + int getvalue = -1; + try { + getvalue = Integer.valueOf(value); + } catch (NumberFormatException e){ + throw new NumberFormatException("string is not integer: " + value); + } + return getvalue; + } + + private RatingDefinition parseRatingDefinition_t(XmlPullParser parser) + throws XmlPullParserException, IOException { + RatingDefinition builder = new RatingDefinition(); + //Log.w(TAG, " parseRatingDefinition_t:"+parser.getAttributeCount()); + for (int i = 0; i < parser.getAttributeCount(); i++) { + String attr = parser.getAttributeName(i); + switch (attr) { + /*case ATTR_NAME: + builder.setName(parser.getAttributeValue(i)); + break;*/ + case ATTR_TITLE: + case ATTR_NAME: + //Log.w(TAG, " attr:"+attr+", value:"+parser.getAttributeValue(i)); + builder.setTitle(parser.getAttributeValue(i)); + break; + case ATTR_DESCRIPTION: + // Log.w(TAG, " attr:"+attr+", value:"+parser.getAttributeValue(i)); + builder.setDescription(parser.getAttributeValue(i)); + break; + case ATTR_RADING_ID: + //Log.w(TAG, " attr:"+attr+", value:"+parser.getAttributeValue(i)); + break; + } + } + return builder; + } + + private void clearState() { + /*mBlockedRatings.clear(); + mParentalControlsEnabled = false;*/ + } + + public class ContentRatingSystemT { + private String mName; + private String mCountry; + private int mRegion; + private final List<RatingDefinition> mRatings = new ArrayList<>(); + + public void ContentRatingSystemT(){ + } + + public void setName(String name) { + if (name == null || name.equals("")) + mName = "NULL"; + else + mName = name; + } + + public void setCountry(String country) { + if (country == null || country.equals("")) + mCountry = "NULL"; + else + mCountry = country; + } + + public void setRegion(int region) { + mRegion = region; + } + + public int getRegion() { + return mRegion; + } + + public String getName() { + return mName; + } + public String getCountry() { + return mCountry; + } + public void addRatingBuilder(RatingDefinition rating) { + if (mRatings == null) { + Log.d(TAG,"addRatingBuilder,mRating is NULL"); + return; + } + mRatings.add(rating); + } + public List<RatingDefinition> getRatingDefinitions() { + return mRatings; + } + public String toString(){ + String s = "Name:"+mName+",Country:" + mCountry + "\n RatingDefinition : \n"; + for (RatingDefinition rating : mRatings) + s = s + rating.toString(); + return s; + } + + public void clear() { + mRatings.clear(); + } + } + + public class RatingDefinition { + private String mTitle; + private String mDescription; + public void RatingDefinition(){ + } + + public void setTitle(String name) { + if (name == null || name.equals("")) + mTitle = "NULL"; + else + mTitle = name; + } + public void setDescription(String description) { + if (description == null || description.equals("")) + mDescription = "NULL"; + else + mDescription = description; + } + public String getTitle() { + return mTitle; + } + public String getDescription() { + return mDescription; + } + + public String toString(){ + String s = " Title:" + mTitle + ",Description:" + mDescription+"\n"; + return s; + } + } +}
\ No newline at end of file diff --git a/core/java/com/droidlogic/app/tv/DroidLogicOverlayView.java b/core/java/com/droidlogic/app/tv/DroidLogicOverlayView.java index df00f1d..b3dd37e 100644 --- a/core/java/com/droidlogic/app/tv/DroidLogicOverlayView.java +++ b/core/java/com/droidlogic/app/tv/DroidLogicOverlayView.java @@ -11,9 +11,10 @@ import android.widget.TextView; public abstract class DroidLogicOverlayView extends FrameLayout { private static final String TAG = "DroidLogicOverlayView"; - protected ImageView mImageView; - protected TextView mTextView; - protected View mSubtitleView; + protected ImageView mImageView; + protected TextView mTextView; + protected View mSubtitleView; + protected TextView mEasTextView; public DroidLogicOverlayView(Context context) { this(context, null); @@ -47,6 +48,14 @@ public abstract class DroidLogicOverlayView extends FrameLayout { mTextView.setText(resId); } + public void setTextForEas(CharSequence text){ + mEasTextView.setText(text); + } + + public void setEasTextVisibility(boolean visible) { + mEasTextView.setVisibility(visible ? VISIBLE : GONE); + } + public void setTextVisibility(boolean visible) { mTextView.setVisibility(visible ? VISIBLE : GONE); } diff --git a/core/java/com/droidlogic/app/tv/DroidLogicTvInputService.java b/core/java/com/droidlogic/app/tv/DroidLogicTvInputService.java index d1eec8c..0989cee 100644 --- a/core/java/com/droidlogic/app/tv/DroidLogicTvInputService.java +++ b/core/java/com/droidlogic/app/tv/DroidLogicTvInputService.java @@ -393,9 +393,11 @@ public class DroidLogicTvInputService extends TvInputService implements public void onSigChanged(TVInSignalInfo signal_info) { } + @Override public void StorDBonEvent(TvControlManager.ScannerEvent event) { - mTvStoreManager.onStoreEvent(event); + if (mTvStoreManager != null) + mTvStoreManager.onStoreEvent(event); } public void resetScanStoreListener() { @@ -478,6 +480,10 @@ public class DroidLogicTvInputService extends TvInputService implements mSurface = null; stopTvPlay(session.mId); } + + if (mHardware != null && mSurface != null && mSurface.isValid()) { + mHardware.setSurface(mSurface, mConfigs[0]); + } } public int doTune(Uri uri, int sessionId) { @@ -501,7 +507,7 @@ public class DroidLogicTvInputService extends TvInputService implements private int startTvPlay() { Log.d(TAG, "startTvPlay inputId=" + mCurrentInputId + " surface=" + mSurface); if (mHardware != null && mSurface != null && mSurface.isValid()) { - mHardware.setSurface(mSurface, mConfigs[0]); + //mHardware.setSurface(mSurface, mConfigs[0]); selectHdmiDevice(mDeviceId); return ACTION_SUCCESS; } @@ -509,6 +515,7 @@ public class DroidLogicTvInputService extends TvInputService implements } private int stopTvPlay(int sessionId) { + Log.d(TAG, "stopTvPlay:"+sessionId+" mHardware:"+mHardware); if (mHardware != null) { mHardware.setSurface(null, mConfigs[0]); tvPlayStopped(sessionId); @@ -670,4 +677,13 @@ public class DroidLogicTvInputService extends TvInputService implements private float getUptimeSeconds() { return (float)SystemClock.uptimeMillis() / 1000; } + + public void notifyAppEasStatus(boolean isStarted){ + Log.d(TAG, "notifyAppEasStatus:"+isStarted); + Bundle bundle = new Bundle(); + bundle.putInt(DroidLogicTvUtils.SIG_INFO_EAS_STATUS, isStarted ? 1 : 0); + if (mSession != null) { + mSession.notifySessionEvent(DroidLogicTvUtils.SIG_INFO_EAS_EVENT, bundle); + } + } } diff --git a/core/java/com/droidlogic/app/tv/DroidLogicTvUtils.java b/core/java/com/droidlogic/app/tv/DroidLogicTvUtils.java index 0a80335..4039133 100644 --- a/core/java/com/droidlogic/app/tv/DroidLogicTvUtils.java +++ b/core/java/com/droidlogic/app/tv/DroidLogicTvUtils.java @@ -105,6 +105,8 @@ public class DroidLogicTvUtils public static final int SIG_INFO_TYPE_ADTV = 5; public static final int SIG_INFO_TYPE_OTHER = 6; + public static final String SIG_INFO_EAS_EVENT = "dtv_eas_event"; + public static final String SIG_INFO_EAS_STATUS = "eas_status"; /** * source input type need to switch */ @@ -192,6 +194,13 @@ public class DroidLogicTvUtils /*auto tracks call*/ public static final String ACTION_DTV_AUTO_TRACKS = "dtv_auto_tracks"; + /*when it's on ,block all program without rating*/ + public static final String ACTION_BLOCK_NORATING = "block_norating"; + public static final String PARAM_NORATING_ENABLE = "enable_norating"; + public static final int NORATING_OFF = 0; + public static final int NORATING_ON = 1; + public static final int NORATING_UNLOCK_CURRENT = 2; + /*set type call*/ public static final String ACTION_DTV_SET_TYPE = "dtv_set_type"; public static final String PARA_TYPE = "dtv_type"; @@ -224,6 +233,8 @@ public class DroidLogicTvUtils public static final int OPEN_DEV_FOR_SCAN_DTV = 2; public static final int CLOSE_DEV_FOR_SCAN = 3; + public static final String SYSTEM_CAPTION_STYLE_ENABLE = "accessibility_captioning_style_enabled"; + /** * used for TvSettings to switch hdmi source * {@link #SOURCE_NAME} @@ -248,10 +259,15 @@ public class DroidLogicTvUtils public static final String TV_ATV_CHANNEL_INDEX = "tv_atv_channel_index"; public static final String TV_DTV_CHANNEL_INDEX = "tv_dtv_channel_index"; public static final String TV_CURRENT_CHANNEL_IS_RADIO = "tv_current_channel_is_radio"; + public static final String BLOCK_NORATING = "block_norating"; public static final String TV_KEY_DTV_NUMBER_MODE = "tv_dtv_number_mode"; public static final String TV_KEY_DTV_TYPE = "tv_dtv_type"; + public static final String SIGNAL_TYPE_ERROR = "error"; + public static final String ALL_CHANNELS_NUMBER = "all_channels_number"; + public static final String DTV_TYPE_SWITCHED = "dtv_type_switched"; + private static final UriMatcher sUriMatcher; public static final int NO_MATCH = UriMatcher.NO_MATCH; public static final int MATCH_CHANNEL = 1; @@ -274,6 +290,16 @@ public class DroidLogicTvUtils sUriMatcher.addURI(TvContract.AUTHORITY, "watched_program/#", MATCH_WATCHED_PROGRAM_ID); } + public static String getCurrentSignalType(Context context) { + String dtvType = Settings.System.getString(context.getContentResolver(), DroidLogicTvUtils.TV_KEY_DTV_TYPE); + if (dtvType == null) { + return DroidLogicTvUtils.SIGNAL_TYPE_ERROR; + } else { + Log.d(TAG, "getCurrentSignalType = " + dtvType); + return dtvType; + } + } + public static int matchsWhich(Uri uri) { return sUriMatcher.match(uri); } @@ -688,9 +714,10 @@ public class DroidLogicTvUtils "CA_TV_FR_E", "CA_TV_FR_G", "CA_TV_FR_8", "CA_TV_FR_13", "CA_TV_FR_16", "CA_TV_FR_18" }; + public static TvContentRating[] parseDRatings(String jsonString) { String RatingDomain = "com.android.tv"; - + Log.d(TAG, "parseDRatings:"+jsonString); if (jsonString == null || jsonString.isEmpty()) return null; @@ -732,38 +759,38 @@ public class DroidLogicTvUtils JSONArray ratings = g.optJSONArray("rx"); if (ratings != null) { JSONObject ratingValues = ratings.optJSONObject(0); + if (null == ratingValues) + continue; int dimension = ratingValues.optInt("d", -1); int value = ratingValues.optInt("r", -1); if (dimension == -1 || value == -1) continue; if (region == 1) {//US ratings - if (dimension == 7 - /*&& ratingDescription != null - && ratingDescription.startsWith("MPAA-")*/ - ) { - TvContentRating r = TvContentRating.createRating(RatingDomain, "US_MV", - DroidLogicTvUtils.US_ContentRatingDimensions[dimension][value]); - RatingList.add(r); - Log.d(TAG, "add rating:"+r.flattenToString()); - } else /*if (ratingDescription != null - && ratingDescription.startsWith("TV-") - )*/ { - ArrayList<String> subRatings = new ArrayList<String>(); - for (int j = 1; j < ratings.length(); j++) { - JSONObject subRatingValues = ratings.optJSONObject(j); - int subDimension = subRatingValues.optInt("d", -1); - int subValue = subRatingValues.optInt("r", -1); - if (subDimension == -1 || subValue == -1) - continue; - subRatings.add(DroidLogicTvUtils.US_ContentRatingDimensions[subDimension][subValue]); + for (int j = 0; j < ratings.length(); j++) { + JSONObject subRatingValues = ratings.optJSONObject(j); + int subDimension = subRatingValues.optInt("d", -1); + int subValue = subRatingValues.optInt("r", -1); + + if (subDimension == -1 || subValue == -1) + continue; + if (subDimension > 7 || + subValue >= DroidLogicTvUtils.US_ContentRatingDimensions[subDimension].length || + TextUtils.isEmpty(DroidLogicTvUtils.US_ContentRatingDimensions[subDimension][subValue])) { + continue; + } + if (subDimension == 7) { + TvContentRating r = TvContentRating.createRating(RatingDomain, "US_MV", + DroidLogicTvUtils.US_ContentRatingDimensions[subDimension][subValue]); + RatingList.add(r); + Log.d(TAG, "mv add rating:"+r.flattenToString()); + } else { + if (subDimension == 255) + subDimension = 0; + TvContentRating r = TvContentRating.createRating(RatingDomain, "US_TV", + DroidLogicTvUtils.US_ContentRatingDimensions[subDimension][subValue]); + RatingList.add(r); + Log.d(TAG, "tv add rating:"+r.flattenToString()); } - if (dimension == 255) - dimension = 0; - TvContentRating r = TvContentRating.createRating(RatingDomain, "US_TV", - DroidLogicTvUtils.US_ContentRatingDimensions[dimension][value], - subRatings.toArray(new String[subRatings.size()])); - RatingList.add(r); - Log.d(TAG, "add rating:"+r.flattenToString()); } } else if (region == 2) {//Canadian ratings for (int j = 0; j < ratings.length(); j++) { @@ -773,12 +800,20 @@ public class DroidLogicTvUtils if (Dimension == -1 || Value == -1) continue; if (Dimension == 0) { + if (Value >= DroidLogicTvUtils.CA_EN_ContentRatingDimensions.length || + TextUtils.isEmpty(DroidLogicTvUtils.CA_EN_ContentRatingDimensions[Value])) { + continue; + } //canadian english language rating TvContentRating r = TvContentRating.createRating(RatingDomain, "CA_TV_EN", DroidLogicTvUtils.CA_EN_ContentRatingDimensions[Value]); RatingList.add(r); Log.d(TAG, "add rating:"+r.flattenToString()); } else if (Dimension == 1) { + if (Value >= DroidLogicTvUtils.CA_FR_ContentRatingDimensions.length || + TextUtils.isEmpty(DroidLogicTvUtils.CA_FR_ContentRatingDimensions[Value])) { + continue; + } //canadian frech language rating TvContentRating r = TvContentRating.createRating(RatingDomain, "CA_TV_FR", DroidLogicTvUtils.CA_FR_ContentRatingDimensions[Value]); @@ -829,7 +864,7 @@ public class DroidLogicTvUtils if ((dlsv & VBI_RATING_S) == VBI_RATING_S) subRatings.add("US_TV_S"); if ((dlsv & VBI_RATING_V) == VBI_RATING_V) - subRatings.add("US_TV_V"); + subRatings.add(TextUtils.equals(ratings[auth][id], "US_TV_Y7")? "US_TV_FV" : "US_TV_V"); return TvContentRating.createRating(RatingDomain, region[auth], ratings[auth][id], diff --git a/core/java/com/droidlogic/app/tv/EasEvent.java b/core/java/com/droidlogic/app/tv/EasEvent.java new file mode 100644 index 0000000..e32d140 --- a/dev/null +++ b/core/java/com/droidlogic/app/tv/EasEvent.java @@ -0,0 +1,152 @@ +package com.droidlogic.app.tv; + +import android.os.Parcel; +import android.util.Log; + +public class EasEvent { + private static final String TAG = "EasEvent"; + public int tableId; //table id + public int extension; //subtable id + public int version; //version_number + public int currentNext; //current_next_indicator + public int sequenceNum; //sequence version + public int protocolVersion; //protocol version + public int easEventId; //eas event id + public int[] easOrigCode; //eas event orig code + public int easEventCodeLen; //eas event code len + public int[] easEventCode; //eas event code + public int alertMessageTimeRemaining; //alert msg remain time + public int eventStartTime; //eas event start time + public int eventDuration; //event dur + public int alertPriority; //alert priority + public int detailsOOBSourceID; //details oob source id + public int detailsMajorChannelNumber; //details major channel num + public int detailsMinorChannelNumber; //details minor channel num + public int audioOOBSourceID; //audio oob source id + public int locationCount; //location count + public Location[] location; //location info + public int exceptionCount; //exception count + public ExceptionList[] exceptionList; //exception info + public int multiTextCount; //multi_text count + public MultiStr[] multiText; //nature and alert multi str information structure. + public int descriptorTextCount; //descriptor text count. + public Descriptor[] descriptor; //descriptor structure. + + public class Location { + public int stateCode; + public int countySubdiv; + public int countyCode; + } + public class ExceptionList { + public int inBandRefer; + public int exceptionMajorChannelNumber; //the exception major channel num + public int exceptionMinorChannelNumber; //the exception minor channel num + public int exceptionOOBSourceID; //the exception oob source id + } + public class MultiStr { + public int[] lang; //the language of mlti str + public int type; //the str type, alert or nature + public int compressionType; //compression type + public int mode; //mode + public int numberBytes; //number bytes + public int[] compressedStr; //the compressed str + } + public class Descriptor { + public int tag; //descriptor_tag + public int length; //descriptor_length + public int[] data; //content + } + + public void printEasEventInfo(){ + Log.i(TAG,"[EasEventInfo]"+ + "\n alertMessageTimeRemaining = "+alertMessageTimeRemaining+ + "\n alertPriority = "+alertPriority+ + "\n detailsMajorChannelNumber = "+detailsMajorChannelNumber+ + "\n detailsMinorChannelNumber = "+detailsMinorChannelNumber); + } + + public void readEasEvent(Parcel p) { + Log.i(TAG,"readEasEvent"); + int i, j, k; + tableId = p.readInt(); + extension = p.readInt(); + version = p.readInt(); + currentNext = p.readInt(); + sequenceNum = p.readInt(); + protocolVersion = p.readInt(); + easEventId = p.readInt(); + easOrigCode = new int[3]; + for (j=0;j<3;j++) { + easOrigCode[j] = p.readInt(); + } + easEventCodeLen = p.readInt(); + if (easEventCodeLen != 0) { + easEventCode = new int[easEventCodeLen]; + for (j=0;j<easEventCodeLen;j++) + easEventCode[j] = p.readInt(); + } + alertMessageTimeRemaining = p.readInt(); + eventStartTime = p.readInt(); + eventDuration = p.readInt(); + alertPriority = p.readInt(); + detailsOOBSourceID = p.readInt(); + detailsMajorChannelNumber = p.readInt(); + detailsMinorChannelNumber = p.readInt(); + audioOOBSourceID = p.readInt(); + locationCount = p.readInt(); + if (locationCount != 0) { + location = new Location[locationCount]; + for (j=0;j<locationCount;j++) { + location[j] = new Location(); + location[j].stateCode = p.readInt(); + location[j].countySubdiv = p.readInt(); + location[j].countyCode = p.readInt(); + } + } + exceptionCount = p.readInt(); + if (exceptionCount != 0) { + exceptionList = new ExceptionList[exceptionCount]; + for (j=0;j<exceptionCount;j++) { + exceptionList[j] = new ExceptionList(); + exceptionList[j].inBandRefer = p.readInt(); + exceptionList[j].exceptionMajorChannelNumber = p.readInt(); + exceptionList[j].exceptionMinorChannelNumber = p.readInt(); + exceptionList[j].exceptionOOBSourceID = p.readInt(); + } + } + multiTextCount = p.readInt(); + if (multiTextCount != 0) { + multiText = new MultiStr[multiTextCount]; + for (j=0;j<multiTextCount;j++) { + multiText[j] = new MultiStr(); + multiText[j].lang = new int[3]; + multiText[j].lang[0] = p.readInt(); + multiText[j].lang[1] = p.readInt(); + multiText[j].lang[2] = p.readInt(); + multiText[j].type = p.readInt(); + multiText[j].compressionType = p.readInt(); + multiText[j].mode = p.readInt(); + multiText[j].numberBytes = p.readInt(); + multiText[j].compressedStr = new int[multiText[j].numberBytes]; + for (k=0;k<multiText[j].numberBytes;k++) { + multiText[j].compressedStr[k] = p.readInt(); + } + } + } + descriptorTextCount = p.readInt(); + if (descriptorTextCount != 0) { + descriptor = new Descriptor[descriptorTextCount]; + for (j=0;j<descriptorTextCount;j++) { + descriptor[j] = new Descriptor(); + descriptor[j].tag = p.readInt(); + descriptor[j].length = p.readInt(); + descriptor[j].data = new int[descriptor[j].length]; + for (k=0;k<descriptor[j].length;k++) { + descriptor[j].data[k] = p.readInt(); + } + } + } + + } + } + diff --git a/core/java/com/droidlogic/app/tv/EasManager.java b/core/java/com/droidlogic/app/tv/EasManager.java new file mode 100644 index 0000000..236d630 --- a/dev/null +++ b/core/java/com/droidlogic/app/tv/EasManager.java @@ -0,0 +1,33 @@ +package com.droidlogic.app.tv; + +import android.os.Parcel; +import android.util.Log; + +public class EasManager { + private static final String TAG = "EasManager"; + private static final long GPS_UTC_OFFSET_IN_SECONDS = 315964800; + private static final int EAS_TEXT_MESSAGE = 0; + private static final int EAS_LOW_PRIORITY = 4; + private static final int EAS_MEDIUM_PRIORITY = 8; + private static final int EAS_HIGH_PRIORITY = 12; + + private EasEvent preEasEvent = null; + private EasEvent curEasEvent = null; + + public boolean isEasEventNeedProcess(EasEvent easEvent) { + Log.i(TAG,"isEasEventNeedProcess"); + curEasEvent = easEvent; + easEvent.printEasEventInfo(); + if (easEvent.protocolVersion != 0) { + return false; + } + + if (easEvent.alertPriority == EAS_TEXT_MESSAGE) { + return false; + } + + preEasEvent = easEvent; + return true; + } + } + diff --git a/core/java/com/droidlogic/app/tv/Program.java b/core/java/com/droidlogic/app/tv/Program.java index 0e32f6d..cf5287a 100644 --- a/core/java/com/droidlogic/app/tv/Program.java +++ b/core/java/com/droidlogic/app/tv/Program.java @@ -13,8 +13,8 @@ import java.util.Objects; * A convenience class to create and insert program information into the database. */ public final class Program implements Comparable<Program> { - private static final long INVALID_LONG_VALUE = -1; - private static final int INVALID_INT_VALUE = -1; + public static final long INVALID_LONG_VALUE = -1; + public static final int INVALID_INT_VALUE = -1; private long mId; private long mChannelId; @@ -35,6 +35,8 @@ public final class Program implements Comparable<Program> { private TvContentRating[] mContentRatings; private String mInternalProviderData; private boolean mIsAppointed; + private String mVersion; + private String mEitExt; private Program() { mId = INVALID_LONG_VALUE; @@ -47,6 +49,8 @@ public final class Program implements Comparable<Program> { mVideoWidth = INVALID_INT_VALUE; mVideoHeight = INVALID_INT_VALUE; mIsAppointed = false; + mVersion = null; + mEitExt = null; } public long getId() { @@ -109,6 +113,10 @@ public final class Program implements Comparable<Program> { return mContentRatings; } + public void setContentRatings(TvContentRating[] rating) { + mContentRatings = rating; + } + public String getPosterArtUri() { return mPosterArtUri; } @@ -134,6 +142,22 @@ public final class Program implements Comparable<Program> { mIsAppointed = isAppointed; } + public String getVersion() { + return mVersion; + } + + public void setVersion(String version) { + mVersion = version; + } + + public String getEitExt() { + return mEitExt; + } + + public void setEitExt(String ext) { + mEitExt = ext; + } + @Override public int hashCode() { return Objects.hash(mChannelId, mStartTimeUtcMillis, mEndTimeUtcMillis, @@ -162,7 +186,9 @@ public final class Program implements Comparable<Program> { && Arrays.equals(mContentRatings, program.mContentRatings) && Arrays.equals(mCanonicalGenres, program.mCanonicalGenres) && mSeasonNumber == program.mSeasonNumber - && mEpisodeNumber == program.mEpisodeNumber; + && mEpisodeNumber == program.mEpisodeNumber + && TextUtils.equals(mVersion, program.mVersion) + && TextUtils.equals(mEitExt, program.mEitExt); } public boolean matchsWithoutDescription(Program program) { @@ -178,7 +204,9 @@ public final class Program implements Comparable<Program> { && Arrays.equals(mContentRatings, program.mContentRatings) && Arrays.equals(mCanonicalGenres, program.mCanonicalGenres) && mSeasonNumber == program.mSeasonNumber - && mEpisodeNumber == program.mEpisodeNumber; + && mEpisodeNumber == program.mEpisodeNumber + && Objects.equals(contentRatingsToString(mContentRatings), + contentRatingsToString(program.mContentRatings)); } @Override @@ -206,7 +234,8 @@ public final class Program implements Comparable<Program> { .append(", thumbnailUri=").append(mThumbnailUri) .append(", contentRatings=").append(mContentRatings) .append(", genres=").append(mCanonicalGenres) - .append(", isAppointed=").append(mIsAppointed); + .append(", isAppointed=").append(mIsAppointed) + .append(", ext=").append(mVersion).append(":"+mEitExt); return builder.append("}").toString(); } @@ -232,6 +261,8 @@ public final class Program implements Comparable<Program> { mCanonicalGenres = other.mCanonicalGenres; mContentRatings = other.mContentRatings; mIsAppointed = other.mIsAppointed; + mVersion = other.mVersion; + mEitExt = other.mEitExt; } public ContentValues toContentValues() { @@ -315,6 +346,16 @@ public final class Program implements Comparable<Program> { } values.put(TvContract.Programs.COLUMN_INTERNAL_PROVIDER_FLAG1, mIsAppointed ? 1 : 0); values.put(TvContract.Programs.COLUMN_INTERNAL_PROVIDER_FLAG2, mProgramId); + if (!TextUtils.isEmpty(mVersion)) { + values.put(TvContract.Programs.COLUMN_VERSION_NUMBER, mVersion); + } else { + values.putNull(TvContract.Programs.COLUMN_VERSION_NUMBER); + } + if (!TextUtils.isEmpty(mEitExt)) { + values.put(TvContract.Programs.COLUMN_INTERNAL_PROVIDER_FLAG3, mEitExt); + } else { + values.putNull(TvContract.Programs.COLUMN_INTERNAL_PROVIDER_FLAG3); + } return values; } @@ -397,6 +438,14 @@ public final class Program implements Comparable<Program> { if (index >= 0) { builder.setProgramId(cursor.getInt(index)); } + index = cursor.getColumnIndex(TvContract.Programs.COLUMN_VERSION_NUMBER); + if (index >= 0 && !cursor.isNull(index)) { + builder.setVersion(cursor.getString(index)); + } + index = cursor.getColumnIndex(TvContract.Programs.COLUMN_INTERNAL_PROVIDER_FLAG3); + if (index >=0 && !cursor.isNull(index)) { + builder.setEitExt(cursor.getString(index)); + } return builder.build(); } @@ -506,6 +555,17 @@ public final class Program implements Comparable<Program> { mProgram.mIsAppointed = isAppointed; return this; } + + public Builder setVersion(String version) { + mProgram.mVersion = version; + return this; + } + + public Builder setEitExt(String ext) { + mProgram.mEitExt = ext; + return this; + } + public Program build() { return mProgram; } diff --git a/core/java/com/droidlogic/app/tv/TVTime.java b/core/java/com/droidlogic/app/tv/TVTime.java index dd723c9..a91d01b 100644 --- a/core/java/com/droidlogic/app/tv/TVTime.java +++ b/core/java/com/droidlogic/app/tv/TVTime.java @@ -3,11 +3,12 @@ package com.droidlogic.app.tv; import android.content.Context; import android.provider.Settings; import android.os.SystemClock; +import android.util.Log; import java.util.Date; import com.droidlogic.app.SystemControlManager; - +import com.droidlogic.app.DaylightSavingTime; /** *TV时间管理 */ @@ -39,6 +40,10 @@ public class TVTime{ && (Math.abs(diff) > 1000)) { SystemClock.setCurrentTimeMillis(time); diff = 0; + DaylightSavingTime daylightSavingTime = DaylightSavingTime.getInstance(); + daylightSavingTime.updateDaylightSavingTimeForce(); + Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AUTO_TIME, 0); + Log.d("DroidLogic", "setTime"); } Settings.System.putLong(mContext.getContentResolver(), TV_KEY_TVTIME, diff); diff --git a/core/java/com/droidlogic/app/tv/TvControlCommand.java b/core/java/com/droidlogic/app/tv/TvControlCommand.java index 6440f04..0709a88 100644 --- a/core/java/com/droidlogic/app/tv/TvControlCommand.java +++ b/core/java/com/droidlogic/app/tv/TvControlCommand.java @@ -254,7 +254,11 @@ public interface TvControlCommand { int EPG_EVENT_CALLBACK = 542; int VFRAME_BMP_EVENT_CALLBACK = 543; int SCANNING_FRAME_STABLE_CALLBACK = 544; - int SCAN_LCN_CALLBACK = 545; + int FRONTEND_EVENT_CALLBACK = 545; + int RECORDER_EVENT_CALLBACK = 546; + int SCAN_LCN_CALLBACK = 547; + int RRT_EVENT_CALLBACK = 548; + int EAS_EVENT_CALLBACK = 549; // CALLBACK END // SSM @@ -484,6 +488,7 @@ public interface TvControlCommand { int START_AUTO_BACKLIGHT = 1456; int STOP_AUTO_BACKLIGHT = 1457; int IS_AUTO_BACKLIGHTING = 1458; + int HDMIAV_HOTPLUGDETECT_ONOFF = 1459; int GET_AVERAGE_LUMA = 1480; int GET_AUTO_BACKLIGHT_DATA = 1481; @@ -494,4 +499,16 @@ public interface TvControlCommand { int TV_SET_FRONTEND = 1486; int SET_AUDIO_OUTMODE = 1501; int GET_AUDIO_OUTMODE = 1502; + int GET_AUDIO_STREAM_OUTMODE = 1503; + + int SET_AMAUDIO_VOLUME = 1504; + int GET_AMAUDIO_VOLUME = 1505; + int SAVE_AMAUDIO_VOLUME = 1506; + int GET_SAVE_AMAUDIO_VOLUME = 1507; + int DTV_UPDATE_RRT = 1508; + int DTV_SEARCH_RRT = 1509; + int DTV_UPDATE_EAS = 1510; + + int DTV_RECORDING_CMD = 1600; + int DTV_PLAY_CMD = 1610; } diff --git a/core/java/com/droidlogic/app/tv/TvControlManager.java b/core/java/com/droidlogic/app/tv/TvControlManager.java index f741813..0749ae0 100644 --- a/core/java/com/droidlogic/app/tv/TvControlManager.java +++ b/core/java/com/droidlogic/app/tv/TvControlManager.java @@ -43,6 +43,7 @@ import android.text.TextUtils; //import android.media.audiofx.Hpeq; import static com.droidlogic.app.tv.TvControlCommand.*; +import com.droidlogic.app.tv.EasEvent; public class TvControlManager { private static final String TAG = "TvControlManager"; @@ -116,8 +117,15 @@ public class TvControlManager { private ScanningFrameStableListener mScanningFrameStableListener = null; private VframBMPEventListener mVframBMPListener = null; private EpgEventListener mEpgListener = null; + private RRT5SourceUpdateListener mRrtListener = null; private AVPlaybackListener mAVPlaybackListener = null; + private EasEventListener mEasListener = null; + private int rrt5XmlLoadStatus = 0; + public static int EVENT_RRT_SCAN_START = 1; + public static int EVENT_RRT_SCAN_END = 3; + + private EasManager easManager = new EasManager(); private static TvControlManager mInstance; private native final void native_setup(Object tv_this); @@ -221,6 +229,26 @@ public class TvControlManager { return ret; } + public int sendCmdStringArray(int cmd, int id, String[] values) { + libtv_log_open(); + Parcel request = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + request.writeInt(cmd); + request.writeInt(id); + + for (int i = 0; i < values.length; i++) { + request.writeString(values[i]); + } + request.setDataPosition(0); + processCmd(request, reply); + reply.setDataPosition(0); + int ret = reply.readInt(); + + request.recycle(); + reply.recycle(); + return ret; + } + class EventHandler extends Handler { int dataArray[]; int cmdArray[]; @@ -326,6 +354,7 @@ public class TvControlManager { scan_ev.accessControlled = p.readInt(); scan_ev.hidden = p.readInt(); scan_ev.hideGuide = p.readInt(); + scan_ev.vct = p.readString(); } @Override @@ -502,9 +531,48 @@ public class TvControlManager { mCloseCaptionListener.onCloseCaptionProcess(dataArray, cmdArray); } break; - default: - Log.e(TAG, "Unknown message type " + msg.what); + + case RECORDER_EVENT_CALLBACK: + p = ((Parcel) (msg.obj)); + if (mRecorderEventListener != null) { + RecorderEvent ev = new RecorderEvent(); + ev.Id = p.readString(); + ev.Status = p.readInt(); + ev.Error = p.readInt(); + mRecorderEventListener.onRecoderEvent(ev); + } break; + + case RRT_EVENT_CALLBACK: + p = ((Parcel) (msg.obj)); + if (mRrtListener != null) { + int result = p.readInt(); + Log.e(TAG, "RRT_EVENT_CALLBACK:" + result); + rrt5XmlLoadStatus = result; + mRrtListener.onRRT5InfoUpdated(result); + } + break; + + case EAS_EVENT_CALLBACK: + Log.i(TAG,"get EAS_event_callBack"); + p = ((Parcel) (msg.obj)); + if (mEasListener != null) { + Log.i(TAG,"mEaslister is not null"); + int sectionCount = p.readInt(); + Log.i(TAG,"eas section count = "+sectionCount); + for (int count = 0; count<sectionCount; count++) { + EasEvent curEasEvent = new EasEvent(); + curEasEvent.readEasEvent(p); + if (easManager.isEasEventNeedProcess(curEasEvent)) { + mEasListener.processDetailsChannelAlert(curEasEvent); + } + } + } + + break; + default: + Log.e(TAG, "Unknown message type " + msg.what); + break; } } } @@ -629,6 +697,17 @@ public class TvControlManager { } /** + * @Function: GetHotPlugDetect + * @Description: Get hotplug detect enable status + * @Param: + * @Return: true refer to on, and false refers to off + */ + public boolean GetHotPlugDetectEnableStatus() { + int ret = sendCmd(HDMIAV_HOTPLUGDETECT_ONOFF); + return (ret == 1 ? true:false); + } + + /** * @Function: GetLastSourceInput * @Description: Get last source input * @Param: @@ -1245,6 +1324,52 @@ public class TvControlManager { return sendCmd(GET_AUDIO_OUTMODE); } + public int GetAudioStreamOutmode(){ + return sendCmd(GET_AUDIO_STREAM_OUTMODE); + } + + public static final int AM_AUDIO_TV = 0; + public static final int AM_AUDIO_AV1 = 1; + public static final int AM_AUDIO_AV2 = 2; + public static final int AM_AUDIO_YPBPR1 = 3; + public static final int AM_AUDIO_YPBPR2 = 4; + public static final int AM_AUDIO_HDMI1 = 5; + public static final int AM_AUDIO_HDMI2 = 6; + public static final int AM_AUDIO_HDMI3 = 7; + public static final int AM_AUDIO_HDMI4 = 8; + public static final int AM_AUDIO_VGA = 9; + public static final int AM_AUDIO_MPEG = 10; + public static final int AM_AUDIO_DTV = 11; + public static final int AM_AUDIO_SVIDEO = 12; + public static final int AM_AUDIO_IPTV = 13; + public static final int AM_AUDIO_DUMMY = 14; + public static final int AM_AUDIO_SPDIF = 15; + public static final int AM_AUDIO_ADTV = 16; + + public int SetAmAudioVolume(int volume, int source) { + int val[] = new int[]{volume}; + if (source == AM_AUDIO_MPEG) { + SystemProperties.set("persist.media.player.volume", + String.valueOf(volume)); + } + + return sendCmdIntArray(SET_AMAUDIO_VOLUME, val); + } + + public int GetAmAudioVolume() { + return sendCmd(GET_AMAUDIO_VOLUME); + } + + public int SaveAmAudioVolume(int volume, int source) { + int val[] = new int[]{volume, source}; + return sendCmdIntArray(SAVE_AMAUDIO_VOLUME, val); + } + + public int GetSaveAmAudioVolume(int source) { + int val[] = new int[]{source}; + return sendCmdIntArray(GET_SAVE_AMAUDIO_VOLUME, val); + } + public enum Noise_Reduction_Mode { REDUCE_NOISE_CLOSE(0), REDUCE_NOISE_WEAK(1), @@ -4248,11 +4373,13 @@ public class TvControlManager { base = r.readInt() - 1; bpl.ID = 1 ; bpl.freq= r.readInt(); + bpl.channelNum = r.readInt(); FList.add(bpl); for (int i = 1; i < size; i++) { FreqList pl = new FreqList(); pl.ID = r.readInt() - base; pl.freq= r.readInt(); + pl.channelNum = r.readInt(); FList.add(pl); } cmd.recycle(); @@ -4274,11 +4401,13 @@ public class TvControlManager { base = r.readInt() - 1; bpl.ID = 1 ; bpl.freq= r.readInt(); + bpl.channelNum = r.readInt(); FList.add(bpl); for (int i = 1; i < size; i++) { FreqList pl = new FreqList(); pl.ID = r.readInt() - base; pl.freq= r.readInt(); + pl.channelNum = r.readInt(); FList.add(pl); } cmd.recycle(); @@ -4446,6 +4575,7 @@ public class TvControlManager { public int accessControlled; public int hidden; public int hideGuide; + public String vct; } public class ScannerLcnInfo { @@ -4457,7 +4587,6 @@ public class TvControlManager { public int[] valid; } - public static class ScanMode { private int scanMode; @@ -4561,6 +4690,75 @@ public class TvControlManager { void onEvent(EpgEvent ev); } + //rrt + public void SetRRT5SourceUpdateListener(RRT5SourceUpdateListener l) { + mRrtListener = l; + } + + public interface RRT5SourceUpdateListener { + void onRRT5InfoUpdated(int status); + } + + public int updateRRTRes(int freq, int module, int mode) { + if (rrt5XmlLoadStatus == EVENT_RRT_SCAN_START) { + Log.d(TAG, "abandon updateRRTRes,becasue current status is : " + rrt5XmlLoadStatus); + return -1; + } + Log.d(TAG, "updateRRTRes,freq: " + freq+",module:"+module+",mode:"+mode); + int val[] = new int[]{freq, module, mode}; + rrt5XmlLoadStatus = EVENT_RRT_SCAN_START; + return sendCmdIntArray(DTV_UPDATE_RRT, val); + } + + public class RrtSearchInfo { + public String rating_region_name; + public String dimensions_name; + public String rating_value_text; + } + + public RrtSearchInfo SearchRrtInfo(int rating_region_id, int dimension_id, int value_id) { + Parcel cmd = Parcel.obtain(); + Parcel r = Parcel.obtain(); + Log.d(TAG, "rating_region_id: " + rating_region_id); + Log.d(TAG, "dimension_id: " + dimension_id); + Log.d(TAG, "value_id: " + value_id); + cmd.writeInt(DTV_SEARCH_RRT); + cmd.writeInt(rating_region_id); + cmd.writeInt(dimension_id); + cmd.writeInt(value_id); + sendCmdToTv(cmd, r); + + RrtSearchInfo tmpRet = new RrtSearchInfo(); + int cnt = r.readInt(); + if (cnt != 0) { + tmpRet.dimensions_name = r.readString(); + } + + cnt = r.readInt(); + if (cnt != 0) { + tmpRet.rating_region_name = r.readString(); + } + + cnt = r.readInt(); + if (cnt != 0) { + tmpRet.rating_value_text = r.readString(); + } + cmd.recycle(); + r.recycle(); + + Log.d(TAG, "rating_region_name: " + tmpRet.dimensions_name); + Log.d(TAG, "dimensions_name: " + tmpRet.rating_region_name); + Log.d(TAG, "rating_value_text: " + tmpRet.rating_value_text); + return tmpRet; + } + + public void setEasListener(EasEventListener l) { + mEasListener = l; + } + public interface EasEventListener { + void processDetailsChannelAlert(EasEvent ev); + } + public class VFrameEvent{ public int FrameNum; public int FrameSize; @@ -5427,6 +5625,7 @@ public class TvControlManager { public class FreqList { public int ID; public int freq; + public int channelNum; } /** @@ -6153,6 +6352,10 @@ public class TvControlManager { public final static int EVENT_AV_SCRAMBLED = 3; public final static int EVENT_AV_UNSUPPORT = 4; public final static int EVENT_AV_VIDEO_AVAILABLE = 5; + public final static int EVENT_AV_TIMESHIFT_REC_FAIL = 6; + public final static int EVENT_AV_TIMESHIFT_PLAY_FAIL = 7; + public final static int EVENT_AV_TIMESHIFT_START_TIME_CHANGED = 8; + public final static int EVENT_AV_TIMESHIFT_CURRENT_TIME_CHANGED = 9; public final static int AUDIO_UNMUTE_FOR_TV = 0; public final static int AUDIO_MUTE_FOR_TV = 1; @@ -6473,5 +6676,87 @@ public class TvControlManager { r.recycle(); return ret; } + + // frontend event + public class RecorderEvent { + //frontend events + public static final int EVENT_RECORDER_START = 1; + public static final int EVENT_RECORDER_STOP = 2; + + public int Status; + public int Error; + public String Id; + } + public interface RecorderEventListener { + void onRecoderEvent(RecorderEvent ev); + }; + + private RecorderEventListener mRecorderEventListener = null; + public void SetRecorderEventListener(RecorderEventListener l) { + libtv_log_open(); + mRecorderEventListener = l; + } + + + public static final int RECORDING_CMD_STOP = 0; + public static final int RECORDING_CMD_PREPARE = 1; + public static final int RECORDING_CMD_START = 2; + + public int sendRecordingCmd(int cmd, String id, String param) { + String para[] = new String[]{id, param}; + return sendCmdStringArray(DTV_RECORDING_CMD, cmd, para); + } + + public int prepareRecording(String id, String param) { + return sendRecordingCmd(RECORDING_CMD_PREPARE, id, param); + } + + public int startRecording(String id, String param) { + return sendRecordingCmd(RECORDING_CMD_START, id, param); + } + + public int stopRecording(String id, String param) { + return sendRecordingCmd(RECORDING_CMD_STOP, id, param); + } + + public static final int PLAY_CMD_STOP = 0; + public static final int PLAY_CMD_START = 1; + public static final int PLAY_CMD_PAUSE = 2; + public static final int PLAY_CMD_RESUME = 3; + public static final int PLAY_CMD_SEEK = 4; + public static final int PLAY_CMD_SETPARAM = 5; + + public int sendPlayCmd(int cmd, String id, String param) { + String para[] = new String[]{id, param}; + return sendCmdStringArray(DTV_PLAY_CMD, cmd, para); + } + + public int startPlay(String id, String param) { + //SystemProperties.set ("media.audio.enable_asso", (adPrepare)? "1" : "0"); + //SystemProperties.set ("media.audio.mix_asso", String.valueOf(adMixingLevel)); + return sendPlayCmd(PLAY_CMD_START, id, param); + } + + public int stopPlay(String id, String param) { + return sendPlayCmd(PLAY_CMD_STOP, id, param); + } + + public int pausePlay(String id) { + return sendPlayCmd(PLAY_CMD_PAUSE, id, null); + } + + public int resumePlay(String id) { + return sendPlayCmd(PLAY_CMD_RESUME, id, null); + } + + public int seekPlay(String id, String param) { + return sendPlayCmd(PLAY_CMD_SEEK, id, param); + } + + public int setPlayParam(String id, String param) { + return sendPlayCmd(PLAY_CMD_SETPARAM, id, param); + } + + } diff --git a/core/java/com/droidlogic/app/tv/TvDataBaseManager.java b/core/java/com/droidlogic/app/tv/TvDataBaseManager.java index 193281b..b8ee7d7 100644 --- a/core/java/com/droidlogic/app/tv/TvDataBaseManager.java +++ b/core/java/com/droidlogic/app/tv/TvDataBaseManager.java @@ -32,6 +32,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Arrays; +import java.util.Objects; import com.droidlogic.app.tv.DroidLogicTvUtils.*; @@ -426,6 +427,10 @@ public class TvDataBaseManager { map.put(ChannelInfo.KEY_ACCESS_CONTROL, String.valueOf(channel.getAccessControled())); map.put(ChannelInfo.KEY_HIDDEN, String.valueOf(channel.getHidden())); map.put(ChannelInfo.KEY_HIDE_GUIDE, String.valueOf(channel.getHideGuide())); + map.put(ChannelInfo.KEY_CONTENT_RATINGS, DroidLogicTvUtils.TvString.toString(channel.getContentRatings())); + map.put(ChannelInfo.KEY_SIGNAL_TYPE, DroidLogicTvUtils.TvString.toString(channel.getSignalType())); + map.put(ChannelInfo.KEY_VCT, "\""+channel.getVct()+"\""); + map.put(ChannelInfo.KEY_EITV, Arrays.toString(channel.getEitVersions())); String output = DroidLogicTvUtils.mapToJson(map); values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, output); @@ -474,6 +479,7 @@ public class TvDataBaseManager { map.put(ChannelInfo.KEY_AUDIO_EXTS, Arrays.toString(channel.getAudioExts())); map.put(ChannelInfo.KEY_AUDIO_LANGS, DroidLogicTvUtils.TvString.toString(channel.getAudioLangs())); map.put(ChannelInfo.KEY_AUDIO_TRACK_INDEX, String.valueOf(channel.getAudioTrackIndex())); + map.put(ChannelInfo.KEY_AUDIO_OUTPUT_MODE, String.valueOf(channel.getAudioOutPutMode())); map.put(ChannelInfo.KEY_AUDIO_CHANNEL, String.valueOf(channel.getAudioChannel())); map.put(ChannelInfo.KEY_SUBT_TYPES, Arrays.toString(channel.getSubtitleTypes())); map.put(ChannelInfo.KEY_SUBT_PIDS, Arrays.toString(channel.getSubtitlePids())); @@ -482,6 +488,8 @@ public class TvDataBaseManager { map.put(ChannelInfo.KEY_SUBT_ID2S, Arrays.toString(channel.getSubtitleId2s())); map.put(ChannelInfo.KEY_SUBT_LANGS, DroidLogicTvUtils.TvString.toString(channel.getSubtitleLangs())); map.put(ChannelInfo.KEY_SUBT_TRACK_INDEX, String.valueOf(channel.getSubtitleTrackIndex())); + map.put(ChannelInfo.KEY_CONTENT_RATINGS, DroidLogicTvUtils.TvString.toString(channel.getContentRatings())); + map.put(ChannelInfo.KEY_SIGNAL_TYPE, DroidLogicTvUtils.TvString.toString(channel.getSignalType())); return map; } @@ -746,6 +754,125 @@ public class TvDataBaseManager { } } + public void updateOrinsertChannelInList(ArrayList<ChannelInfo> updatelist, ArrayList<ChannelInfo> insertlist, boolean isdtv) { + ArrayList<ContentProviderOperation> ops = new ArrayList<>(); + for (ChannelInfo one : updatelist) { + long id = one.getId(); + if (id == -1) { + id = queryChannelIdInDb(one); + Log.d(TAG, "updateOrinsertChannelInList find id = " + id); + } + if (id < 0) { + ops.add(creatOperation(isdtv, false, id, one)); + } else { + ops.add(creatOperation(isdtv, true, id, one)); + } + Log.d(TAG, "updateOrinsertChannelInList add update = " + one.getDisplayNumber()); + } + for (ChannelInfo one : insertlist) { + ops.add(creatOperation(isdtv, false, -1, one)); + Log.d(TAG, "updateOrinsertChannelInList add insert = " + one.getDisplayNumber()); + } + try { + mContentResolver.applyBatch(TvContract.AUTHORITY, ops); + } catch (RemoteException | OperationApplicationException e) { + Log.e(TAG, "updateOrinsertChannelInList Failed = " + e.getMessage()); + } + ops.clear(); + } + + private ContentProviderOperation creatOperation(boolean isdtv, boolean isupdate, long id, ChannelInfo ch) { + if (isdtv) { + if (isupdate) { + return ContentProviderOperation.newUpdate( + TvContract.buildChannelUri(id)) + .withValues(buildDtvChannelData(ch)) + .build(); + } else { + return ContentProviderOperation.newInsert( + TvContract.Channels.CONTENT_URI) + .withValues(buildDtvChannelData(ch)) + .build(); + } + } else { + if (isupdate) { + return ContentProviderOperation.newUpdate( + TvContract.buildChannelUri(id)) + .withValues(buildAtvChannelData(ch)) + .build(); + } else { + return ContentProviderOperation.newInsert( + TvContract.Channels.CONTENT_URI) + .withValues(buildAtvChannelData(ch)) + .build(); + } + } + } + + public long queryChannelIdInDb(ChannelInfo channel) { + long id = -1;//-1 means not init; -2 means not exist + if (channel != null) { + id = channel.getId(); + if (id > -1) { + return id; + } + } else { + return id; + } + Uri channelsUri = TvContract.buildChannelsUriForInput(channel.getInputId()); + String[] projection = {Channels._ID, + Channels.COLUMN_SERVICE_ID, + Channels.COLUMN_ORIGINAL_NETWORK_ID, + Channels.COLUMN_TRANSPORT_STREAM_ID, + Channels.COLUMN_DISPLAY_NUMBER, + Channels.COLUMN_DISPLAY_NAME, + Channels.COLUMN_INTERNAL_PROVIDER_DATA}; + + Cursor cursor = null; + try { + boolean found = false; + cursor = mContentResolver.query(channelsUri, projection, Channels.COLUMN_SERVICE_TYPE + "=?", new String[]{channel.getServiceType()}, null); + while (cursor != null && cursor.moveToNext()) { + long rowId = cursor.getLong(findPosition(projection, Channels._ID)); + + if (channel.getId() == -1) { + int serviceId = cursor.getInt(findPosition(projection, Channels.COLUMN_SERVICE_ID)); + int originalNetworkId = cursor.getInt(findPosition(projection, Channels.COLUMN_ORIGINAL_NETWORK_ID)); + int transportStreamId = cursor.getInt(findPosition(projection, Channels.COLUMN_TRANSPORT_STREAM_ID)); + String name = cursor.getString(findPosition(projection, Channels.COLUMN_DISPLAY_NAME)); + int frequency = 0; + int index = cursor.getColumnIndex(Channels.COLUMN_INTERNAL_PROVIDER_DATA); + if (index >= 0) { + Map<String, String> parsedMap = DroidLogicTvUtils.jsonToMap(cursor.getString(index)); + frequency = Integer.parseInt(parsedMap.get(ChannelInfo.KEY_FREQUENCY)); + } + if ((serviceId == channel.getServiceId() + && originalNetworkId == channel.getOriginalNetworkId() + && transportStreamId == channel.getTransportStreamId() + && frequency == channel.getFrequency() + && TextUtils.equals(name, channel.getDisplayName())) || (channel.isAnalogChannel() && frequency == channel.getFrequency())) + found = true; + } + + if (found) { + id = rowId; + return id; + } + } + if (id == -1) + return -2; + } catch (Exception e) { + //TODO + Log.e(TAG, "queryChannelIdInDb Failed = " + e.getMessage()); + e.printStackTrace(); + } finally { + if (cursor != null) { + cursor.close(); + } + } + return -1; + } + // If a channel exists, update it. If not, insert a new one. public void updateOrinsertAtvChannel(ChannelInfo channel) { int updateRet = updateAtvChannel(channel); @@ -1123,7 +1250,7 @@ public class TvDataBaseManager { private static final int BATCH_OPERATION_COUNT = 100; - private boolean isATSCSpecialProgram(Program program) { + private static boolean isATSCSpecialProgram(Program program) { //If program's startTime == EndTime == 0, //it is a special program for descr update in atsc. return program.getStartTimeUtcMillis() == 0 @@ -1141,16 +1268,115 @@ public class TvDataBaseManager { * information. */ public void updatePrograms(Uri channelUri, List<Program> newPrograms) { - updatePrograms(channelUri, newPrograms, false); + updatePrograms(channelUri, newPrograms, null, false); + } + + public static final class ComparatorValues implements Comparator<Program> { + @Override + public int compare(Program object1, Program object2) { + long m1 = object1.getStartTimeUtcMillis(); + long m2 = object2.getStartTimeUtcMillis(); + int result = 0; + if (m1 > m2) + { + result = 1; + } + if (m1 < m2) + { + result=-1; + } + return result; + } } - public void updatePrograms(Uri channelUri, List<Program> newPrograms, boolean isAtsc) { + public boolean isProgramAtTime(Program program, Long timeUtcMillis) { + return (timeUtcMillis != null + && timeUtcMillis >= program.getStartTimeUtcMillis() + && timeUtcMillis < program.getEndTimeUtcMillis()); + } + + public boolean updatePrograms(Long channelId, List<Program> newPrograms, Long timeUtcMillis) { + boolean updated = false; + Log.d(TAG, "updatePrograms epg start-----"); + for (Program p: newPrograms) { + String sql_start ; + Program oldProgram = null; + String sql_query ; + Cursor cursor ; + Log.d(TAG, "updatePrograms epg title:"+p.getTitle()+" des:"+p.getDescription()+" chid:"+p.getChannelId()+" id:"+p.getId()+" start:" + p.getStartTimeUtcMillis() + " end:" + p.getEndTimeUtcMillis()); + if (isATSCSpecialProgram(p)) + { + // if (true) + // continue; + //sql_query = "(_id=" + p.getId() + ")"; + sql_query = "(" + TvContract.Programs.COLUMN_CHANNEL_ID + "=" + channelId + ") AND ("+ TvContract.Programs.COLUMN_INTERNAL_PROVIDER_FLAG2 +"=" + p.getProgramId() + ")"; + cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, null, sql_query, null, null); + if (cursor != null && cursor.getCount() != 0) { + cursor.moveToNext(); + oldProgram = Program.fromCursor(cursor); + } + if (cursor != null) { + cursor.close(); + } + if (oldProgram != null && !TextUtils.equals(p.getDescription(), oldProgram.getDescription())) + { + ContentValues vals = new ContentValues(); + vals.put(TvContract.Programs.COLUMN_SHORT_DESCRIPTION, p.getDescription()); + Log.d(TAG, "updatePrograms sql sql_query:" + sql_query); + mContentResolver.update(TvContract.Programs.CONTENT_URI, vals, sql_query, null); + } + else + { + Log.d(TAG, "updatePrograms isATSCSpecialProgram true"); + } + } + else + { + sql_start = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "=" + p.getStartTimeUtcMillis() + " AND " + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + " = " +p.getEndTimeUtcMillis(); + oldProgram = null; + sql_query = "(" + TvContract.Programs.COLUMN_CHANNEL_ID + "=" + channelId + ") AND (" + sql_start + ")"; + cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, null, sql_query, null, null); + if (cursor != null && cursor.getCount() != 0) { + cursor.moveToNext(); + oldProgram = Program.fromCursor(cursor); + } + if (cursor != null) { + cursor.close(); + } + if (oldProgram == null || !isProgramEq(oldProgram, p)) + { + sql_start = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=" + p.getStartTimeUtcMillis() + " AND " + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + " > " +p.getStartTimeUtcMillis(); + String sql_end = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=" + p.getEndTimeUtcMillis() + " AND " + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + " > " +p.getEndTimeUtcMillis(); + String sql_del = "(" + TvContract.Programs.COLUMN_CHANNEL_ID + "=" + channelId + ") AND ((" + sql_start + ") OR (" + sql_end + "))"; + if (oldProgram == null) { + Log.d(TAG, "updatePrograms oldProgram is null insert sql:" + sql_del); + } else { + Log.d(TAG, "updatePrograms not eq insert sql:" + sql_del); + } + mContentResolver.delete(TvContract.Programs.CONTENT_URI, sql_del, null); + mContentResolver.insert(TvContract.Programs.CONTENT_URI, p.toContentValues()); + updated = isProgramAtTime(p, timeUtcMillis); + } + else + { + Log.d(TAG, "updatePrograms no insert true"); + } + } + } + Log.d(TAG, "updatePrograms epg end-----"); + return updated; + } + public boolean updatePrograms(Uri channelUri, List<Program> newPrograms, Long timeUtcMillis, boolean isAtsc) { + boolean updated = false; final int fetchedProgramsCount = newPrograms.size(); if (fetchedProgramsCount == 0) { - return; + return updated; } List<Program> oldPrograms = getPrograms(TvContract.buildProgramsUriForChannel(channelUri)); + Collections.sort(newPrograms, new ComparatorValues()); + Collections.sort(oldPrograms, new ComparatorValues()); + //Log.d(TAG, "updatePrograms sort programs "); Program firstNewProgram = null; for (Program program : newPrograms) { if (isAtsc && !isATSCSpecialProgram(program)) { @@ -1159,6 +1385,10 @@ public class TvDataBaseManager { } } +// for (Program p : newPrograms) { +// Log.d(TAG, "epg todo:cid("+p.getChannelId()+")eid("+p.getProgramId()+")desc("+p.getTitle()+")desc2("+p.getDescription()+")time("+p.getStartTimeUtcMillis()+"-"+p.getEndTimeUtcMillis()+")"); +// } + int oldProgramsIndex = 0; int newProgramsIndex = 0; @@ -1186,7 +1416,7 @@ public class TvDataBaseManager { //Log.d(TAG, "ext desr:"+newProgram.getProgramId()); for (Program program : oldPrograms) { //Log.d(TAG, "old:"+program.getProgramId()); - if (program.getProgramId() == newProgram.getProgramId()) { + if (program.getProgramId() == newProgram.getProgramId()) {//same event id if (TextUtils.equals(program.getDescription(), newProgram.getDescription())) break; program.setDescription(newProgram.getDescription()); @@ -1194,7 +1424,15 @@ public class TvDataBaseManager { TvContract.buildProgramUri(program.getId())) .withValues(program.toContentValues()) .build()); - Log.d(TAG, "\tupdate descr"); + /*Program p = new Program.Builder(program) + .build(); + ops.add(ContentProviderOperation.newInsert(TvContract.Programs.CONTENT_URI) + .withValues(p.toContentValues()) + .build()); + ops.add(ContentProviderOperation.newDelete(TvContract.buildProgramUri(program.getId())) + .build()); + */ + //Log.d(TAG, "\tepg etm:cid("+program.getChannelId()+")eid("+program.getProgramId()+")"); break; } } @@ -1204,40 +1442,52 @@ public class TvDataBaseManager { // Exact match. No need to update. Move on to the next programs. oldProgramsIndex++; newProgramsIndex++; - Log.d(TAG, "\tmatch"); + //Log.d(TAG, "\tepg match:cid("+newProgram.getChannelId()+")eid("+newProgram.getProgramId()+")desc("+newProgram.getTitle()+")time("+newProgram.getStartTimeUtcMillis()+"-"+newProgram.getEndTimeUtcMillis()+")"); } else if (needsUpdate(oldProgram, newProgram)) { // Partial match. Update the old program with the new one. // NOTE: Use 'update' in this case instead of 'insert' and 'delete'. There could // be application specific settings which belong to the old program. ops.add(ContentProviderOperation.newUpdate( - TvContract.buildProgramUri(oldProgram.getProgramId())) + TvContract.buildProgramUri(oldProgram.getId())) .withValues(newProgram.toContentValues()) .build()); oldProgramsIndex++; newProgramsIndex++; - Log.d(TAG, "\tupdate"); + + updated = isProgramAtTime(newProgram, timeUtcMillis); + + Log.d(TAG, "\tepg update:cid("+newProgram.getChannelId()+")eid("+newProgram.getProgramId()+")desc("+newProgram.getTitle()+")time("+newProgram.getStartTimeUtcMillis()+"-"+newProgram.getEndTimeUtcMillis()+")id("+oldProgram.getId()+")"); } else if (oldProgram.getEndTimeUtcMillis() < newProgram.getEndTimeUtcMillis()) { // No match. Remove the old program first to see if the next program in // {@code oldPrograms} partially matches the new program. ops.add(ContentProviderOperation.newDelete( - TvContract.buildProgramUri(oldProgram.getProgramId())) + TvContract.buildProgramUri(oldProgram.getId())) .build()); oldProgramsIndex++; - Log.d(TAG, "\tdelete old"); + + updated = isProgramAtTime(oldProgram, timeUtcMillis); + + Log.d(TAG, "\tepg delete:"+oldProgram.getId()+":cid("+oldProgram.getChannelId()+")eid("+oldProgram.getProgramId()+")desc("+oldProgram.getTitle()+")time("+oldProgram.getStartTimeUtcMillis()+"-"+oldProgram.getEndTimeUtcMillis()+")"); } else { if (!isATSCSpecialProgram(newProgram)) { // No match. The new program does not match any of the old programs. Insert it // as a new program. addNewProgram = true; newProgramsIndex++; - Log.d(TAG, "\tnew insert"); + + updated = isProgramAtTime(newProgram, timeUtcMillis); + + Log.d(TAG, "\tepg new:cid("+newProgram.getChannelId()+")eid("+newProgram.getProgramId()+")desc("+newProgram.getTitle()+")time("+newProgram.getStartTimeUtcMillis()+"-"+newProgram.getEndTimeUtcMillis()+")id("+newProgram.getId()+")"); } } } else { if (!isATSCSpecialProgram(newProgram)) { // No old programs. Just insert new programs. addNewProgram = true; - Log.d(TAG, "no old, insert new"); + + updated = isProgramAtTime(newProgram, timeUtcMillis); + + Log.d(TAG, "\tepg new:(old none):cid("+newProgram.getChannelId()+")eid("+newProgram.getProgramId()+")desc("+newProgram.getTitle()+")time("+newProgram.getStartTimeUtcMillis()+"-"+newProgram.getEndTimeUtcMillis()+")id("+newProgram.getId()+")"); } newProgramsIndex++; } @@ -1256,11 +1506,12 @@ public class TvDataBaseManager { mContentResolver.applyBatch(TvContract.AUTHORITY, ops); } catch (RemoteException | OperationApplicationException e) { Log.e(TAG, "Failed to insert programs.", e); - return; + return updated; } ops.clear(); } } + return updated; } public void updateProgram(Program program) { @@ -1271,6 +1522,32 @@ public class TvDataBaseManager { * Returns {@code true} if the {@code oldProgram} program needs to be updated with the * {@code newProgram} program. */ + private static boolean isProgramEq(Program oldProgram, Program newProgram) { + // NOTE: Here, we update the old program if it has the same title and overlaps with the new + // program. The test logic is just an example and you can modify this. E.g. check whether + // the both programs have the same program ID if your EPG supports any ID for the programs. + if (oldProgram.getTitle() == null || oldProgram.getTitle().isEmpty()) { + Log.d(TAG, "getTitle is null"); + return false; + } else if (!oldProgram.getTitle().equals(newProgram.getTitle())) { + Log.d(TAG, "getTitle is not eq"); + return false; + } else if (oldProgram.getDescription() == null && newProgram.getDescription() != null) { + Log.d(TAG, "getDescription is old is null new not null"); + return false; + } else if (!Objects.equals(Program.contentRatingsToString(oldProgram.getContentRatings()), + Program.contentRatingsToString(newProgram.getContentRatings()))) { + Log.d(TAG, "ratings not eq"); + return false; + } else { + Log.d(TAG, "isProgramEq is eq true"); + return true; + } + } + /** + * Returns {@code true} if the {@code oldProgram} program needs to be updated with the + * {@code newProgram} program. + */ private static boolean needsUpdate(Program oldProgram, Program newProgram) { // NOTE: Here, we update the old program if it has the same title and overlaps with the new // program. The test logic is just an example and you can modify this. E.g. check whether @@ -1373,4 +1650,44 @@ public class TvDataBaseManager { return program; } + + public int deleteProgram(ChannelInfo channel) { + return deleteProgram(channel.getId()); + } + + public int deleteProgram(Long channelId) { + int deleteCount = mContentResolver.delete( + TvContract.Programs.CONTENT_URI, + TvContract.Programs.COLUMN_CHANNEL_ID + "=?", + new String[] { String.valueOf(channelId)}); + if (deleteCount > 0) { + Log.d(TAG, "Deleted " + deleteCount + " programs"); + } + return deleteCount; + } + + public int deleteProgram(Long channelId, String versionNotEqual, String eitExt) { + int deleteCount = mContentResolver.delete( + TvContract.Programs.CONTENT_URI, + TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " + + TvContract.Programs.COLUMN_VERSION_NUMBER + "!=? AND " + + TvContract.Programs.COLUMN_INTERNAL_PROVIDER_FLAG3 + "=?", + new String[] { String.valueOf(channelId), versionNotEqual, eitExt}); + if (deleteCount > 0) { + Log.d(TAG, "Deleted " + deleteCount + " programs"); + } + return deleteCount; + } + + public int deletePrograms(Long channelId, String versionNotEqual) { + int deleteCount = mContentResolver.delete( + TvContract.Programs.CONTENT_URI, + TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " + + TvContract.Programs.COLUMN_VERSION_NUMBER + "!=?", + new String[] { String.valueOf(channelId), versionNotEqual}); + if (deleteCount > 0) { + Log.d(TAG, "Deleted " + deleteCount + " programs"); + } + return deleteCount; + } } diff --git a/core/java/com/droidlogic/app/tv/TvInputBaseSession.java b/core/java/com/droidlogic/app/tv/TvInputBaseSession.java index 0993620..f28af29 100644 --- a/core/java/com/droidlogic/app/tv/TvInputBaseSession.java +++ b/core/java/com/droidlogic/app/tv/TvInputBaseSession.java @@ -46,6 +46,9 @@ public abstract class TvInputBaseSession extends TvInputService.Session implemen private TvControlManager mTvControlManager; protected DroidLogicOverlayView mOverlayView = null; + protected boolean isBlockNoRatingEnable = false; + protected boolean isUnlockCurrent_NR = false; + public TvInputBaseSession(Context context, String inputId, int deviceId) { super(context); mContext = context; @@ -54,6 +57,10 @@ public abstract class TvInputBaseSession extends TvInputService.Session implemen mTvControlManager = TvControlManager.getInstance(); mSessionHandler = new Handler(context.getMainLooper(), this); + int block_norating = Settings.System.getInt(mContext.getContentResolver(), DroidLogicTvUtils.BLOCK_NORATING, 0); + isBlockNoRatingEnable = block_norating == 0 ? false : true; + if (DEBUG) + Log.d(TAG, "isBlockNoRatingEnable = " + isBlockNoRatingEnable); } public void setSessionId(int id) { @@ -74,7 +81,7 @@ public abstract class TvInputBaseSession extends TvInputService.Session implemen public void doRelease() { Log.d(TAG, "doRelease"); - setAudiodMute(false); + //setAudiodMute(false); setOverlayViewEnabled(false); if (mOverlayView != null) { mOverlayView.releaseResource(); @@ -158,12 +165,10 @@ public abstract class TvInputBaseSession extends TvInputService.Session implemen @Override public void notifyVideoUnavailable(int reason) { Log.d(TAG, "notifyVideoUnavailable: "+reason); + super.notifyVideoUnavailable(reason); if (mOverlayView != null) { - super.notifyVideoAvailable(); mOverlayView.setImageVisibility(true); mOverlayView.setTextVisibility(false); - } else { - super.notifyVideoUnavailable(reason); } } @@ -171,18 +176,17 @@ public abstract class TvInputBaseSession extends TvInputService.Session implemen if (mOverlayView != null) { mOverlayView.setImageVisibility(false); mOverlayView.setTextVisibility(false); + mOverlayView.setSubtitleVisibility(false); } } private void setAudiodMute(boolean mute) { if (mute) { - SystemProperties.set("persist.sys.tvview.blocked", "true"); - mTvControlManager.SetAudioMuteForTv(TvControlManager.AUDIO_MUTE_FOR_TV); - mTvControlManager.SetAudioMuteKeyStatus(TvControlManager.AUDIO_MUTE_FOR_TV); + //SystemProperties.set("persist.sys.tvview.blocked", "true"); + mTvControlManager.setAmAudioPreMute(TvControlManager.AUDIO_MUTE_FOR_TV); } else { - SystemProperties.set("persist.sys.tvview.blocked", "false"); - mTvControlManager.SetAudioMuteForTv(TvControlManager.AUDIO_UNMUTE_FOR_TV); - mTvControlManager.SetAudioMuteKeyStatus(TvControlManager.AUDIO_UNMUTE_FOR_TV); + //SystemProperties.set("persist.sys.tvview.blocked", "false"); + mTvControlManager.setAmAudioPreMute(TvControlManager.AUDIO_UNMUTE_FOR_TV); } } diff --git a/core/java/com/droidlogic/app/tv/TvStoreManager.java b/core/java/com/droidlogic/app/tv/TvStoreManager.java index 7f4c315..155923d 100644 --- a/core/java/com/droidlogic/app/tv/TvStoreManager.java +++ b/core/java/com/droidlogic/app/tv/TvStoreManager.java @@ -9,8 +9,15 @@ import android.util.Log; import android.os.Bundle; import android.content.Context; import android.media.tv.TvContract; -import android.provider.Settings; - +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.os.SystemProperties; +import android.os.HandlerThread; + +import com.droidlogic.app.tv.TvControlManager; +import com.droidlogic.app.tv.TvControlManager.FreqList; +import com.droidlogic.app.tv.TvControlManager.TvMode; public abstract class TvStoreManager { public static final String TAG = "TvStoreManager"; @@ -26,16 +33,24 @@ public abstract class TvStoreManager { private TvControlManager.ScanMode mScanMode = null; private TvControlManager.SortMode mSortMode = null; - + private TvControlManager mTvControlManager = null; private ArrayList<TvControlManager.ScannerLcnInfo> mLcnInfo = null; /*for store in search*/ private boolean isFinalStoreStage = false; private boolean isRealtimeStore = true; - + private HandlerThread mhandlerThread; + private Handler mChildHandler; private ArrayList<ChannelInfo> mChannelsOld = null; private ArrayList<ChannelInfo> mChannelsNew = null; + private ArrayList<ChannelInfo> mChannelsExist = null; + private ArrayList<ChannelInfo> mChannelsAll = null; + + private ArrayList<FreqList> mATSC_T = null; + private ArrayList<FreqList> mATSC_C_STD = null; + private ArrayList<FreqList> mATSC_C_LRC = null; + private ArrayList<FreqList> mATSC_HRC = null; private boolean on_channel_store_tschanged = true; @@ -51,9 +66,12 @@ public abstract class TvStoreManager { mInitialLcnNumber = mInitialDisplayNumber; mTvDataBaseManager = new TvDataBaseManager(mContext); - + mTvControlManager = TvControlManager.getInstance(); display_number_start = mInitialDisplayNumber; lcn_overflow_start = mInitialLcnNumber; + mhandlerThread = new HandlerThread("dealevent"); + mhandlerThread.start(); + mChildHandler = new Handler(mhandlerThread.getLooper(), new ChildCallback()); } public void setInitialLcnNumber(int initialLcnNumber) { @@ -69,8 +87,9 @@ public abstract class TvStoreManager { public abstract void onScanEnd(); - public void onScanExit() {} + public void onScanExit(int freg) {} + public void onScanEndBeforeStore(int freg) {} private Bundle getScanEventBundle(TvControlManager.ScannerEvent mEvent) { Bundle bundle = new Bundle(); @@ -162,8 +181,20 @@ public abstract class TvStoreManager { mChannelsOld.addAll(mTvDataBaseManager.getChannelList(mInputId, TvContract.Channels.SERVICE_TYPE_OTHER)); Log.d(TAG, "Store> channel next:" + mDisplayNumber); } + if (mChannelsAll == null) { + mChannelsAll = new ArrayList<ChannelInfo>(); + } + } + private void reinitChannels() { + if (mChannelsExist == null) { + mChannelsExist = mTvDataBaseManager.getChannelList(mInputId, TvContract.Channels.SERVICE_TYPE_AUDIO_VIDEO); + mChannelsExist.addAll(mTvDataBaseManager.getChannelList(mInputId, TvContract.Channels.SERVICE_TYPE_AUDIO)); + mChannelsExist.addAll(mTvDataBaseManager.getChannelList(mInputId, TvContract.Channels.SERVICE_TYPE_OTHER)); + } + if (mChannelsAll == null) { + mChannelsAll = new ArrayList<ChannelInfo>(); + } } - private ChannelInfo createDtvChannelInfo(TvControlManager.ScannerEvent event) { String name = null; String serviceType; @@ -237,6 +268,9 @@ public abstract class TvStoreManager { .setAccessControled(event.accessControlled) .setHidden(event.hidden) .setHideGuide(event.hideGuide) + .setVct(event.vct) + .setSignalType(DroidLogicTvUtils.getCurrentSignalType(mContext) == DroidLogicTvUtils.SIGNAL_TYPE_ERROR + ? TvContract.Channels.TYPE_ATSC_T : DroidLogicTvUtils.getCurrentSignalType(mContext)) .build(); } @@ -313,6 +347,9 @@ public abstract class TvStoreManager { .setAccessControled(event.accessControlled) .setHidden(event.hidden) .setHideGuide(event.hideGuide) + .setContentRatings(null) + .setSignalType(DroidLogicTvUtils.getCurrentSignalType(mContext) == DroidLogicTvUtils.SIGNAL_TYPE_ERROR + ? TvContract.Channels.TYPE_ATSC_T : DroidLogicTvUtils.getCurrentSignalType(mContext)) .build(); } @@ -339,9 +376,14 @@ public abstract class TvStoreManager { if (mChannelsNew == null) mChannelsNew = new ArrayList(); - mChannelsNew.add(channel); + //not add the same channel + int newindex = dealRepeatCacheChannels(channel); + if (newindex > -1) { + channel = mChannelsNew.get(newindex); + Log.d(TAG, "cacheChannel update id = " + channel.getId()); + } - Log.d(TAG, "store save [" + channel.getDisplayNumber() + "][" + channel.getFrequency() + "][" + channel.getServiceType() + "][" + channel.getDisplayName() + "]"); + Log.d(TAG, "store save [" + channel.getDisplayNumber() + "][" + channel.getFrequency() + "][" + channel.getServiceType() + "][" + channel.getDisplayName() + "][" + channel.getId() + "]"); if (mScanMode.isDTVManulScan() || mScanMode.isATVManualScan()) { if (on_channel_store_tschanged) { @@ -351,6 +393,53 @@ public abstract class TvStoreManager { } } + private int dealRepeatCacheChannels(ChannelInfo ch) { + if (ch == null) { + return -1; + } + boolean hasaddtoall = false; + for (int j = 0; j < mChannelsAll.size(); j++) { + ChannelInfo tempch = mChannelsAll.get(j); + if (tempch != null && tempch.isSameChannel(ch)) { + if (tempch.getId() < 0) { + long id = mTvDataBaseManager.queryChannelIdInDb(tempch); + if (id > -1) { + ch.setId(id); + } + } else { + ch.setId(tempch.getId()); + } + + mChannelsAll.remove(j); + mChannelsAll.add(j, ch); + hasaddtoall = true; + Log.d(TAG, "dealRepeatCacheChannels exist in all = " + mChannelsAll.get(j).getDisplayNumber() + ", id = " + mChannelsAll.get(j).getId() + ", type = " + mChannelsAll.get(j).getType()); + if (ch.isAnalogChannel() || ch.isAtscChannel()) { + return -1;//atsc and analog channel don't need to cache the same channel as dtmb channel DisplayNumber may change + } + } + } + if (!hasaddtoall) { + mChannelsAll.add(ch); + Log.d(TAG, "dealRepeatCacheChannels not exist in all = " + ch.getDisplayNumber()); + } + boolean hasaddtonew = false; + for (int i = 0; i < mChannelsNew.size(); i++) { + ChannelInfo tempch = mChannelsNew.get(i); + if (tempch != null && tempch.isSameChannel(ch)) { + Log.d(TAG, "dealRepeatCacheChannels exist in new = " + tempch.getDisplayNumber()); + mChannelsNew.remove(i); + mChannelsNew.add(i, ch); + hasaddtonew = true; + return i; + } + } + if (!hasaddtonew) { + mChannelsNew.add(ch); + Log.d(TAG, "dealRepeatCacheChannels not exist in new = " + ch.getDisplayNumber()); + } + return mChannelsNew.size() -1; + } private boolean isChannelInListbyId(ChannelInfo channel, ArrayList<ChannelInfo> list) { if (list == null) @@ -569,6 +658,12 @@ public abstract class TvStoreManager { private void storeTvChannel(boolean isRealtimeStore, boolean isFinalStore) { Bundle bundle = null; + ArrayList<ChannelInfo> dtvchannelsnew= new ArrayList<ChannelInfo>(); + ArrayList<ChannelInfo> atvchannelsnew= new ArrayList<ChannelInfo>(); + ArrayList<ChannelInfo> dtvchannelsinsert; + ArrayList<ChannelInfo> dtvchannelsupdate; + ArrayList<ChannelInfo> atvchannelsinsert; + ArrayList<ChannelInfo> atvchannelsupdate; Log.d(TAG, "isRealtimeStore:" + isRealtimeStore + " isFinalStore:"+ isFinalStore); @@ -610,10 +705,13 @@ public abstract class TvStoreManager { } if (isRealtimeStore) { - if (c.isAnalogChannel()) - mTvDataBaseManager.updateOrinsertAtvChannelWithNumber(c); - else - mTvDataBaseManager.updateOrinsertDtvChannelWithNumber(c); + if (c.isAnalogChannel()) { + //mTvDataBaseManager.updateOrinsertAtvChannelWithNumber(c); + atvchannelsnew.add(c); + } else { + //mTvDataBaseManager.updateOrinsertDtvChannelWithNumber(c); + dtvchannelsnew.add(c); + } } else { if (c.isAnalogChannel()) mTvDataBaseManager.insertAtvChannel(c, c.getDisplayNumber()); @@ -621,8 +719,8 @@ public abstract class TvStoreManager { mTvDataBaseManager.insertDtvChannel(c, c.getDisplayNumber()); } - Log.d(TAG, ((isRealtimeStore) ? "update/insert [" : "insert [") + c.getDisplayNumber() - + "][" + c.getFrequency() + "][" + c.getServiceType() + "][" + c.getDisplayName() + "]"); + /*Log.d(TAG, ((isRealtimeStore) ? "update/insert [" : "insert [") + c.getDisplayNumber() + + "][" + c.getFrequency() + "][" + c.getServiceType() + "][" + c.getDisplayName() + "]");*/ if (isFinalStore) { bundle = getDisplayNumBunlde(c.getNumber()); @@ -630,19 +728,152 @@ public abstract class TvStoreManager { } } } + if (atvchannelsnew != null && atvchannelsnew.size() > 0) { + atvchannelsupdate = getNeedUpdateChannel(atvchannelsnew); + atvchannelsinsert= getNeedInsertChannel(atvchannelsnew); + mTvDataBaseManager.updateOrinsertChannelInList(atvchannelsupdate, atvchannelsinsert, false); + } + if (dtvchannelsnew != null && dtvchannelsnew.size() > 0) { + dtvchannelsupdate = getNeedUpdateChannel(dtvchannelsnew); + dtvchannelsinsert= getNeedInsertChannel(dtvchannelsnew); + mTvDataBaseManager.updateOrinsertChannelInList(dtvchannelsupdate, dtvchannelsinsert, true); + } lcn_overflow_start = mInitialLcnNumber; display_number_start = mInitialDisplayNumber; on_channel_store_tschanged = true; mChannelsOld = null; mChannelsNew = null; + mChannelsExist = null; + } + + private ArrayList<ChannelInfo> getNeedUpdateChannel(ArrayList<ChannelInfo> list) { + ArrayList<ChannelInfo> needupdate = new ArrayList<ChannelInfo>(); + for (int i = 0; i < list.size(); i++) { + for (int j = 0; j < mChannelsAll.size(); j++) { + ChannelInfo tempch = mChannelsAll.get(j); + if (tempch != null && TextUtils.equals(tempch.getDisplayNumber(), list.get(i).getDisplayNumber()) && tempch.getFrequency() == list.get(i).getFrequency()) { + ChannelInfo updateinfo = list.get(i); + if (tempch.getId() > -1) { + updateinfo.setId(tempch.getId()); + } + needupdate.add(updateinfo); + } + } + } + Log.d(TAG, "getNeedUpdateChannel size = " + needupdate.size()); + return needupdate; } + private ArrayList<ChannelInfo> getNeedInsertChannel(ArrayList<ChannelInfo> list) { + ArrayList<ChannelInfo> needinsert = new ArrayList<ChannelInfo>(); + boolean exist = false; + for (int i = 0; i < list.size(); i++) { + for (int j = 0; j < mChannelsAll.size(); j++) { + ChannelInfo tempch = mChannelsAll.get(j); + if (tempch != null && TextUtils.equals(tempch.getDisplayNumber(), list.get(i).getDisplayNumber()) && tempch.getFrequency() == list.get(i).getFrequency()) { + exist = true; + break; + } + } + if (!exist) { + needinsert.add(list.get(i)); + } else { + exist = false; + } + } + Log.d(TAG, "getNeedInsertChannel size = " + needinsert.size()); + return needinsert; + } + + private boolean getIsSameDisplayNumber(ChannelInfo chan) { + int size = mChannelsExist.size(); + for (int i = 0; i < size; i++) { + if (chan.getDisplayNumber().equals(mChannelsExist.get(i).getDisplayNumber()) && (chan.getFrequency() != mChannelsExist.get(i).getFrequency())) { + return true; + } + } + return false; + } + + private int getDvbPhysicalNumFromListByFre(ArrayList<FreqList> mlist, int freq, int diff) { + int size = mlist.size(); + for (int i = 0; i < size; i++) { + if (freq == mlist.get(i).freq) { + return i + 2; + } + } + for (int i = 0; i < size; i++) { + if (mlist.get(i).freq - diff < freq && freq < mlist.get(i).freq + diff) { + return i + 2; + } + } + return -1; + } + + private int getDvbPhysicalNumByFre(TvMode tvMode, int freq) { + + int diff = 3000000; + String type = tvMode.toType(); + int physicalNum = -1; + Log.d(TAG, "type:" + type + " freq :" + freq); + if (type.equals(TvContract.Channels.TYPE_ATSC_T)) { + tvMode.setList(0); + if (mATSC_T == null) { + mATSC_T = mTvControlManager.DTVGetScanFreqList(tvMode.getMode()); + } + physicalNum = getDvbPhysicalNumFromListByFre(mATSC_T, freq, diff); + return physicalNum; + } + if (type.equals(TvContract.Channels.TYPE_ATSC_C)) { + tvMode.setList(1); + if (mATSC_C_STD == null) { + mATSC_C_STD = mTvControlManager.DTVGetScanFreqList(tvMode.getMode()); + } + physicalNum = getDvbPhysicalNumFromListByFre(mATSC_C_STD, freq, diff); + if (physicalNum != -1) { + //error + return physicalNum; + } + tvMode.setList(2); + if (mATSC_C_LRC == null) { + mATSC_C_LRC = mTvControlManager.DTVGetScanFreqList(tvMode.getMode()); + } + physicalNum = getDvbPhysicalNumFromListByFre(mATSC_C_LRC, freq, diff); + if (physicalNum != -1) { + //error + return physicalNum; + } + tvMode.setList(3); + if (mATSC_HRC == null) { + mATSC_HRC = mTvControlManager.DTVGetScanFreqList(tvMode.getMode()); + } + physicalNum = getDvbPhysicalNumFromListByFre(mATSC_HRC, freq, diff); + if (physicalNum != -1) { + //error + return physicalNum; + } + } + return physicalNum; + } public void onStoreEvent(TvControlManager.ScannerEvent event) { + sendStoreEvent(event); + } + + private void sendStoreEvent(TvControlManager.ScannerEvent event) { + Message msg = new Message(); + msg.arg1 = event.type; + msg.obj = event; + mChildHandler.sendMessage(msg); + } + + public void dealStoreEvent(TvControlManager.ScannerEvent event) { ChannelInfo channel = null; String name = null; Bundle bundle = null; - + TvMode mode = null; + int freq = 0; + int physicalNum = -1; Log.d(TAG, "onEvent:" + event.type + " :" + mDisplayNumber); switch (event.type) { @@ -677,8 +908,11 @@ public abstract class TvStoreManager { } if (mScanMode.isDTVManulScan()) - initChannelsExist(); - + initChannelsExist(); + /*get exist channel info list*/ + reinitChannels(); + TvControlManager.FEParas fep = + new TvControlManager.FEParas(DroidLogicTvUtils.getObjectString(event.paras, "fe")); channel = createDtvChannelInfo(event); if (mDisplayNumber2 != null) @@ -690,13 +924,38 @@ public abstract class TvStoreManager { channel.setDisplayNumber(""+event.majorChannelNumber+"-"+event.minorChannelNumber); int vct = DroidLogicTvUtils.getObjectValueInt(event.paras, "srv", "vct", 0); Log.d(TAG, "srv.vct:"+vct); - if (vct == 1)//one-part channnel numbers for digital cable system. - channel.setDisplayNumber(""+event.minorChannelNumber); + if (vct == 1 && ((event.majorChannelNumber >> 4) == 0x3f)) { + //one-part channnel numbers for digital cable system. + //see atsc a/65 page 35, if major_channel_number hi 6 bit is 11 1111 + //one_part_number = (major_channel_number & 0x00f) << 10 + mino_channel_number + int one_part_number = ((event.majorChannelNumber & 0x00f) << 10) + event.minorChannelNumber; + Log.d(TAG, "set one_part_number:"+ one_part_number + " maj:" + event.majorChannelNumber + " min:" +event.minorChannelNumber); + if (one_part_number == 0) { + mode = fep.getMode(); + freq = fep.getFrequency(); + physicalNum = getDvbPhysicalNumByFre(mode, freq); + if (physicalNum > 0) + channel.setDisplayNumber(""+physicalNum+"-"+channel.getServiceId()); + else + channel.setDisplayNumber("0"+"-"+channel.getServiceId()); + } else { + channel.setDisplayNumber(""+one_part_number); + } + } } - Log.d(TAG, "reset number to " + channel.getDisplayNumber()); - + /*if (getIsSameDisplayNumber(channel) == true) { + //is same + mode = fep.getMode(); + freq = fep.getFrequency(); + physicalNum = getDvbPhysicalNumByFre(mode, freq); + if (physicalNum > 0) + channel.setDisplayNumber(""+physicalNum+"-"+channel.getServiceId()); + Log.d(TAG, "----Channels physicalNum set DisplayName:" + physicalNum + " getDisplayNumber:" + channel.getDisplayNumber()); + }*/ channel.print(); + /*add seach channel*/ + mChannelsExist.add(channel); cacheChannel(event, channel); if (mDisplayNumber2 != null) { @@ -712,7 +971,6 @@ public abstract class TvStoreManager { case TvControlManager.EVENT_ATV_PROG_DATA: Log.d(TAG, "atv prog data"); - checkOrPatchBeginLost(event); if (isFinalStoreStage && !mScanMode.isATVManualScan()) @@ -750,7 +1008,7 @@ public abstract class TvStoreManager { break; case TvControlManager.EVENT_SCAN_PROGRESS: - Log.d(TAG, event.precent + "%\tfreq[" + event.freq + "] lock[" + event.lock + "] strength[" + event.strength + "] quality[" + event.quality + "]"); + Log.d(TAG, event.precent + "%\tfreq[" + event.freq + "] lock[" + event.lock + "] strength[" + event.strength + "] quality[" + event.quality + "] mode[" + event.mode + "]"); checkOrPatchBeginLost(event); @@ -786,7 +1044,10 @@ public abstract class TvStoreManager { case TvControlManager.EVENT_STORE_END: Log.d(TAG, "Store end"); - + if (null != mChannelsNew && 0 != mChannelsNew.size()) { + Log.d(TAG, "Store end mChannelsNew.size=" + mChannelsNew.size()); + onScanEndBeforeStore(event.freq); + } storeTvChannel(isRealtimeStore, isFinalStoreStage); bundle = getScanEventBundle(event); @@ -815,8 +1076,9 @@ public abstract class TvStoreManager { } mScanMode = null; + mChannelsAll = null; - onScanExit(); + onScanExit(event.freq); bundle = getScanEventBundle(event); onEvent(DroidLogicTvUtils.SIG_INFO_C_SCAN_EXIT_EVENT, bundle); @@ -827,5 +1089,12 @@ public abstract class TvStoreManager { } } + private class ChildCallback implements Handler.Callback { + @Override + public boolean handleMessage(Message msg) { + dealStoreEvent((TvControlManager.ScannerEvent)msg.obj); + return false; + } + } } diff --git a/libtvbinder/include/tvcmd.h b/libtvbinder/include/tvcmd.h index 7f1b3fd..eec85e2 100644 --- a/libtvbinder/include/tvcmd.h +++ b/libtvbinder/include/tvcmd.h @@ -257,6 +257,11 @@ enum tvcmd_e { EPG_EVENT_CALLBACK = 542, VFRAME_BMP_EVENT_CALLBACK = 543, SCANNING_FRAME_STABLE_CALLBACK = 544, + FRONTEND_EVENT_CALLBACK = 545, + RECORDER_EVENT_CALLBACK = 546, + SCAN_LCN_CALLBACK = 547, + RRT_EVENT_CALLBACK = 548, + EAS_EVENT_CALLBACK = 549, // CALLBACK END // SSM @@ -481,9 +486,6 @@ enum tvcmd_e { DTV_GET_AUDIO_CHANNEL_MOD = 1427, DTV_GET_FREQ_BY_PROG_ID = 1428, DTV_GET_VIDEO_FMT_INFO = 1429, - DTV_START_RECORD = 1430, - DTV_STOP_RECORD = 1431, - //DTV_SET_RECORD_ALL_TS = 1432, SAVE_PROGRAM_ID = 1440, GET_PROGRAM_ID = 1441, DTV_SET_AUDIO_AD = 1442, @@ -509,6 +511,18 @@ enum tvcmd_e { SET_AUDIO_OUTMODE = 1501, GET_AUDIO_OUTMODE = 1502, + GET_AUDIO_STREAM_OUTMODE = 1503, + + SET_AMAUDIO_VOLUME = 1504, + GET_AMAUDIO_VOLUME = 1505, + SAVE_AMAUDIO_VOLUME = 1506, + GET_SAVE_AMAUDIO_VOLUME = 1507, + DTV_UPDATE_RRT = 1508, + DTV_SEARCH_RRT = 1509, + DTV_UPDATE_EAS = 1510, + + DTV_RECORDING_CMD = 1600, + DTV_PLAY_CMD = 1610, }; #endif //ANDROID_AMLOGIC_TVCMD_H |