diff options
Diffstat (limited to 'src/com/android/tv/tuner/setup')
6 files changed, 493 insertions, 58 deletions
diff --git a/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java b/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java index 97d9ece3..53678a85 100644 --- a/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java +++ b/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java @@ -36,6 +36,24 @@ public class ConnectionTypeFragment extends SetupMultiPaneFragment { "com.android.tv.tuner.setup.ConnectionTypeFragment"; @Override + public void onCreate(Bundle savedInstanceState) { + ((TunerSetupActivity) getActivity()).generateTunerHal(); + super.onCreate(savedInstanceState); + } + + @Override + public void onResume() { + ((TunerSetupActivity) getActivity()).generateTunerHal(); + super.onResume(); + } + + @Override + public void onDestroy() { + ((TunerSetupActivity) getActivity()).clearTunerHal(); + super.onDestroy(); + } + + @Override protected SetupGuidedStepFragment onCreateContentFragment() { return new ContentFragment(); } diff --git a/src/com/android/tv/tuner/setup/PostalCodeFragment.java b/src/com/android/tv/tuner/setup/PostalCodeFragment.java new file mode 100644 index 00000000..a4dd494c --- /dev/null +++ b/src/com/android/tv/tuner/setup/PostalCodeFragment.java @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2017 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.android.tv.tuner.setup; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v17.leanback.widget.GuidanceStylist.Guidance; +import android.support.v17.leanback.widget.GuidedAction; +import android.support.v17.leanback.widget.GuidedActionsStylist; +import android.text.InputFilter; +import android.text.Spanned; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.tv.R; +import com.android.tv.common.ui.setup.SetupGuidedStepFragment; +import com.android.tv.common.ui.setup.SetupMultiPaneFragment; +import com.android.tv.tuner.util.PostalCodeUtils; + +import java.util.List; + +/** + * A fragment for initial screen. + */ +public class PostalCodeFragment extends SetupMultiPaneFragment { + public static final String ACTION_CATEGORY = + "com.android.tv.tuner.setup.PostalCodeFragment"; + private static final int VIEW_TYPE_EDITABLE = 1; + + @Override + protected SetupGuidedStepFragment onCreateContentFragment() { + ContentFragment fragment = new ContentFragment(); + Bundle arguments = new Bundle(); + arguments.putBoolean(SetupGuidedStepFragment.KEY_THREE_PANE, true); + fragment.setArguments(arguments); + return fragment; + } + + @Override + protected String getActionCategory() { + return ACTION_CATEGORY; + } + + @Override + protected boolean needsDoneButton() { + return true; + } + + @Override + protected boolean needsSkipButton() { + return true; + } + + @Override + protected void setOnClickAction(View view, final String category, final int actionId) { + if (actionId == ACTION_DONE) { + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + CharSequence postalCode = + ((ContentFragment) getContentFragment()).mEditAction.getTitle(); + if (postalCode != null && postalCode.length() == 5) { + PostalCodeUtils.setLastPostalCode(getContext(), postalCode.toString()); + onActionClick(category, actionId); + } else { + ContentFragment contentFragment = (ContentFragment) getContentFragment(); + contentFragment.mEditAction.setDescription( + getString(R.string.postal_code_invalid_warning)); + contentFragment.notifyActionChanged(0); + contentFragment.mEditedActionView.performClick(); + } + } + }); + } else if (actionId == ACTION_SKIP) { + super.setOnClickAction(view, category, ACTION_SKIP); + } + } + + public static class ContentFragment extends SetupGuidedStepFragment { + private GuidedAction mEditAction; + private View mEditedActionView; + private View mDoneActionView; + private boolean mProceed; + + @Override + public void onGuidedActionFocused(GuidedAction action) { + if (action.equals(mEditAction)) { + if (mProceed) { + // "NEXT" in IME was just clicked, moves focus to Done button. + if (mDoneActionView == null) { + mDoneActionView = getActivity().findViewById(R.id.button_done); + } + mDoneActionView.requestFocus(); + mProceed = false; + } else { + // Directly opens IME to input postal/zip code. + if (mEditedActionView == null) { + mEditedActionView = getView().findViewById(R.id.guidedactions_editable); + ((TextView) mEditedActionView.findViewById(R.id.guidedactions_item_title)) + .setFilters(new InputFilter[]{new InputFilter() { + @Override + public CharSequence filter(CharSequence source, int start, + int end, Spanned dest, int dstart, int dend) { + try { + Integer.parseInt(source.toString()); + return null; + } catch (NumberFormatException e) { + return ""; + } + } + }, new InputFilter.LengthFilter(5)}); + } + mEditedActionView.performClick(); + } + } + } + + @Override + public long onGuidedActionEditedAndProceed(GuidedAction action) { + mProceed = true; + return 0; + } + + @NonNull + @Override + public Guidance onCreateGuidance(Bundle savedInstanceState) { + String title = getString(R.string.postal_code_guidance_title); + String description = getString(R.string.postal_code_guidance_description); + String breadcrumb = getString(R.string.ut_setup_breadcrumb); + return new Guidance(title, description, breadcrumb, null); + } + + @Override + public void onCreateActions(@NonNull List<GuidedAction> actions, + Bundle savedInstanceState) { + String description = getString(R.string.postal_code_action_description); + mEditAction = new GuidedAction.Builder(getActivity()).id(0).editable(true) + .description(description).build(); + actions.add(mEditAction); + } + + @Override + protected String getActionCategory() { + return ACTION_CATEGORY; + } + + @Override + public GuidedActionsStylist onCreateActionsStylist() { + return new GuidedActionsStylist() { + @Override + public int getItemViewType(GuidedAction action) { + if (action.isEditable()) { + return VIEW_TYPE_EDITABLE; + } + return super.getItemViewType(action); + } + + @Override + public int onProvideItemLayoutId(int viewType) { + if (viewType == VIEW_TYPE_EDITABLE) { + return R.layout.guided_action_editable; + } + return super.onProvideItemLayoutId(viewType); + } + }; + } + } +}
\ No newline at end of file diff --git a/src/com/android/tv/tuner/setup/ScanFragment.java b/src/com/android/tv/tuner/setup/ScanFragment.java index 4b3ffe40..75b28e32 100644 --- a/src/com/android/tv/tuner/setup/ScanFragment.java +++ b/src/com/android/tv/tuner/setup/ScanFragment.java @@ -21,6 +21,7 @@ import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; import android.os.ConditionVariable; import android.os.Handler; @@ -35,12 +36,11 @@ import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; -import com.android.tv.common.AutoCloseableUtils; import com.android.tv.common.SoftPreconditions; import com.android.tv.common.ui.setup.SetupFragment; import com.android.tv.tuner.ChannelScanFileParser; -import com.android.tv.tuner.TunerHal; import com.android.tv.tuner.R; +import com.android.tv.tuner.TunerHal; import com.android.tv.tuner.TunerPreferences; import com.android.tv.tuner.data.Channel; import com.android.tv.tuner.data.PsipData; @@ -51,7 +51,6 @@ import com.android.tv.tuner.source.TsStreamer; import com.android.tv.tuner.source.TunerTsStreamer; import com.android.tv.tuner.tvinput.ChannelDataManager; import com.android.tv.tuner.tvinput.EventDetector; -import com.android.tv.tuner.util.TunerInputInfoUtils; import junit.framework.Assert; @@ -67,6 +66,7 @@ import java.util.concurrent.TimeUnit; public class ScanFragment extends SetupFragment { private static final String TAG = "ScanFragment"; private static final boolean DEBUG = false; + // In the fake mode, the connection to antenna or cable is not necessary. // Instead dummy channels are added. private static final boolean FAKE_MODE = false; @@ -98,6 +98,7 @@ public class ScanFragment extends SetupFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "onCreateView"); View view = super.onCreateView(inflater, container, savedInstanceState); mChannelDataManager = new ChannelDataManager(getActivity()); mChannelDataManager.checkDataVersion(getActivity()); @@ -120,13 +121,19 @@ public class ScanFragment extends SetupFragment { } }); Bundle args = getArguments(); + int tunerType = (args == null ? 0 : args.getInt(TunerSetupActivity.KEY_TUNER_TYPE, 0)); // TODO: Handle the case when the fragment is restored. startScan(args == null ? 0 : args.getInt(EXTRA_FOR_CHANNEL_SCAN_FILE, 0)); TextView scanTitleView = (TextView) view.findViewById(R.id.tune_title); - if (TunerInputInfoUtils.isBuiltInTuner(getActivity())){ - scanTitleView.setText(R.string.bt_channel_scan); - } else { - scanTitleView.setText(R.string.ut_channel_scan); + switch (tunerType) { + case TunerHal.TUNER_TYPE_USB: + scanTitleView.setText(R.string.ut_channel_scan); + break; + case TunerHal.TUNER_TYPE_NETWORK: + scanTitleView.setText(R.string.nt_channel_scan); + break; + default: + scanTitleView.setText(R.string.bt_channel_scan); } return view; } @@ -147,12 +154,14 @@ public class ScanFragment extends SetupFragment { } @Override - public void onDetach() { + public void onPause() { + Log.d(TAG, "onPause"); if (mChannelScanTask != null) { // Ensure scan task will stop. + Log.w(TAG, "The activity went to the background. Stopping channel scan."); mChannelScanTask.stopScan(); } - super.onDetach(); + super.onPause(); } /** @@ -168,7 +177,9 @@ public class ScanFragment extends SetupFragment { new Handler().postDelayed(new Runnable() { @Override public void run() { - mChannelScanTask.showFinishingProgressDialog(); + if (mChannelScanTask != null) { + mChannelScanTask.showFinishingProgressDialog(); + } } }, SHOW_PROGRESS_DIALOG_DELAY_MS); @@ -255,7 +266,7 @@ public class ScanFragment extends SetupFragment { if (FAKE_MODE) { mScanTsStreamer = new FakeTsStreamer(this); } else { - TunerHal hal = TunerHal.createInstance(mActivity.getApplicationContext()); + TunerHal hal = ((TunerSetupActivity) mActivity).getTunerHal(); if (hal == null) { throw new RuntimeException("Failed to open a DVB device"); } @@ -316,10 +327,17 @@ public class ScanFragment extends SetupFragment { @Override protected void onProgressUpdate(Integer... values) { - mProgressBar.setProgress(values[0]); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + mProgressBar.setProgress(values[0], true); + } else { + mProgressBar.setProgress(values[0]); + } } private void stopScan() { + if (mLatch != null) { + mLatch.countDown(); + } mConditionStopped.open(); } @@ -360,11 +378,7 @@ public class ScanFragment extends SetupFragment { if (mConditionStopped.block(-1)) { break; } - onProgressUpdate(MAX_PROGRESS * i++ / mScanChannelList.size()); - } - if (mScanTsStreamer instanceof TunerTsStreamer) { - AutoCloseableUtils.closeQuietly( - ((TunerTsStreamer) mScanTsStreamer).getTunerHal()); + publishProgress(MAX_PROGRESS * i++ / mScanChannelList.size()); } mChannelDataManager.notifyScanCompleted(); if (!mConditionStopped.block(-1)) { @@ -454,7 +468,13 @@ public class ScanFragment extends SetupFragment { if (mFinishingProgressDialog != null) { mFinishingProgressDialog.dismiss(); } - onActionClick(ACTION_CATEGORY, mIsCanceled ? ACTION_CANCEL : ACTION_FINISH); + // If the fragment is not resumed, the next fragment (scan result page) can't be + // displayed. In that case, just close the activity. + if (isResumed()) { + onActionClick(ACTION_CATEGORY, mIsCanceled ? ACTION_CANCEL : ACTION_FINISH); + } else if (getActivity() != null) { + getActivity().finish(); + } mChannelScanTask = null; } } diff --git a/src/com/android/tv/tuner/setup/ScanResultFragment.java b/src/com/android/tv/tuner/setup/ScanResultFragment.java index 068543cd..3b8cd823 100644 --- a/src/com/android/tv/tuner/setup/ScanResultFragment.java +++ b/src/com/android/tv/tuner/setup/ScanResultFragment.java @@ -26,6 +26,7 @@ import android.support.v17.leanback.widget.GuidedAction; import com.android.tv.common.ui.setup.SetupGuidedStepFragment; import com.android.tv.common.ui.setup.SetupMultiPaneFragment; import com.android.tv.tuner.R; +import com.android.tv.tuner.TunerHal; import com.android.tv.tuner.TunerPreferences; import com.android.tv.tuner.util.TunerInputInfoUtils; @@ -76,11 +77,19 @@ public class ScanResultFragment extends SetupMultiPaneFragment { mChannelCountOnPreference, mChannelCountOnPreference); breadcrumb = null; } else { + Bundle args = getArguments(); + int tunerType = + (args == null ? 0 : args.getInt(TunerSetupActivity.KEY_TUNER_TYPE, 0)); title = getString(R.string.ut_result_not_found_title); - if (TunerInputInfoUtils.isBuiltInTuner(getActivity())) { - description = getString(R.string.bt_result_not_found_description); - } else { - description = getString(R.string.ut_result_not_found_description); + switch (tunerType) { + case TunerHal.TUNER_TYPE_USB: + description = getString(R.string.ut_result_not_found_description); + break; + case TunerHal.TUNER_TYPE_NETWORK: + description = getString(R.string.nt_result_not_found_description); + break; + default: + description = getString(R.string.bt_result_not_found_description); } breadcrumb = getString(R.string.ut_setup_breadcrumb); } diff --git a/src/com/android/tv/tuner/setup/TunerSetupActivity.java b/src/com/android/tv/tuner/setup/TunerSetupActivity.java index 78121bc5..f618c699 100644 --- a/src/com/android/tv/tuner/setup/TunerSetupActivity.java +++ b/src/com/android/tv/tuner/setup/TunerSetupActivity.java @@ -29,35 +29,53 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.tv.TvContract; +import android.os.AsyncTask; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.VisibleForTesting; import android.support.v4.app.NotificationCompat; +import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.widget.Toast; import com.android.tv.TvApplication; +import com.android.tv.common.AutoCloseableUtils; import com.android.tv.common.TvCommonConstants; import com.android.tv.common.TvCommonUtils; import com.android.tv.common.ui.setup.SetupActivity; import com.android.tv.common.ui.setup.SetupFragment; import com.android.tv.common.ui.setup.SetupMultiPaneFragment; +import com.android.tv.experiments.Experiments; import com.android.tv.tuner.R; import com.android.tv.tuner.TunerHal; import com.android.tv.tuner.TunerPreferences; import com.android.tv.tuner.tvinput.TunerTvInputService; -import com.android.tv.tuner.util.TunerInputInfoUtils; +import com.android.tv.tuner.util.PostalCodeUtils; +import com.android.tv.util.LocationUtils; + +import java.util.Locale; +import java.util.concurrent.Executor; /** * An activity that serves tuner setup process. */ public class TunerSetupActivity extends SetupActivity { - private final String TAG = "TunerSetupActivity"; + private static final String TAG = "TunerSetupActivity"; + private static final boolean DEBUG = false; + + /** + * Key for passing tuner type to sub-fragments. + */ + public static final String KEY_TUNER_TYPE = "TunerSetupActivity.tunerType"; + // For the recommendation card private static final String TV_ACTIVITY_CLASS_NAME = "com.android.tv.TvActivity"; private static final String NOTIFY_TAG = "TunerSetup"; private static final int NOTIFY_ID = 1000; private static final String TAG_DRAWABLE = "drawable"; private static final String TAG_ICON = "ic_launcher_s"; + private static final int PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1; private static final int CHANNEL_MAP_SCAN_FILE[] = { R.raw.ut_us_atsc_center_frequencies_8vsb, @@ -69,9 +87,13 @@ public class TunerSetupActivity extends SetupActivity { R.raw.ut_kr_dev_cj_cable_center_frequencies_qam256}; private ScanFragment mLastScanFragment; + private Integer mTunerType; + private TunerHalFactory mTunerHalFactory; + private boolean mNeedToShowPostalCodeFragment; @Override protected void onCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "onCreate"); TvApplication.setCurrentRunningProcess(this, false); super.onCreate(savedInstanceState); // TODO: check {@link shouldShowRequestPermissionRationale}. @@ -79,13 +101,49 @@ public class TunerSetupActivity extends SetupActivity { != PackageManager.PERMISSION_GRANTED) { // No need to check the request result. requestPermissions(new String[] {android.Manifest.permission.ACCESS_COARSE_LOCATION}, - 0); + PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION); + } + mTunerType = TunerHal.getTunerTypeAndCount(this).first; + if (mTunerType == null) { + finish(); + } else { + mTunerHalFactory = new TunerHalFactory(getApplicationContext()); + } + try { + // Updating postal code takes time, therefore we called it here for "warm-up". + PostalCodeUtils.setLastPostalCode(this, null); + PostalCodeUtils.updatePostalCode(this); + } catch (Exception e) { + // Do nothing. If the last known postal code is null, we'll show guided fragment to + // prompt users to input postal code before ConnectionTypeFragment is shown. + Log.i(TAG, "Can't get postal code:" + e); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + if (requestCode == PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED + && Experiments.CLOUD_EPG.get()) { + try { + // Updating postal code takes time, therefore we should update postal code + // right after the permission is granted, so that the subsequent operations, + // especially EPG fetcher, could get the newly updated postal code. + PostalCodeUtils.updatePostalCode(this); + } catch (Exception e) { + // Do nothing + } + } } } @Override protected Fragment onCreateInitialFragment() { SetupFragment fragment = new WelcomeFragment(); + Bundle args = new Bundle(); + args.putInt(KEY_TUNER_TYPE, mTunerType); + fragment.setArguments(args); fragment.setShortDistance(SetupFragment.FRAGMENT_EXIT_TRANSITION | SetupFragment.FRAGMENT_REENTER_TRANSITION); return fragment; @@ -102,33 +160,41 @@ public class TunerSetupActivity extends SetupActivity { finish(); break; default: { - SetupFragment fragment = new ConnectionTypeFragment(); - fragment.setShortDistance(SetupFragment.FRAGMENT_ENTER_TRANSITION - | SetupFragment.FRAGMENT_RETURN_TRANSITION); - showFragment(fragment, true); + if (mNeedToShowPostalCodeFragment + || Locale.US.getCountry().equalsIgnoreCase( + LocationUtils.getCurrentCountry(getApplicationContext())) + && TextUtils.isEmpty(PostalCodeUtils.getLastPostalCode(this))) { + // We cannot get postal code automatically. Postal code input fragment + // should always be shown even if users have input some valid postal + // code in this activity before. + mNeedToShowPostalCodeFragment = true; + showPostalCodeFragment(); + } else { + showConnectionTypeFragment(); + } break; } } return true; + case PostalCodeFragment.ACTION_CATEGORY: + if (actionId == SetupMultiPaneFragment.ACTION_DONE + || actionId == SetupMultiPaneFragment.ACTION_SKIP) { + showConnectionTypeFragment(); + } + return true; case ConnectionTypeFragment.ACTION_CATEGORY: - TunerHal hal = TunerHal.createInstance(getApplicationContext()); - if (hal == null) { + if (mTunerHalFactory.get() == null) { finish(); Toast.makeText(getApplicationContext(), R.string.ut_channel_scan_tuner_unavailable,Toast.LENGTH_LONG).show(); return true; } - try { - hal.close(); - } catch (Exception e) { - Log.e(TAG, "Tuner hal close failed", e); - return true; - } mLastScanFragment = new ScanFragment(); - Bundle args = new Bundle(); - args.putInt(ScanFragment.EXTRA_FOR_CHANNEL_SCAN_FILE, + Bundle args1 = new Bundle(); + args1.putInt(ScanFragment.EXTRA_FOR_CHANNEL_SCAN_FILE, CHANNEL_MAP_SCAN_FILE[actionId]); - mLastScanFragment.setArguments(args); + args1.putInt(KEY_TUNER_TYPE, mTunerType); + mLastScanFragment.setArguments(args1); showFragment(mLastScanFragment, true); return true; case ScanFragment.ACTION_CATEGORY: @@ -137,7 +203,11 @@ public class TunerSetupActivity extends SetupActivity { getFragmentManager().popBackStack(); return true; case ScanFragment.ACTION_FINISH: + mTunerHalFactory.clear(); SetupFragment fragment = new ScanResultFragment(); + Bundle args2 = new Bundle(); + args2.putInt(KEY_TUNER_TYPE, mTunerType); + fragment.setArguments(args2); fragment.setShortDistance(SetupFragment.FRAGMENT_EXIT_TRANSITION | SetupFragment.FRAGMENT_REENTER_TRANSITION); showFragment(fragment, true); @@ -213,7 +283,7 @@ public class TunerSetupActivity extends SetupActivity { String inputId = TvContract.buildInputId(new ComponentName(context.getPackageName(), TunerTvInputService.class.getName())); - // Make an intent to launch the setup activity of USB tuner TV input. + // Make an intent to launch the setup activity of TV tuner input. Intent intent = TvCommonUtils.createSetupIntent( new Intent(context, TunerSetupActivity.class), inputId); intent.putExtra(TvCommonConstants.EXTRA_INPUT_ID, inputId); @@ -224,6 +294,27 @@ public class TunerSetupActivity extends SetupActivity { } /** + * Gets the currently used tuner HAL. + */ + TunerHal getTunerHal() { + return mTunerHalFactory.get(); + } + + /** + * Generates tuner HAL. + */ + void generateTunerHal() { + mTunerHalFactory.generate(); + } + + /** + * Clears the currently used tuner HAL. + */ + void clearTunerHal() { + mTunerHalFactory.clear(); + } + + /** * Returns a {@link PendingIntent} to launch the tuner TV input service. * * @param context a {@link Context} instance @@ -242,12 +333,19 @@ public class TunerSetupActivity extends SetupActivity { Resources resources = context.getResources(); String focusedTitle = resources.getString( R.string.ut_setup_recommendation_card_focused_title); - String title; - if (TunerInputInfoUtils.isBuiltInTuner(context)) { - title = resources.getString(R.string.bt_setup_recommendation_card_title); - } else { - title = resources.getString(R.string.ut_setup_recommendation_card_title); + int titleStringId = 0; + switch (TunerHal.getTunerTypeAndCount(context).first) { + case TunerHal.TUNER_TYPE_BUILT_IN: + titleStringId = R.string.bt_setup_recommendation_card_title; + break; + case TunerHal.TUNER_TYPE_USB: + titleStringId = R.string.ut_setup_recommendation_card_title; + break; + case TunerHal.TUNER_TYPE_NETWORK: + titleStringId = R.string.nt_setup_recommendation_card_title; + break; } + String title = resources.getString(titleStringId); Bitmap largeIcon = BitmapFactory.decodeResource(resources, R.drawable.recommendation_antenna); @@ -269,6 +367,20 @@ public class TunerSetupActivity extends SetupActivity { notificationManager.notify(NOTIFY_TAG, NOTIFY_ID, notification); } + private void showPostalCodeFragment() { + SetupFragment fragment = new PostalCodeFragment(); + fragment.setShortDistance(SetupFragment.FRAGMENT_ENTER_TRANSITION + | SetupFragment.FRAGMENT_RETURN_TRANSITION); + showFragment(fragment, true); + } + + private void showConnectionTypeFragment() { + SetupFragment fragment = new ConnectionTypeFragment(); + fragment.setShortDistance(SetupFragment.FRAGMENT_ENTER_TRANSITION + | SetupFragment.FRAGMENT_RETURN_TRANSITION); + showFragment(fragment, true); + } + /** * Cancels the previously shown recommendation card. * @@ -279,4 +391,80 @@ public class TunerSetupActivity extends SetupActivity { .getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancel(NOTIFY_TAG, NOTIFY_ID); } -} + + @VisibleForTesting + static class TunerHalFactory { + private Context mContext; + @VisibleForTesting + TunerHal mTunerHal; + private GenerateTunerHalTask mGenerateTunerHalTask; + private final Executor mExecutor; + + TunerHalFactory(Context context) { + this(context, AsyncTask.SERIAL_EXECUTOR); + } + + TunerHalFactory(Context context, Executor executor) { + mContext = context; + mExecutor = executor; + } + + /** + * Returns tuner HAL currently used. If it's {@code null} and tuner HAL is not generated + * before, tries to generate it synchronously. + */ + TunerHal get() { + if (mGenerateTunerHalTask != null + && mGenerateTunerHalTask.getStatus() != AsyncTask.Status.FINISHED) { + try { + return mGenerateTunerHalTask.get(); + } catch (Exception e) { + Log.e(TAG, "Cannot get Tuner HAL: " + e); + } + } else if (mGenerateTunerHalTask == null && mTunerHal == null) { + mTunerHal = createInstance(); + } + return mTunerHal; + } + + /** + * Generates tuner hal for scanning with asynchronous tasks. + */ + void generate() { + if (mGenerateTunerHalTask == null && mTunerHal == null) { + mGenerateTunerHalTask = new GenerateTunerHalTask(); + mGenerateTunerHalTask.executeOnExecutor(mExecutor); + } + } + + /** + * Clears the currently used tuner hal. + */ + void clear() { + if (mGenerateTunerHalTask != null) { + mGenerateTunerHalTask.cancel(true); + mGenerateTunerHalTask = null; + } + if (mTunerHal != null) { + AutoCloseableUtils.closeQuietly(mTunerHal); + mTunerHal = null; + } + } + + protected TunerHal createInstance() { + return TunerHal.createInstance(mContext); + } + + class GenerateTunerHalTask extends AsyncTask<Void, Void, TunerHal> { + @Override + protected TunerHal doInBackground(Void... args) { + return createInstance(); + } + + @Override + protected void onPostExecute(TunerHal tunerHal) { + mTunerHal = tunerHal; + } + } + } +}
\ No newline at end of file diff --git a/src/com/android/tv/tuner/setup/WelcomeFragment.java b/src/com/android/tv/tuner/setup/WelcomeFragment.java index 7e809411..a3dddc72 100644 --- a/src/com/android/tv/tuner/setup/WelcomeFragment.java +++ b/src/com/android/tv/tuner/setup/WelcomeFragment.java @@ -27,6 +27,7 @@ import android.view.ViewGroup; import com.android.tv.common.ui.setup.SetupGuidedStepFragment; import com.android.tv.common.ui.setup.SetupMultiPaneFragment; import com.android.tv.tuner.R; +import com.android.tv.tuner.TunerHal; import com.android.tv.tuner.TunerPreferences; import com.android.tv.tuner.util.TunerInputInfoUtils; @@ -41,7 +42,9 @@ public class WelcomeFragment extends SetupMultiPaneFragment { @Override protected SetupGuidedStepFragment onCreateContentFragment() { - return new ContentFragment(); + ContentFragment fragment = new ContentFragment(); + fragment.setArguments(getArguments()); + return fragment; } @Override @@ -70,20 +73,33 @@ public class WelcomeFragment extends SetupMultiPaneFragment { public Guidance onCreateGuidance(Bundle savedInstanceState) { String title; String description; + int tunerType = getArguments().getInt(TunerSetupActivity.KEY_TUNER_TYPE, + TunerHal.TUNER_TYPE_BUILT_IN); if (mChannelCountOnPreference == 0) { - if (TunerInputInfoUtils.isBuiltInTuner(getActivity())) { - title = getString(R.string.bt_setup_new_title); - description = getString(R.string.bt_setup_new_description); - } else { - title = getString(R.string.ut_setup_new_title); - description = getString(R.string.ut_setup_new_description); + switch (tunerType) { + case TunerHal.TUNER_TYPE_USB: + title = getString(R.string.ut_setup_new_title); + description = getString(R.string.ut_setup_new_description); + break; + case TunerHal.TUNER_TYPE_NETWORK: + title = getString(R.string.nt_setup_new_title); + description = getString(R.string.nt_setup_new_description); + break; + default: + title = getString(R.string.bt_setup_new_title); + description = getString(R.string.bt_setup_new_description); } } else { title = getString(R.string.bt_setup_again_title); - if (TunerInputInfoUtils.isBuiltInTuner(getActivity())) { - description = getString(R.string.bt_setup_again_description); - } else { - description = getString(R.string.ut_setup_again_description); + switch (tunerType) { + case TunerHal.TUNER_TYPE_USB: + description = getString(R.string.ut_setup_again_description); + break; + case TunerHal.TUNER_TYPE_NETWORK: + description = getString(R.string.nt_setup_again_description); + break; + default: + description = getString(R.string.bt_setup_again_description); } } return new Guidance(title, description, null, null); |