/* * Copyright (C) 2011 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.test.tilebenchmark; import android.app.Activity; import android.content.Intent; import android.content.Context; import android.graphics.Bitmap; import android.os.AsyncTask; import android.os.Bundle; import android.os.CountDownTimer; import android.util.Log; import android.util.Pair; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.ToggleButton; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; /** * Interface for profiling the webview's scrolling, with simple controls on how * to scroll, and what content to load. */ public class ProfileActivity extends Activity { private static final int TIMED_RECORD_MILLIS = 2000; public interface ProfileCallback { public void profileCallback(RunData data); } public static final String TEMP_FILENAME = "profile.tiles"; Button mInspectButton; ToggleButton mCaptureButton; Spinner mVelocitySpinner; Spinner mMovementSpinner; EditText mUrl; ProfiledWebView mWeb; ProfileCallback mCallback; LoggingWebViewClient mLoggingWebViewClient = new LoggingWebViewClient(); AutoLoggingWebViewClient mAutoLoggingWebViewClient = new AutoLoggingWebViewClient(); TimedLoggingWebViewClient mTimedLoggingWebViewClient = new TimedLoggingWebViewClient(); private enum TestingState { NOT_TESTING, PRE_TESTING, START_TESTING, STOP_TESTING, SAVED_TESTING }; private class VelocitySelectedListener implements OnItemSelectedListener { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { String speedStr = parent.getItemAtPosition(position).toString(); int speedInt = Integer.parseInt(speedStr); mWeb.setAutoScrollSpeed(speedInt); } @Override public void onNothingSelected(AdapterView parent) { } } private class MovementSelectedListener implements OnItemSelectedListener { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { String movementStr = parent.getItemAtPosition(position).toString(); if (movementStr == getResources().getString(R.string.movement_auto_scroll)) { mWeb.setWebViewClient(mAutoLoggingWebViewClient); mCaptureButton.setEnabled(false); mVelocitySpinner.setEnabled(true); } else if (movementStr == getResources().getString(R.string.movement_manual)) { mWeb.setWebViewClient(mLoggingWebViewClient); mCaptureButton.setEnabled(true); mVelocitySpinner.setEnabled(false); } else if (movementStr == getResources().getString(R.string.movement_timed)) { mWeb.setWebViewClient(mTimedLoggingWebViewClient); mCaptureButton.setEnabled(false); mVelocitySpinner.setEnabled(false); } } @Override public void onNothingSelected(AdapterView parent) { } } private class LoggingWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); mUrl.setText(url); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); view.requestFocus(); ((ProfiledWebView)view).onPageFinished(); } } private class AutoLoggingWebViewClient extends LoggingWebViewClient { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); startViewProfiling(true); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); setTestingState(TestingState.PRE_TESTING); } } private class TimedLoggingWebViewClient extends LoggingWebViewClient { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); startViewProfiling(false); // after a fixed time after page finished, stop testing new CountDownTimer(TIMED_RECORD_MILLIS, TIMED_RECORD_MILLIS) { @Override public void onTick(long millisUntilFinished) { } @Override public void onFinish() { mWeb.stopScrollTest(); } }.start(); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); setTestingState(TestingState.PRE_TESTING); } } private class StoreFileTask extends AsyncTask, Void, Void> { @Override protected Void doInBackground(Pair... params) { try { FileOutputStream fos = openFileOutput(params[0].first, Context.MODE_PRIVATE); ObjectOutputStream out = new ObjectOutputStream(fos); out.writeObject(params[0].second); out.close(); } catch (IOException ex) { ex.printStackTrace(); } return null; } @Override protected void onPostExecute(Void v) { setTestingState(TestingState.SAVED_TESTING); } } public void setTestingState(TestingState state) { switch (state) { case NOT_TESTING: mUrl.setBackgroundResource(R.color.background_not_testing); mInspectButton.setEnabled(true); mMovementSpinner.setEnabled(true); break; case PRE_TESTING: mInspectButton.setEnabled(false); mMovementSpinner.setEnabled(false); break; case START_TESTING: mCaptureButton.setChecked(true); mUrl.setBackgroundResource(R.color.background_start_testing); mInspectButton.setEnabled(false); mMovementSpinner.setEnabled(false); break; case STOP_TESTING: mCaptureButton.setChecked(false); mUrl.setBackgroundResource(R.color.background_stop_testing); break; case SAVED_TESTING: mInspectButton.setEnabled(true); mMovementSpinner.setEnabled(true); break; } } /** auto - automatically scroll. */ private void startViewProfiling(boolean auto) { // toggle capture button to indicate capture state to user mWeb.startScrollTest(mCallback, auto); setTestingState(TestingState.START_TESTING); } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mInspectButton = (Button) findViewById(R.id.inspect); mCaptureButton = (ToggleButton) findViewById(R.id.capture); mVelocitySpinner = (Spinner) findViewById(R.id.velocity); mMovementSpinner = (Spinner) findViewById(R.id.movement); mUrl = (EditText) findViewById(R.id.url); mWeb = (ProfiledWebView) findViewById(R.id.web); setCallback(new ProfileCallback() { @SuppressWarnings("unchecked") @Override public void profileCallback(RunData data) { new StoreFileTask().execute(new Pair( TEMP_FILENAME, data)); Log.d("ProfileActivity", "stored " + data.frames.length + " frames in file"); setTestingState(TestingState.STOP_TESTING); } }); // Inspect button (opens PlaybackActivity) mInspectButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(ProfileActivity.this, PlaybackActivity.class)); } }); // Velocity spinner ArrayAdapter adapter = ArrayAdapter.createFromResource( this, R.array.velocity_array, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item); mVelocitySpinner.setAdapter(adapter); mVelocitySpinner.setOnItemSelectedListener( new VelocitySelectedListener()); mVelocitySpinner.setSelection(3); // Movement spinner String content[] = { getResources().getString(R.string.movement_auto_scroll), getResources().getString(R.string.movement_manual), getResources().getString(R.string.movement_timed) }; adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, content); adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item); mMovementSpinner.setAdapter(adapter); mMovementSpinner.setOnItemSelectedListener( new MovementSelectedListener()); mMovementSpinner.setSelection(0); // Capture toggle button mCaptureButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mCaptureButton.isChecked()) { startViewProfiling(false); } else { mWeb.stopScrollTest(); } } }); // Custom profiling WebView mWeb.init(this); mWeb.setWebViewClient(new LoggingWebViewClient()); // URL text entry mUrl.setOnEditorActionListener(new OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { String url = mUrl.getText().toString(); mWeb.loadUrl(url); mWeb.requestFocus(); return true; } }); setTestingState(TestingState.NOT_TESTING); } public void setCallback(ProfileCallback callback) { mCallback = callback; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && mWeb.canGoBack()) { mWeb.goBack(); return true; } return super.onKeyDown(keyCode, event); } }