11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccipackage org.chromium.chromecast.shell; 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.app.Activity; 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.BroadcastReceiver; 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.Context; 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.Intent; 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.content.IntentFilter; 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.media.AudioManager; 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.net.Uri; 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.os.Bundle; 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.support.v4.content.LocalBroadcastManager; 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.util.Log; 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.KeyEvent; 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.MotionEvent; 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.view.WindowManager; 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport android.widget.Toast; 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.base.CommandLine; 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.content.browser.ActivityContentVideoViewClient; 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.content.browser.ContentVideoViewClient; 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.content.browser.ContentViewClient; 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.content.browser.ContentViewCore; 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.ui.base.WindowAndroid; 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Activity for managing the Cast shell. 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccipublic class CastShellActivity extends Activity { 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private static final String TAG = "CastShellActivity"; 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private static final String ACTIVE_SHELL_URL_KEY = "activeUrl"; 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private static final int DEFAULT_HEIGHT_PIXELS = 720; 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public static final String ACTION_EXTRA_RESOLUTION_HEIGHT = 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "org.chromium.chromecast.shell.intent.extra.RESOLUTION_HEIGHT"; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private CastWindowManager mCastWindowManager; 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private AudioManager mAudioManager; 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private BroadcastReceiver mBroadcastReceiver; 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Native window instance. 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(byungchul, gunsch): CastShellActivity, CastWindowAndroid, and native CastWindowAndroid 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // have a one-to-one relationship. Consider instantiating CastWindow here and CastWindow having 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // this native shell instance. 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private long mNativeCastWindow; 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Returns whether or not CastShellActivity should launch the browser startup sequence. 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Intended to be overridden. 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected boolean shouldLaunchBrowser() { 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected void onCreate(final Bundle savedInstanceState) { 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci super.onCreate(savedInstanceState); 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci exitIfUrlMissing(); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (shouldLaunchBrowser()) { 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!CastBrowserHelper.initializeBrowser(getApplicationContext())) { 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Toast.makeText(this, 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci R.string.browser_process_initialization_failed, 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Toast.LENGTH_SHORT).show(); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finish(); 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Whenever our app is visible, volume controls should modify the music stream. 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // For more information read: 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // http://developer.android.com/training/managing-audio/volume-playback.html 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci setVolumeControlStream(AudioManager.STREAM_MUSIC); 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Set flags to both exit sleep mode when this activity starts and 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // avoid entering sleep mode while playing media. We cannot distinguish 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // between video and audio so this applies to both. 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci setContentView(R.layout.cast_shell_activity); 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mCastWindowManager = (CastWindowManager) findViewById(R.id.shell_container); 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mCastWindowManager.setDelegate(new CastWindowManager.Delegate() { 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public void onCreated() { 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public void onClosed() { 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mNativeCastWindow = 0; 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mCastWindowManager.setDelegate(null); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finish(); 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }); 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci setResolution(); 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mCastWindowManager.setWindow(new WindowAndroid(this)); 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci registerBroadcastReceiver(); 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci String url = getIntent().getDataString(); 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Log.d(TAG, "onCreate startupUrl: " + url); 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mNativeCastWindow = mCastWindowManager.launchCastWindow(url); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci getActiveContentViewCore().setContentViewClient(new ContentViewClient() { 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public ContentVideoViewClient getContentVideoViewClient() { 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return new ActivityContentVideoViewClient(CastShellActivity.this); 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }); 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected void onDestroy() { 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci super.onDestroy(); 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unregisterBroadcastReceiver(); 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mNativeCastWindow != 0) { 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mCastWindowManager.stopCastWindow(mNativeCastWindow, false /* gracefully */); 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mNativeCastWindow = 0; 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected void onNewIntent(Intent intent) { 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Only handle direct intents (e.g. "fling") if this activity is also managing 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the browser process. 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!shouldLaunchBrowser()) return; 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci String url = intent.getDataString(); 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Log.d(TAG, "onNewIntent: " + url); 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Reset broadcast intent uri and receiver. 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci setIntent(intent); 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci exitIfUrlMissing(); 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci getActiveCastWindow().loadUrl(url); 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected void onResume() { 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci super.onResume(); 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Inform ContentView that this activity is being shown. 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ContentViewCore view = getActiveContentViewCore(); 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (view != null) view.onShow(); 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Request audio focus so any other audio playback doesn't continue in the background. 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mAudioManager.requestAudioFocus( 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN) 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Log.e(TAG, "Failed to obtain audio focus"); 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected void onPause() { 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // As soon as the cast app is no longer in the foreground, we ought to immediately tear 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // everything down. Apps should not continue running and playing sound in the background. 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci super.onPause(); 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Release the audio focus. Note that releasing audio focus does not stop audio playback, 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // it just notifies the framework that this activity has stopped playing audio. 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mAudioManager.abandonAudioFocus(null) != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Log.e(TAG, "Failed to abandon audio focus"); 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ContentViewCore view = getActiveContentViewCore(); 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (view != null) view.onHide(); 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finishGracefully(); 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected void finishGracefully() { 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mNativeCastWindow != 0) { 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mCastWindowManager.stopCastWindow(mNativeCastWindow, true /* gracefully */); 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mNativeCastWindow = 0; 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private void registerBroadcastReceiver() { 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mBroadcastReceiver == null) { 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mBroadcastReceiver = new BroadcastReceiver() { 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public void onReceive(Context context, Intent intent) { 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Log.d(TAG, "Received intent: action=" + intent.getAction()); 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (CastWindowAndroid.ACTION_ENABLE_DEV_TOOLS.equals(intent.getAction())) { 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mCastWindowManager.nativeEnableDevTools(true); 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (CastWindowAndroid.ACTION_DISABLE_DEV_TOOLS.equals( 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci intent.getAction())) { 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mCastWindowManager.nativeEnableDevTools(false); 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IntentFilter devtoolsBroadcastIntentFilter = new IntentFilter(); 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci devtoolsBroadcastIntentFilter.addAction(CastWindowAndroid.ACTION_ENABLE_DEV_TOOLS); 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci devtoolsBroadcastIntentFilter.addAction(CastWindowAndroid.ACTION_DISABLE_DEV_TOOLS); 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LocalBroadcastManager.getInstance(this) 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci .registerReceiver(mBroadcastReceiver, devtoolsBroadcastIntentFilter); 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private void unregisterBroadcastReceiver() { 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this); 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci broadcastManager.unregisterReceiver(mBroadcastReceiver); 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private void setResolution() { 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int requestedHeight = getIntent().getIntExtra( 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ACTION_EXTRA_RESOLUTION_HEIGHT, DEFAULT_HEIGHT_PIXELS); 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int displayHeight = getResources().getDisplayMetrics().heightPixels; 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Clamp within [DEFAULT_HEIGHT_PIXELS, displayHeight] 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int desiredHeight = 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Math.min(displayHeight, Math.max(DEFAULT_HEIGHT_PIXELS, requestedHeight)); 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci double deviceScaleFactor = ((double) displayHeight) / desiredHeight; 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Log.d(TAG, "Using scale factor " + deviceScaleFactor + " to set height " + desiredHeight); 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CommandLine.getInstance().appendSwitchWithValue("force-device-scale-factor", 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci String.valueOf(deviceScaleFactor)); 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private void exitIfUrlMissing() { 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Intent intent = getIntent(); 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (intent != null && intent.getData() != null && !intent.getData().equals(Uri.EMPTY)) { 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Log an exception so that the exit cause is obvious when reading the logs. 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Log.e(TAG, "Activity will not start", 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new IllegalArgumentException("Intent did not contain a valid url")); 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci System.exit(-1); 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return The currently visible {@link CastWindowAndroid} or null if one is not showing. 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public CastWindowAndroid getActiveCastWindow() { 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mCastWindowManager.getActiveCastWindow(); 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return The {@link ContentViewCore} owned by the currently visible {@link CastWindowAndroid}, 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * or null if one is not showing. 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public ContentViewCore getActiveContentViewCore() { 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CastWindowAndroid shell = getActiveCastWindow(); 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return shell != null ? shell.getContentViewCore() : null; 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public boolean onKeyUp(int keyCode, KeyEvent event) { 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (keyCode != KeyEvent.KEYCODE_BACK) { 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return super.onKeyUp(keyCode, event); 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Just finish this activity to go back to the previous activity or launcher. 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finishGracefully(); 2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public boolean dispatchKeyEvent(KeyEvent event) { 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int keyCode = event.getKeyCode(); 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (keyCode == KeyEvent.KEYCODE_BACK) { 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return super.dispatchKeyEvent(event); 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public boolean dispatchGenericMotionEvent(MotionEvent ev) { 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public boolean dispatchKeyShortcutEvent(KeyEvent event) { 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public boolean dispatchTouchEvent(MotionEvent ev) { 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @Override 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public boolean dispatchTrackballEvent(MotionEvent ev) { 2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 292